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