memberlist_types/
err.rs

1use smol_str::SmolStr;
2use transformable::Transformable;
3
4/// Error response from the remote peer
5#[viewit::viewit(
6  vis_all = "pub(crate)",
7  getters(vis_all = "pub"),
8  setters(vis_all = "pub", prefix = "with")
9)]
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
12#[cfg_attr(feature = "serde", serde(transparent))]
13#[cfg_attr(
14  feature = "rkyv",
15  derive(::rkyv::Serialize, ::rkyv::Deserialize, ::rkyv::Archive)
16)]
17#[cfg_attr(
18  feature = "rkyv",
19  rkyv(derive(Debug, PartialEq, Eq, Hash), compare(PartialEq))
20)]
21#[repr(transparent)]
22pub struct ErrorResponse {
23  #[viewit(
24    getter(
25      const,
26      style = "ref",
27      attrs(doc = "Returns the msg of the error response")
28    ),
29    setter(attrs(doc = "Sets the msg of the error response (Builder pattern)"))
30  )]
31  message: SmolStr,
32}
33
34impl ErrorResponse {
35  /// Create a new error response
36  pub fn new(message: impl Into<SmolStr>) -> Self {
37    Self {
38      message: message.into(),
39    }
40  }
41
42  /// Returns the msg of the error response
43  pub fn set_message(&mut self, msg: impl Into<SmolStr>) -> &mut Self {
44    self.message = msg.into();
45    self
46  }
47}
48
49impl core::fmt::Display for ErrorResponse {
50  fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51    write!(f, "{}", self.message)
52  }
53}
54
55impl std::error::Error for ErrorResponse {}
56
57impl From<ErrorResponse> for SmolStr {
58  fn from(err: ErrorResponse) -> Self {
59    err.message
60  }
61}
62
63impl From<SmolStr> for ErrorResponse {
64  fn from(msg: SmolStr) -> Self {
65    Self { message: msg }
66  }
67}
68
69impl Transformable for ErrorResponse {
70  type Error = <SmolStr as Transformable>::Error;
71
72  fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
73    self.message.encode(dst)
74  }
75
76  fn encoded_len(&self) -> usize {
77    self.message.encoded_len()
78  }
79
80  fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
81  where
82    Self: Sized,
83  {
84    let (len, message) = SmolStr::decode(src)?;
85    Ok((len, Self { message }))
86  }
87
88  async fn encode_to_async_writer<W: futures::io::AsyncWrite + Send + Unpin>(
89    &self,
90    writer: &mut W,
91  ) -> std::io::Result<usize> {
92    <SmolStr as Transformable>::encode_to_async_writer(&self.message, writer).await
93  }
94
95  fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
96    <SmolStr as Transformable>::encode_to_writer(&self.message, writer)
97  }
98
99  fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
100  where
101    Self: Sized,
102  {
103    <SmolStr as Transformable>::decode_from_reader(reader).map(|(n, message)| (n, Self { message }))
104  }
105
106  async fn decode_from_async_reader<R: futures::io::AsyncRead + Send + Unpin>(
107    reader: &mut R,
108  ) -> std::io::Result<(usize, Self)>
109  where
110    Self: Sized,
111  {
112    <SmolStr as Transformable>::decode_from_async_reader(reader)
113      .await
114      .map(|(n, message)| (n, Self { message }))
115  }
116}
117
118#[cfg(test)]
119const _: () = {
120  use rand::{distr::Alphanumeric, Rng};
121
122  impl ErrorResponse {
123    fn generate(size: usize) -> Self {
124      let rng = rand::rng();
125      let err = rng
126        .sample_iter(&Alphanumeric)
127        .take(size)
128        .collect::<Vec<u8>>();
129      let err = String::from_utf8(err).unwrap();
130      Self::new(err)
131    }
132  }
133};
134
135#[cfg(test)]
136mod tests {
137  use super::*;
138
139  #[test]
140  fn test_error_response() {
141    for i in 0..100 {
142      let err = ErrorResponse::generate(i);
143      let mut buf = vec![0; err.encoded_len()];
144      let encoded_len = err.encode(&mut buf).unwrap();
145      assert_eq!(encoded_len, err.encoded_len());
146      let (decoded_len, decoded) = ErrorResponse::decode(&buf).unwrap();
147      assert_eq!(decoded_len, encoded_len);
148      assert_eq!(decoded, err);
149    }
150  }
151}