Skip to content

custom error via associated type #589

@carlocorradini

Description

@carlocorradini

Add an associated type Error to traits (should impl From<DekuError>).
This allows users to customize the returned error, enhancing the overall developer experience.
If the traits are derived using procedural macros, the default value is DekuError (type Error = DekuError).

DekuReader:

pub trait DekuReader<'a, Ctx = ()> {
    type Error: From<DekuError>;

    fn from_reader_with_ctx<R: no_std_io::Read + no_std_io::Seek>(
        reader: &mut Reader<R>,
        ctx: Ctx,
    ) -> Result<Self, Self::Error>
    where
        Self: Sized;
}

DekuWriter:

pub trait DekuWriter<Ctx = ()> {
    type Error: From<DekuError>;

    fn to_writer<W: no_std_io::Write + no_std_io::Seek>(
        &self,
        writer: &mut Writer<W>,
        ctx: Ctx,
    ) -> Result<(), Self::Error>;
}

The latter also applies to their container (DekuContainerRead and DekuContainerWrite).

Example:

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("deku: {0}")]
    Deku(#[from] deku::DekuError),
    #[error("id {0} is not even")]
    Id(u8),
    #[error("size {0} is not odd")]
    Size(u8),
}

#[derive(Debug, Clone)]
pub struct Header {
    id: u8,
    size: u8,
}

impl DekuReader<'_> for Header {
    type Error = Error;

    fn from_reader_with_ctx<R: Read + Seek>(
        reader: &mut Reader<R>,
        _: (),
    ) -> Result<Self, Self::Error> {
        // Identifier
        let id = u8::from_reader_with_ctx(reader, ())?;
        if id % 2 != 0 { return Err(Self::Error::Id(id)); } // Check

        // Size
        let size = u8::from_reader_with_ctx(reader, ())?;
        if size % 2 != 1 { return Err(Self::Error::Size(size)); } // Check

        Ok(Self{ id, size })
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions