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