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