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