memberlist_proto/
meta.rs

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