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::{
12 cmp,
13 fmt::Debug,
14 io, iter,
15 time::{Duration, SystemTime, UNIX_EPOCH},
16};
17use std::{fmt, mem};
18
19include!(concat!(env!("OUT_DIR"), "/zed.messages.rs"));
20
21pub trait EnvelopedMessage: Clone + Debug + Serialize + Sized + Send + Sync + 'static {
22 const NAME: &'static str;
23 const PRIORITY: MessagePriority;
24 fn into_envelope(
25 self,
26 id: u32,
27 responding_to: Option<u32>,
28 original_sender_id: Option<PeerId>,
29 ) -> Envelope;
30 fn from_envelope(envelope: Envelope) -> Option<Self>;
31}
32
33pub trait EntityMessage: EnvelopedMessage {
34 type Entity;
35 fn remote_entity_id(&self) -> u64;
36}
37
38pub trait RequestMessage: EnvelopedMessage {
39 type Response: EnvelopedMessage;
40}
41
42pub trait AnyTypedEnvelope: 'static + Send + Sync {
43 fn payload_type_id(&self) -> TypeId;
44 fn payload_type_name(&self) -> &'static str;
45 fn as_any(&self) -> &dyn Any;
46 fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
47 fn is_background(&self) -> bool;
48 fn original_sender_id(&self) -> Option<PeerId>;
49 fn sender_id(&self) -> ConnectionId;
50 fn message_id(&self) -> u32;
51}
52
53pub enum MessagePriority {
54 Foreground,
55 Background,
56}
57
58impl<T: EnvelopedMessage> AnyTypedEnvelope for TypedEnvelope<T> {
59 fn payload_type_id(&self) -> TypeId {
60 TypeId::of::<T>()
61 }
62
63 fn payload_type_name(&self) -> &'static str {
64 T::NAME
65 }
66
67 fn as_any(&self) -> &dyn Any {
68 self
69 }
70
71 fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
72 self
73 }
74
75 fn is_background(&self) -> bool {
76 matches!(T::PRIORITY, MessagePriority::Background)
77 }
78
79 fn original_sender_id(&self) -> Option<PeerId> {
80 self.original_sender_id
81 }
82
83 fn sender_id(&self) -> ConnectionId {
84 self.sender_id
85 }
86
87 fn message_id(&self) -> u32 {
88 self.message_id
89 }
90}
91
92impl PeerId {
93 pub fn from_u64(peer_id: u64) -> Self {
94 let owner_id = (peer_id >> 32) as u32;
95 let id = peer_id as u32;
96 Self { owner_id, id }
97 }
98
99 pub fn as_u64(self) -> u64 {
100 ((self.owner_id as u64) << 32) | (self.id as u64)
101 }
102}
103
104impl Copy for PeerId {}
105
106impl Eq for PeerId {}
107
108impl Ord for PeerId {
109 fn cmp(&self, other: &Self) -> cmp::Ordering {
110 self.owner_id
111 .cmp(&other.owner_id)
112 .then_with(|| self.id.cmp(&other.id))
113 }
114}
115
116impl PartialOrd for PeerId {
117 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
118 Some(self.cmp(other))
119 }
120}
121
122impl std::hash::Hash for PeerId {
123 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
124 self.owner_id.hash(state);
125 self.id.hash(state);
126 }
127}
128
129impl fmt::Display for PeerId {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(f, "{}/{}", self.owner_id, self.id)
132 }
133}
134
135messages!(
136 (Ack, Foreground),
137 (AckBufferOperation, Background),
138 (AckChannelMessage, Background),
139 (AddNotification, Foreground),
140 (AddProjectCollaborator, Foreground),
141 (ApplyCodeAction, Background),
142 (ApplyCodeActionResponse, Background),
143 (ApplyCompletionAdditionalEdits, Background),
144 (ApplyCompletionAdditionalEditsResponse, Background),
145 (BufferReloaded, Foreground),
146 (BufferSaved, Foreground),
147 (Call, Foreground),
148 (CallCanceled, Foreground),
149 (CancelCall, Foreground),
150 (ChannelMessageSent, Foreground),
151 (CopyProjectEntry, Foreground),
152 (CreateBufferForPeer, Foreground),
153 (CreateChannel, Foreground),
154 (CreateChannelResponse, Foreground),
155 (CreateProjectEntry, Foreground),
156 (CreateRoom, Foreground),
157 (CreateRoomResponse, Foreground),
158 (DeclineCall, Foreground),
159 (DeleteChannel, Foreground),
160 (DeleteNotification, Foreground),
161 (DeleteProjectEntry, Foreground),
162 (Error, Foreground),
163 (ExpandProjectEntry, Foreground),
164 (ExpandProjectEntryResponse, Foreground),
165 (Follow, Foreground),
166 (FollowResponse, Foreground),
167 (FormatBuffers, Foreground),
168 (FormatBuffersResponse, Foreground),
169 (FuzzySearchUsers, Foreground),
170 (GetChannelMembers, Foreground),
171 (GetChannelMembersResponse, Foreground),
172 (GetChannelMessages, Background),
173 (GetChannelMessagesById, Background),
174 (GetChannelMessagesResponse, Background),
175 (GetCodeActions, Background),
176 (GetCodeActionsResponse, Background),
177 (GetCompletions, Background),
178 (GetCompletionsResponse, Background),
179 (GetDefinition, Background),
180 (GetDefinitionResponse, Background),
181 (GetDocumentHighlights, Background),
182 (GetDocumentHighlightsResponse, Background),
183 (GetHover, Background),
184 (GetHoverResponse, Background),
185 (GetNotifications, Foreground),
186 (GetNotificationsResponse, Foreground),
187 (GetPrivateUserInfo, Foreground),
188 (GetPrivateUserInfoResponse, Foreground),
189 (GetProjectSymbols, Background),
190 (GetProjectSymbolsResponse, Background),
191 (GetReferences, Background),
192 (GetReferencesResponse, Background),
193 (GetTypeDefinition, Background),
194 (GetTypeDefinitionResponse, Background),
195 (GetUsers, Foreground),
196 (Hello, Foreground),
197 (IncomingCall, Foreground),
198 (InlayHints, Background),
199 (InlayHintsResponse, Background),
200 (InviteChannelMember, Foreground),
201 (JoinChannel2, Foreground),
202 (JoinChannel, Foreground),
203 (JoinChannelBuffer, Foreground),
204 (JoinChannelBufferResponse, Foreground),
205 (JoinChannelChat, Foreground),
206 (JoinChannelChatResponse, Foreground),
207 (JoinProject, Foreground),
208 (JoinProjectResponse, Foreground),
209 (JoinRoom, Foreground),
210 (JoinRoomResponse, Foreground),
211 (LeaveChannelBuffer, Background),
212 (JoinChannelCall, Foreground),
213 (JoinChannelCallResponse, Foreground),
214 (LeaveChannelCall, Foreground),
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 (GetDocumentHighlights, GetDocumentHighlightsResponse),
320 (GetHover, GetHoverResponse),
321 (GetNotifications, GetNotificationsResponse),
322 (GetPrivateUserInfo, GetPrivateUserInfoResponse),
323 (GetProjectSymbols, GetProjectSymbolsResponse),
324 (GetReferences, GetReferencesResponse),
325 (GetTypeDefinition, GetTypeDefinitionResponse),
326 (GetUsers, UsersResponse),
327 (IncomingCall, Ack),
328 (InlayHints, InlayHintsResponse),
329 (InviteChannelMember, Ack),
330 (JoinChannel, JoinRoomResponse),
331 (JoinChannel2, JoinRoomResponse),
332 (JoinChannelCall, JoinChannelCallResponse),
333 (LeaveChannelCall, Ack),
334 (JoinChannelBuffer, JoinChannelBufferResponse),
335 (JoinChannelChat, JoinChannelChatResponse),
336 (JoinProject, JoinProjectResponse),
337 (JoinRoom, JoinRoomResponse),
338 (LeaveChannelBuffer, Ack),
339 (LeaveRoom, Ack),
340 (MarkNotificationRead, Ack),
341 (MoveChannel, Ack),
342 (OnTypeFormatting, OnTypeFormattingResponse),
343 (OpenBufferById, OpenBufferResponse),
344 (OpenBufferByPath, OpenBufferResponse),
345 (OpenBufferForSymbol, OpenBufferForSymbolResponse),
346 (PerformRename, PerformRenameResponse),
347 (Ping, Ack),
348 (PrepareRename, PrepareRenameResponse),
349 (RefreshInlayHints, Ack),
350 (RejoinChannelBuffers, RejoinChannelBuffersResponse),
351 (RejoinRoom, RejoinRoomResponse),
352 (ReloadBuffers, ReloadBuffersResponse),
353 (RemoveChannelMember, Ack),
354 (RemoveChannelMessage, Ack),
355 (RemoveContact, Ack),
356 (RenameChannel, RenameChannelResponse),
357 (RenameProjectEntry, ProjectEntryResponse),
358 (RequestContact, Ack),
359 (
360 ResolveCompletionDocumentation,
361 ResolveCompletionDocumentationResponse
362 ),
363 (ResolveInlayHint, ResolveInlayHintResponse),
364 (RespondToChannelInvite, Ack),
365 (RespondToContactRequest, Ack),
366 (SaveBuffer, BufferSaved),
367 (SearchProject, SearchProjectResponse),
368 (SendChannelMessage, SendChannelMessageResponse),
369 (SetChannelMemberRole, Ack),
370 (SetChannelVisibility, Ack),
371 (ShareProject, ShareProjectResponse),
372 (SynchronizeBuffers, SynchronizeBuffersResponse),
373 (Test, Test),
374 (UpdateBuffer, Ack),
375 (UpdateParticipantLocation, Ack),
376 (UpdateProject, Ack),
377 (UpdateWorktree, Ack),
378 (LspExtExpandMacro, LspExtExpandMacroResponse),
379 (SetRoomParticipantRole, Ack),
380);
381
382entity_messages!(
383 {project_id, ShareProject},
384 AddProjectCollaborator,
385 ApplyCodeAction,
386 ApplyCompletionAdditionalEdits,
387 BufferReloaded,
388 BufferSaved,
389 CopyProjectEntry,
390 CreateBufferForPeer,
391 CreateProjectEntry,
392 DeleteProjectEntry,
393 ExpandProjectEntry,
394 FormatBuffers,
395 GetCodeActions,
396 GetCompletions,
397 GetDefinition,
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, anyhow::Error> {
520 while let Some(bytes) = self.stream.next().await {
521 match bytes? {
522 WebSocketMessage::Binary(bytes) => {
523 zstd::stream::copy_decode(bytes.as_slice(), &mut self.encoding_buffer).unwrap();
524 let envelope = Envelope::decode(self.encoding_buffer.as_slice())
525 .map_err(io::Error::from)?;
526
527 self.encoding_buffer.clear();
528 self.encoding_buffer.shrink_to(MAX_BUFFER_LEN);
529 return Ok(Message::Envelope(envelope));
530 }
531 WebSocketMessage::Ping(_) => return Ok(Message::Ping),
532 WebSocketMessage::Pong(_) => return Ok(Message::Pong),
533 WebSocketMessage::Close(_) => break,
534 _ => {}
535 }
536 }
537 Err(anyhow!("connection closed"))
538 }
539}
540
541impl From<Timestamp> for SystemTime {
542 fn from(val: Timestamp) -> Self {
543 UNIX_EPOCH
544 .checked_add(Duration::new(val.seconds, val.nanos))
545 .unwrap()
546 }
547}
548
549impl From<SystemTime> for Timestamp {
550 fn from(time: SystemTime) -> Self {
551 let duration = time.duration_since(UNIX_EPOCH).unwrap();
552 Self {
553 seconds: duration.as_secs(),
554 nanos: duration.subsec_nanos(),
555 }
556 }
557}
558
559impl From<u128> for Nonce {
560 fn from(nonce: u128) -> Self {
561 let upper_half = (nonce >> 64) as u64;
562 let lower_half = nonce as u64;
563 Self {
564 upper_half,
565 lower_half,
566 }
567 }
568}
569
570impl From<Nonce> for u128 {
571 fn from(nonce: Nonce) -> Self {
572 let upper_half = (nonce.upper_half as u128) << 64;
573 let lower_half = nonce.lower_half as u128;
574 upper_half | lower_half
575 }
576}
577
578pub fn split_worktree_update(
579 mut message: UpdateWorktree,
580 max_chunk_size: usize,
581) -> impl Iterator<Item = UpdateWorktree> {
582 let mut done_files = false;
583
584 let mut repository_map = message
585 .updated_repositories
586 .into_iter()
587 .map(|repo| (repo.work_directory_id, repo))
588 .collect::<HashMap<_, _>>();
589
590 iter::from_fn(move || {
591 if done_files {
592 return None;
593 }
594
595 let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
596 let updated_entries: Vec<_> = message
597 .updated_entries
598 .drain(..updated_entries_chunk_size)
599 .collect();
600
601 let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
602 let removed_entries = message
603 .removed_entries
604 .drain(..removed_entries_chunk_size)
605 .collect();
606
607 done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
608
609 let mut updated_repositories = Vec::new();
610
611 if !repository_map.is_empty() {
612 for entry in &updated_entries {
613 if let Some(repo) = repository_map.remove(&entry.id) {
614 updated_repositories.push(repo)
615 }
616 }
617 }
618
619 let removed_repositories = if done_files {
620 mem::take(&mut message.removed_repositories)
621 } else {
622 Default::default()
623 };
624
625 if done_files {
626 updated_repositories.extend(mem::take(&mut repository_map).into_values());
627 }
628
629 Some(UpdateWorktree {
630 project_id: message.project_id,
631 worktree_id: message.worktree_id,
632 root_name: message.root_name.clone(),
633 abs_path: message.abs_path.clone(),
634 updated_entries,
635 removed_entries,
636 scan_id: message.scan_id,
637 is_last_update: done_files && message.is_last_update,
638 updated_repositories,
639 removed_repositories,
640 })
641 })
642}
643
644#[cfg(test)]
645mod tests {
646 use super::*;
647
648 #[gpui::test]
649 async fn test_buffer_size() {
650 let (tx, rx) = futures::channel::mpsc::unbounded();
651 let mut sink = MessageStream::new(tx.sink_map_err(|_| anyhow!("")));
652 sink.write(Message::Envelope(Envelope {
653 payload: Some(envelope::Payload::UpdateWorktree(UpdateWorktree {
654 root_name: "abcdefg".repeat(10),
655 ..Default::default()
656 })),
657 ..Default::default()
658 }))
659 .await
660 .unwrap();
661 assert!(sink.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
662 sink.write(Message::Envelope(Envelope {
663 payload: Some(envelope::Payload::UpdateWorktree(UpdateWorktree {
664 root_name: "abcdefg".repeat(1000000),
665 ..Default::default()
666 })),
667 ..Default::default()
668 }))
669 .await
670 .unwrap();
671 assert!(sink.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
672
673 let mut stream = MessageStream::new(rx.map(anyhow::Ok));
674 stream.read().await.unwrap();
675 assert!(stream.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
676 stream.read().await.unwrap();
677 assert!(stream.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
678 }
679
680 #[gpui::test]
681 fn test_converting_peer_id_from_and_to_u64() {
682 let peer_id = PeerId {
683 owner_id: 10,
684 id: 3,
685 };
686 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
687 let peer_id = PeerId {
688 owner_id: u32::MAX,
689 id: 3,
690 };
691 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
692 let peer_id = PeerId {
693 owner_id: 10,
694 id: u32::MAX,
695 };
696 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
697 let peer_id = PeerId {
698 owner_id: u32::MAX,
699 id: u32::MAX,
700 };
701 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
702 }
703}