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
 10pub use prost::{DecodeError, Message};
 11use serde::Serialize;
 12use std::{
 13    any::{Any, TypeId},
 14    cmp,
 15    fmt::{self, Debug},
 16    iter, mem,
 17    path::{Path, PathBuf},
 18    sync::Arc,
 19    time::{Duration, SystemTime, UNIX_EPOCH},
 20};
 21
 22include!(concat!(env!("OUT_DIR"), "/zed.messages.rs"));
 23
 24pub const SSH_PEER_ID: PeerId = PeerId { owner_id: 0, id: 0 };
 25pub const SSH_PROJECT_ID: u64 = 0;
 26
 27pub trait EnvelopedMessage: Clone + Debug + Serialize + Sized + Send + Sync + 'static {
 28    const NAME: &'static str;
 29    const PRIORITY: MessagePriority;
 30    fn into_envelope(
 31        self,
 32        id: u32,
 33        responding_to: Option<u32>,
 34        original_sender_id: Option<PeerId>,
 35    ) -> Envelope;
 36    fn from_envelope(envelope: Envelope) -> Option<Self>;
 37}
 38
 39pub trait EntityMessage: EnvelopedMessage {
 40    type Entity;
 41    fn remote_entity_id(&self) -> u64;
 42}
 43
 44pub trait RequestMessage: EnvelopedMessage {
 45    type Response: EnvelopedMessage;
 46}
 47
 48pub trait AnyTypedEnvelope: 'static + Send + Sync {
 49    fn payload_type_id(&self) -> TypeId;
 50    fn payload_type_name(&self) -> &'static str;
 51    fn as_any(&self) -> &dyn Any;
 52    fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
 53    fn is_background(&self) -> bool;
 54    fn original_sender_id(&self) -> Option<PeerId>;
 55    fn sender_id(&self) -> PeerId;
 56    fn message_id(&self) -> u32;
 57}
 58
 59pub enum MessagePriority {
 60    Foreground,
 61    Background,
 62}
 63
 64impl<T: EnvelopedMessage> AnyTypedEnvelope for TypedEnvelope<T> {
 65    fn payload_type_id(&self) -> TypeId {
 66        TypeId::of::<T>()
 67    }
 68
 69    fn payload_type_name(&self) -> &'static str {
 70        T::NAME
 71    }
 72
 73    fn as_any(&self) -> &dyn Any {
 74        self
 75    }
 76
 77    fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
 78        self
 79    }
 80
 81    fn is_background(&self) -> bool {
 82        matches!(T::PRIORITY, MessagePriority::Background)
 83    }
 84
 85    fn original_sender_id(&self) -> Option<PeerId> {
 86        self.original_sender_id
 87    }
 88
 89    fn sender_id(&self) -> PeerId {
 90        self.sender_id
 91    }
 92
 93    fn message_id(&self) -> u32 {
 94        self.message_id
 95    }
 96}
 97
 98impl PeerId {
 99    pub fn from_u64(peer_id: u64) -> Self {
100        let owner_id = (peer_id >> 32) as u32;
101        let id = peer_id as u32;
102        Self { owner_id, id }
103    }
104
105    pub fn as_u64(self) -> u64 {
106        ((self.owner_id as u64) << 32) | (self.id as u64)
107    }
108}
109
110impl Copy for PeerId {}
111
112impl Eq for PeerId {}
113
114impl Ord for PeerId {
115    fn cmp(&self, other: &Self) -> cmp::Ordering {
116        self.owner_id
117            .cmp(&other.owner_id)
118            .then_with(|| self.id.cmp(&other.id))
119    }
120}
121
122impl PartialOrd for PeerId {
123    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
124        Some(self.cmp(other))
125    }
126}
127
128impl std::hash::Hash for PeerId {
129    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
130        self.owner_id.hash(state);
131        self.id.hash(state);
132    }
133}
134
135impl fmt::Display for PeerId {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        write!(f, "{}/{}", self.owner_id, self.id)
138    }
139}
140
141pub trait FromProto {
142    fn from_proto(proto: String) -> Self;
143}
144
145pub trait ToProto {
146    fn to_proto(self) -> String;
147}
148
149impl FromProto for PathBuf {
150    #[cfg(target_os = "windows")]
151    fn from_proto(proto: String) -> Self {
152        proto.split("/").collect()
153    }
154
155    #[cfg(not(target_os = "windows"))]
156    fn from_proto(proto: String) -> Self {
157        PathBuf::from(proto)
158    }
159}
160
161impl FromProto for Arc<Path> {
162    fn from_proto(proto: String) -> Self {
163        PathBuf::from_proto(proto).into()
164    }
165}
166
167impl ToProto for PathBuf {
168    #[cfg(target_os = "windows")]
169    fn to_proto(self) -> String {
170        self.components()
171            .map(|comp| comp.as_os_str().to_string_lossy().to_string())
172            .collect::<Vec<_>>()
173            .join("/")
174    }
175
176    #[cfg(not(target_os = "windows"))]
177    fn to_proto(self) -> String {
178        self.to_string_lossy().to_string()
179    }
180}
181
182impl ToProto for &Path {
183    #[cfg(target_os = "windows")]
184    fn to_proto(self) -> String {
185        self.components()
186            .map(|comp| comp.as_os_str().to_string_lossy().to_string())
187            .collect::<Vec<_>>()
188            .join("/")
189    }
190
191    #[cfg(not(target_os = "windows"))]
192    fn to_proto(self) -> String {
193        self.to_string_lossy().to_string()
194    }
195}
196
197messages!(
198    (AcceptTermsOfService, Foreground),
199    (AcceptTermsOfServiceResponse, Foreground),
200    (Ack, Foreground),
201    (AckBufferOperation, Background),
202    (AckChannelMessage, Background),
203    (ActivateToolchain, Foreground),
204    (ActiveToolchain, Foreground),
205    (ActiveToolchainResponse, Foreground),
206    (AddNotification, Foreground),
207    (AddProjectCollaborator, Foreground),
208    (AddWorktree, Foreground),
209    (AddWorktreeResponse, Foreground),
210    (AdvertiseContexts, Foreground),
211    (ApplyCodeAction, Background),
212    (ApplyCodeActionResponse, Background),
213    (ApplyCompletionAdditionalEdits, Background),
214    (ApplyCompletionAdditionalEditsResponse, Background),
215    (BlameBuffer, Foreground),
216    (BlameBufferResponse, Foreground),
217    (BufferReloaded, Foreground),
218    (BufferSaved, Foreground),
219    (Call, Foreground),
220    (CallCanceled, Foreground),
221    (CancelCall, Foreground),
222    (CancelLanguageServerWork, Foreground),
223    (ChannelMessageSent, Foreground),
224    (ChannelMessageUpdate, Foreground),
225    (CloseBuffer, Foreground),
226    (Commit, Background),
227    (ComputeEmbeddings, Background),
228    (ComputeEmbeddingsResponse, Background),
229    (CopyProjectEntry, Foreground),
230    (CountLanguageModelTokens, Background),
231    (CountLanguageModelTokensResponse, Background),
232    (CreateBufferForPeer, Foreground),
233    (CreateChannel, Foreground),
234    (CreateChannelResponse, Foreground),
235    (CreateContext, Foreground),
236    (CreateContextResponse, Foreground),
237    (CreateProjectEntry, Foreground),
238    (CreateRoom, Foreground),
239    (CreateRoomResponse, Foreground),
240    (DeclineCall, Foreground),
241    (DeleteChannel, Foreground),
242    (DeleteNotification, Foreground),
243    (DeleteProjectEntry, Foreground),
244    (EndStream, Foreground),
245    (Error, Foreground),
246    (ExpandProjectEntry, Foreground),
247    (ExpandProjectEntryResponse, Foreground),
248    (FindSearchCandidatesResponse, Background),
249    (FindSearchCandidates, Background),
250    (FlushBufferedMessages, Foreground),
251    (ExpandAllForProjectEntry, Foreground),
252    (ExpandAllForProjectEntryResponse, Foreground),
253    (Follow, Foreground),
254    (FollowResponse, Foreground),
255    (ApplyCodeActionKind, Foreground),
256    (ApplyCodeActionKindResponse, Foreground),
257    (FormatBuffers, Foreground),
258    (FormatBuffersResponse, Foreground),
259    (FuzzySearchUsers, Foreground),
260    (GetCachedEmbeddings, Background),
261    (GetCachedEmbeddingsResponse, Background),
262    (GetChannelMembers, Foreground),
263    (GetChannelMembersResponse, Foreground),
264    (GetChannelMessages, Background),
265    (GetChannelMessagesById, Background),
266    (GetChannelMessagesResponse, Background),
267    (GetCodeActions, Background),
268    (GetCodeActionsResponse, Background),
269    (GetCompletions, Background),
270    (GetCompletionsResponse, Background),
271    (GetDeclaration, Background),
272    (GetDeclarationResponse, Background),
273    (GetDefinition, Background),
274    (GetDefinitionResponse, Background),
275    (GetDocumentHighlights, Background),
276    (GetDocumentHighlightsResponse, Background),
277    (GetDocumentSymbols, Background),
278    (GetDocumentSymbolsResponse, Background),
279    (GetHover, Background),
280    (GetHoverResponse, Background),
281    (GetNotifications, Foreground),
282    (GetNotificationsResponse, Foreground),
283    (GetPanicFiles, Background),
284    (GetPanicFilesResponse, Background),
285    (GetPathMetadata, Background),
286    (GetPathMetadataResponse, Background),
287    (GetPermalinkToLine, Foreground),
288    (GetPermalinkToLineResponse, Foreground),
289    (GetPrivateUserInfo, Foreground),
290    (GetPrivateUserInfoResponse, Foreground),
291    (GetProjectSymbols, Background),
292    (GetProjectSymbolsResponse, Background),
293    (GetReferences, Background),
294    (GetReferencesResponse, Background),
295    (GetSignatureHelp, Background),
296    (GetSignatureHelpResponse, Background),
297    (GetSupermavenApiKey, Background),
298    (GetSupermavenApiKeyResponse, Background),
299    (GetTypeDefinition, Background),
300    (GetTypeDefinitionResponse, Background),
301    (GetImplementation, Background),
302    (GetImplementationResponse, Background),
303    (GetLlmToken, Background),
304    (GetLlmTokenResponse, Background),
305    (OpenUnstagedDiff, Foreground),
306    (OpenUnstagedDiffResponse, Foreground),
307    (OpenUncommittedDiff, Foreground),
308    (OpenUncommittedDiffResponse, Foreground),
309    (GetUsers, Foreground),
310    (GitGetBranches, Background),
311    (GitBranchesResponse, Background),
312    (Hello, Foreground),
313    (HideToast, Background),
314    (IncomingCall, Foreground),
315    (InlayHints, Background),
316    (InlayHintsResponse, Background),
317    (InstallExtension, Background),
318    (InviteChannelMember, Foreground),
319    (JoinChannel, Foreground),
320    (JoinChannelBuffer, Foreground),
321    (JoinChannelBufferResponse, Foreground),
322    (JoinChannelChat, Foreground),
323    (JoinChannelChatResponse, Foreground),
324    (JoinProject, Foreground),
325    (JoinProjectResponse, Foreground),
326    (JoinRoom, Foreground),
327    (JoinRoomResponse, Foreground),
328    (LanguageServerLog, Foreground),
329    (LanguageServerPromptRequest, Foreground),
330    (LanguageServerPromptResponse, Foreground),
331    (LeaveChannelBuffer, Background),
332    (LeaveChannelChat, Foreground),
333    (LeaveProject, Foreground),
334    (LeaveRoom, Foreground),
335    (LinkedEditingRange, Background),
336    (LinkedEditingRangeResponse, Background),
337    (ListRemoteDirectory, Background),
338    (ListRemoteDirectoryResponse, Background),
339    (ListToolchains, Foreground),
340    (ListToolchainsResponse, Foreground),
341    (LspExtExpandMacro, Background),
342    (LspExtExpandMacroResponse, Background),
343    (LspExtOpenDocs, Background),
344    (LspExtOpenDocsResponse, Background),
345    (LspExtSwitchSourceHeader, Background),
346    (LspExtSwitchSourceHeaderResponse, Background),
347    (MarkNotificationRead, Foreground),
348    (MoveChannel, Foreground),
349    (MultiLspQuery, Background),
350    (MultiLspQueryResponse, Background),
351    (OnTypeFormatting, Background),
352    (OnTypeFormattingResponse, Background),
353    (OpenBufferById, Background),
354    (OpenBufferByPath, Background),
355    (OpenBufferForSymbol, Background),
356    (OpenBufferForSymbolResponse, Background),
357    (OpenBufferResponse, Background),
358    (OpenCommitMessageBuffer, Background),
359    (OpenContext, Foreground),
360    (OpenContextResponse, Foreground),
361    (OpenNewBuffer, Foreground),
362    (OpenServerSettings, Foreground),
363    (PerformRename, Background),
364    (PerformRenameResponse, Background),
365    (Ping, Foreground),
366    (PrepareRename, Background),
367    (PrepareRenameResponse, Background),
368    (ProjectEntryResponse, Foreground),
369    (RefreshInlayHints, Foreground),
370    (RefreshLlmToken, Background),
371    (RegisterBufferWithLanguageServers, Background),
372    (RejoinChannelBuffers, Foreground),
373    (RejoinChannelBuffersResponse, Foreground),
374    (RejoinRemoteProjects, Foreground),
375    (RejoinRemoteProjectsResponse, Foreground),
376    (RejoinRoom, Foreground),
377    (RejoinRoomResponse, Foreground),
378    (ReloadBuffers, Foreground),
379    (ReloadBuffersResponse, Foreground),
380    (RemoveChannelMember, Foreground),
381    (RemoveChannelMessage, Foreground),
382    (RemoveContact, Foreground),
383    (RemoveProjectCollaborator, Foreground),
384    (RemoveWorktree, Foreground),
385    (RenameChannel, Foreground),
386    (RenameChannelResponse, Foreground),
387    (RenameProjectEntry, Foreground),
388    (RequestContact, Foreground),
389    (ResolveCompletionDocumentation, Background),
390    (ResolveCompletionDocumentationResponse, Background),
391    (ResolveInlayHint, Background),
392    (ResolveInlayHintResponse, Background),
393    (RefreshCodeLens, Background),
394    (GetCodeLens, Background),
395    (GetCodeLensResponse, Background),
396    (RespondToChannelInvite, Foreground),
397    (RespondToContactRequest, Foreground),
398    (RestartLanguageServers, Foreground),
399    (RoomUpdated, Foreground),
400    (SaveBuffer, Foreground),
401    (SendChannelMessage, Background),
402    (SendChannelMessageResponse, Background),
403    (SetChannelMemberRole, Foreground),
404    (SetChannelVisibility, Foreground),
405    (SetRoomParticipantRole, Foreground),
406    (ShareProject, Foreground),
407    (ShareProjectResponse, Foreground),
408    (ShowContacts, Foreground),
409    (ShutdownRemoteServer, Foreground),
410    (Stage, Background),
411    (StartLanguageServer, Foreground),
412    (SubscribeToChannels, Foreground),
413    (SyncExtensions, Background),
414    (SyncExtensionsResponse, Background),
415    (BreakpointsForFile, Background),
416    (ToggleBreakpoint, Foreground),
417    (SynchronizeBuffers, Foreground),
418    (SynchronizeBuffersResponse, Foreground),
419    (SynchronizeContexts, Foreground),
420    (SynchronizeContextsResponse, Foreground),
421    (TaskContext, Background),
422    (TaskContextForLocation, Background),
423    (Test, Foreground),
424    (Toast, Background),
425    (Unfollow, Foreground),
426    (UnshareProject, Foreground),
427    (Unstage, Background),
428    (UpdateBuffer, Foreground),
429    (UpdateBufferFile, Foreground),
430    (UpdateChannelBuffer, Foreground),
431    (UpdateChannelBufferCollaborators, Foreground),
432    (UpdateChannelMessage, Foreground),
433    (UpdateChannels, Foreground),
434    (UpdateContacts, Foreground),
435    (UpdateContext, Foreground),
436    (UpdateDiagnosticSummary, Foreground),
437    (UpdateDiffBases, Foreground),
438    (UpdateFollowers, Foreground),
439    (UpdateGitBranch, Background),
440    (UpdateInviteInfo, Foreground),
441    (UpdateLanguageServer, Foreground),
442    (UpdateNotification, Foreground),
443    (UpdateParticipantLocation, Foreground),
444    (UpdateProject, Foreground),
445    (UpdateProjectCollaborator, Foreground),
446    (UpdateUserChannels, Foreground),
447    (UpdateUserPlan, Foreground),
448    (UpdateWorktree, Foreground),
449    (UpdateWorktreeSettings, Foreground),
450    (UpdateRepository, Foreground),
451    (RemoveRepository, Foreground),
452    (UsersResponse, Foreground),
453    (GitReset, Background),
454    (GitCheckoutFiles, Background),
455    (GitShow, Background),
456    (GitCommitDetails, Background),
457    (SetIndexText, Background),
458    (Push, Background),
459    (Fetch, Background),
460    (GetRemotes, Background),
461    (GetRemotesResponse, Background),
462    (Pull, Background),
463    (RemoteMessageResponse, Background),
464    (AskPassRequest, Background),
465    (AskPassResponse, Background),
466    (GitCreateBranch, Background),
467    (GitChangeBranch, Background),
468    (CheckForPushedCommits, Background),
469    (CheckForPushedCommitsResponse, Background),
470    (GitDiff, Background),
471    (GitDiffResponse, Background),
472    (GitInit, Background),
473);
474
475request_messages!(
476    (AcceptTermsOfService, AcceptTermsOfServiceResponse),
477    (ApplyCodeAction, ApplyCodeActionResponse),
478    (
479        ApplyCompletionAdditionalEdits,
480        ApplyCompletionAdditionalEditsResponse
481    ),
482    (Call, Ack),
483    (CancelCall, Ack),
484    (Commit, Ack),
485    (CopyProjectEntry, ProjectEntryResponse),
486    (ComputeEmbeddings, ComputeEmbeddingsResponse),
487    (CreateChannel, CreateChannelResponse),
488    (CreateProjectEntry, ProjectEntryResponse),
489    (CreateRoom, CreateRoomResponse),
490    (DeclineCall, Ack),
491    (DeleteChannel, Ack),
492    (DeleteProjectEntry, ProjectEntryResponse),
493    (ExpandProjectEntry, ExpandProjectEntryResponse),
494    (ExpandAllForProjectEntry, ExpandAllForProjectEntryResponse),
495    (Follow, FollowResponse),
496    (ApplyCodeActionKind, ApplyCodeActionKindResponse),
497    (FormatBuffers, FormatBuffersResponse),
498    (FuzzySearchUsers, UsersResponse),
499    (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
500    (GetChannelMembers, GetChannelMembersResponse),
501    (GetChannelMessages, GetChannelMessagesResponse),
502    (GetChannelMessagesById, GetChannelMessagesResponse),
503    (GetCodeActions, GetCodeActionsResponse),
504    (GetCompletions, GetCompletionsResponse),
505    (GetDefinition, GetDefinitionResponse),
506    (GetDeclaration, GetDeclarationResponse),
507    (GetImplementation, GetImplementationResponse),
508    (GetDocumentHighlights, GetDocumentHighlightsResponse),
509    (GetDocumentSymbols, GetDocumentSymbolsResponse),
510    (GetHover, GetHoverResponse),
511    (GetLlmToken, GetLlmTokenResponse),
512    (GetNotifications, GetNotificationsResponse),
513    (GetPrivateUserInfo, GetPrivateUserInfoResponse),
514    (GetProjectSymbols, GetProjectSymbolsResponse),
515    (GetReferences, GetReferencesResponse),
516    (GetSignatureHelp, GetSignatureHelpResponse),
517    (OpenUnstagedDiff, OpenUnstagedDiffResponse),
518    (OpenUncommittedDiff, OpenUncommittedDiffResponse),
519    (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
520    (GetTypeDefinition, GetTypeDefinitionResponse),
521    (LinkedEditingRange, LinkedEditingRangeResponse),
522    (ListRemoteDirectory, ListRemoteDirectoryResponse),
523    (GetUsers, UsersResponse),
524    (IncomingCall, Ack),
525    (InlayHints, InlayHintsResponse),
526    (GetCodeLens, GetCodeLensResponse),
527    (InviteChannelMember, Ack),
528    (JoinChannel, JoinRoomResponse),
529    (JoinChannelBuffer, JoinChannelBufferResponse),
530    (JoinChannelChat, JoinChannelChatResponse),
531    (JoinProject, JoinProjectResponse),
532    (JoinRoom, JoinRoomResponse),
533    (LeaveChannelBuffer, Ack),
534    (LeaveRoom, Ack),
535    (MarkNotificationRead, Ack),
536    (MoveChannel, Ack),
537    (OnTypeFormatting, OnTypeFormattingResponse),
538    (OpenBufferById, OpenBufferResponse),
539    (OpenBufferByPath, OpenBufferResponse),
540    (OpenBufferForSymbol, OpenBufferForSymbolResponse),
541    (OpenCommitMessageBuffer, OpenBufferResponse),
542    (OpenNewBuffer, OpenBufferResponse),
543    (PerformRename, PerformRenameResponse),
544    (Ping, Ack),
545    (PrepareRename, PrepareRenameResponse),
546    (CountLanguageModelTokens, CountLanguageModelTokensResponse),
547    (RefreshInlayHints, Ack),
548    (RefreshCodeLens, Ack),
549    (RejoinChannelBuffers, RejoinChannelBuffersResponse),
550    (RejoinRoom, RejoinRoomResponse),
551    (ReloadBuffers, ReloadBuffersResponse),
552    (RemoveChannelMember, Ack),
553    (RemoveChannelMessage, Ack),
554    (UpdateChannelMessage, Ack),
555    (RemoveContact, Ack),
556    (RenameChannel, RenameChannelResponse),
557    (RenameProjectEntry, ProjectEntryResponse),
558    (RequestContact, Ack),
559    (
560        ResolveCompletionDocumentation,
561        ResolveCompletionDocumentationResponse
562    ),
563    (ResolveInlayHint, ResolveInlayHintResponse),
564    (RespondToChannelInvite, Ack),
565    (RespondToContactRequest, Ack),
566    (SaveBuffer, BufferSaved),
567    (Stage, Ack),
568    (FindSearchCandidates, FindSearchCandidatesResponse),
569    (SendChannelMessage, SendChannelMessageResponse),
570    (SetChannelMemberRole, Ack),
571    (SetChannelVisibility, Ack),
572    (ShareProject, ShareProjectResponse),
573    (SynchronizeBuffers, SynchronizeBuffersResponse),
574    (TaskContextForLocation, TaskContext),
575    (Test, Test),
576    (Unstage, Ack),
577    (UpdateBuffer, Ack),
578    (UpdateParticipantLocation, Ack),
579    (UpdateProject, Ack),
580    (UpdateWorktree, Ack),
581    (UpdateRepository, Ack),
582    (RemoveRepository, Ack),
583    (LspExtExpandMacro, LspExtExpandMacroResponse),
584    (LspExtOpenDocs, LspExtOpenDocsResponse),
585    (SetRoomParticipantRole, Ack),
586    (BlameBuffer, BlameBufferResponse),
587    (RejoinRemoteProjects, RejoinRemoteProjectsResponse),
588    (MultiLspQuery, MultiLspQueryResponse),
589    (RestartLanguageServers, Ack),
590    (OpenContext, OpenContextResponse),
591    (CreateContext, CreateContextResponse),
592    (SynchronizeContexts, SynchronizeContextsResponse),
593    (LspExtSwitchSourceHeader, LspExtSwitchSourceHeaderResponse),
594    (AddWorktree, AddWorktreeResponse),
595    (ShutdownRemoteServer, Ack),
596    (RemoveWorktree, Ack),
597    (OpenServerSettings, OpenBufferResponse),
598    (GetPermalinkToLine, GetPermalinkToLineResponse),
599    (FlushBufferedMessages, Ack),
600    (LanguageServerPromptRequest, LanguageServerPromptResponse),
601    (GitGetBranches, GitBranchesResponse),
602    (UpdateGitBranch, Ack),
603    (ListToolchains, ListToolchainsResponse),
604    (ActivateToolchain, Ack),
605    (ActiveToolchain, ActiveToolchainResponse),
606    (GetPathMetadata, GetPathMetadataResponse),
607    (GetPanicFiles, GetPanicFilesResponse),
608    (CancelLanguageServerWork, Ack),
609    (SyncExtensions, SyncExtensionsResponse),
610    (InstallExtension, Ack),
611    (RegisterBufferWithLanguageServers, Ack),
612    (GitShow, GitCommitDetails),
613    (GitReset, Ack),
614    (GitCheckoutFiles, Ack),
615    (SetIndexText, Ack),
616    (Push, RemoteMessageResponse),
617    (Fetch, RemoteMessageResponse),
618    (GetRemotes, GetRemotesResponse),
619    (Pull, RemoteMessageResponse),
620    (AskPassRequest, AskPassResponse),
621    (GitCreateBranch, Ack),
622    (GitChangeBranch, Ack),
623    (CheckForPushedCommits, CheckForPushedCommitsResponse),
624    (GitDiff, GitDiffResponse),
625    (GitInit, Ack),
626    (ToggleBreakpoint, Ack),
627);
628
629entity_messages!(
630    {project_id, ShareProject},
631    AddProjectCollaborator,
632    AddWorktree,
633    ApplyCodeAction,
634    ApplyCompletionAdditionalEdits,
635    BlameBuffer,
636    BufferReloaded,
637    BufferSaved,
638    CloseBuffer,
639    Commit,
640    CopyProjectEntry,
641    CreateBufferForPeer,
642    CreateProjectEntry,
643    DeleteProjectEntry,
644    ExpandProjectEntry,
645    ExpandAllForProjectEntry,
646    FindSearchCandidates,
647    ApplyCodeActionKind,
648    FormatBuffers,
649    GetCodeActions,
650    GetCodeLens,
651    GetCompletions,
652    GetDefinition,
653    GetDeclaration,
654    GetImplementation,
655    GetDocumentHighlights,
656    GetDocumentSymbols,
657    GetHover,
658    GetProjectSymbols,
659    GetReferences,
660    GetSignatureHelp,
661    OpenUnstagedDiff,
662    OpenUncommittedDiff,
663    GetTypeDefinition,
664    InlayHints,
665    JoinProject,
666    LeaveProject,
667    LinkedEditingRange,
668    MultiLspQuery,
669    RestartLanguageServers,
670    OnTypeFormatting,
671    OpenNewBuffer,
672    OpenBufferById,
673    OpenBufferByPath,
674    OpenBufferForSymbol,
675    OpenCommitMessageBuffer,
676    PerformRename,
677    PrepareRename,
678    RefreshInlayHints,
679    RefreshCodeLens,
680    ReloadBuffers,
681    RemoveProjectCollaborator,
682    RenameProjectEntry,
683    ResolveCompletionDocumentation,
684    ResolveInlayHint,
685    SaveBuffer,
686    Stage,
687    StartLanguageServer,
688    SynchronizeBuffers,
689    TaskContextForLocation,
690    UnshareProject,
691    Unstage,
692    UpdateBuffer,
693    UpdateBufferFile,
694    UpdateDiagnosticSummary,
695    UpdateDiffBases,
696    UpdateLanguageServer,
697    UpdateProject,
698    UpdateProjectCollaborator,
699    UpdateWorktree,
700    UpdateRepository,
701    RemoveRepository,
702    UpdateWorktreeSettings,
703    LspExtExpandMacro,
704    LspExtOpenDocs,
705    AdvertiseContexts,
706    OpenContext,
707    CreateContext,
708    UpdateContext,
709    SynchronizeContexts,
710    LspExtSwitchSourceHeader,
711    LanguageServerLog,
712    Toast,
713    HideToast,
714    OpenServerSettings,
715    GetPermalinkToLine,
716    LanguageServerPromptRequest,
717    GitGetBranches,
718    UpdateGitBranch,
719    ListToolchains,
720    ActivateToolchain,
721    ActiveToolchain,
722    GetPathMetadata,
723    CancelLanguageServerWork,
724    RegisterBufferWithLanguageServers,
725    GitShow,
726    GitReset,
727    GitCheckoutFiles,
728    SetIndexText,
729
730    Push,
731    Fetch,
732    GetRemotes,
733    Pull,
734    AskPassRequest,
735    GitChangeBranch,
736    GitCreateBranch,
737    CheckForPushedCommits,
738    GitDiff,
739    GitInit,
740    BreakpointsForFile,
741    ToggleBreakpoint,
742);
743
744entity_messages!(
745    {channel_id, Channel},
746    ChannelMessageSent,
747    ChannelMessageUpdate,
748    RemoveChannelMessage,
749    UpdateChannelMessage,
750    UpdateChannelBuffer,
751    UpdateChannelBufferCollaborators,
752);
753
754impl From<Timestamp> for SystemTime {
755    fn from(val: Timestamp) -> Self {
756        UNIX_EPOCH
757            .checked_add(Duration::new(val.seconds, val.nanos))
758            .unwrap()
759    }
760}
761
762impl From<SystemTime> for Timestamp {
763    fn from(time: SystemTime) -> Self {
764        let duration = time.duration_since(UNIX_EPOCH).unwrap();
765        Self {
766            seconds: duration.as_secs(),
767            nanos: duration.subsec_nanos(),
768        }
769    }
770}
771
772impl From<u128> for Nonce {
773    fn from(nonce: u128) -> Self {
774        let upper_half = (nonce >> 64) as u64;
775        let lower_half = nonce as u64;
776        Self {
777            upper_half,
778            lower_half,
779        }
780    }
781}
782
783impl From<Nonce> for u128 {
784    fn from(nonce: Nonce) -> Self {
785        let upper_half = (nonce.upper_half as u128) << 64;
786        let lower_half = nonce.lower_half as u128;
787        upper_half | lower_half
788    }
789}
790
791#[cfg(any(test, feature = "test-support"))]
792pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 2;
793#[cfg(not(any(test, feature = "test-support")))]
794pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 256;
795
796#[derive(Clone, Debug)]
797pub enum WorktreeRelatedMessage {
798    UpdateWorktree(UpdateWorktree),
799    UpdateRepository(UpdateRepository),
800    RemoveRepository(RemoveRepository),
801}
802
803impl From<UpdateWorktree> for WorktreeRelatedMessage {
804    fn from(value: UpdateWorktree) -> Self {
805        Self::UpdateWorktree(value)
806    }
807}
808
809impl From<UpdateRepository> for WorktreeRelatedMessage {
810    fn from(value: UpdateRepository) -> Self {
811        Self::UpdateRepository(value)
812    }
813}
814
815impl From<RemoveRepository> for WorktreeRelatedMessage {
816    fn from(value: RemoveRepository) -> Self {
817        Self::RemoveRepository(value)
818    }
819}
820
821pub fn split_worktree_update(mut message: UpdateWorktree) -> impl Iterator<Item = UpdateWorktree> {
822    let mut done = false;
823
824    iter::from_fn(move || {
825        if done {
826            return None;
827        }
828
829        let updated_entries_chunk_size = cmp::min(
830            message.updated_entries.len(),
831            MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
832        );
833        let updated_entries: Vec<_> = message
834            .updated_entries
835            .drain(..updated_entries_chunk_size)
836            .collect();
837
838        let removed_entries_chunk_size = cmp::min(
839            message.removed_entries.len(),
840            MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
841        );
842        let removed_entries = message
843            .removed_entries
844            .drain(..removed_entries_chunk_size)
845            .collect();
846
847        let mut updated_repositories = Vec::new();
848        let mut limit = MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE;
849        while let Some(repo) = message.updated_repositories.first_mut() {
850            let updated_statuses_limit = cmp::min(repo.updated_statuses.len(), limit);
851            let removed_statuses_limit = cmp::min(repo.removed_statuses.len(), limit);
852
853            updated_repositories.push(RepositoryEntry {
854                work_directory_id: repo.work_directory_id,
855                branch_summary: repo.branch_summary.clone(),
856                updated_statuses: repo
857                    .updated_statuses
858                    .drain(..updated_statuses_limit)
859                    .collect(),
860                removed_statuses: repo
861                    .removed_statuses
862                    .drain(..removed_statuses_limit)
863                    .collect(),
864                current_merge_conflicts: repo.current_merge_conflicts.clone(),
865            });
866            if repo.removed_statuses.is_empty() && repo.updated_statuses.is_empty() {
867                message.updated_repositories.remove(0);
868            }
869            limit = limit.saturating_sub(removed_statuses_limit + updated_statuses_limit);
870            if limit == 0 {
871                break;
872            }
873        }
874
875        done = message.updated_entries.is_empty()
876            && message.removed_entries.is_empty()
877            && message.updated_repositories.is_empty();
878
879        let removed_repositories = if done {
880            mem::take(&mut message.removed_repositories)
881        } else {
882            Default::default()
883        };
884
885        Some(UpdateWorktree {
886            project_id: message.project_id,
887            worktree_id: message.worktree_id,
888            root_name: message.root_name.clone(),
889            abs_path: message.abs_path.clone(),
890            updated_entries,
891            removed_entries,
892            scan_id: message.scan_id,
893            is_last_update: done && message.is_last_update,
894            updated_repositories,
895            removed_repositories,
896        })
897    })
898}
899
900pub fn split_repository_update(
901    mut update: UpdateRepository,
902) -> impl Iterator<Item = UpdateRepository> {
903    let mut updated_statuses_iter = mem::take(&mut update.updated_statuses).into_iter().fuse();
904    let mut removed_statuses_iter = mem::take(&mut update.removed_statuses).into_iter().fuse();
905    let mut is_first = true;
906    std::iter::from_fn(move || {
907        let updated_statuses = updated_statuses_iter
908            .by_ref()
909            .take(MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE)
910            .collect::<Vec<_>>();
911        let removed_statuses = removed_statuses_iter
912            .by_ref()
913            .take(MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE)
914            .collect::<Vec<_>>();
915        if updated_statuses.is_empty() && removed_statuses.is_empty() && !is_first {
916            return None;
917        }
918        is_first = false;
919        Some(UpdateRepository {
920            updated_statuses,
921            removed_statuses,
922            ..update.clone()
923        })
924    })
925}
926
927pub fn split_worktree_related_message(
928    message: WorktreeRelatedMessage,
929) -> Box<dyn Iterator<Item = WorktreeRelatedMessage> + Send> {
930    match message {
931        WorktreeRelatedMessage::UpdateWorktree(message) => {
932            Box::new(split_worktree_update(message).map(WorktreeRelatedMessage::UpdateWorktree))
933        }
934        WorktreeRelatedMessage::UpdateRepository(message) => {
935            Box::new(split_repository_update(message).map(WorktreeRelatedMessage::UpdateRepository))
936        }
937        WorktreeRelatedMessage::RemoveRepository(update) => Box::new([update.into()].into_iter()),
938    }
939}
940
941#[cfg(test)]
942mod tests {
943    use super::*;
944
945    #[test]
946    fn test_converting_peer_id_from_and_to_u64() {
947        let peer_id = PeerId {
948            owner_id: 10,
949            id: 3,
950        };
951        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
952        let peer_id = PeerId {
953            owner_id: u32::MAX,
954            id: 3,
955        };
956        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
957        let peer_id = PeerId {
958            owner_id: 10,
959            id: u32::MAX,
960        };
961        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
962        let peer_id = PeerId {
963            owner_id: u32::MAX,
964            id: u32::MAX,
965        };
966        assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
967    }
968
969    #[test]
970    #[cfg(target_os = "windows")]
971    fn test_proto() {
972        fn generate_proto_path(path: PathBuf) -> PathBuf {
973            let proto = path.to_proto();
974            PathBuf::from_proto(proto)
975        }
976
977        let path = PathBuf::from("C:\\foo\\bar");
978        assert_eq!(path, generate_proto_path(path.clone()));
979
980        let path = PathBuf::from("C:/foo/bar/");
981        assert_eq!(path, generate_proto_path(path.clone()));
982
983        let path = PathBuf::from("C:/foo\\bar\\");
984        assert_eq!(path, generate_proto_path(path.clone()));
985    }
986}