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