cuprate_epee_encoding/
container_as_blob.rs1use alloc::{string::ToString, vec, vec::Vec};
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use ref_cast::RefCast;
5
6use crate::{error::*, EpeeValue, InnerMarker, Marker};
7
8#[derive(RefCast)]
9#[repr(transparent)]
10pub struct ContainerAsBlob<T: Containerable + EpeeValue>(Vec<T>);
11
12impl<T: Containerable + EpeeValue> From<Vec<T>> for ContainerAsBlob<T> {
13 fn from(value: Vec<T>) -> Self {
14 Self(value)
15 }
16}
17
18impl<T: Containerable + EpeeValue> From<ContainerAsBlob<T>> for Vec<T> {
19 fn from(value: ContainerAsBlob<T>) -> Self {
20 value.0
21 }
22}
23
24impl<'a, T: Containerable + EpeeValue> From<&'a Vec<T>> for &'a ContainerAsBlob<T> {
25 fn from(value: &'a Vec<T>) -> Self {
26 ContainerAsBlob::ref_cast(value)
27 }
28}
29
30impl<T: Containerable + EpeeValue> EpeeValue for ContainerAsBlob<T> {
31 const MARKER: Marker = Marker::new(InnerMarker::String);
32
33 fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
34 let bytes = Bytes::read(r, marker)?;
35 if bytes.len() % T::SIZE != 0 {
36 return Err(Error::Value(
37 "Can't convert blob container to Vec type.".to_string(),
38 ));
39 }
40
41 Ok(Self(bytes.chunks(T::SIZE).map(T::from_bytes).collect()))
42 }
43
44 fn should_write(&self) -> bool {
45 !self.0.is_empty()
46 }
47
48 fn epee_default_value() -> Option<Self> {
49 Some(Self(vec![]))
50 }
51
52 fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
53 let mut buf = BytesMut::with_capacity(self.0.len() * T::SIZE);
54 self.0.iter().for_each(|tt| tt.push_bytes(&mut buf));
55 buf.write(w)
56 }
57}
58
59pub trait Containerable {
60 const SIZE: usize;
61
62 fn from_bytes(bytes: &[u8]) -> Self;
66
67 fn push_bytes(&self, buf: &mut BytesMut);
68}
69
70macro_rules! int_container_able {
71 ($int:ty ) => {
72 impl Containerable for $int {
73 const SIZE: usize = size_of::<$int>();
74
75 fn from_bytes(bytes: &[u8]) -> Self {
76 <$int>::from_le_bytes(bytes.try_into().unwrap())
77 }
78
79 fn push_bytes(&self, buf: &mut BytesMut) {
80 buf.put_slice(&self.to_le_bytes())
81 }
82 }
83 };
84}
85
86int_container_able!(u16);
87int_container_able!(u32);
88int_container_able!(u64);
89int_container_able!(u128);
90
91int_container_able!(i8);
92int_container_able!(i16);
93int_container_able!(i32);
94int_container_able!(i64);
95int_container_able!(i128);