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    (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}