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