proto.rs

  1#![allow(non_snake_case)]
  2
  3pub mod error;
  4mod macros;
  5mod typed_envelope;
  6
  7pub use error::*;
  8pub use typed_envelope::*;
  9
 10use anyhow::anyhow;
 11use collections::HashMap;
 12use futures::{future::BoxFuture, Future};
 13pub use prost::{DecodeError, Message};
 14use serde::Serialize;
 15use std::{
 16    any::{Any, TypeId},
 17    cmp,
 18    fmt::{self, Debug},
 19    iter, mem,
 20    sync::Arc,
 21    time::{Duration, Instant, SystemTime, UNIX_EPOCH},
 22};
 23
 24include!(concat!(env!("OUT_DIR"), "/zed.messages.rs"));
 25
 26pub trait EnvelopedMessage: Clone + Debug + Serialize + Sized + Send + Sync + 'static {
 27    const NAME: &'static str;
 28    const PRIORITY: MessagePriority;
 29    fn into_envelope(
 30        self,
 31        id: u32,
 32        responding_to: Option<u32>,
 33        original_sender_id: Option<PeerId>,
 34    ) -> Envelope;
 35    fn from_envelope(envelope: Envelope) -> Option<Self>;
 36}
 37
 38pub trait EntityMessage: EnvelopedMessage {
 39    type Entity;
 40    fn remote_entity_id(&self) -> u64;
 41}
 42
 43pub trait RequestMessage: EnvelopedMessage {
 44    type Response: EnvelopedMessage;
 45}
 46
 47pub trait AnyTypedEnvelope: 'static + Send + Sync {
 48    fn payload_type_id(&self) -> TypeId;
 49    fn payload_type_name(&self) -> &'static str;
 50    fn as_any(&self) -> &dyn Any;
 51    fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
 52    fn is_background(&self) -> bool;
 53    fn original_sender_id(&self) -> Option<PeerId>;
 54    fn sender_id(&self) -> PeerId;
 55    fn message_id(&self) -> u32;
 56}
 57
 58pub enum MessagePriority {
 59    Foreground,
 60    Background,
 61}
 62
 63pub trait ProtoClient: Send + Sync {
 64    fn request(
 65        &self,
 66        envelope: Envelope,
 67        request_type: &'static str,
 68    ) -> BoxFuture<'static, anyhow::Result<Envelope>>;
 69
 70    fn send(&self, envelope: Envelope) -> anyhow::Result<()>;
 71}
 72
 73#[derive(Clone)]
 74pub struct AnyProtoClient(Arc<dyn ProtoClient>);
 75
 76impl<T> From<Arc<T>> for AnyProtoClient
 77where
 78    T: ProtoClient + 'static,
 79{
 80    fn from(client: Arc<T>) -> Self {
 81        Self(client)
 82    }
 83}
 84
 85impl AnyProtoClient {
 86    pub fn new<T: ProtoClient + 'static>(client: Arc<T>) -> Self {
 87        Self(client)
 88    }
 89
 90    pub fn request<T: RequestMessage>(
 91        &self,
 92        request: T,
 93    ) -> impl Future<Output = anyhow::Result<T::Response>> {
 94        let envelope = request.into_envelope(0, None, None);
 95        let response = self.0.request(envelope, T::NAME);
 96        async move {
 97            T::Response::from_envelope(response.await?)
 98                .ok_or_else(|| anyhow!("received response of the wrong type"))
 99        }
100    }
101
102    pub fn send<T: EnvelopedMessage>(&self, request: T) -> anyhow::Result<()> {
103        let envelope = request.into_envelope(0, None, None);
104        self.0.send(envelope)
105    }
106}
107
108impl<T: EnvelopedMessage> AnyTypedEnvelope for TypedEnvelope<T> {
109    fn payload_type_id(&self) -> TypeId {
110        TypeId::of::<T>()
111    }
112
113    fn payload_type_name(&self) -> &'static str {
114        T::NAME
115    }
116
117    fn as_any(&self) -> &dyn Any {
118        self
119    }
120
121    fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
122        self
123    }
124
125    fn is_background(&self) -> bool {
126        matches!(T::PRIORITY, MessagePriority::Background)
127    }
128
129    fn original_sender_id(&self) -> Option<PeerId> {
130        self.original_sender_id
131    }
132
133    fn sender_id(&self) -> PeerId {
134        self.sender_id
135    }
136
137    fn message_id(&self) -> u32 {
138        self.message_id
139    }
140}
141
142impl PeerId {
143    pub fn from_u64(peer_id: u64) -> Self {
144        let owner_id = (peer_id >> 32) as u32;
145        let id = peer_id as u32;
146        Self { owner_id, id }
147    }
148
149    pub fn as_u64(self) -> u64 {
150        ((self.owner_id as u64) << 32) | (self.id as u64)
151    }
152}
153
154impl Copy for PeerId {}
155
156impl Eq for PeerId {}
157
158impl Ord for PeerId {
159    fn cmp(&self, other: &Self) -> cmp::Ordering {
160        self.owner_id
161            .cmp(&other.owner_id)
162            .then_with(|| self.id.cmp(&other.id))
163    }
164}
165
166impl PartialOrd for PeerId {
167    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
168        Some(self.cmp(other))
169    }
170}
171
172impl std::hash::Hash for PeerId {
173    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
174        self.owner_id.hash(state);
175        self.id.hash(state);
176    }
177}
178
179impl fmt::Display for PeerId {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        write!(f, "{}/{}", self.owner_id, self.id)
182    }
183}
184
185messages!(
186    (Ack, Foreground),
187    (AckBufferOperation, Background),
188    (AckChannelMessage, Background),
189    (AddNotification, Foreground),
190    (AddProjectCollaborator, Foreground),
191    (ApplyCodeAction, Background),
192    (ApplyCodeActionResponse, Background),
193    (ApplyCompletionAdditionalEdits, Background),
194    (ApplyCompletionAdditionalEditsResponse, Background),
195    (BufferReloaded, Foreground),
196    (BufferSaved, Foreground),
197    (Call, Foreground),
198    (CallCanceled, Foreground),
199    (CancelCall, Foreground),
200    (ChannelMessageSent, Foreground),
201    (ChannelMessageUpdate, Foreground),
202    (CompleteWithLanguageModel, Background),
203    (ComputeEmbeddings, Background),
204    (ComputeEmbeddingsResponse, Background),
205    (CopyProjectEntry, Foreground),
206    (CountTokensWithLanguageModel, Background),
207    (CountTokensResponse, Background),
208    (CreateBufferForPeer, Foreground),
209    (CreateChannel, Foreground),
210    (CreateChannelResponse, Foreground),
211    (CreateProjectEntry, Foreground),
212    (CreateRoom, Foreground),
213    (CreateRoomResponse, Foreground),
214    (DeclineCall, Foreground),
215    (DeleteChannel, Foreground),
216    (DeleteNotification, Foreground),
217    (UpdateNotification, Foreground),
218    (DeleteProjectEntry, Foreground),
219    (EndStream, Foreground),
220    (Error, Foreground),
221    (ExpandProjectEntry, Foreground),
222    (ExpandProjectEntryResponse, Foreground),
223    (Follow, Foreground),
224    (FollowResponse, Foreground),
225    (FormatBuffers, Foreground),
226    (FormatBuffersResponse, Foreground),
227    (FuzzySearchUsers, Foreground),
228    (GetCachedEmbeddings, Background),
229    (GetCachedEmbeddingsResponse, Background),
230    (GetChannelMembers, Foreground),
231    (GetChannelMembersResponse, Foreground),
232    (GetChannelMessages, Background),
233    (GetChannelMessagesById, Background),
234    (GetChannelMessagesResponse, Background),
235    (GetCodeActions, Background),
236    (GetCodeActionsResponse, Background),
237    (GetCompletions, Background),
238    (GetCompletionsResponse, Background),
239    (GetDefinition, Background),
240    (GetDefinitionResponse, Background),
241    (GetDocumentHighlights, Background),
242    (GetDocumentHighlightsResponse, Background),
243    (GetHover, Background),
244    (GetHoverResponse, Background),
245    (GetNotifications, Foreground),
246    (GetNotificationsResponse, Foreground),
247    (GetPrivateUserInfo, Foreground),
248    (GetPrivateUserInfoResponse, Foreground),
249    (GetProjectSymbols, Background),
250    (GetProjectSymbolsResponse, Background),
251    (GetReferences, Background),
252    (GetReferencesResponse, Background),
253    (GetSignatureHelp, Background),
254    (GetSignatureHelpResponse, Background),
255    (GetSupermavenApiKey, Background),
256    (GetSupermavenApiKeyResponse, Background),
257    (GetTypeDefinition, Background),
258    (GetTypeDefinitionResponse, Background),
259    (GetImplementation, Background),
260    (GetImplementationResponse, Background),
261    (GetUsers, Foreground),
262    (Hello, Foreground),
263    (IncomingCall, Foreground),
264    (InlayHints, Background),
265    (InlayHintsResponse, Background),
266    (InviteChannelMember, Foreground),
267    (JoinChannel, Foreground),
268    (JoinChannelBuffer, Foreground),
269    (JoinChannelBufferResponse, Foreground),
270    (JoinChannelChat, Foreground),
271    (JoinChannelChatResponse, Foreground),
272    (JoinProject, Foreground),
273    (JoinHostedProject, Foreground),
274    (JoinProjectResponse, Foreground),
275    (JoinRoom, Foreground),
276    (JoinRoomResponse, Foreground),
277    (LanguageModelResponse, Background),
278    (LeaveChannelBuffer, Background),
279    (LeaveChannelChat, Foreground),
280    (LeaveProject, Foreground),
281    (LeaveRoom, Foreground),
282    (MarkNotificationRead, Foreground),
283    (MoveChannel, Foreground),
284    (OnTypeFormatting, Background),
285    (OnTypeFormattingResponse, Background),
286    (OpenBufferById, Background),
287    (OpenBufferByPath, Background),
288    (OpenBufferForSymbol, Background),
289    (OpenBufferForSymbolResponse, Background),
290    (OpenBufferResponse, Background),
291    (PerformRename, Background),
292    (PerformRenameResponse, Background),
293    (Ping, Foreground),
294    (PrepareRename, Background),
295    (PrepareRenameResponse, Background),
296    (ProjectEntryResponse, Foreground),
297    (RefreshInlayHints, Foreground),
298    (RejoinChannelBuffers, Foreground),
299    (RejoinChannelBuffersResponse, Foreground),
300    (RejoinRoom, Foreground),
301    (RejoinRoomResponse, Foreground),
302    (ReloadBuffers, Foreground),
303    (ReloadBuffersResponse, Foreground),
304    (RemoveChannelMember, Foreground),
305    (RemoveChannelMessage, Foreground),
306    (UpdateChannelMessage, Foreground),
307    (RemoveContact, Foreground),
308    (RemoveProjectCollaborator, Foreground),
309    (RenameChannel, Foreground),
310    (RenameChannelResponse, Foreground),
311    (RenameProjectEntry, Foreground),
312    (RequestContact, Foreground),
313    (ResolveCompletionDocumentation, Background),
314    (ResolveCompletionDocumentationResponse, Background),
315    (ResolveInlayHint, Background),
316    (ResolveInlayHintResponse, Background),
317    (RespondToChannelInvite, Foreground),
318    (RespondToContactRequest, Foreground),
319    (RoomUpdated, Foreground),
320    (SaveBuffer, Foreground),
321    (SetChannelMemberRole, Foreground),
322    (SetChannelVisibility, Foreground),
323    (SearchProject, Background),
324    (SearchProjectResponse, Background),
325    (SendChannelMessage, Background),
326    (SendChannelMessageResponse, Background),
327    (ShareProject, Foreground),
328    (ShareProjectResponse, Foreground),
329    (ShowContacts, Foreground),
330    (StartLanguageServer, Foreground),
331    (SubscribeToChannels, Foreground),
332    (SynchronizeBuffers, Foreground),
333    (SynchronizeBuffersResponse, Foreground),
334    (TaskContextForLocation, Background),
335    (TaskContext, Background),
336    (TaskTemplates, Background),
337    (TaskTemplatesResponse, Background),
338    (Test, Foreground),
339    (Unfollow, Foreground),
340    (UnshareProject, Foreground),
341    (UpdateBuffer, Foreground),
342    (UpdateBufferFile, Foreground),
343    (UpdateChannelBuffer, Foreground),
344    (UpdateChannelBufferCollaborators, Foreground),
345    (UpdateChannels, Foreground),
346    (UpdateUserChannels, Foreground),
347    (UpdateContacts, Foreground),
348    (UpdateDiagnosticSummary, Foreground),
349    (UpdateDiffBase, Foreground),
350    (UpdateFollowers, Foreground),
351    (UpdateInviteInfo, Foreground),
352    (UpdateLanguageServer, Foreground),
353    (UpdateParticipantLocation, Foreground),
354    (UpdateProject, Foreground),
355    (UpdateProjectCollaborator, Foreground),
356    (UpdateWorktree, Foreground),
357    (UpdateWorktreeSettings, Foreground),
358    (UsersResponse, Foreground),
359    (LspExtExpandMacro, Background),
360    (LspExtExpandMacroResponse, Background),
361    (SetRoomParticipantRole, Foreground),
362    (BlameBuffer, Foreground),
363    (BlameBufferResponse, Foreground),
364    (CreateDevServerProject, Background),
365    (CreateDevServerProjectResponse, Foreground),
366    (CreateDevServer, Foreground),
367    (CreateDevServerResponse, Foreground),
368    (DevServerInstructions, Foreground),
369    (ShutdownDevServer, Foreground),
370    (ReconnectDevServer, Foreground),
371    (ReconnectDevServerResponse, Foreground),
372    (ShareDevServerProject, Foreground),
373    (JoinDevServerProject, Foreground),
374    (RejoinRemoteProjects, Foreground),
375    (RejoinRemoteProjectsResponse, Foreground),
376    (MultiLspQuery, Background),
377    (MultiLspQueryResponse, Background),
378    (DevServerProjectsUpdate, Foreground),
379    (ValidateDevServerProjectRequest, Background),
380    (ListRemoteDirectory, Background),
381    (ListRemoteDirectoryResponse, Background),
382    (UpdateDevServerProject, Background),
383    (DeleteDevServer, Foreground),
384    (DeleteDevServerProject, Foreground),
385    (RegenerateDevServerToken, Foreground),
386    (RegenerateDevServerTokenResponse, Foreground),
387    (RenameDevServer, Foreground),
388    (OpenNewBuffer, Foreground),
389    (RestartLanguageServers, Foreground),
390    (LinkedEditingRange, Background),
391    (LinkedEditingRangeResponse, Background),
392    (AdvertiseContexts, Foreground),
393    (OpenContext, Foreground),
394    (OpenContextResponse, Foreground),
395    (UpdateContext, Foreground),
396    (SynchronizeContexts, Foreground),
397    (SynchronizeContextsResponse, Foreground),
398);
399
400request_messages!(
401    (ApplyCodeAction, ApplyCodeActionResponse),
402    (
403        ApplyCompletionAdditionalEdits,
404        ApplyCompletionAdditionalEditsResponse
405    ),
406    (Call, Ack),
407    (CancelCall, Ack),
408    (CopyProjectEntry, ProjectEntryResponse),
409    (CompleteWithLanguageModel, LanguageModelResponse),
410    (ComputeEmbeddings, ComputeEmbeddingsResponse),
411    (CountTokensWithLanguageModel, CountTokensResponse),
412    (CreateChannel, CreateChannelResponse),
413    (CreateProjectEntry, ProjectEntryResponse),
414    (CreateRoom, CreateRoomResponse),
415    (DeclineCall, Ack),
416    (DeleteChannel, Ack),
417    (DeleteProjectEntry, ProjectEntryResponse),
418    (ExpandProjectEntry, ExpandProjectEntryResponse),
419    (Follow, FollowResponse),
420    (FormatBuffers, FormatBuffersResponse),
421    (FuzzySearchUsers, UsersResponse),
422    (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
423    (GetChannelMembers, GetChannelMembersResponse),
424    (GetChannelMessages, GetChannelMessagesResponse),
425    (GetChannelMessagesById, GetChannelMessagesResponse),
426    (GetCodeActions, GetCodeActionsResponse),
427    (GetCompletions, GetCompletionsResponse),
428    (GetDefinition, GetDefinitionResponse),
429    (GetImplementation, GetImplementationResponse),
430    (GetDocumentHighlights, GetDocumentHighlightsResponse),
431    (GetHover, GetHoverResponse),
432    (GetNotifications, GetNotificationsResponse),
433    (GetPrivateUserInfo, GetPrivateUserInfoResponse),
434    (GetProjectSymbols, GetProjectSymbolsResponse),
435    (GetReferences, GetReferencesResponse),
436    (GetSignatureHelp, GetSignatureHelpResponse),
437    (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
438    (GetTypeDefinition, GetTypeDefinitionResponse),
439    (LinkedEditingRange, LinkedEditingRangeResponse),
440    (ListRemoteDirectory, ListRemoteDirectoryResponse),
441    (UpdateDevServerProject, Ack),
442    (GetUsers, UsersResponse),
443    (IncomingCall, Ack),
444    (InlayHints, InlayHintsResponse),
445    (InviteChannelMember, Ack),
446    (JoinChannel, JoinRoomResponse),
447    (JoinChannelBuffer, JoinChannelBufferResponse),
448    (JoinChannelChat, JoinChannelChatResponse),
449    (JoinHostedProject, JoinProjectResponse),
450    (JoinProject, JoinProjectResponse),
451    (JoinRoom, JoinRoomResponse),
452    (LeaveChannelBuffer, Ack),
453    (LeaveRoom, Ack),
454    (MarkNotificationRead, Ack),
455    (MoveChannel, Ack),
456    (OnTypeFormatting, OnTypeFormattingResponse),
457    (OpenBufferById, OpenBufferResponse),
458    (OpenBufferByPath, OpenBufferResponse),
459    (OpenBufferForSymbol, OpenBufferForSymbolResponse),
460    (OpenNewBuffer, OpenBufferResponse),
461    (PerformRename, PerformRenameResponse),
462    (Ping, Ack),
463    (PrepareRename, PrepareRenameResponse),
464    (RefreshInlayHints, Ack),
465    (RejoinChannelBuffers, RejoinChannelBuffersResponse),
466    (RejoinRoom, RejoinRoomResponse),
467    (ReloadBuffers, ReloadBuffersResponse),
468    (RemoveChannelMember, Ack),
469    (RemoveChannelMessage, Ack),
470    (UpdateChannelMessage, Ack),
471    (RemoveContact, Ack),
472    (RenameChannel, RenameChannelResponse),
473    (RenameProjectEntry, ProjectEntryResponse),
474    (RequestContact, Ack),
475    (
476        ResolveCompletionDocumentation,
477        ResolveCompletionDocumentationResponse
478    ),
479    (ResolveInlayHint, ResolveInlayHintResponse),
480    (RespondToChannelInvite, Ack),
481    (RespondToContactRequest, Ack),
482    (SaveBuffer, BufferSaved),
483    (SearchProject, SearchProjectResponse),
484    (SendChannelMessage, SendChannelMessageResponse),
485    (SetChannelMemberRole, Ack),
486    (SetChannelVisibility, Ack),
487    (ShareProject, ShareProjectResponse),
488    (SynchronizeBuffers, SynchronizeBuffersResponse),
489    (TaskContextForLocation, TaskContext),
490    (TaskTemplates, TaskTemplatesResponse),
491    (Test, Test),
492    (UpdateBuffer, Ack),
493    (UpdateParticipantLocation, Ack),
494    (UpdateProject, Ack),
495    (UpdateWorktree, Ack),
496    (LspExtExpandMacro, LspExtExpandMacroResponse),
497    (SetRoomParticipantRole, Ack),
498    (BlameBuffer, BlameBufferResponse),
499    (CreateDevServerProject, CreateDevServerProjectResponse),
500    (CreateDevServer, CreateDevServerResponse),
501    (ShutdownDevServer, Ack),
502    (ShareDevServerProject, ShareProjectResponse),
503    (JoinDevServerProject, JoinProjectResponse),
504    (RejoinRemoteProjects, RejoinRemoteProjectsResponse),
505    (ReconnectDevServer, ReconnectDevServerResponse),
506    (ValidateDevServerProjectRequest, Ack),
507    (MultiLspQuery, MultiLspQueryResponse),
508    (DeleteDevServer, Ack),
509    (DeleteDevServerProject, Ack),
510    (RegenerateDevServerToken, RegenerateDevServerTokenResponse),
511    (RenameDevServer, Ack),
512    (RestartLanguageServers, Ack),
513    (OpenContext, OpenContextResponse),
514    (SynchronizeContexts, SynchronizeContextsResponse),
515);
516
517entity_messages!(
518    {project_id, ShareProject},
519    AddProjectCollaborator,
520    ApplyCodeAction,
521    ApplyCompletionAdditionalEdits,
522    BlameBuffer,
523    BufferReloaded,
524    BufferSaved,
525    CopyProjectEntry,
526    CreateBufferForPeer,
527    CreateProjectEntry,
528    DeleteProjectEntry,
529    ExpandProjectEntry,
530    FormatBuffers,
531    GetCodeActions,
532    GetCompletions,
533    GetDefinition,
534    GetImplementation,
535    GetDocumentHighlights,
536    GetHover,
537    GetProjectSymbols,
538    GetReferences,
539    GetSignatureHelp,
540    GetTypeDefinition,
541    InlayHints,
542    JoinProject,
543    LeaveProject,
544    LinkedEditingRange,
545    MultiLspQuery,
546    RestartLanguageServers,
547    OnTypeFormatting,
548    OpenNewBuffer,
549    OpenBufferById,
550    OpenBufferByPath,
551    OpenBufferForSymbol,
552    PerformRename,
553    PrepareRename,
554    RefreshInlayHints,
555    ReloadBuffers,
556    RemoveProjectCollaborator,
557    RenameProjectEntry,
558    ResolveCompletionDocumentation,
559    ResolveInlayHint,
560    SaveBuffer,
561    SearchProject,
562    StartLanguageServer,
563    SynchronizeBuffers,
564    TaskContextForLocation,
565    TaskTemplates,
566    UnshareProject,
567    UpdateBuffer,
568    UpdateBufferFile,
569    UpdateDiagnosticSummary,
570    UpdateDiffBase,
571    UpdateLanguageServer,
572    UpdateProject,
573    UpdateProjectCollaborator,
574    UpdateWorktree,
575    UpdateWorktreeSettings,
576    LspExtExpandMacro,
577    AdvertiseContexts,
578    OpenContext,
579    UpdateContext,
580    SynchronizeContexts,
581);
582
583entity_messages!(
584    {channel_id, Channel},
585    ChannelMessageSent,
586    ChannelMessageUpdate,
587    RemoveChannelMessage,
588    UpdateChannelMessage,
589    UpdateChannelBuffer,
590    UpdateChannelBufferCollaborators,
591);
592
593impl From<Timestamp> for SystemTime {
594    fn from(val: Timestamp) -> Self {
595        UNIX_EPOCH
596            .checked_add(Duration::new(val.seconds, val.nanos))
597            .unwrap()
598    }
599}
600
601impl From<SystemTime> for Timestamp {
602    fn from(time: SystemTime) -> Self {
603        let duration = time.duration_since(UNIX_EPOCH).unwrap();
604        Self {
605            seconds: duration.as_secs(),
606            nanos: duration.subsec_nanos(),
607        }
608    }
609}
610
611impl From<u128> for Nonce {
612    fn from(nonce: u128) -> Self {
613        let upper_half = (nonce >> 64) as u64;
614        let lower_half = nonce as u64;
615        Self {
616            upper_half,
617            lower_half,
618        }
619    }
620}
621
622impl From<Nonce> for u128 {
623    fn from(nonce: Nonce) -> Self {
624        let upper_half = (nonce.upper_half as u128) << 64;
625        let lower_half = nonce.lower_half as u128;
626        upper_half | lower_half
627    }
628}
629
630pub fn split_worktree_update(
631    mut message: UpdateWorktree,
632    max_chunk_size: usize,
633) -> impl Iterator<Item = UpdateWorktree> {
634    let mut done_files = false;
635
636    let mut repository_map = message
637        .updated_repositories
638        .into_iter()
639        .map(|repo| (repo.work_directory_id, repo))
640        .collect::<HashMap<_, _>>();
641
642    iter::from_fn(move || {
643        if done_files {
644            return None;
645        }
646
647        let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
648        let updated_entries: Vec<_> = message
649            .updated_entries
650            .drain(..updated_entries_chunk_size)
651            .collect();
652
653        let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
654        let removed_entries = message
655            .removed_entries
656            .drain(..removed_entries_chunk_size)
657            .collect();
658
659        done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
660
661        let mut updated_repositories = Vec::new();
662
663        if !repository_map.is_empty() {
664            for entry in &updated_entries {
665                if let Some(repo) = repository_map.remove(&entry.id) {
666                    updated_repositories.push(repo)
667                }
668            }
669        }
670
671        let removed_repositories = if done_files {
672            mem::take(&mut message.removed_repositories)
673        } else {
674            Default::default()
675        };
676
677        if done_files {
678            updated_repositories.extend(mem::take(&mut repository_map).into_values());
679        }
680
681        Some(UpdateWorktree {
682            project_id: message.project_id,
683            worktree_id: message.worktree_id,
684            root_name: message.root_name.clone(),
685            abs_path: message.abs_path.clone(),
686            updated_entries,
687            removed_entries,
688            scan_id: message.scan_id,
689            is_last_update: done_files && message.is_last_update,
690            updated_repositories,
691            removed_repositories,
692        })
693    })
694}
695
696#[cfg(test)]
697mod tests {
698    use super::*;
699
700    #[test]
701    fn test_converting_peer_id_from_and_to_u64() {
702        let peer_id = PeerId {
703            owner_id: 10,
704            id: 3,
705        };
706        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
707        let peer_id = PeerId {
708            owner_id: u32::MAX,
709            id: 3,
710        };
711        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
712        let peer_id = PeerId {
713            owner_id: 10,
714            id: u32::MAX,
715        };
716        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
717        let peer_id = PeerId {
718            owner_id: u32::MAX,
719            id: u32::MAX,
720        };
721        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
722    }
723}