dusk_cdf/
element.rs

1mod impls;
2mod scalar;
3
4#[cfg(test)]
5mod tests;
6
7use std::io;
8
9use crate::{Config, DecoderContext, EncoderContext, Preamble};
10
11pub use scalar::Scalar;
12
13/// Element that can be encoded into a CDF file
14pub trait EncodableElement: Element {
15    /// Write the type into the buffer.
16    ///
17    /// # Panics
18    ///
19    /// The buffer must, provided a correct definition of [`Element::len`], contain enough bytes to
20    /// fully serialize the type. This can be checked via [`Element::validate_buffer`].
21    fn to_buffer(&self, ctx: &mut EncoderContext, buf: &mut [u8]);
22
23    /// Serialize the object into a bytes array.
24    fn to_vec(&self, ctx: &mut EncoderContext) -> Vec<u8> {
25        let len = Self::len(ctx.config());
26        let mut bytes = vec![0u8; len];
27
28        self.to_buffer(ctx, &mut bytes);
29
30        bytes
31    }
32
33    /// Read an element into the buffer, returning the remainder bytes
34    ///
35    /// Assume its inside a validate buffer context
36    fn encode<'a>(&self, ctx: &mut EncoderContext, buf: &'a mut [u8]) -> &'a mut [u8] {
37        self.to_buffer(ctx, buf);
38
39        &mut buf[Self::len(ctx.config())..]
40    }
41
42    /// Send the bytes representation of an element to a writer
43    fn try_to_writer<W>(&self, mut writer: W, ctx: &mut EncoderContext) -> io::Result<usize>
44    where
45        W: io::Write,
46    {
47        writer.write(&self.to_vec(ctx))
48    }
49}
50
51/// Element that can be decoded from a CDF file
52pub trait DecodableElement: Sized + Element {
53    /// Deserialize the type from a given buffer
54    ///
55    /// As in [`EncodableElement::to_buffer`] the implementor of this function can assume the buffer is big
56    /// enough to contain all the required bytes.
57    fn try_from_buffer_in_place<'a, 'b>(
58        &'a mut self,
59        ctx: &DecoderContext<'a>,
60        buf: &'b [u8],
61    ) -> io::Result<()>;
62
63    /// Create a new instance of the type from the provided buffer
64    fn try_from_buffer<'b>(ctx: &DecoderContext, buf: &'b [u8]) -> io::Result<Self> {
65        let mut slf = Self::default();
66
67        slf.try_from_buffer_in_place(ctx, buf)?;
68
69        Ok(slf)
70    }
71
72    /// Write an element from the buffer, and return the remainder bytes
73    ///
74    /// Assume its inside a validate buffer context
75    fn try_decode_in_place<'a, 'b>(
76        &mut self,
77        ctx: &DecoderContext<'a>,
78        buf: &'b [u8],
79    ) -> io::Result<&'b [u8]> {
80        self.try_from_buffer_in_place(ctx, buf)
81            .map(|_| &buf[Self::len(ctx.config())..])
82    }
83
84    /// Write an element from the buffer, and return the remainder bytes
85    ///
86    /// Assume its inside a validate buffer context
87    fn try_decode<'a, 'b>(ctx: &DecoderContext<'a>, buf: &'b [u8]) -> io::Result<(Self, &'b [u8])> {
88        let mut slf = Self::default();
89
90        let buf = slf.try_decode_in_place(ctx, buf)?;
91
92        Ok((slf, buf))
93    }
94
95    /// Fetch a new element from a context
96    fn try_from_reader<R>(ctx: &DecoderContext, mut reader: R) -> io::Result<Self>
97    where
98        R: io::Read,
99    {
100        let mut slf = vec![0u8; Self::len(ctx.config())];
101
102        let _ = reader.read(&mut slf)?;
103
104        Self::try_from_buffer(ctx, &slf)
105    }
106}
107
108/// Describe a CDF element
109pub trait Element: Default {
110    /// Serializable length
111    ///
112    /// Every element is a function of the config so seek/lookups will be constant-time.
113    ///
114    /// The serialized type must not contain more bytes than specified here. However, it might,
115    /// optionally, use less bytes. Regardless, it will consume this defined amount of bytes during
116    /// serialization.
117    fn len(ctx: &Config) -> usize;
118
119    /// Perform the internal validations of the associated element
120    fn validate(&self, preamble: &Preamble) -> io::Result<()>;
121
122    /// Assert the buffer is big enough to store the type
123    fn validate_buffer(config: &Config, buffer: &[u8]) -> io::Result<()> {
124        if buffer.len() < Self::len(config) {
125            return Err(io::Error::new(
126                io::ErrorKind::InvalidData,
127                "the provided buffer isn't big enough",
128            ));
129        }
130
131        Ok(())
132    }
133}