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 (UpdateUserPlan, Foreground),
363 (UpdateWorktree, Foreground),
364 (UpdateWorktreeSettings, Foreground),
365 (UsersResponse, Foreground),
366 (LspExtExpandMacro, Background),
367 (LspExtExpandMacroResponse, Background),
368 (SetRoomParticipantRole, Foreground),
369 (BlameBuffer, Foreground),
370 (BlameBufferResponse, Foreground),
371 (CreateDevServerProject, Background),
372 (CreateDevServerProjectResponse, Foreground),
373 (CreateDevServer, Foreground),
374 (CreateDevServerResponse, Foreground),
375 (DevServerInstructions, Foreground),
376 (ShutdownDevServer, Foreground),
377 (ReconnectDevServer, Foreground),
378 (ReconnectDevServerResponse, Foreground),
379 (ShareDevServerProject, Foreground),
380 (JoinDevServerProject, Foreground),
381 (RejoinRemoteProjects, Foreground),
382 (RejoinRemoteProjectsResponse, Foreground),
383 (MultiLspQuery, Background),
384 (MultiLspQueryResponse, Background),
385 (DevServerProjectsUpdate, Foreground),
386 (ValidateDevServerProjectRequest, Background),
387 (ListRemoteDirectory, Background),
388 (ListRemoteDirectoryResponse, Background),
389 (UpdateDevServerProject, Background),
390 (DeleteDevServer, Foreground),
391 (DeleteDevServerProject, Foreground),
392 (RegenerateDevServerToken, Foreground),
393 (RegenerateDevServerTokenResponse, Foreground),
394 (RenameDevServer, Foreground),
395 (OpenNewBuffer, Foreground),
396 (RestartLanguageServers, Foreground),
397 (LinkedEditingRange, Background),
398 (LinkedEditingRangeResponse, Background),
399 (AdvertiseContexts, Foreground),
400 (OpenContext, Foreground),
401 (OpenContextResponse, Foreground),
402 (CreateContext, Foreground),
403 (CreateContextResponse, Foreground),
404 (UpdateContext, Foreground),
405 (SynchronizeContexts, Foreground),
406 (SynchronizeContextsResponse, Foreground),
407 (AddWorktree, Foreground),
408 (AddWorktreeResponse, Foreground),
409);
410
411request_messages!(
412 (ApplyCodeAction, ApplyCodeActionResponse),
413 (
414 ApplyCompletionAdditionalEdits,
415 ApplyCompletionAdditionalEditsResponse
416 ),
417 (Call, Ack),
418 (CancelCall, Ack),
419 (CopyProjectEntry, ProjectEntryResponse),
420 (ComputeEmbeddings, ComputeEmbeddingsResponse),
421 (CreateChannel, CreateChannelResponse),
422 (CreateProjectEntry, ProjectEntryResponse),
423 (CreateRoom, CreateRoomResponse),
424 (DeclineCall, Ack),
425 (DeleteChannel, Ack),
426 (DeleteProjectEntry, ProjectEntryResponse),
427 (ExpandProjectEntry, ExpandProjectEntryResponse),
428 (Follow, FollowResponse),
429 (FormatBuffers, FormatBuffersResponse),
430 (FuzzySearchUsers, UsersResponse),
431 (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
432 (GetChannelMembers, GetChannelMembersResponse),
433 (GetChannelMessages, GetChannelMessagesResponse),
434 (GetChannelMessagesById, GetChannelMessagesResponse),
435 (GetCodeActions, GetCodeActionsResponse),
436 (GetCompletions, GetCompletionsResponse),
437 (GetDefinition, GetDefinitionResponse),
438 (GetImplementation, GetImplementationResponse),
439 (GetDocumentHighlights, GetDocumentHighlightsResponse),
440 (GetHover, GetHoverResponse),
441 (GetNotifications, GetNotificationsResponse),
442 (GetPrivateUserInfo, GetPrivateUserInfoResponse),
443 (GetProjectSymbols, GetProjectSymbolsResponse),
444 (GetReferences, GetReferencesResponse),
445 (GetSignatureHelp, GetSignatureHelpResponse),
446 (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
447 (GetTypeDefinition, GetTypeDefinitionResponse),
448 (LinkedEditingRange, LinkedEditingRangeResponse),
449 (ListRemoteDirectory, ListRemoteDirectoryResponse),
450 (UpdateDevServerProject, Ack),
451 (GetUsers, UsersResponse),
452 (IncomingCall, Ack),
453 (InlayHints, InlayHintsResponse),
454 (InviteChannelMember, Ack),
455 (JoinChannel, JoinRoomResponse),
456 (JoinChannelBuffer, JoinChannelBufferResponse),
457 (JoinChannelChat, JoinChannelChatResponse),
458 (JoinHostedProject, JoinProjectResponse),
459 (JoinProject, JoinProjectResponse),
460 (JoinRoom, JoinRoomResponse),
461 (LeaveChannelBuffer, Ack),
462 (LeaveRoom, Ack),
463 (MarkNotificationRead, Ack),
464 (MoveChannel, Ack),
465 (OnTypeFormatting, OnTypeFormattingResponse),
466 (OpenBufferById, OpenBufferResponse),
467 (OpenBufferByPath, OpenBufferResponse),
468 (OpenBufferForSymbol, OpenBufferForSymbolResponse),
469 (OpenNewBuffer, OpenBufferResponse),
470 (PerformRename, PerformRenameResponse),
471 (Ping, Ack),
472 (PrepareRename, PrepareRenameResponse),
473 (CompleteWithLanguageModel, CompleteWithLanguageModelResponse),
474 (
475 StreamCompleteWithLanguageModel,
476 StreamCompleteWithLanguageModelResponse
477 ),
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 GetImplementation,
552 GetDocumentHighlights,
553 GetHover,
554 GetProjectSymbols,
555 GetReferences,
556 GetSignatureHelp,
557 GetTypeDefinition,
558 InlayHints,
559 JoinProject,
560 LeaveProject,
561 LinkedEditingRange,
562 MultiLspQuery,
563 RestartLanguageServers,
564 OnTypeFormatting,
565 OpenNewBuffer,
566 OpenBufferById,
567 OpenBufferByPath,
568 OpenBufferForSymbol,
569 PerformRename,
570 PrepareRename,
571 RefreshInlayHints,
572 ReloadBuffers,
573 RemoveProjectCollaborator,
574 RenameProjectEntry,
575 ResolveCompletionDocumentation,
576 ResolveInlayHint,
577 SaveBuffer,
578 SearchProject,
579 StartLanguageServer,
580 SynchronizeBuffers,
581 TaskContextForLocation,
582 TaskTemplates,
583 UnshareProject,
584 UpdateBuffer,
585 UpdateBufferFile,
586 UpdateDiagnosticSummary,
587 UpdateDiffBase,
588 UpdateLanguageServer,
589 UpdateProject,
590 UpdateProjectCollaborator,
591 UpdateWorktree,
592 UpdateWorktreeSettings,
593 LspExtExpandMacro,
594 AdvertiseContexts,
595 OpenContext,
596 CreateContext,
597 UpdateContext,
598 SynchronizeContexts,
599);
600
601entity_messages!(
602 {channel_id, Channel},
603 ChannelMessageSent,
604 ChannelMessageUpdate,
605 RemoveChannelMessage,
606 UpdateChannelMessage,
607 UpdateChannelBuffer,
608 UpdateChannelBufferCollaborators,
609);
610
611impl From<Timestamp> for SystemTime {
612 fn from(val: Timestamp) -> Self {
613 UNIX_EPOCH
614 .checked_add(Duration::new(val.seconds, val.nanos))
615 .unwrap()
616 }
617}
618
619impl From<SystemTime> for Timestamp {
620 fn from(time: SystemTime) -> Self {
621 let duration = time.duration_since(UNIX_EPOCH).unwrap();
622 Self {
623 seconds: duration.as_secs(),
624 nanos: duration.subsec_nanos(),
625 }
626 }
627}
628
629impl From<u128> for Nonce {
630 fn from(nonce: u128) -> Self {
631 let upper_half = (nonce >> 64) as u64;
632 let lower_half = nonce as u64;
633 Self {
634 upper_half,
635 lower_half,
636 }
637 }
638}
639
640impl From<Nonce> for u128 {
641 fn from(nonce: Nonce) -> Self {
642 let upper_half = (nonce.upper_half as u128) << 64;
643 let lower_half = nonce.lower_half as u128;
644 upper_half | lower_half
645 }
646}
647
648pub fn split_worktree_update(
649 mut message: UpdateWorktree,
650 max_chunk_size: usize,
651) -> impl Iterator<Item = UpdateWorktree> {
652 let mut done_files = false;
653
654 let mut repository_map = message
655 .updated_repositories
656 .into_iter()
657 .map(|repo| (repo.work_directory_id, repo))
658 .collect::<HashMap<_, _>>();
659
660 iter::from_fn(move || {
661 if done_files {
662 return None;
663 }
664
665 let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
666 let updated_entries: Vec<_> = message
667 .updated_entries
668 .drain(..updated_entries_chunk_size)
669 .collect();
670
671 let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
672 let removed_entries = message
673 .removed_entries
674 .drain(..removed_entries_chunk_size)
675 .collect();
676
677 done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
678
679 let mut updated_repositories = Vec::new();
680
681 if !repository_map.is_empty() {
682 for entry in &updated_entries {
683 if let Some(repo) = repository_map.remove(&entry.id) {
684 updated_repositories.push(repo)
685 }
686 }
687 }
688
689 let removed_repositories = if done_files {
690 mem::take(&mut message.removed_repositories)
691 } else {
692 Default::default()
693 };
694
695 if done_files {
696 updated_repositories.extend(mem::take(&mut repository_map).into_values());
697 }
698
699 Some(UpdateWorktree {
700 project_id: message.project_id,
701 worktree_id: message.worktree_id,
702 root_name: message.root_name.clone(),
703 abs_path: message.abs_path.clone(),
704 updated_entries,
705 removed_entries,
706 scan_id: message.scan_id,
707 is_last_update: done_files && message.is_last_update,
708 updated_repositories,
709 removed_repositories,
710 })
711 })
712}
713
714#[cfg(test)]
715mod tests {
716 use super::*;
717
718 #[test]
719 fn test_converting_peer_id_from_and_to_u64() {
720 let peer_id = PeerId {
721 owner_id: 10,
722 id: 3,
723 };
724 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
725 let peer_id = PeerId {
726 owner_id: u32::MAX,
727 id: 3,
728 };
729 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
730 let peer_id = PeerId {
731 owner_id: 10,
732 id: u32::MAX,
733 };
734 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
735 let peer_id = PeerId {
736 owner_id: u32::MAX,
737 id: u32::MAX,
738 };
739 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
740 }
741}