memberlist_types/
meta.rs

1use byteorder::{ByteOrder, NetworkEndian};
2use bytes::{Bytes, BytesMut};
3use nodecraft::{CheapClone, Transformable};
4
5/// Invalid meta error.
6#[derive(Debug, thiserror::Error)]
7#[error("the size of meta must between [0-255] bytes, got {0}")]
8pub struct LargeMeta(usize);
9
10/// The metadata of a node in the cluster.
11#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
12#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(transparent))]
14#[cfg_attr(
15  feature = "rkyv",
16  derive(::rkyv::Serialize, ::rkyv::Deserialize, ::rkyv::Archive)
17)]
18#[cfg_attr(
19  feature = "rkyv",
20  rkyv(derive(Debug, PartialEq, Eq, Hash), compare(PartialEq))
21)]
22pub struct Meta(Bytes);
23
24impl Default for Meta {
25  #[inline]
26  fn default() -> Self {
27    Self::empty()
28  }
29}
30
31impl CheapClone for Meta {}
32
33impl Meta {
34  /// The maximum size of a name in bytes.
35  pub const MAX_SIZE: usize = 512;
36
37  /// Create an empty meta.
38  #[inline]
39  pub const fn empty() -> Meta {
40    Meta(Bytes::new())
41  }
42
43  /// Create a meta from a static str.
44  #[inline]
45  pub const fn from_static_str(s: &'static str) -> Result<Self, LargeMeta> {
46    if s.len() > Self::MAX_SIZE {
47      return Err(LargeMeta(s.len()));
48    }
49    Ok(Self(Bytes::from_static(s.as_bytes())))
50  }
51
52  /// Create a meta from a static bytes.
53  #[inline]
54  pub const fn from_static(s: &'static [u8]) -> Result<Self, LargeMeta> {
55    if s.len() > Self::MAX_SIZE {
56      return Err(LargeMeta(s.len()));
57    }
58    Ok(Self(Bytes::from_static(s)))
59  }
60
61  /// Returns the meta as a byte slice.
62  #[inline]
63  pub fn as_bytes(&self) -> &[u8] {
64    &self.0
65  }
66
67  /// Returns true if the meta is empty.
68  #[inline]
69  pub fn is_empty(&self) -> bool {
70    self.0.is_empty()
71  }
72
73  /// Returns the length of the meta in bytes.
74  #[inline]
75  pub fn len(&self) -> usize {
76    self.0.len()
77  }
78}
79
80impl AsRef<[u8]> for Meta {
81  fn as_ref(&self) -> &[u8] {
82    self.as_bytes()
83  }
84}
85
86impl core::ops::Deref for Meta {
87  type Target = [u8];
88
89  fn deref(&self) -> &Self::Target {
90    self.as_bytes()
91  }
92}
93
94impl core::cmp::PartialEq<[u8]> for Meta {
95  fn eq(&self, other: &[u8]) -> bool {
96    self.as_bytes().eq(other)
97  }
98}
99
100impl core::cmp::PartialEq<&[u8]> for Meta {
101  fn eq(&self, other: &&[u8]) -> bool {
102    self.as_bytes().eq(*other)
103  }
104}
105
106impl core::cmp::PartialEq<Bytes> for Meta {
107  fn eq(&self, other: &Bytes) -> bool {
108    self.as_bytes().eq(other.as_ref())
109  }
110}
111
112impl core::cmp::PartialEq<Vec<u8>> for Meta {
113  fn eq(&self, other: &Vec<u8>) -> bool {
114    self.as_bytes().eq(other.as_slice())
115  }
116}
117
118impl TryFrom<&str> for Meta {
119  type Error = LargeMeta;
120
121  fn try_from(s: &str) -> Result<Self, Self::Error> {
122    if s.len() > Self::MAX_SIZE {
123      return Err(LargeMeta(s.len()));
124    }
125    Ok(Self(Bytes::copy_from_slice(s.as_bytes())))
126  }
127}
128
129impl TryFrom<String> for Meta {
130  type Error = LargeMeta;
131
132  fn try_from(s: String) -> Result<Self, Self::Error> {
133    Meta::try_from(s.into_bytes())
134  }
135}
136
137impl TryFrom<Bytes> for Meta {
138  type Error = LargeMeta;
139
140  fn try_from(s: Bytes) -> Result<Self, Self::Error> {
141    if s.len() > Self::MAX_SIZE {
142      return Err(LargeMeta(s.len()));
143    }
144    Ok(Self(s))
145  }
146}
147
148impl TryFrom<Vec<u8>> for Meta {
149  type Error = LargeMeta;
150
151  fn try_from(s: Vec<u8>) -> Result<Self, Self::Error> {
152    Meta::try_from(Bytes::from(s))
153  }
154}
155
156impl TryFrom<&[u8]> for Meta {
157  type Error = LargeMeta;
158
159  fn try_from(s: &[u8]) -> Result<Self, Self::Error> {
160    if s.len() > Self::MAX_SIZE {
161      return Err(LargeMeta(s.len()));
162    }
163    Ok(Self(Bytes::copy_from_slice(s)))
164  }
165}
166
167impl TryFrom<&Bytes> for Meta {
168  type Error = LargeMeta;
169
170  fn try_from(s: &Bytes) -> Result<Self, Self::Error> {
171    if s.len() > Self::MAX_SIZE {
172      return Err(LargeMeta(s.len()));
173    }
174    Ok(Self(s.clone()))
175  }
176}
177
178impl TryFrom<BytesMut> for Meta {
179  type Error = LargeMeta;
180
181  fn try_from(s: BytesMut) -> Result<Self, Self::Error> {
182    if s.len() > Self::MAX_SIZE {
183      return Err(LargeMeta(s.len()));
184    }
185    Ok(Self(s.freeze()))
186  }
187}
188
189/// Meta error.
190#[derive(Debug, thiserror::Error)]
191pub enum MetaError {
192  /// Invalid meta.
193  #[error(transparent)]
194  LargeMeta(#[from] LargeMeta),
195  /// Not enough bytes to decode meta.
196  #[error("not enough bytes to decode meta")]
197  NotEnoughBytes,
198  /// Encode buffer too small.
199  #[error("the buffer did not contain enough bytes to encode meta")]
200  BufferTooSmall,
201}
202
203impl Transformable for Meta {
204  type Error = MetaError;
205
206  fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
207    let encoded_len = self.encoded_len();
208    if dst.len() < self.encoded_len() {
209      return Err(Self::Error::BufferTooSmall);
210    }
211
212    NetworkEndian::write_u16(dst, encoded_len as u16);
213    dst[2..encoded_len].copy_from_slice(self.as_bytes());
214    Ok(encoded_len)
215  }
216
217  fn encoded_len(&self) -> usize {
218    core::mem::size_of::<u16>() + self.len()
219  }
220
221  fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
222  where
223    Self: Sized,
224  {
225    if src.len() < core::mem::size_of::<u16>() {
226      return Err(Self::Error::NotEnoughBytes);
227    }
228
229    let len = NetworkEndian::read_u16(&src[0..2]) as usize;
230    if len > src.len() {
231      return Err(Self::Error::NotEnoughBytes);
232    }
233
234    Self::try_from(&src[2..len])
235      .map_err(Self::Error::LargeMeta)
236      .map(|meta| (len, meta))
237  }
238}
239
240#[cfg(test)]
241mod tests {
242  use super::*;
243
244  #[test]
245  fn test_try_from_string() {
246    let meta = Meta::try_from("hello".to_string()).unwrap();
247    assert_eq!(meta, Meta::from_static_str("hello").unwrap());
248    assert!(Meta::from_static([0; 513].as_slice()).is_err());
249  }
250
251  #[test]
252  fn test_try_from_bytes() {
253    let meta = Meta::try_from(Bytes::from("hello")).unwrap();
254    assert_eq!(meta, Bytes::from("hello"));
255
256    assert!(Meta::try_from(Bytes::from("a".repeat(513).into_bytes())).is_err());
257  }
258
259  #[test]
260  fn test_try_from_bytes_mut() {
261    let meta = Meta::try_from(BytesMut::from("hello")).unwrap();
262    assert_eq!(meta, "hello".as_bytes().to_vec());
263
264    assert!(Meta::try_from(BytesMut::from([0; 513].as_slice())).is_err());
265  }
266
267  #[test]
268  fn test_try_from_bytes_ref() {
269    let meta = Meta::try_from(&Bytes::from("hello")).unwrap();
270    assert_eq!(meta, "hello".as_bytes());
271
272    assert!(Meta::try_from(&Bytes::from("a".repeat(513).into_bytes())).is_err());
273  }
274
275  #[test]
276  fn test_default() {
277    let meta = Meta::default();
278    assert!(meta.is_empty());
279
280    assert_eq!(Meta::empty().as_ref(), &[]);
281  }
282}