proto.rs

  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}