1use std::string::ToString;
32
33#[derive(Debug, Clone, PartialEq, Eq)]
37pub enum DecodeError {
38 Truncated { field: &'static str, need: usize, have: usize },
40 LengthOverflow { field: &'static str, len: u64, remaining: usize },
42 BadTag { field: &'static str, tag: u8 },
44 NotUtf8 { field: &'static str },
46 TrailingBytes { field: &'static str, left: usize },
49}
50
51impl core::fmt::Display for DecodeError {
52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53 match self {
54 DecodeError::Truncated { field, need, have } => write!(
55 f,
56 "ABI decode: truncated reading `{field}` — need {need} bytes, {have} left"
57 ),
58 DecodeError::LengthOverflow { field, len, remaining } => write!(
59 f,
60 "ABI decode: `{field}` declares {len} bytes but only {remaining} remain"
61 ),
62 DecodeError::BadTag { field, tag } => {
63 write!(f, "ABI decode: `{field}` carries invalid tag byte {tag}")
64 }
65 DecodeError::NotUtf8 { field } => write!(f, "ABI decode: `{field}` is not UTF-8"),
66 DecodeError::TrailingBytes { field, left } => write!(
67 f,
68 "ABI decode: {left} trailing byte(s) after `{field}` — encoder and decoder \
69 disagree about the shape"
70 ),
71 }
72 }
73}
74
75#[derive(Default)]
77pub struct Writer {
78 buf: Vec<u8>,
79}
80
81impl Writer {
82 pub fn new() -> Self {
83 Self { buf: Vec::new() }
84 }
85
86 pub fn finish(self) -> Vec<u8> {
87 self.buf
88 }
89
90 pub fn u8(&mut self, v: u8) -> &mut Self {
91 self.buf.push(v);
92 self
93 }
94
95 pub fn u16(&mut self, v: u16) -> &mut Self {
96 self.buf.extend_from_slice(&v.to_le_bytes());
97 self
98 }
99
100 pub fn u32(&mut self, v: u32) -> &mut Self {
101 self.buf.extend_from_slice(&v.to_le_bytes());
102 self
103 }
104
105 pub fn u64(&mut self, v: u64) -> &mut Self {
106 self.buf.extend_from_slice(&v.to_le_bytes());
107 self
108 }
109
110 pub fn i64(&mut self, v: i64) -> &mut Self {
111 self.buf.extend_from_slice(&v.to_le_bytes());
112 self
113 }
114
115 pub fn bool(&mut self, v: bool) -> &mut Self {
116 self.buf.push(u8::from(v));
117 self
118 }
119
120 pub fn bytes(&mut self, v: &[u8]) -> &mut Self {
123 self.u32(v.len() as u32);
124 self.buf.extend_from_slice(v);
125 self
126 }
127
128 pub fn str(&mut self, v: &str) -> &mut Self {
129 self.bytes(v.as_bytes())
130 }
131
132 pub fn opt_str(&mut self, v: Option<&str>) -> &mut Self {
134 match v {
135 None => self.u8(0),
136 Some(s) => self.u8(1).str(s),
137 }
138 }
139
140 pub fn opt_bytes(&mut self, v: Option<&[u8]>) -> &mut Self {
141 match v {
142 None => self.u8(0),
143 Some(b) => self.u8(1).bytes(b),
144 }
145 }
146}
147
148pub struct Reader<'a> {
150 buf: &'a [u8],
151 pos: usize,
152}
153
154impl<'a> Reader<'a> {
155 pub fn new(buf: &'a [u8]) -> Self {
156 Self { buf, pos: 0 }
157 }
158
159 pub fn remaining(&self) -> usize {
160 self.buf.len() - self.pos
161 }
162
163 pub fn expect_end(&self, field: &'static str) -> Result<(), DecodeError> {
168 if self.remaining() == 0 {
169 Ok(())
170 } else {
171 Err(DecodeError::TrailingBytes { field, left: self.remaining() })
172 }
173 }
174
175 fn take(&mut self, n: usize, field: &'static str) -> Result<&'a [u8], DecodeError> {
176 if self.remaining() < n {
177 return Err(DecodeError::Truncated { field, need: n, have: self.remaining() });
178 }
179 let out = &self.buf[self.pos..self.pos + n];
180 self.pos += n;
181 Ok(out)
182 }
183
184 pub fn u8(&mut self, field: &'static str) -> Result<u8, DecodeError> {
185 Ok(self.take(1, field)?[0])
186 }
187
188 pub fn u16(&mut self, field: &'static str) -> Result<u16, DecodeError> {
189 let b = self.take(2, field)?;
190 Ok(u16::from_le_bytes([b[0], b[1]]))
191 }
192
193 pub fn u32(&mut self, field: &'static str) -> Result<u32, DecodeError> {
194 let b = self.take(4, field)?;
195 Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
196 }
197
198 pub fn u64(&mut self, field: &'static str) -> Result<u64, DecodeError> {
199 let b = self.take(8, field)?;
200 let mut a = [0u8; 8];
201 a.copy_from_slice(b);
202 Ok(u64::from_le_bytes(a))
203 }
204
205 pub fn i64(&mut self, field: &'static str) -> Result<i64, DecodeError> {
206 Ok(self.u64(field)? as i64)
207 }
208
209 pub fn bool(&mut self, field: &'static str) -> Result<bool, DecodeError> {
210 match self.u8(field)? {
211 0 => Ok(false),
212 1 => Ok(true),
213 tag => Err(DecodeError::BadTag { field, tag }),
214 }
215 }
216
217 pub fn bytes(&mut self, field: &'static str) -> Result<Vec<u8>, DecodeError> {
218 let len = self.u32(field)? as usize;
219 if len > self.remaining() {
220 return Err(DecodeError::LengthOverflow {
221 field,
222 len: len as u64,
223 remaining: self.remaining(),
224 });
225 }
226 Ok(self.take(len, field)?.to_vec())
227 }
228
229 pub fn str(&mut self, field: &'static str) -> Result<String, DecodeError> {
230 let b = self.bytes(field)?;
231 String::from_utf8(b).map_err(|_| DecodeError::NotUtf8 { field })
232 }
233
234 pub fn opt_str(&mut self, field: &'static str) -> Result<Option<String>, DecodeError> {
235 match self.u8(field)? {
236 0 => Ok(None),
237 1 => Ok(Some(self.str(field)?)),
238 tag => Err(DecodeError::BadTag { field, tag }),
239 }
240 }
241
242 pub fn opt_bytes(&mut self, field: &'static str) -> Result<Option<Vec<u8>>, DecodeError> {
243 match self.u8(field)? {
244 0 => Ok(None),
245 1 => Ok(Some(self.bytes(field)?)),
246 tag => Err(DecodeError::BadTag { field, tag }),
247 }
248 }
249
250 pub fn count(&mut self, field: &'static str) -> Result<usize, DecodeError> {
253 let n = self.u32(field)? as usize;
254 if n > self.remaining() {
255 return Err(DecodeError::LengthOverflow {
256 field,
257 len: n as u64,
258 remaining: self.remaining(),
259 });
260 }
261 Ok(n)
262 }
263}
264
265pub fn write_result<T>(w: &mut Writer, v: &Result<T, String>, ok: impl FnOnce(&mut Writer, &T)) {
267 match v {
268 Ok(t) => {
269 w.u8(0);
270 ok(w, t);
271 }
272 Err(e) => {
273 w.u8(1);
274 w.str(e);
275 }
276 }
277}
278
279pub fn read_result<T>(
281 r: &mut Reader<'_>,
282 field: &'static str,
283 ok: impl FnOnce(&mut Reader<'_>) -> Result<T, DecodeError>,
284) -> Result<Result<T, String>, DecodeError> {
285 match r.u8(field)? {
286 0 => Ok(Ok(ok(r)?)),
287 1 => Ok(Err(r.str(field)?)),
288 tag => Err(DecodeError::BadTag { field, tag }),
289 }
290}
291
292impl DecodeError {
293 pub fn message(&self) -> String {
295 self.to_string()
296 }
297}