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 (AddWorktree, Foreground),
410 (AddWorktreeResponse, Foreground),
411);
412
413request_messages!(
414 (AcceptTermsOfService, AcceptTermsOfServiceResponse),
415 (ApplyCodeAction, ApplyCodeActionResponse),
416 (
417 ApplyCompletionAdditionalEdits,
418 ApplyCompletionAdditionalEditsResponse
419 ),
420 (Call, Ack),
421 (CancelCall, Ack),
422 (CopyProjectEntry, ProjectEntryResponse),
423 (ComputeEmbeddings, ComputeEmbeddingsResponse),
424 (CreateChannel, CreateChannelResponse),
425 (CreateProjectEntry, ProjectEntryResponse),
426 (CreateRoom, CreateRoomResponse),
427 (DeclineCall, Ack),
428 (DeleteChannel, Ack),
429 (DeleteProjectEntry, ProjectEntryResponse),
430 (ExpandProjectEntry, ExpandProjectEntryResponse),
431 (Follow, FollowResponse),
432 (FormatBuffers, FormatBuffersResponse),
433 (FuzzySearchUsers, UsersResponse),
434 (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
435 (GetChannelMembers, GetChannelMembersResponse),
436 (GetChannelMessages, GetChannelMessagesResponse),
437 (GetChannelMessagesById, GetChannelMessagesResponse),
438 (GetCodeActions, GetCodeActionsResponse),
439 (GetCompletions, GetCompletionsResponse),
440 (GetDefinition, GetDefinitionResponse),
441 (GetDeclaration, GetDeclarationResponse),
442 (GetImplementation, GetImplementationResponse),
443 (GetDocumentHighlights, GetDocumentHighlightsResponse),
444 (GetHover, GetHoverResponse),
445 (GetLlmToken, GetLlmTokenResponse),
446 (GetNotifications, GetNotificationsResponse),
447 (GetPrivateUserInfo, GetPrivateUserInfoResponse),
448 (GetProjectSymbols, GetProjectSymbolsResponse),
449 (GetReferences, GetReferencesResponse),
450 (GetSignatureHelp, GetSignatureHelpResponse),
451 (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
452 (GetTypeDefinition, GetTypeDefinitionResponse),
453 (LinkedEditingRange, LinkedEditingRangeResponse),
454 (ListRemoteDirectory, ListRemoteDirectoryResponse),
455 (UpdateDevServerProject, Ack),
456 (GetUsers, UsersResponse),
457 (IncomingCall, Ack),
458 (InlayHints, InlayHintsResponse),
459 (InviteChannelMember, Ack),
460 (JoinChannel, JoinRoomResponse),
461 (JoinChannelBuffer, JoinChannelBufferResponse),
462 (JoinChannelChat, JoinChannelChatResponse),
463 (JoinHostedProject, JoinProjectResponse),
464 (JoinProject, JoinProjectResponse),
465 (JoinRoom, JoinRoomResponse),
466 (LeaveChannelBuffer, Ack),
467 (LeaveRoom, Ack),
468 (MarkNotificationRead, Ack),
469 (MoveChannel, Ack),
470 (OnTypeFormatting, OnTypeFormattingResponse),
471 (OpenBufferById, OpenBufferResponse),
472 (OpenBufferByPath, OpenBufferResponse),
473 (OpenBufferForSymbol, OpenBufferForSymbolResponse),
474 (OpenNewBuffer, OpenBufferResponse),
475 (PerformRename, PerformRenameResponse),
476 (Ping, Ack),
477 (PrepareRename, PrepareRenameResponse),
478 (CountLanguageModelTokens, CountLanguageModelTokensResponse),
479 (RefreshInlayHints, Ack),
480 (RejoinChannelBuffers, RejoinChannelBuffersResponse),
481 (RejoinRoom, RejoinRoomResponse),
482 (ReloadBuffers, ReloadBuffersResponse),
483 (RemoveChannelMember, Ack),
484 (RemoveChannelMessage, Ack),
485 (UpdateChannelMessage, Ack),
486 (RemoveContact, Ack),
487 (RenameChannel, RenameChannelResponse),
488 (RenameProjectEntry, ProjectEntryResponse),
489 (RequestContact, Ack),
490 (
491 ResolveCompletionDocumentation,
492 ResolveCompletionDocumentationResponse
493 ),
494 (ResolveInlayHint, ResolveInlayHintResponse),
495 (RespondToChannelInvite, Ack),
496 (RespondToContactRequest, Ack),
497 (SaveBuffer, BufferSaved),
498 (SearchProject, SearchProjectResponse),
499 (SendChannelMessage, SendChannelMessageResponse),
500 (SetChannelMemberRole, Ack),
501 (SetChannelVisibility, Ack),
502 (ShareProject, ShareProjectResponse),
503 (SynchronizeBuffers, SynchronizeBuffersResponse),
504 (TaskContextForLocation, TaskContext),
505 (TaskTemplates, TaskTemplatesResponse),
506 (Test, Test),
507 (UpdateBuffer, Ack),
508 (UpdateParticipantLocation, Ack),
509 (UpdateProject, Ack),
510 (UpdateWorktree, Ack),
511 (LspExtExpandMacro, LspExtExpandMacroResponse),
512 (SetRoomParticipantRole, Ack),
513 (BlameBuffer, BlameBufferResponse),
514 (CreateDevServerProject, CreateDevServerProjectResponse),
515 (CreateDevServer, CreateDevServerResponse),
516 (ShutdownDevServer, Ack),
517 (ShareDevServerProject, ShareProjectResponse),
518 (JoinDevServerProject, JoinProjectResponse),
519 (RejoinRemoteProjects, RejoinRemoteProjectsResponse),
520 (ReconnectDevServer, ReconnectDevServerResponse),
521 (ValidateDevServerProjectRequest, Ack),
522 (MultiLspQuery, MultiLspQueryResponse),
523 (DeleteDevServer, Ack),
524 (DeleteDevServerProject, Ack),
525 (RegenerateDevServerToken, RegenerateDevServerTokenResponse),
526 (RenameDevServer, Ack),
527 (RestartLanguageServers, Ack),
528 (OpenContext, OpenContextResponse),
529 (CreateContext, CreateContextResponse),
530 (SynchronizeContexts, SynchronizeContextsResponse),
531 (AddWorktree, AddWorktreeResponse),
532);
533
534entity_messages!(
535 {project_id, ShareProject},
536 AddProjectCollaborator,
537 ApplyCodeAction,
538 ApplyCompletionAdditionalEdits,
539 BlameBuffer,
540 BufferReloaded,
541 BufferSaved,
542 CopyProjectEntry,
543 CreateBufferForPeer,
544 CreateProjectEntry,
545 DeleteProjectEntry,
546 ExpandProjectEntry,
547 FormatBuffers,
548 GetCodeActions,
549 GetCompletions,
550 GetDefinition,
551 GetDeclaration,
552 GetImplementation,
553 GetDocumentHighlights,
554 GetHover,
555 GetProjectSymbols,
556 GetReferences,
557 GetSignatureHelp,
558 GetTypeDefinition,
559 InlayHints,
560 JoinProject,
561 LeaveProject,
562 LinkedEditingRange,
563 MultiLspQuery,
564 RestartLanguageServers,
565 OnTypeFormatting,
566 OpenNewBuffer,
567 OpenBufferById,
568 OpenBufferByPath,
569 OpenBufferForSymbol,
570 PerformRename,
571 PrepareRename,
572 RefreshInlayHints,
573 ReloadBuffers,
574 RemoveProjectCollaborator,
575 RenameProjectEntry,
576 ResolveCompletionDocumentation,
577 ResolveInlayHint,
578 SaveBuffer,
579 SearchProject,
580 StartLanguageServer,
581 SynchronizeBuffers,
582 TaskContextForLocation,
583 TaskTemplates,
584 UnshareProject,
585 UpdateBuffer,
586 UpdateBufferFile,
587 UpdateDiagnosticSummary,
588 UpdateDiffBase,
589 UpdateLanguageServer,
590 UpdateProject,
591 UpdateProjectCollaborator,
592 UpdateWorktree,
593 UpdateWorktreeSettings,
594 LspExtExpandMacro,
595 AdvertiseContexts,
596 OpenContext,
597 CreateContext,
598 UpdateContext,
599 SynchronizeContexts,
600);
601
602entity_messages!(
603 {channel_id, Channel},
604 ChannelMessageSent,
605 ChannelMessageUpdate,
606 RemoveChannelMessage,
607 UpdateChannelMessage,
608 UpdateChannelBuffer,
609 UpdateChannelBufferCollaborators,
610);
611
612impl From<Timestamp> for SystemTime {
613 fn from(val: Timestamp) -> Self {
614 UNIX_EPOCH
615 .checked_add(Duration::new(val.seconds, val.nanos))
616 .unwrap()
617 }
618}
619
620impl From<SystemTime> for Timestamp {
621 fn from(time: SystemTime) -> Self {
622 let duration = time.duration_since(UNIX_EPOCH).unwrap();
623 Self {
624 seconds: duration.as_secs(),
625 nanos: duration.subsec_nanos(),
626 }
627 }
628}
629
630impl From<u128> for Nonce {
631 fn from(nonce: u128) -> Self {
632 let upper_half = (nonce >> 64) as u64;
633 let lower_half = nonce as u64;
634 Self {
635 upper_half,
636 lower_half,
637 }
638 }
639}
640
641impl From<Nonce> for u128 {
642 fn from(nonce: Nonce) -> Self {
643 let upper_half = (nonce.upper_half as u128) << 64;
644 let lower_half = nonce.lower_half as u128;
645 upper_half | lower_half
646 }
647}
648
649pub fn split_worktree_update(
650 mut message: UpdateWorktree,
651 max_chunk_size: usize,
652) -> impl Iterator<Item = UpdateWorktree> {
653 let mut done_files = false;
654
655 let mut repository_map = message
656 .updated_repositories
657 .into_iter()
658 .map(|repo| (repo.work_directory_id, repo))
659 .collect::<HashMap<_, _>>();
660
661 iter::from_fn(move || {
662 if done_files {
663 return None;
664 }
665
666 let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
667 let updated_entries: Vec<_> = message
668 .updated_entries
669 .drain(..updated_entries_chunk_size)
670 .collect();
671
672 let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
673 let removed_entries = message
674 .removed_entries
675 .drain(..removed_entries_chunk_size)
676 .collect();
677
678 done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
679
680 let mut updated_repositories = Vec::new();
681
682 if !repository_map.is_empty() {
683 for entry in &updated_entries {
684 if let Some(repo) = repository_map.remove(&entry.id) {
685 updated_repositories.push(repo)
686 }
687 }
688 }
689
690 let removed_repositories = if done_files {
691 mem::take(&mut message.removed_repositories)
692 } else {
693 Default::default()
694 };
695
696 if done_files {
697 updated_repositories.extend(mem::take(&mut repository_map).into_values());
698 }
699
700 Some(UpdateWorktree {
701 project_id: message.project_id,
702 worktree_id: message.worktree_id,
703 root_name: message.root_name.clone(),
704 abs_path: message.abs_path.clone(),
705 updated_entries,
706 removed_entries,
707 scan_id: message.scan_id,
708 is_last_update: done_files && message.is_last_update,
709 updated_repositories,
710 removed_repositories,
711 })
712 })
713}
714
715#[cfg(test)]
716mod tests {
717 use super::*;
718
719 #[test]
720 fn test_converting_peer_id_from_and_to_u64() {
721 let peer_id = PeerId {
722 owner_id: 10,
723 id: 3,
724 };
725 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
726 let peer_id = PeerId {
727 owner_id: u32::MAX,
728 id: 3,
729 };
730 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
731 let peer_id = PeerId {
732 owner_id: 10,
733 id: u32::MAX,
734 };
735 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
736 let peer_id = PeerId {
737 owner_id: u32::MAX,
738 id: u32::MAX,
739 };
740 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
741 }
742}