1#![allow(non_snake_case)]
2
3pub mod error;
4mod macros;
5mod typed_envelope;
6
7pub use error::*;
8pub use typed_envelope::*;
9
10use collections::HashMap;
11pub use prost::Message;
12use serde::Serialize;
13use std::any::{Any, TypeId};
14use std::time::Instant;
15use std::{
16 cmp,
17 fmt::Debug,
18 iter,
19 time::{Duration, SystemTime, UNIX_EPOCH},
20};
21use std::{fmt, mem};
22
23include!(concat!(env!("OUT_DIR"), "/zed.messages.rs"));
24
25pub trait EnvelopedMessage: Clone + Debug + Serialize + Sized + Send + Sync + 'static {
26 const NAME: &'static str;
27 const PRIORITY: MessagePriority;
28 fn into_envelope(
29 self,
30 id: u32,
31 responding_to: Option<u32>,
32 original_sender_id: Option<PeerId>,
33 ) -> Envelope;
34 fn from_envelope(envelope: Envelope) -> Option<Self>;
35}
36
37pub trait EntityMessage: EnvelopedMessage {
38 type Entity;
39 fn remote_entity_id(&self) -> u64;
40}
41
42pub trait RequestMessage: EnvelopedMessage {
43 type Response: EnvelopedMessage;
44}
45
46pub trait AnyTypedEnvelope: 'static + Send + Sync {
47 fn payload_type_id(&self) -> TypeId;
48 fn payload_type_name(&self) -> &'static str;
49 fn as_any(&self) -> &dyn Any;
50 fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
51 fn is_background(&self) -> bool;
52 fn original_sender_id(&self) -> Option<PeerId>;
53 fn sender_id(&self) -> PeerId;
54 fn message_id(&self) -> u32;
55}
56
57pub enum MessagePriority {
58 Foreground,
59 Background,
60}
61
62impl<T: EnvelopedMessage> AnyTypedEnvelope for TypedEnvelope<T> {
63 fn payload_type_id(&self) -> TypeId {
64 TypeId::of::<T>()
65 }
66
67 fn payload_type_name(&self) -> &'static str {
68 T::NAME
69 }
70
71 fn as_any(&self) -> &dyn Any {
72 self
73 }
74
75 fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
76 self
77 }
78
79 fn is_background(&self) -> bool {
80 matches!(T::PRIORITY, MessagePriority::Background)
81 }
82
83 fn original_sender_id(&self) -> Option<PeerId> {
84 self.original_sender_id
85 }
86
87 fn sender_id(&self) -> PeerId {
88 self.sender_id
89 }
90
91 fn message_id(&self) -> u32 {
92 self.message_id
93 }
94}
95
96impl PeerId {
97 pub fn from_u64(peer_id: u64) -> Self {
98 let owner_id = (peer_id >> 32) as u32;
99 let id = peer_id as u32;
100 Self { owner_id, id }
101 }
102
103 pub fn as_u64(self) -> u64 {
104 ((self.owner_id as u64) << 32) | (self.id as u64)
105 }
106}
107
108impl Copy for PeerId {}
109
110impl Eq for PeerId {}
111
112impl Ord for PeerId {
113 fn cmp(&self, other: &Self) -> cmp::Ordering {
114 self.owner_id
115 .cmp(&other.owner_id)
116 .then_with(|| self.id.cmp(&other.id))
117 }
118}
119
120impl PartialOrd for PeerId {
121 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
122 Some(self.cmp(other))
123 }
124}
125
126impl std::hash::Hash for PeerId {
127 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
128 self.owner_id.hash(state);
129 self.id.hash(state);
130 }
131}
132
133impl fmt::Display for PeerId {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "{}/{}", self.owner_id, self.id)
136 }
137}
138
139messages!(
140 (Ack, Foreground),
141 (AckBufferOperation, Background),
142 (AckChannelMessage, Background),
143 (AddNotification, Foreground),
144 (AddProjectCollaborator, Foreground),
145 (ApplyCodeAction, Background),
146 (ApplyCodeActionResponse, Background),
147 (ApplyCompletionAdditionalEdits, Background),
148 (ApplyCompletionAdditionalEditsResponse, Background),
149 (BufferReloaded, Foreground),
150 (BufferSaved, Foreground),
151 (Call, Foreground),
152 (CallCanceled, Foreground),
153 (CancelCall, Foreground),
154 (ChannelMessageSent, Foreground),
155 (ChannelMessageUpdate, Foreground),
156 (CompleteWithLanguageModel, Background),
157 (ComputeEmbeddings, Background),
158 (ComputeEmbeddingsResponse, Background),
159 (CopyProjectEntry, Foreground),
160 (CountTokensWithLanguageModel, Background),
161 (CountTokensResponse, Background),
162 (CreateBufferForPeer, Foreground),
163 (CreateChannel, Foreground),
164 (CreateChannelResponse, Foreground),
165 (CreateProjectEntry, Foreground),
166 (CreateRoom, Foreground),
167 (CreateRoomResponse, Foreground),
168 (DeclineCall, Foreground),
169 (DeleteChannel, Foreground),
170 (DeleteNotification, Foreground),
171 (UpdateNotification, Foreground),
172 (DeleteProjectEntry, Foreground),
173 (EndStream, Foreground),
174 (Error, Foreground),
175 (ExpandProjectEntry, Foreground),
176 (ExpandProjectEntryResponse, Foreground),
177 (Follow, Foreground),
178 (FollowResponse, Foreground),
179 (FormatBuffers, Foreground),
180 (FormatBuffersResponse, Foreground),
181 (FuzzySearchUsers, Foreground),
182 (GetCachedEmbeddings, Background),
183 (GetCachedEmbeddingsResponse, Background),
184 (GetChannelMembers, Foreground),
185 (GetChannelMembersResponse, Foreground),
186 (GetChannelMessages, Background),
187 (GetChannelMessagesById, Background),
188 (GetChannelMessagesResponse, Background),
189 (GetCodeActions, Background),
190 (GetCodeActionsResponse, Background),
191 (GetCompletions, Background),
192 (GetCompletionsResponse, Background),
193 (GetDefinition, Background),
194 (GetDefinitionResponse, Background),
195 (GetDocumentHighlights, Background),
196 (GetDocumentHighlightsResponse, Background),
197 (GetHover, Background),
198 (GetHoverResponse, Background),
199 (GetNotifications, Foreground),
200 (GetNotificationsResponse, Foreground),
201 (GetPrivateUserInfo, Foreground),
202 (GetPrivateUserInfoResponse, Foreground),
203 (GetProjectSymbols, Background),
204 (GetProjectSymbolsResponse, Background),
205 (GetReferences, Background),
206 (GetReferencesResponse, Background),
207 (GetSupermavenApiKey, Background),
208 (GetSupermavenApiKeyResponse, Background),
209 (GetTypeDefinition, Background),
210 (GetTypeDefinitionResponse, Background),
211 (GetImplementation, Background),
212 (GetImplementationResponse, Background),
213 (GetUsers, Foreground),
214 (Hello, Foreground),
215 (IncomingCall, Foreground),
216 (InlayHints, Background),
217 (InlayHintsResponse, Background),
218 (InviteChannelMember, Foreground),
219 (JoinChannel, Foreground),
220 (JoinChannelBuffer, Foreground),
221 (JoinChannelBufferResponse, Foreground),
222 (JoinChannelChat, Foreground),
223 (JoinChannelChatResponse, Foreground),
224 (JoinProject, Foreground),
225 (JoinHostedProject, Foreground),
226 (JoinProjectResponse, Foreground),
227 (JoinRoom, Foreground),
228 (JoinRoomResponse, Foreground),
229 (LanguageModelResponse, Background),
230 (LeaveChannelBuffer, Background),
231 (LeaveChannelChat, Foreground),
232 (LeaveProject, Foreground),
233 (LeaveRoom, Foreground),
234 (MarkNotificationRead, Foreground),
235 (MoveChannel, Foreground),
236 (OnTypeFormatting, Background),
237 (OnTypeFormattingResponse, Background),
238 (OpenBufferById, Background),
239 (OpenBufferByPath, Background),
240 (OpenBufferForSymbol, Background),
241 (OpenBufferForSymbolResponse, Background),
242 (OpenBufferResponse, Background),
243 (PerformRename, Background),
244 (PerformRenameResponse, Background),
245 (Ping, Foreground),
246 (PrepareRename, Background),
247 (PrepareRenameResponse, Background),
248 (ProjectEntryResponse, Foreground),
249 (RefreshInlayHints, Foreground),
250 (RejoinChannelBuffers, Foreground),
251 (RejoinChannelBuffersResponse, Foreground),
252 (RejoinRoom, Foreground),
253 (RejoinRoomResponse, Foreground),
254 (ReloadBuffers, Foreground),
255 (ReloadBuffersResponse, Foreground),
256 (RemoveChannelMember, Foreground),
257 (RemoveChannelMessage, Foreground),
258 (UpdateChannelMessage, Foreground),
259 (RemoveContact, Foreground),
260 (RemoveProjectCollaborator, Foreground),
261 (RenameChannel, Foreground),
262 (RenameChannelResponse, Foreground),
263 (RenameProjectEntry, Foreground),
264 (RequestContact, Foreground),
265 (ResolveCompletionDocumentation, Background),
266 (ResolveCompletionDocumentationResponse, Background),
267 (ResolveInlayHint, Background),
268 (ResolveInlayHintResponse, Background),
269 (RespondToChannelInvite, Foreground),
270 (RespondToContactRequest, Foreground),
271 (RoomUpdated, Foreground),
272 (SaveBuffer, Foreground),
273 (SetChannelMemberRole, Foreground),
274 (SetChannelVisibility, Foreground),
275 (SearchProject, Background),
276 (SearchProjectResponse, Background),
277 (SendChannelMessage, Background),
278 (SendChannelMessageResponse, Background),
279 (ShareProject, Foreground),
280 (ShareProjectResponse, Foreground),
281 (ShowContacts, Foreground),
282 (StartLanguageServer, Foreground),
283 (SubscribeToChannels, Foreground),
284 (SynchronizeBuffers, Foreground),
285 (SynchronizeBuffersResponse, Foreground),
286 (TaskContextForLocation, Background),
287 (TaskContext, Background),
288 (TaskTemplates, Background),
289 (TaskTemplatesResponse, Background),
290 (Test, Foreground),
291 (Unfollow, Foreground),
292 (UnshareProject, Foreground),
293 (UpdateBuffer, Foreground),
294 (UpdateBufferFile, Foreground),
295 (UpdateChannelBuffer, Foreground),
296 (UpdateChannelBufferCollaborators, Foreground),
297 (UpdateChannels, Foreground),
298 (UpdateUserChannels, Foreground),
299 (UpdateContacts, Foreground),
300 (UpdateDiagnosticSummary, Foreground),
301 (UpdateDiffBase, Foreground),
302 (UpdateFollowers, Foreground),
303 (UpdateInviteInfo, Foreground),
304 (UpdateLanguageServer, Foreground),
305 (UpdateParticipantLocation, Foreground),
306 (UpdateProject, Foreground),
307 (UpdateProjectCollaborator, Foreground),
308 (UpdateWorktree, Foreground),
309 (UpdateWorktreeSettings, Foreground),
310 (UsersResponse, Foreground),
311 (LspExtExpandMacro, Background),
312 (LspExtExpandMacroResponse, Background),
313 (SetRoomParticipantRole, Foreground),
314 (BlameBuffer, Foreground),
315 (BlameBufferResponse, Foreground),
316 (CreateDevServerProject, Background),
317 (CreateDevServerProjectResponse, Foreground),
318 (CreateDevServer, Foreground),
319 (CreateDevServerResponse, Foreground),
320 (DevServerInstructions, Foreground),
321 (ShutdownDevServer, Foreground),
322 (ReconnectDevServer, Foreground),
323 (ReconnectDevServerResponse, Foreground),
324 (ShareDevServerProject, Foreground),
325 (JoinDevServerProject, Foreground),
326 (RejoinRemoteProjects, Foreground),
327 (RejoinRemoteProjectsResponse, Foreground),
328 (MultiLspQuery, Background),
329 (MultiLspQueryResponse, Background),
330 (DevServerProjectsUpdate, Foreground),
331 (ValidateDevServerProjectRequest, Background),
332 (DeleteDevServer, Foreground),
333 (DeleteDevServerProject, Foreground),
334 (RegenerateDevServerToken, Foreground),
335 (RegenerateDevServerTokenResponse, Foreground),
336 (RenameDevServer, Foreground),
337 (OpenNewBuffer, Foreground),
338 (RestartLanguageServers, Foreground),
339);
340
341request_messages!(
342 (ApplyCodeAction, ApplyCodeActionResponse),
343 (
344 ApplyCompletionAdditionalEdits,
345 ApplyCompletionAdditionalEditsResponse
346 ),
347 (Call, Ack),
348 (CancelCall, Ack),
349 (CopyProjectEntry, ProjectEntryResponse),
350 (CompleteWithLanguageModel, LanguageModelResponse),
351 (ComputeEmbeddings, ComputeEmbeddingsResponse),
352 (CountTokensWithLanguageModel, CountTokensResponse),
353 (CreateChannel, CreateChannelResponse),
354 (CreateProjectEntry, ProjectEntryResponse),
355 (CreateRoom, CreateRoomResponse),
356 (DeclineCall, Ack),
357 (DeleteChannel, Ack),
358 (DeleteProjectEntry, ProjectEntryResponse),
359 (ExpandProjectEntry, ExpandProjectEntryResponse),
360 (Follow, FollowResponse),
361 (FormatBuffers, FormatBuffersResponse),
362 (FuzzySearchUsers, UsersResponse),
363 (GetCachedEmbeddings, GetCachedEmbeddingsResponse),
364 (GetChannelMembers, GetChannelMembersResponse),
365 (GetChannelMessages, GetChannelMessagesResponse),
366 (GetChannelMessagesById, GetChannelMessagesResponse),
367 (GetCodeActions, GetCodeActionsResponse),
368 (GetCompletions, GetCompletionsResponse),
369 (GetDefinition, GetDefinitionResponse),
370 (GetImplementation, GetImplementationResponse),
371 (GetDocumentHighlights, GetDocumentHighlightsResponse),
372 (GetHover, GetHoverResponse),
373 (GetNotifications, GetNotificationsResponse),
374 (GetPrivateUserInfo, GetPrivateUserInfoResponse),
375 (GetProjectSymbols, GetProjectSymbolsResponse),
376 (GetReferences, GetReferencesResponse),
377 (GetSupermavenApiKey, GetSupermavenApiKeyResponse),
378 (GetTypeDefinition, GetTypeDefinitionResponse),
379 (GetUsers, UsersResponse),
380 (IncomingCall, Ack),
381 (InlayHints, InlayHintsResponse),
382 (InviteChannelMember, Ack),
383 (JoinChannel, JoinRoomResponse),
384 (JoinChannelBuffer, JoinChannelBufferResponse),
385 (JoinChannelChat, JoinChannelChatResponse),
386 (JoinHostedProject, JoinProjectResponse),
387 (JoinProject, JoinProjectResponse),
388 (JoinRoom, JoinRoomResponse),
389 (LeaveChannelBuffer, Ack),
390 (LeaveRoom, Ack),
391 (MarkNotificationRead, Ack),
392 (MoveChannel, Ack),
393 (OnTypeFormatting, OnTypeFormattingResponse),
394 (OpenBufferById, OpenBufferResponse),
395 (OpenBufferByPath, OpenBufferResponse),
396 (OpenBufferForSymbol, OpenBufferForSymbolResponse),
397 (OpenNewBuffer, OpenBufferResponse),
398 (PerformRename, PerformRenameResponse),
399 (Ping, Ack),
400 (PrepareRename, PrepareRenameResponse),
401 (RefreshInlayHints, Ack),
402 (RejoinChannelBuffers, RejoinChannelBuffersResponse),
403 (RejoinRoom, RejoinRoomResponse),
404 (ReloadBuffers, ReloadBuffersResponse),
405 (RemoveChannelMember, Ack),
406 (RemoveChannelMessage, Ack),
407 (UpdateChannelMessage, Ack),
408 (RemoveContact, Ack),
409 (RenameChannel, RenameChannelResponse),
410 (RenameProjectEntry, ProjectEntryResponse),
411 (RequestContact, Ack),
412 (
413 ResolveCompletionDocumentation,
414 ResolveCompletionDocumentationResponse
415 ),
416 (ResolveInlayHint, ResolveInlayHintResponse),
417 (RespondToChannelInvite, Ack),
418 (RespondToContactRequest, Ack),
419 (SaveBuffer, BufferSaved),
420 (SearchProject, SearchProjectResponse),
421 (SendChannelMessage, SendChannelMessageResponse),
422 (SetChannelMemberRole, Ack),
423 (SetChannelVisibility, Ack),
424 (ShareProject, ShareProjectResponse),
425 (SynchronizeBuffers, SynchronizeBuffersResponse),
426 (TaskContextForLocation, TaskContext),
427 (TaskTemplates, TaskTemplatesResponse),
428 (Test, Test),
429 (UpdateBuffer, Ack),
430 (UpdateParticipantLocation, Ack),
431 (UpdateProject, Ack),
432 (UpdateWorktree, Ack),
433 (LspExtExpandMacro, LspExtExpandMacroResponse),
434 (SetRoomParticipantRole, Ack),
435 (BlameBuffer, BlameBufferResponse),
436 (CreateDevServerProject, CreateDevServerProjectResponse),
437 (CreateDevServer, CreateDevServerResponse),
438 (ShutdownDevServer, Ack),
439 (ShareDevServerProject, ShareProjectResponse),
440 (JoinDevServerProject, JoinProjectResponse),
441 (RejoinRemoteProjects, RejoinRemoteProjectsResponse),
442 (ReconnectDevServer, ReconnectDevServerResponse),
443 (ValidateDevServerProjectRequest, Ack),
444 (MultiLspQuery, MultiLspQueryResponse),
445 (DeleteDevServer, Ack),
446 (DeleteDevServerProject, Ack),
447 (RegenerateDevServerToken, RegenerateDevServerTokenResponse),
448 (RenameDevServer, Ack),
449 (RestartLanguageServers, Ack)
450);
451
452entity_messages!(
453 {project_id, ShareProject},
454 AddProjectCollaborator,
455 ApplyCodeAction,
456 ApplyCompletionAdditionalEdits,
457 BlameBuffer,
458 BufferReloaded,
459 BufferSaved,
460 CopyProjectEntry,
461 CreateBufferForPeer,
462 CreateProjectEntry,
463 DeleteProjectEntry,
464 ExpandProjectEntry,
465 FormatBuffers,
466 GetCodeActions,
467 GetCompletions,
468 GetDefinition,
469 GetImplementation,
470 GetDocumentHighlights,
471 GetHover,
472 GetProjectSymbols,
473 GetReferences,
474 GetTypeDefinition,
475 InlayHints,
476 JoinProject,
477 LeaveProject,
478 MultiLspQuery,
479 RestartLanguageServers,
480 OnTypeFormatting,
481 OpenNewBuffer,
482 OpenBufferById,
483 OpenBufferByPath,
484 OpenBufferForSymbol,
485 PerformRename,
486 PrepareRename,
487 RefreshInlayHints,
488 ReloadBuffers,
489 RemoveProjectCollaborator,
490 RenameProjectEntry,
491 ResolveCompletionDocumentation,
492 ResolveInlayHint,
493 SaveBuffer,
494 SearchProject,
495 StartLanguageServer,
496 SynchronizeBuffers,
497 TaskContextForLocation,
498 TaskTemplates,
499 UnshareProject,
500 UpdateBuffer,
501 UpdateBufferFile,
502 UpdateDiagnosticSummary,
503 UpdateDiffBase,
504 UpdateLanguageServer,
505 UpdateProject,
506 UpdateProjectCollaborator,
507 UpdateWorktree,
508 UpdateWorktreeSettings,
509 LspExtExpandMacro,
510);
511
512entity_messages!(
513 {channel_id, Channel},
514 ChannelMessageSent,
515 ChannelMessageUpdate,
516 RemoveChannelMessage,
517 UpdateChannelMessage,
518 UpdateChannelBuffer,
519 UpdateChannelBufferCollaborators,
520);
521
522impl From<Timestamp> for SystemTime {
523 fn from(val: Timestamp) -> Self {
524 UNIX_EPOCH
525 .checked_add(Duration::new(val.seconds, val.nanos))
526 .unwrap()
527 }
528}
529
530impl From<SystemTime> for Timestamp {
531 fn from(time: SystemTime) -> Self {
532 let duration = time.duration_since(UNIX_EPOCH).unwrap();
533 Self {
534 seconds: duration.as_secs(),
535 nanos: duration.subsec_nanos(),
536 }
537 }
538}
539
540impl From<u128> for Nonce {
541 fn from(nonce: u128) -> Self {
542 let upper_half = (nonce >> 64) as u64;
543 let lower_half = nonce as u64;
544 Self {
545 upper_half,
546 lower_half,
547 }
548 }
549}
550
551impl From<Nonce> for u128 {
552 fn from(nonce: Nonce) -> Self {
553 let upper_half = (nonce.upper_half as u128) << 64;
554 let lower_half = nonce.lower_half as u128;
555 upper_half | lower_half
556 }
557}
558
559pub fn split_worktree_update(
560 mut message: UpdateWorktree,
561 max_chunk_size: usize,
562) -> impl Iterator<Item = UpdateWorktree> {
563 let mut done_files = false;
564
565 let mut repository_map = message
566 .updated_repositories
567 .into_iter()
568 .map(|repo| (repo.work_directory_id, repo))
569 .collect::<HashMap<_, _>>();
570
571 iter::from_fn(move || {
572 if done_files {
573 return None;
574 }
575
576 let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
577 let updated_entries: Vec<_> = message
578 .updated_entries
579 .drain(..updated_entries_chunk_size)
580 .collect();
581
582 let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
583 let removed_entries = message
584 .removed_entries
585 .drain(..removed_entries_chunk_size)
586 .collect();
587
588 done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
589
590 let mut updated_repositories = Vec::new();
591
592 if !repository_map.is_empty() {
593 for entry in &updated_entries {
594 if let Some(repo) = repository_map.remove(&entry.id) {
595 updated_repositories.push(repo)
596 }
597 }
598 }
599
600 let removed_repositories = if done_files {
601 mem::take(&mut message.removed_repositories)
602 } else {
603 Default::default()
604 };
605
606 if done_files {
607 updated_repositories.extend(mem::take(&mut repository_map).into_values());
608 }
609
610 Some(UpdateWorktree {
611 project_id: message.project_id,
612 worktree_id: message.worktree_id,
613 root_name: message.root_name.clone(),
614 abs_path: message.abs_path.clone(),
615 updated_entries,
616 removed_entries,
617 scan_id: message.scan_id,
618 is_last_update: done_files && message.is_last_update,
619 updated_repositories,
620 removed_repositories,
621 })
622 })
623}
624
625#[cfg(test)]
626mod tests {
627 use super::*;
628
629 #[test]
630 fn test_converting_peer_id_from_and_to_u64() {
631 let peer_id = PeerId {
632 owner_id: 10,
633 id: 3,
634 };
635 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
636 let peer_id = PeerId {
637 owner_id: u32::MAX,
638 id: 3,
639 };
640 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
641 let peer_id = PeerId {
642 owner_id: 10,
643 id: u32::MAX,
644 };
645 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
646 let peer_id = PeerId {
647 owner_id: u32::MAX,
648 id: u32::MAX,
649 };
650 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
651 }
652}