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