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