memberlist_proto/
address.rs

1use nodecraft::CheapClone;
2
3use super::{
4  Data, DataRef, DecodeError, EncodeError,
5  utils::{merge, skip},
6};
7
8/// `MaybeResolvedAddress` is used to represent an address that may or may not be resolved.
9#[derive(
10  Clone,
11  Copy,
12  Debug,
13  PartialEq,
14  Eq,
15  Hash,
16  derive_more::Display,
17  derive_more::TryUnwrap,
18  derive_more::Unwrap,
19  derive_more::IsVariant,
20)]
21#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
24#[unwrap(ref, ref_mut)]
25#[try_unwrap(ref, ref_mut)]
26pub enum MaybeResolvedAddress<A, R> {
27  /// The resolved address, which means that can be directly used to communicate with the remote node.
28  #[display("{_0}")]
29  Resolved(R),
30  /// The unresolved address, which means that need to be resolved before using it to communicate with the remote node.
31  #[display("{_0}")]
32  Unresolved(A),
33}
34
35impl<A: CheapClone, R: CheapClone> CheapClone for MaybeResolvedAddress<A, R> {
36  fn cheap_clone(&self) -> Self {
37    match self {
38      Self::Resolved(addr) => Self::Resolved(addr.cheap_clone()),
39      Self::Unresolved(addr) => Self::Unresolved(addr.cheap_clone()),
40    }
41  }
42}
43
44impl<A, R> MaybeResolvedAddress<A, R> {
45  /// Creates a resolved address.
46  #[inline]
47  pub const fn resolved(addr: R) -> Self {
48    Self::Resolved(addr)
49  }
50
51  /// Creates an unresolved address.
52  #[inline]
53  pub const fn unresolved(addr: A) -> Self {
54    Self::Unresolved(addr)
55  }
56
57  /// Converts from `&MaybeResolvedAddress<A, R>` to `MaybeResolvedAddress<&A, &R>`.
58  #[inline]
59  pub const fn as_ref(&self) -> MaybeResolvedAddress<&A, &R> {
60    match self {
61      Self::Resolved(addr) => MaybeResolvedAddress::Resolved(addr),
62      Self::Unresolved(addr) => MaybeResolvedAddress::Unresolved(addr),
63    }
64  }
65
66  /// Converts from `&mut MaybeResolvedAddress<A, R>` to `MaybeResolvedAddress<&mut A, &mut R>`.
67  #[inline]
68  pub const fn as_mut(&mut self) -> MaybeResolvedAddress<&mut A, &mut R> {
69    match self {
70      Self::Resolved(addr) => MaybeResolvedAddress::Resolved(addr),
71      Self::Unresolved(addr) => MaybeResolvedAddress::Unresolved(addr),
72    }
73  }
74}
75
76const RESOLVED_TAG: u8 = 1;
77const UNRESOLVED_TAG: u8 = 2;
78
79impl<A, R> MaybeResolvedAddress<A, R>
80where
81  A: Data,
82  R: Data,
83{
84  #[inline]
85  const fn resolved_byte() -> u8 {
86    merge(R::WIRE_TYPE, RESOLVED_TAG)
87  }
88
89  #[inline]
90  const fn unresolved_byte() -> u8 {
91    merge(A::WIRE_TYPE, UNRESOLVED_TAG)
92  }
93}
94
95impl<'a, A, R> DataRef<'a, MaybeResolvedAddress<A, R>>
96  for MaybeResolvedAddress<A::Ref<'a>, R::Ref<'a>>
97where
98  A: Data,
99  R: Data,
100{
101  fn decode(buf: &'a [u8]) -> Result<(usize, Self), DecodeError>
102  where
103    Self: Sized,
104  {
105    let mut offset = 0;
106    let buf_len = buf.len();
107    let mut addr = None;
108
109    while offset < buf_len {
110      match buf[offset] {
111        byte if byte == MaybeResolvedAddress::<A, R>::resolved_byte() => {
112          if addr.is_some() {
113            return Err(DecodeError::duplicate_field(
114              "MaybeResolvedAddress",
115              "value",
116              RESOLVED_TAG,
117            ));
118          }
119
120          offset += 1;
121
122          let (len, val) = <R::Ref<'_> as DataRef<'_, R>>::decode_length_delimited(&buf[offset..])?;
123          offset += len;
124          addr = Some(Self::Resolved(val));
125        }
126        byte if byte == MaybeResolvedAddress::<A, R>::unresolved_byte() => {
127          if addr.is_some() {
128            return Err(DecodeError::duplicate_field(
129              "MaybeResolvedAddress",
130              "value",
131              UNRESOLVED_TAG,
132            ));
133          }
134          offset += 1;
135
136          let (len, val) = <A::Ref<'_> as DataRef<'_, A>>::decode_length_delimited(&buf[offset..])?;
137          offset += len;
138          addr = Some(Self::Unresolved(val));
139        }
140        _ => offset += skip("MaybeResolvedAddress", &buf[offset..])?,
141      }
142    }
143
144    let addr = addr.ok_or_else(|| DecodeError::missing_field("MaybeResolvedAddress", "value"))?;
145    Ok((offset, addr))
146  }
147}
148
149impl<A, R> Data for MaybeResolvedAddress<A, R>
150where
151  A: Data,
152  R: Data,
153{
154  type Ref<'a> = MaybeResolvedAddress<A::Ref<'a>, R::Ref<'a>>;
155
156  fn from_ref(val: Self::Ref<'_>) -> Result<Self, DecodeError>
157  where
158    Self: Sized,
159  {
160    match val {
161      MaybeResolvedAddress::Resolved(addr) => R::from_ref(addr).map(Self::Resolved),
162      MaybeResolvedAddress::Unresolved(addr) => A::from_ref(addr).map(Self::Unresolved),
163    }
164  }
165
166  fn encoded_len(&self) -> usize {
167    1 + match self {
168      Self::Resolved(addr) => addr.encoded_len_with_length_delimited(),
169      Self::Unresolved(addr) => addr.encoded_len_with_length_delimited(),
170    }
171  }
172
173  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
174    let mut offset = 0;
175    let buf_len = buf.len();
176    match self {
177      Self::Resolved(addr) => {
178        if buf_len < 1 {
179          return Err(EncodeError::insufficient_buffer(
180            self.encoded_len(),
181            buf_len,
182          ));
183        }
184
185        buf[offset] = Self::resolved_byte();
186        offset += 1;
187        offset += addr.encode_length_delimited(&mut buf[offset..])?;
188      }
189      Self::Unresolved(addr) => {
190        if buf_len < 1 {
191          return Err(EncodeError::insufficient_buffer(
192            self.encoded_len(),
193            buf_len,
194          ));
195        }
196
197        buf[offset] = Self::unresolved_byte();
198        offset += 1;
199        offset += addr.encode_length_delimited(&mut buf[offset..])?;
200      }
201    }
202
203    #[cfg(debug_assertions)]
204    super::debug_assert_write_eq::<Self>(offset, self.encoded_len());
205
206    Ok(offset)
207  }
208}