memberlist_proto/
err.rs

1use smol_str::SmolStr;
2
3use super::{Data, DataRef, DecodeError, EncodeError, WireType, merge, skip};
4
5/// Error response from the remote peer
6#[viewit::viewit(
7  vis_all = "pub(crate)",
8  getters(vis_all = "pub"),
9  setters(vis_all = "pub", prefix = "with")
10)]
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
13#[repr(transparent)]
14pub struct ErrorResponse {
15  #[viewit(
16    getter(
17      const,
18      style = "ref",
19      attrs(doc = "Returns the msg of the error response")
20    ),
21    setter(attrs(doc = "Sets the msg of the error response (Builder pattern)"))
22  )]
23  message: SmolStr,
24}
25
26impl ErrorResponse {
27  const MESSAGE_TAG: u8 = 1;
28  const MESSAGE_BYTE: u8 = merge(WireType::LengthDelimited, Self::MESSAGE_TAG);
29
30  /// Create a new error response
31  pub fn new(message: impl Into<SmolStr>) -> Self {
32    Self {
33      message: message.into(),
34    }
35  }
36
37  /// Returns the msg of the error response
38  pub fn set_message(&mut self, msg: impl Into<SmolStr>) -> &mut Self {
39    self.message = msg.into();
40    self
41  }
42}
43
44impl Data for ErrorResponse {
45  type Ref<'a> = ErrorResponseRef<'a>;
46
47  fn from_ref(val: Self::Ref<'_>) -> Result<Self, DecodeError>
48  where
49    Self: Sized,
50  {
51    Ok(Self {
52      message: val.message.into(),
53    })
54  }
55
56  fn encoded_len(&self) -> usize {
57    1 + self.message.encoded_len_with_length_delimited()
58  }
59
60  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
61    let mut offset = 0;
62    if buf.is_empty() {
63      return Err(EncodeError::insufficient_buffer(self.encoded_len(), 0));
64    }
65
66    buf[offset] = Self::MESSAGE_BYTE;
67    offset += 1;
68    offset += self.message.encode_length_delimited(&mut buf[offset..])?;
69    #[cfg(debug_assertions)]
70    super::debug_assert_write_eq::<Self>(offset, self.encoded_len());
71    Ok(offset)
72  }
73}
74
75impl core::fmt::Display for ErrorResponse {
76  fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
77    write!(f, "{}", self.message)
78  }
79}
80
81impl std::error::Error for ErrorResponse {}
82
83impl From<ErrorResponse> for SmolStr {
84  fn from(err: ErrorResponse) -> Self {
85    err.message
86  }
87}
88
89impl From<SmolStr> for ErrorResponse {
90  fn from(msg: SmolStr) -> Self {
91    Self { message: msg }
92  }
93}
94
95/// Reference type of error response from the remote peer
96#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
97#[repr(transparent)]
98pub struct ErrorResponseRef<'a> {
99  message: &'a str,
100}
101
102impl<'a> ErrorResponseRef<'a> {
103  /// Returns message of the error response
104  #[inline]
105  pub const fn message(&self) -> &'a str {
106    self.message
107  }
108}
109
110impl<'a> DataRef<'a, ErrorResponse> for ErrorResponseRef<'a> {
111  fn decode(src: &'a [u8]) -> Result<(usize, Self), DecodeError>
112  where
113    Self: Sized,
114  {
115    let mut offset = 0;
116    let mut msg = None;
117
118    while offset < src.len() {
119      match src[offset] {
120        ErrorResponse::MESSAGE_BYTE => {
121          if msg.is_some() {
122            return Err(DecodeError::duplicate_field(
123              "ErrorResponse",
124              "msg",
125              ErrorResponse::MESSAGE_TAG,
126            ));
127          }
128          offset += 1;
129
130          let (bytes_read, value) =
131            <&str as DataRef<SmolStr>>::decode_length_delimited(&src[offset..])?;
132          offset += bytes_read;
133          msg = Some(value);
134        }
135        _ => offset += skip("ErrorResponse", &src[offset..])?,
136      }
137    }
138
139    Ok((
140      offset,
141      Self {
142        message: msg.unwrap_or_default(),
143      },
144    ))
145  }
146}
147
148#[cfg(test)]
149mod tests {
150  use arbitrary::{Arbitrary, Unstructured};
151
152  use super::*;
153
154  #[test]
155  fn test_access() {
156    let mut data = vec![0; 1024];
157    rand::fill(&mut data[..]);
158
159    let mut data = Unstructured::new(&data);
160    let err = ErrorResponse::arbitrary(&mut data).unwrap();
161    assert_eq!(err.message(), &err.message);
162  }
163}