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