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