1use smol_str::SmolStr;
2
3use super::{Data, DataRef, DecodeError, EncodeError, WireType, merge, skip};
4
5#[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 pub fn new(message: impl Into<SmolStr>) -> Self {
32 Self {
33 message: message.into(),
34 }
35 }
36
37 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#[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 #[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}