cuprate_epee_encoding/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
2#[cfg(test)]
63use hex as _;
64
65extern crate alloc;
66
67use alloc::string::ToString;
68use core::str::from_utf8 as str_from_utf8;
69
70use bytes::{Buf, BufMut, Bytes, BytesMut};
71
72pub mod container_as_blob;
73pub mod error;
74mod io;
75pub mod macros;
76pub mod marker;
77mod value;
78mod varint;
79
80pub use error::*;
81use io::*;
82pub use marker::{InnerMarker, Marker};
83pub use value::{EpeeValue, EpeeValueLimits};
84pub use varint::{read_varint, write_varint};
85
86const HEADER: &[u8] = b"\x01\x11\x01\x01\x01\x01\x02\x01\x01";
89const MAX_STRING_LEN_POSSIBLE: usize = 2000000000;
91const MAX_DEPTH_OF_SKIPPED_OBJECTS: u8 = 20;
93const MAX_NUM_FIELDS: u64 = 1000;
95
96pub trait EpeeObjectBuilder<T>: Default + Sized {
98 fn add_field<B: Buf>(&mut self, name: &str, b: &mut B) -> Result<bool>;
104
105 fn finish(self) -> Result<T>;
107}
108
109pub trait EpeeObject: Sized {
111 type Builder: EpeeObjectBuilder<Self>;
112
113 fn number_of_fields(&self) -> u64;
115
116 fn write_fields<B: BufMut>(self, w: &mut B) -> Result<()>;
118}
119
120pub fn from_bytes<T: EpeeObject, B: Buf>(buf: &mut B) -> Result<T> {
122 read_head_object(buf)
123}
124
125pub fn to_bytes<T: EpeeObject>(val: T) -> Result<BytesMut> {
127 let mut buf = BytesMut::new();
128 write_head_object(val, &mut buf)?;
129 Ok(buf)
130}
131
132fn read_header<B: Buf>(r: &mut B) -> Result<()> {
133 let buf = checked_read(r, |b: &mut B| b.copy_to_bytes(HEADER.len()), HEADER.len())?;
134
135 if &*buf != HEADER {
136 return Err(Error::Format("Data does not contain header"));
137 }
138 Ok(())
139}
140
141fn write_header<B: BufMut>(w: &mut B) -> Result<()> {
142 checked_write(w, BufMut::put_slice, HEADER, HEADER.len())
143}
144
145fn write_head_object<T: EpeeObject, B: BufMut>(val: T, w: &mut B) -> Result<()> {
146 write_header(w)?;
147 val.write(w)
148}
149
150fn read_head_object<T: EpeeObject, B: Buf>(r: &mut B) -> Result<T> {
151 read_header(r)?;
152 let mut skipped_objects = 0;
153 read_object(r, &mut skipped_objects)
154}
155
156fn read_field_name_bytes<B: Buf>(r: &mut B) -> Result<Bytes> {
157 let len: usize = checked_read_primitive(r, Buf::get_u8)?.into();
158
159 if len == 0 {
160 return Err(Error::Format("Field name has a length of 0"));
161 }
162
163 checked_read(r, |b: &mut B| b.copy_to_bytes(len), len)
164}
165
166fn write_field_name<B: BufMut>(val: &str, w: &mut B) -> Result<()> {
167 checked_write_primitive(w, BufMut::put_u8, val.len().try_into()?)?;
168 let slice = val.as_bytes();
169 checked_write(w, BufMut::put_slice, slice, slice.len())
170}
171
172pub fn write_field<T: EpeeValue, B: BufMut>(val: T, field_name: &str, w: &mut B) -> Result<()> {
174 if val.should_write() {
175 write_field_name(field_name, w)?;
176 write_epee_value(val, w)?;
177 }
178 Ok(())
179}
180
181fn read_object<T: EpeeObject, B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<T> {
182 let mut object_builder = T::Builder::default();
183
184 let number_o_field = read_varint(r)?;
185
186 if number_o_field > MAX_NUM_FIELDS {
187 return Err(Error::Format(
188 "Data has object with more fields than the maximum allowed",
189 ));
190 }
191
192 for _ in 0..number_o_field {
193 let field_name_bytes = read_field_name_bytes(r)?;
194 let field_name = str_from_utf8(&field_name_bytes)?;
195
196 if !object_builder.add_field(field_name, r)? {
197 skip_epee_value(r, skipped_objects)?;
198 }
199 }
200 object_builder.finish()
201}
202
203pub fn read_marker<B: Buf>(r: &mut B) -> Result<Marker> {
206 Marker::try_from(checked_read_primitive(r, Buf::get_u8)?)
207}
208
209pub fn read_epee_value<T: EpeeValue, B: Buf>(r: &mut B, limits: EpeeValueLimits) -> Result<T> {
212 let marker = read_marker(r)?;
213 T::read(r, &marker, limits)
214}
215
216fn write_epee_value<T: EpeeValue, B: BufMut>(val: T, w: &mut B) -> Result<()> {
219 checked_write_primitive(w, BufMut::put_u8, T::MARKER.as_u8())?;
220 val.write(w)
221}
222
223pub fn write_bytes<T: AsRef<[u8]>, B: BufMut>(t: T, w: &mut B) -> Result<()> {
250 let bytes = t.as_ref();
251 let len = bytes.len();
252
253 write_varint(len, w)?;
254
255 if w.remaining_mut() < len {
256 return Err(Error::IO("Not enough capacity to write bytes"));
257 }
258
259 w.put_slice(bytes);
260
261 Ok(())
262}
263
264pub fn write_iterator<T, I, B>(iterator: I, w: &mut B) -> Result<()>
292where
293 T: EpeeValue,
294 I: Iterator<Item = T> + ExactSizeIterator,
295 B: BufMut,
296{
297 write_varint(iterator.len(), w)?;
298 for item in iterator {
299 item.write(w)?;
300 }
301 Ok(())
302}
303
304#[derive(Default)]
306struct SkipObjectBuilder;
307
308impl EpeeObjectBuilder<SkipObject> for SkipObjectBuilder {
309 fn add_field<B: Buf>(&mut self, _name: &str, _r: &mut B) -> Result<bool> {
310 Ok(false)
311 }
312
313 fn finish(self) -> Result<SkipObject> {
314 Ok(SkipObject)
315 }
316}
317
318struct SkipObject;
320
321impl EpeeObject for SkipObject {
322 type Builder = SkipObjectBuilder;
323
324 fn number_of_fields(&self) -> u64 {
325 panic!("This is a helper function to use when de-serialising")
326 }
327
328 fn write_fields<B: BufMut>(self, _w: &mut B) -> Result<()> {
329 panic!("This is a helper function to use when de-serialising")
330 }
331}
332
333fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
336 let marker = read_marker(r)?;
337
338 let len = if marker.is_seq { read_varint(r)? } else { 1 };
339
340 if let Some(size) = marker.inner_marker.size() {
341 let bytes_to_skip = size
342 .checked_mul(len.try_into()?)
343 .ok_or(Error::Value("List is too big".to_string()))?;
344 return advance(bytes_to_skip, r);
345 }
346
347 for _ in 0..len {
348 match marker.inner_marker {
349 InnerMarker::I64
350 | InnerMarker::U64
351 | InnerMarker::F64
352 | InnerMarker::I32
353 | InnerMarker::U32
354 | InnerMarker::I16
355 | InnerMarker::U16
356 | InnerMarker::I8
357 | InnerMarker::U8
358 | InnerMarker::Bool => unreachable!("These types are constant size."),
359 InnerMarker::String => {
360 let len = read_varint(r)?;
361 advance(len, r)?;
362 }
363 InnerMarker::Object => {
364 *skipped_objects += 1;
365 if *skipped_objects > MAX_DEPTH_OF_SKIPPED_OBJECTS {
366 return Err(Error::Format("Depth of skipped objects exceeded maximum"));
367 }
368 read_object::<SkipObject, _>(r, skipped_objects)?;
369 *skipped_objects -= 1;
370 }
371 }
372 }
373 Ok(())
374}
375
376fn advance<B: Buf>(n: usize, b: &mut B) -> Result<()> {
377 checked_read(b, |b: &mut B| b.advance(n), n)
378}
379
380const fn max_upfront_capacity<T>() -> usize {
385 2_000_000 / size_of::<T>()
386}