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    (JoinProjectResponse, Foreground),
232    (JoinRoom, Foreground),
233    (JoinRoomResponse, Foreground),
234    (LeaveChannelBuffer, Background),
235    (LeaveChannelChat, Foreground),
236    (LeaveProject, Foreground),
237    (LeaveRoom, Foreground),
238    (MarkNotificationRead, Foreground),
239    (MoveChannel, Foreground),
240    (OnTypeFormatting, Background),
241    (OnTypeFormattingResponse, Background),
242    (OpenBufferById, Background),
243    (OpenBufferByPath, Background),
244    (OpenBufferForSymbol, Background),
245    (OpenBufferForSymbolResponse, Background),
246    (OpenBufferResponse, Background),
247    (PerformRename, Background),
248    (PerformRenameResponse, Background),
249    (Ping, Foreground),
250    (PrepareRename, Background),
251    (PrepareRenameResponse, Background),
252    (ProjectEntryResponse, Foreground),
253    (CountLanguageModelTokens, Background),
254    (CountLanguageModelTokensResponse, Background),
255    (RefreshLlmToken, 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    (SendChannelMessage, Background),
283    (SendChannelMessageResponse, Background),
284    (ShareProject, Foreground),
285    (ShareProjectResponse, Foreground),
286    (ShowContacts, Foreground),
287    (StartLanguageServer, Foreground),
288    (SubscribeToChannels, Foreground),
289    (SynchronizeBuffers, Foreground),
290    (SynchronizeBuffersResponse, Foreground),
291    (TaskContextForLocation, Background),
292    (TaskContext, Background),
293    (Test, Foreground),
294    (Unfollow, Foreground),
295    (UnshareProject, Foreground),
296    (UpdateBuffer, Foreground),
297    (UpdateBufferFile, Foreground),
298    (UpdateChannelBuffer, Foreground),
299    (UpdateChannelBufferCollaborators, Foreground),
300    (UpdateChannels, Foreground),
301    (UpdateUserChannels, Foreground),
302    (UpdateContacts, Foreground),
303    (UpdateDiagnosticSummary, Foreground),
304    (UpdateDiffBase, Foreground),
305    (UpdateFollowers, Foreground),
306    (UpdateInviteInfo, Foreground),
307    (UpdateLanguageServer, Foreground),
308    (UpdateParticipantLocation, Foreground),
309    (UpdateProject, Foreground),
310    (UpdateProjectCollaborator, Foreground),
311    (UpdateUserPlan, Foreground),
312    (UpdateWorktree, Foreground),
313    (UpdateWorktreeSettings, Foreground),
314    (UsersResponse, Foreground),
315    (LspExtExpandMacro, Background),
316    (LspExtExpandMacroResponse, Background),
317    (SetRoomParticipantRole, Foreground),
318    (BlameBuffer, Foreground),
319    (BlameBufferResponse, Foreground),
320    (RejoinRemoteProjects, Foreground),
321    (RejoinRemoteProjectsResponse, Foreground),
322    (MultiLspQuery, Background),
323    (MultiLspQueryResponse, Background),
324    (ListRemoteDirectory, Background),
325    (ListRemoteDirectoryResponse, Background),
326    (OpenNewBuffer, Foreground),
327    (RestartLanguageServers, Foreground),
328    (LinkedEditingRange, Background),
329    (LinkedEditingRangeResponse, Background),
330    (AdvertiseContexts, Foreground),
331    (OpenContext, Foreground),
332    (OpenContextResponse, Foreground),
333    (CreateContext, Foreground),
334    (CreateContextResponse, Foreground),
335    (UpdateContext, Foreground),
336    (SynchronizeContexts, Foreground),
337    (SynchronizeContextsResponse, Foreground),
338    (LspExtSwitchSourceHeader, Background),
339    (LspExtSwitchSourceHeaderResponse, Background),
340    (AddWorktree, Foreground),
341    (AddWorktreeResponse, Foreground),
342    (FindSearchCandidates, Background),
343    (FindSearchCandidatesResponse, Background),
344    (CloseBuffer, Foreground),
345    (ShutdownRemoteServer, Foreground),
346    (RemoveWorktree, Foreground),
347    (LanguageServerLog, Foreground),
348    (Toast, Background),
349    (HideToast, Background),
350    (OpenServerSettings, Foreground),
351    (GetPermalinkToLine, Foreground),
352    (GetPermalinkToLineResponse, Foreground),
353    (FlushBufferedMessages, Foreground),
354    (LanguageServerPromptRequest, Foreground),
355    (LanguageServerPromptResponse, Foreground),
356    (GitBranches, Background),
357    (GitBranchesResponse, Background),
358    (UpdateGitBranch, Background),
359    (ListToolchains, Foreground),
360    (ListToolchainsResponse, Foreground),
361    (ActivateToolchain, Foreground),
362    (ActiveToolchain, Foreground),
363    (ActiveToolchainResponse, Foreground),
364    (GetPathMetadata, Background),
365    (GetPathMetadataResponse, Background),
366    (GetPanicFiles, Background),
367    (GetPanicFilesResponse, Background),
368    (CancelLanguageServerWork, Foreground),
369);
370
371request_messages!(
372    (AcceptTermsOfService, AcceptTermsOfServiceResponse),
373    (ApplyCodeAction, ApplyCodeActionResponse),
374    (
375        ApplyCompletionAdditionalEdits,
376        ApplyCompletionAdditionalEditsResponse
377    ),
378    (Call, Ack),
379    (CancelCall, Ack),
380    (CopyProjectEntry, ProjectEntryResponse),
381    (ComputeEmbeddings, ComputeEmbeddingsResponse),
382    (CreateChannel, CreateChannelResponse),
383    (CreateProjectEntry, ProjectEntryResponse),
384    (CreateRoom, CreateRoomResponse),
385    (DeclineCall, Ack),
386    (DeleteChannel, Ack),
387    (DeleteProjectEntry, ProjectEntryResponse),
388    (ExpandProjectEntry, ExpandProjectEntryResponse),
389    (Follow, FollowResponse),
390    (FormatBuffers, FormatBuffersResponse),
391    (FuzzySearchUsers, UsersResponse),
392    (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
393    (GetChannelMembers, GetChannelMembersResponse),
394    (GetChannelMessages, GetChannelMessagesResponse),
395    (GetChannelMessagesById, GetChannelMessagesResponse),
396    (GetCodeActions, GetCodeActionsResponse),
397    (GetCompletions, GetCompletionsResponse),
398    (GetDefinition, GetDefinitionResponse),
399    (GetDeclaration, GetDeclarationResponse),
400    (GetImplementation, GetImplementationResponse),
401    (GetDocumentHighlights, GetDocumentHighlightsResponse),
402    (GetHover, GetHoverResponse),
403    (GetLlmToken, GetLlmTokenResponse),
404    (GetNotifications, GetNotificationsResponse),
405    (GetPrivateUserInfo, GetPrivateUserInfoResponse),
406    (GetProjectSymbols, GetProjectSymbolsResponse),
407    (GetReferences, GetReferencesResponse),
408    (GetSignatureHelp, GetSignatureHelpResponse),
409    (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
410    (GetTypeDefinition, GetTypeDefinitionResponse),
411    (LinkedEditingRange, LinkedEditingRangeResponse),
412    (ListRemoteDirectory, ListRemoteDirectoryResponse),
413    (GetUsers, UsersResponse),
414    (IncomingCall, Ack),
415    (InlayHints, InlayHintsResponse),
416    (InviteChannelMember, Ack),
417    (JoinChannel, JoinRoomResponse),
418    (JoinChannelBuffer, JoinChannelBufferResponse),
419    (JoinChannelChat, JoinChannelChatResponse),
420    (JoinProject, JoinProjectResponse),
421    (JoinRoom, JoinRoomResponse),
422    (LeaveChannelBuffer, Ack),
423    (LeaveRoom, Ack),
424    (MarkNotificationRead, Ack),
425    (MoveChannel, Ack),
426    (OnTypeFormatting, OnTypeFormattingResponse),
427    (OpenBufferById, OpenBufferResponse),
428    (OpenBufferByPath, OpenBufferResponse),
429    (OpenBufferForSymbol, OpenBufferForSymbolResponse),
430    (OpenNewBuffer, OpenBufferResponse),
431    (PerformRename, PerformRenameResponse),
432    (Ping, Ack),
433    (PrepareRename, PrepareRenameResponse),
434    (CountLanguageModelTokens, CountLanguageModelTokensResponse),
435    (RefreshInlayHints, Ack),
436    (RejoinChannelBuffers, RejoinChannelBuffersResponse),
437    (RejoinRoom, RejoinRoomResponse),
438    (ReloadBuffers, ReloadBuffersResponse),
439    (RemoveChannelMember, Ack),
440    (RemoveChannelMessage, Ack),
441    (UpdateChannelMessage, Ack),
442    (RemoveContact, Ack),
443    (RenameChannel, RenameChannelResponse),
444    (RenameProjectEntry, ProjectEntryResponse),
445    (RequestContact, Ack),
446    (
447        ResolveCompletionDocumentation,
448        ResolveCompletionDocumentationResponse
449    ),
450    (ResolveInlayHint, ResolveInlayHintResponse),
451    (RespondToChannelInvite, Ack),
452    (RespondToContactRequest, Ack),
453    (SaveBuffer, BufferSaved),
454    (FindSearchCandidates, FindSearchCandidatesResponse),
455    (SendChannelMessage, SendChannelMessageResponse),
456    (SetChannelMemberRole, Ack),
457    (SetChannelVisibility, Ack),
458    (ShareProject, ShareProjectResponse),
459    (SynchronizeBuffers, SynchronizeBuffersResponse),
460    (TaskContextForLocation, TaskContext),
461    (Test, Test),
462    (UpdateBuffer, Ack),
463    (UpdateParticipantLocation, Ack),
464    (UpdateProject, Ack),
465    (UpdateWorktree, Ack),
466    (LspExtExpandMacro, LspExtExpandMacroResponse),
467    (SetRoomParticipantRole, Ack),
468    (BlameBuffer, BlameBufferResponse),
469    (RejoinRemoteProjects, RejoinRemoteProjectsResponse),
470    (MultiLspQuery, MultiLspQueryResponse),
471    (RestartLanguageServers, Ack),
472    (OpenContext, OpenContextResponse),
473    (CreateContext, CreateContextResponse),
474    (SynchronizeContexts, SynchronizeContextsResponse),
475    (LspExtSwitchSourceHeader, LspExtSwitchSourceHeaderResponse),
476    (AddWorktree, AddWorktreeResponse),
477    (ShutdownRemoteServer, Ack),
478    (RemoveWorktree, Ack),
479    (OpenServerSettings, OpenBufferResponse),
480    (GetPermalinkToLine, GetPermalinkToLineResponse),
481    (FlushBufferedMessages, Ack),
482    (LanguageServerPromptRequest, LanguageServerPromptResponse),
483    (GitBranches, GitBranchesResponse),
484    (UpdateGitBranch, Ack),
485    (ListToolchains, ListToolchainsResponse),
486    (ActivateToolchain, Ack),
487    (ActiveToolchain, ActiveToolchainResponse),
488    (GetPathMetadata, GetPathMetadataResponse),
489    (GetPanicFiles, GetPanicFilesResponse),
490    (CancelLanguageServerWork, Ack),
491);
492
493entity_messages!(
494    {project_id, ShareProject},
495    AddProjectCollaborator,
496    AddWorktree,
497    ApplyCodeAction,
498    ApplyCompletionAdditionalEdits,
499    BlameBuffer,
500    BufferReloaded,
501    BufferSaved,
502    CloseBuffer,
503    CopyProjectEntry,
504    CreateBufferForPeer,
505    CreateProjectEntry,
506    DeleteProjectEntry,
507    ExpandProjectEntry,
508    FindSearchCandidates,
509    FormatBuffers,
510    GetCodeActions,
511    GetCompletions,
512    GetDefinition,
513    GetDeclaration,
514    GetImplementation,
515    GetDocumentHighlights,
516    GetHover,
517    GetProjectSymbols,
518    GetReferences,
519    GetSignatureHelp,
520    GetTypeDefinition,
521    InlayHints,
522    JoinProject,
523    LeaveProject,
524    LinkedEditingRange,
525    MultiLspQuery,
526    RestartLanguageServers,
527    OnTypeFormatting,
528    OpenNewBuffer,
529    OpenBufferById,
530    OpenBufferByPath,
531    OpenBufferForSymbol,
532    PerformRename,
533    PrepareRename,
534    RefreshInlayHints,
535    ReloadBuffers,
536    RemoveProjectCollaborator,
537    RenameProjectEntry,
538    ResolveCompletionDocumentation,
539    ResolveInlayHint,
540    SaveBuffer,
541    StartLanguageServer,
542    SynchronizeBuffers,
543    TaskContextForLocation,
544    UnshareProject,
545    UpdateBuffer,
546    UpdateBufferFile,
547    UpdateDiagnosticSummary,
548    UpdateDiffBase,
549    UpdateLanguageServer,
550    UpdateProject,
551    UpdateProjectCollaborator,
552    UpdateWorktree,
553    UpdateWorktreeSettings,
554    LspExtExpandMacro,
555    AdvertiseContexts,
556    OpenContext,
557    CreateContext,
558    UpdateContext,
559    SynchronizeContexts,
560    LspExtSwitchSourceHeader,
561    LanguageServerLog,
562    Toast,
563    HideToast,
564    OpenServerSettings,
565    GetPermalinkToLine,
566    LanguageServerPromptRequest,
567    GitBranches,
568    UpdateGitBranch,
569    ListToolchains,
570    ActivateToolchain,
571    ActiveToolchain,
572    GetPathMetadata,
573    CancelLanguageServerWork,
574);
575
576entity_messages!(
577    {channel_id, Channel},
578    ChannelMessageSent,
579    ChannelMessageUpdate,
580    RemoveChannelMessage,
581    UpdateChannelMessage,
582    UpdateChannelBuffer,
583    UpdateChannelBufferCollaborators,
584);
585
586impl From<Timestamp> for SystemTime {
587    fn from(val: Timestamp) -> Self {
588        UNIX_EPOCH
589            .checked_add(Duration::new(val.seconds, val.nanos))
590            .unwrap()
591    }
592}
593
594impl From<SystemTime> for Timestamp {
595    fn from(time: SystemTime) -> Self {
596        let duration = time.duration_since(UNIX_EPOCH).unwrap();
597        Self {
598            seconds: duration.as_secs(),
599            nanos: duration.subsec_nanos(),
600        }
601    }
602}
603
604impl From<u128> for Nonce {
605    fn from(nonce: u128) -> Self {
606        let upper_half = (nonce >> 64) as u64;
607        let lower_half = nonce as u64;
608        Self {
609            upper_half,
610            lower_half,
611        }
612    }
613}
614
615impl From<Nonce> for u128 {
616    fn from(nonce: Nonce) -> Self {
617        let upper_half = (nonce.upper_half as u128) << 64;
618        let lower_half = nonce.lower_half as u128;
619        upper_half | lower_half
620    }
621}
622
623#[cfg(any(test, feature = "test-support"))]
624pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 2;
625#[cfg(not(any(test, feature = "test-support")))]
626pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 256;
627
628pub fn split_worktree_update(mut message: UpdateWorktree) -> impl Iterator<Item = UpdateWorktree> {
629    let mut done_files = false;
630
631    let mut repository_map = message
632        .updated_repositories
633        .into_iter()
634        .map(|repo| (repo.work_directory_id, repo))
635        .collect::<HashMap<_, _>>();
636
637    iter::from_fn(move || {
638        if done_files {
639            return None;
640        }
641
642        let updated_entries_chunk_size = cmp::min(
643            message.updated_entries.len(),
644            MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
645        );
646        let updated_entries: Vec<_> = message
647            .updated_entries
648            .drain(..updated_entries_chunk_size)
649            .collect();
650
651        let removed_entries_chunk_size = cmp::min(
652            message.removed_entries.len(),
653            MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
654        );
655        let removed_entries = message
656            .removed_entries
657            .drain(..removed_entries_chunk_size)
658            .collect();
659
660        done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
661
662        let mut updated_repositories = Vec::new();
663
664        if !repository_map.is_empty() {
665            for entry in &updated_entries {
666                if let Some(repo) = repository_map.remove(&entry.id) {
667                    updated_repositories.push(repo)
668                }
669            }
670        }
671
672        let removed_repositories = if done_files {
673            mem::take(&mut message.removed_repositories)
674        } else {
675            Default::default()
676        };
677
678        if done_files {
679            updated_repositories.extend(mem::take(&mut repository_map).into_values());
680        }
681
682        Some(UpdateWorktree {
683            project_id: message.project_id,
684            worktree_id: message.worktree_id,
685            root_name: message.root_name.clone(),
686            abs_path: message.abs_path.clone(),
687            updated_entries,
688            removed_entries,
689            scan_id: message.scan_id,
690            is_last_update: done_files && message.is_last_update,
691            updated_repositories,
692            removed_repositories,
693        })
694    })
695}
696
697#[cfg(test)]
698mod tests {
699    use super::*;
700
701    #[test]
702    fn test_converting_peer_id_from_and_to_u64() {
703        let peer_id = PeerId {
704            owner_id: 10,
705            id: 3,
706        };
707        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
708        let peer_id = PeerId {
709            owner_id: u32::MAX,
710            id: 3,
711        };
712        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
713        let peer_id = PeerId {
714            owner_id: 10,
715            id: u32::MAX,
716        };
717        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
718        let peer_id = PeerId {
719            owner_id: u32::MAX,
720            id: u32::MAX,
721        };
722        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
723    }
724}