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 (GetImplementation, Background),
196 (GetImplementationResponse, Background),
197 (GetUsers, Foreground),
198 (Hello, Foreground),
199 (IncomingCall, Foreground),
200 (InlayHints, Background),
201 (InlayHintsResponse, Background),
202 (InviteChannelMember, Foreground),
203 (JoinChannel, Foreground),
204 (JoinChannelBuffer, Foreground),
205 (JoinChannelBufferResponse, Foreground),
206 (JoinChannelChat, Foreground),
207 (JoinChannelChatResponse, Foreground),
208 (JoinProject, Foreground),
209 (JoinProjectResponse, Foreground),
210 (JoinRoom, Foreground),
211 (JoinRoomResponse, Foreground),
212 (LeaveChannelBuffer, Background),
213 (LeaveChannelChat, Foreground),
214 (LeaveProject, Foreground),
215 (LeaveRoom, Foreground),
216 (MarkNotificationRead, Foreground),
217 (MoveChannel, Foreground),
218 (OnTypeFormatting, Background),
219 (OnTypeFormattingResponse, Background),
220 (OpenBufferById, Background),
221 (OpenBufferByPath, Background),
222 (OpenBufferForSymbol, Background),
223 (OpenBufferForSymbolResponse, Background),
224 (OpenBufferResponse, Background),
225 (PerformRename, Background),
226 (PerformRenameResponse, Background),
227 (Ping, Foreground),
228 (PrepareRename, Background),
229 (PrepareRenameResponse, Background),
230 (ProjectEntryResponse, Foreground),
231 (RefreshInlayHints, Foreground),
232 (RejoinChannelBuffers, Foreground),
233 (RejoinChannelBuffersResponse, Foreground),
234 (RejoinRoom, Foreground),
235 (RejoinRoomResponse, Foreground),
236 (ReloadBuffers, Foreground),
237 (ReloadBuffersResponse, Foreground),
238 (RemoveChannelMember, Foreground),
239 (RemoveChannelMessage, Foreground),
240 (RemoveContact, Foreground),
241 (RemoveProjectCollaborator, Foreground),
242 (RenameChannel, Foreground),
243 (RenameChannelResponse, Foreground),
244 (RenameProjectEntry, Foreground),
245 (RequestContact, Foreground),
246 (ResolveCompletionDocumentation, Background),
247 (ResolveCompletionDocumentationResponse, Background),
248 (ResolveInlayHint, Background),
249 (ResolveInlayHintResponse, Background),
250 (RespondToChannelInvite, Foreground),
251 (RespondToContactRequest, Foreground),
252 (RoomUpdated, Foreground),
253 (SaveBuffer, Foreground),
254 (SetChannelMemberRole, Foreground),
255 (SetChannelVisibility, Foreground),
256 (SearchProject, Background),
257 (SearchProjectResponse, Background),
258 (SendChannelMessage, Background),
259 (SendChannelMessageResponse, Background),
260 (ShareProject, Foreground),
261 (ShareProjectResponse, Foreground),
262 (ShowContacts, Foreground),
263 (StartLanguageServer, Foreground),
264 (SynchronizeBuffers, Foreground),
265 (SynchronizeBuffersResponse, Foreground),
266 (Test, Foreground),
267 (Unfollow, Foreground),
268 (UnshareProject, Foreground),
269 (UpdateBuffer, Foreground),
270 (UpdateBufferFile, Foreground),
271 (UpdateChannelBuffer, Foreground),
272 (UpdateChannelBufferCollaborators, Foreground),
273 (UpdateChannels, Foreground),
274 (UpdateUserChannels, Foreground),
275 (UpdateContacts, Foreground),
276 (UpdateDiagnosticSummary, Foreground),
277 (UpdateDiffBase, Foreground),
278 (UpdateFollowers, Foreground),
279 (UpdateInviteInfo, Foreground),
280 (UpdateLanguageServer, Foreground),
281 (UpdateParticipantLocation, Foreground),
282 (UpdateProject, Foreground),
283 (UpdateProjectCollaborator, Foreground),
284 (UpdateWorktree, Foreground),
285 (UpdateWorktreeSettings, Foreground),
286 (UsersResponse, Foreground),
287 (LspExtExpandMacro, Background),
288 (LspExtExpandMacroResponse, Background),
289 (SetRoomParticipantRole, Foreground),
290);
291
292request_messages!(
293 (ApplyCodeAction, ApplyCodeActionResponse),
294 (
295 ApplyCompletionAdditionalEdits,
296 ApplyCompletionAdditionalEditsResponse
297 ),
298 (Call, Ack),
299 (CancelCall, Ack),
300 (CopyProjectEntry, ProjectEntryResponse),
301 (CreateChannel, CreateChannelResponse),
302 (CreateProjectEntry, ProjectEntryResponse),
303 (CreateRoom, CreateRoomResponse),
304 (DeclineCall, Ack),
305 (DeleteChannel, Ack),
306 (DeleteProjectEntry, ProjectEntryResponse),
307 (ExpandProjectEntry, ExpandProjectEntryResponse),
308 (Follow, FollowResponse),
309 (FormatBuffers, FormatBuffersResponse),
310 (FuzzySearchUsers, UsersResponse),
311 (GetChannelMembers, GetChannelMembersResponse),
312 (GetChannelMessages, GetChannelMessagesResponse),
313 (GetChannelMessagesById, GetChannelMessagesResponse),
314 (GetCodeActions, GetCodeActionsResponse),
315 (GetCompletions, GetCompletionsResponse),
316 (GetDefinition, GetDefinitionResponse),
317 (GetImplementation, GetImplementationResponse),
318 (GetDocumentHighlights, GetDocumentHighlightsResponse),
319 (GetHover, GetHoverResponse),
320 (GetNotifications, GetNotificationsResponse),
321 (GetPrivateUserInfo, GetPrivateUserInfoResponse),
322 (GetProjectSymbols, GetProjectSymbolsResponse),
323 (GetReferences, GetReferencesResponse),
324 (GetTypeDefinition, GetTypeDefinitionResponse),
325 (GetUsers, UsersResponse),
326 (IncomingCall, Ack),
327 (InlayHints, InlayHintsResponse),
328 (InviteChannelMember, Ack),
329 (JoinChannel, JoinRoomResponse),
330 (JoinChannelBuffer, JoinChannelBufferResponse),
331 (JoinChannelChat, JoinChannelChatResponse),
332 (JoinProject, JoinProjectResponse),
333 (JoinRoom, JoinRoomResponse),
334 (LeaveChannelBuffer, Ack),
335 (LeaveRoom, Ack),
336 (MarkNotificationRead, Ack),
337 (MoveChannel, Ack),
338 (OnTypeFormatting, OnTypeFormattingResponse),
339 (OpenBufferById, OpenBufferResponse),
340 (OpenBufferByPath, OpenBufferResponse),
341 (OpenBufferForSymbol, OpenBufferForSymbolResponse),
342 (PerformRename, PerformRenameResponse),
343 (Ping, Ack),
344 (PrepareRename, PrepareRenameResponse),
345 (RefreshInlayHints, Ack),
346 (RejoinChannelBuffers, RejoinChannelBuffersResponse),
347 (RejoinRoom, RejoinRoomResponse),
348 (ReloadBuffers, ReloadBuffersResponse),
349 (RemoveChannelMember, Ack),
350 (RemoveChannelMessage, Ack),
351 (RemoveContact, Ack),
352 (RenameChannel, RenameChannelResponse),
353 (RenameProjectEntry, ProjectEntryResponse),
354 (RequestContact, Ack),
355 (
356 ResolveCompletionDocumentation,
357 ResolveCompletionDocumentationResponse
358 ),
359 (ResolveInlayHint, ResolveInlayHintResponse),
360 (RespondToChannelInvite, Ack),
361 (RespondToContactRequest, Ack),
362 (SaveBuffer, BufferSaved),
363 (SearchProject, SearchProjectResponse),
364 (SendChannelMessage, SendChannelMessageResponse),
365 (SetChannelMemberRole, Ack),
366 (SetChannelVisibility, Ack),
367 (ShareProject, ShareProjectResponse),
368 (SynchronizeBuffers, SynchronizeBuffersResponse),
369 (Test, Test),
370 (UpdateBuffer, Ack),
371 (UpdateParticipantLocation, Ack),
372 (UpdateProject, Ack),
373 (UpdateWorktree, Ack),
374 (LspExtExpandMacro, LspExtExpandMacroResponse),
375 (SetRoomParticipantRole, Ack),
376);
377
378entity_messages!(
379 {project_id, ShareProject},
380 AddProjectCollaborator,
381 ApplyCodeAction,
382 ApplyCompletionAdditionalEdits,
383 BufferReloaded,
384 BufferSaved,
385 CopyProjectEntry,
386 CreateBufferForPeer,
387 CreateProjectEntry,
388 DeleteProjectEntry,
389 ExpandProjectEntry,
390 FormatBuffers,
391 GetCodeActions,
392 GetCompletions,
393 GetDefinition,
394 GetImplementation,
395 GetDocumentHighlights,
396 GetHover,
397 GetProjectSymbols,
398 GetReferences,
399 GetTypeDefinition,
400 InlayHints,
401 JoinProject,
402 LeaveProject,
403 OnTypeFormatting,
404 OpenBufferById,
405 OpenBufferByPath,
406 OpenBufferForSymbol,
407 PerformRename,
408 PrepareRename,
409 RefreshInlayHints,
410 ReloadBuffers,
411 RemoveProjectCollaborator,
412 RenameProjectEntry,
413 ResolveCompletionDocumentation,
414 ResolveInlayHint,
415 SaveBuffer,
416 SearchProject,
417 StartLanguageServer,
418 SynchronizeBuffers,
419 UnshareProject,
420 UpdateBuffer,
421 UpdateBufferFile,
422 UpdateDiagnosticSummary,
423 UpdateDiffBase,
424 UpdateLanguageServer,
425 UpdateProject,
426 UpdateProjectCollaborator,
427 UpdateWorktree,
428 UpdateWorktreeSettings,
429 LspExtExpandMacro,
430);
431
432entity_messages!(
433 {channel_id, Channel},
434 ChannelMessageSent,
435 RemoveChannelMessage,
436 UpdateChannelBuffer,
437 UpdateChannelBufferCollaborators,
438);
439
440const KIB: usize = 1024;
441const MIB: usize = KIB * 1024;
442const MAX_BUFFER_LEN: usize = MIB;
443
444/// A stream of protobuf messages.
445pub struct MessageStream<S> {
446 stream: S,
447 encoding_buffer: Vec<u8>,
448}
449
450#[allow(clippy::large_enum_variant)]
451#[derive(Debug)]
452pub enum Message {
453 Envelope(Envelope),
454 Ping,
455 Pong,
456}
457
458impl<S> MessageStream<S> {
459 pub fn new(stream: S) -> Self {
460 Self {
461 stream,
462 encoding_buffer: Vec::new(),
463 }
464 }
465
466 pub fn inner_mut(&mut self) -> &mut S {
467 &mut self.stream
468 }
469}
470
471impl<S> MessageStream<S>
472where
473 S: futures::Sink<WebSocketMessage, Error = anyhow::Error> + Unpin,
474{
475 pub async fn write(&mut self, message: Message) -> Result<(), anyhow::Error> {
476 #[cfg(any(test, feature = "test-support"))]
477 const COMPRESSION_LEVEL: i32 = -7;
478
479 #[cfg(not(any(test, feature = "test-support")))]
480 const COMPRESSION_LEVEL: i32 = 4;
481
482 match message {
483 Message::Envelope(message) => {
484 self.encoding_buffer.reserve(message.encoded_len());
485 message
486 .encode(&mut self.encoding_buffer)
487 .map_err(io::Error::from)?;
488 let buffer =
489 zstd::stream::encode_all(self.encoding_buffer.as_slice(), COMPRESSION_LEVEL)
490 .unwrap();
491
492 self.encoding_buffer.clear();
493 self.encoding_buffer.shrink_to(MAX_BUFFER_LEN);
494 self.stream.send(WebSocketMessage::Binary(buffer)).await?;
495 }
496 Message::Ping => {
497 self.stream
498 .send(WebSocketMessage::Ping(Default::default()))
499 .await?;
500 }
501 Message::Pong => {
502 self.stream
503 .send(WebSocketMessage::Pong(Default::default()))
504 .await?;
505 }
506 }
507
508 Ok(())
509 }
510}
511
512impl<S> MessageStream<S>
513where
514 S: futures::Stream<Item = Result<WebSocketMessage, anyhow::Error>> + Unpin,
515{
516 pub async fn read(&mut self) -> Result<Message, anyhow::Error> {
517 while let Some(bytes) = self.stream.next().await {
518 match bytes? {
519 WebSocketMessage::Binary(bytes) => {
520 zstd::stream::copy_decode(bytes.as_slice(), &mut self.encoding_buffer).unwrap();
521 let envelope = Envelope::decode(self.encoding_buffer.as_slice())
522 .map_err(io::Error::from)?;
523
524 self.encoding_buffer.clear();
525 self.encoding_buffer.shrink_to(MAX_BUFFER_LEN);
526 return Ok(Message::Envelope(envelope));
527 }
528 WebSocketMessage::Ping(_) => return Ok(Message::Ping),
529 WebSocketMessage::Pong(_) => return Ok(Message::Pong),
530 WebSocketMessage::Close(_) => break,
531 _ => {}
532 }
533 }
534 Err(anyhow!("connection closed"))
535 }
536}
537
538impl From<Timestamp> for SystemTime {
539 fn from(val: Timestamp) -> Self {
540 UNIX_EPOCH
541 .checked_add(Duration::new(val.seconds, val.nanos))
542 .unwrap()
543 }
544}
545
546impl From<SystemTime> for Timestamp {
547 fn from(time: SystemTime) -> Self {
548 let duration = time.duration_since(UNIX_EPOCH).unwrap();
549 Self {
550 seconds: duration.as_secs(),
551 nanos: duration.subsec_nanos(),
552 }
553 }
554}
555
556impl From<u128> for Nonce {
557 fn from(nonce: u128) -> Self {
558 let upper_half = (nonce >> 64) as u64;
559 let lower_half = nonce as u64;
560 Self {
561 upper_half,
562 lower_half,
563 }
564 }
565}
566
567impl From<Nonce> for u128 {
568 fn from(nonce: Nonce) -> Self {
569 let upper_half = (nonce.upper_half as u128) << 64;
570 let lower_half = nonce.lower_half as u128;
571 upper_half | lower_half
572 }
573}
574
575pub fn split_worktree_update(
576 mut message: UpdateWorktree,
577 max_chunk_size: usize,
578) -> impl Iterator<Item = UpdateWorktree> {
579 let mut done_files = false;
580
581 let mut repository_map = message
582 .updated_repositories
583 .into_iter()
584 .map(|repo| (repo.work_directory_id, repo))
585 .collect::<HashMap<_, _>>();
586
587 iter::from_fn(move || {
588 if done_files {
589 return None;
590 }
591
592 let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
593 let updated_entries: Vec<_> = message
594 .updated_entries
595 .drain(..updated_entries_chunk_size)
596 .collect();
597
598 let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
599 let removed_entries = message
600 .removed_entries
601 .drain(..removed_entries_chunk_size)
602 .collect();
603
604 done_files = message.updated_entries.is_empty() && message.removed_entries.is_empty();
605
606 let mut updated_repositories = Vec::new();
607
608 if !repository_map.is_empty() {
609 for entry in &updated_entries {
610 if let Some(repo) = repository_map.remove(&entry.id) {
611 updated_repositories.push(repo)
612 }
613 }
614 }
615
616 let removed_repositories = if done_files {
617 mem::take(&mut message.removed_repositories)
618 } else {
619 Default::default()
620 };
621
622 if done_files {
623 updated_repositories.extend(mem::take(&mut repository_map).into_values());
624 }
625
626 Some(UpdateWorktree {
627 project_id: message.project_id,
628 worktree_id: message.worktree_id,
629 root_name: message.root_name.clone(),
630 abs_path: message.abs_path.clone(),
631 updated_entries,
632 removed_entries,
633 scan_id: message.scan_id,
634 is_last_update: done_files && message.is_last_update,
635 updated_repositories,
636 removed_repositories,
637 })
638 })
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644
645 #[gpui::test]
646 async fn test_buffer_size() {
647 let (tx, rx) = futures::channel::mpsc::unbounded();
648 let mut sink = MessageStream::new(tx.sink_map_err(|_| anyhow!("")));
649 sink.write(Message::Envelope(Envelope {
650 payload: Some(envelope::Payload::UpdateWorktree(UpdateWorktree {
651 root_name: "abcdefg".repeat(10),
652 ..Default::default()
653 })),
654 ..Default::default()
655 }))
656 .await
657 .unwrap();
658 assert!(sink.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
659 sink.write(Message::Envelope(Envelope {
660 payload: Some(envelope::Payload::UpdateWorktree(UpdateWorktree {
661 root_name: "abcdefg".repeat(1000000),
662 ..Default::default()
663 })),
664 ..Default::default()
665 }))
666 .await
667 .unwrap();
668 assert!(sink.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
669
670 let mut stream = MessageStream::new(rx.map(anyhow::Ok));
671 stream.read().await.unwrap();
672 assert!(stream.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
673 stream.read().await.unwrap();
674 assert!(stream.encoding_buffer.capacity() <= MAX_BUFFER_LEN);
675 }
676
677 #[gpui::test]
678 fn test_converting_peer_id_from_and_to_u64() {
679 let peer_id = PeerId {
680 owner_id: 10,
681 id: 3,
682 };
683 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
684 let peer_id = PeerId {
685 owner_id: u32::MAX,
686 id: 3,
687 };
688 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
689 let peer_id = PeerId {
690 owner_id: 10,
691 id: u32::MAX,
692 };
693 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
694 let peer_id = PeerId {
695 owner_id: u32::MAX,
696 id: u32::MAX,
697 };
698 assert_eq!(PeerId::from_u64(peer_id.as_u64()), peer_id);
699 }
700}