dusk-cdf 0.1.0

PLONK debugger CDF implementation
Documentation
mod fixed_text;
mod impls;
mod scalar;

use std::io;

use crate::{Config, Context, ContextUnit, Preamble};

pub use fixed_text::FixedText;
pub use scalar::Scalar;

/// Describe a CDF element
pub trait Element: Sized {
    /// Configuration for the serialization and deserialization
    type Config: for<'a> From<&'a Config>;

    /// A zeroed/default instance of the type.
    fn zeroed() -> Self;

    /// Serializable length
    ///
    /// Every element is a function of the config so seek/lookups will be constant-time.
    ///
    /// The serialized type must not contain more bytes than specified here. However, it might,
    /// optionally, use less bytes. Regardless, it will consume this defined amount of bytes during
    /// serialization.
    fn len(config: &Self::Config) -> usize;

    /// Write the type into the buffer.
    ///
    /// # Panics
    ///
    /// The buffer must, provided a correct definition of [`Element::len`], contain enough bytes to
    /// fully serialize the type. This can be checkedvia [`Element::validate_buffer_len`].
    fn to_buffer(&self, config: &Self::Config, context: &mut ContextUnit, buf: &mut [u8]);

    /// Deserialize the type from a given buffer
    ///
    /// As in [`Self::to_buffer`] the implementor of this function can assume the buffer is big
    /// enough to contain all the required bytes.
    fn try_from_buffer_in_place<S>(
        &mut self,
        config: &Self::Config,
        context: &mut Context<S>,
        buf: &[u8],
    ) -> io::Result<()>
    where
        S: io::Read + io::Seek;

    /// Perform the internal validations of the associated element
    fn validate(&self, preamble: &Preamble) -> io::Result<()>;

    /// Assert the buffer is big enough to store the type
    fn validate_buffer_len(config: &Self::Config, len: usize) -> io::Result<()> {
        if len < Self::len(config) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "the provided buffer isn't big enough",
            ));
        }

        Ok(())
    }

    /// Serialize the object into a bytes array.
    fn to_vec(&self, config: &Self::Config, context: &mut ContextUnit) -> Vec<u8> {
        let mut bytes = vec![0u8; Self::len(config)];

        self.to_buffer(config, context, &mut bytes);

        bytes
    }

    /// Create a new instance of the type from the provided buffer
    fn try_from_buffer<S>(
        config: &Self::Config,
        context: &mut Context<S>,
        buf: &[u8],
    ) -> io::Result<Self>
    where
        S: io::Read + io::Seek,
    {
        let mut slf = Self::zeroed();

        slf.try_from_buffer_in_place(config, context, buf)?;

        Ok(slf)
    }

    /// Write an element from the buffer, and return the remainder bytes
    ///
    /// Assume its inside a validate buffer context
    fn try_decode_in_place<'a, S>(
        &mut self,
        config: &Self::Config,
        context: &mut Context<S>,
        buf: &'a [u8],
    ) -> io::Result<&'a [u8]>
    where
        S: io::Read + io::Seek,
    {
        self.try_from_buffer_in_place(config, context, buf)
            .map(|_| &buf[Self::len(config)..])
    }

    /// Write an element from the buffer, and return the remainder bytes
    ///
    /// Assume its inside a validate buffer context
    fn try_decode<'a, S>(
        config: &Self::Config,
        context: &mut Context<S>,
        buf: &'a [u8],
    ) -> io::Result<(Self, &'a [u8])>
    where
        S: io::Read + io::Seek,
    {
        let mut slf = Self::zeroed();

        let buf = slf.try_decode_in_place(config, context, buf)?;

        Ok((slf, buf))
    }

    /// Read an element into the buffer, returning the remainder bytes
    ///
    /// Assume its inside a validate buffer context
    fn encode<'a>(
        &self,
        config: &Self::Config,
        context: &mut ContextUnit,
        buf: &'a mut [u8],
    ) -> &'a mut [u8] {
        self.to_buffer(config, context, buf);

        &mut buf[Self::len(config)..]
    }

    /// Send the bytes representation of an element to a writer
    fn try_to_writer<W>(
        &self,
        mut writer: W,
        config: &Self::Config,
        context: &mut ContextUnit,
    ) -> io::Result<usize>
    where
        W: io::Write,
    {
        writer.write(&self.to_vec(config, context))
    }

    /// Fetch a new element from a context
    fn try_from_context<S>(config: &Self::Config, context: &mut Context<S>) -> io::Result<Self>
    where
        S: io::Read + io::Seek,
    {
        let mut slf = vec![0u8; Self::len(config)];

        context
            .source()
            .ok_or_else(|| {
                io::Error::new(io::ErrorKind::Other, "no reader available in the context")
            })
            .and_then(|r| r.read(&mut slf))?;

        Self::try_from_buffer(config, context, &slf)
    }
}