nettext 0.4.1

A text-based data format for cryptographic network protocols
Documentation
use err_derive::Error;

use crate::dec::debug;

/// The type of errors returned by helper functions on `Term`
#[derive(Debug, Clone, Error)]
pub enum TypeError {
    /// The term could not be decoded in the given type
    #[error(display = "Not a {}", _0)]
    WrongType(&'static str),
    /// The term did not have the correct marker
    #[error(display = "Byte marker was not {}", _0)]
    WrongMarker(&'static str),

    /// The term is not an array of the requested length
    #[error(display = "Expected {} items, got {}", _0, _1)]
    WrongLength(usize, usize),

    /// The dictionnary is missing a key
    #[error(display = "Missing key `{}` in dict", _0)]
    MissingKey(String),
    /// The dictionnary contains an invalid key
    #[error(display = "Spurrious/unexpected key `{}` in dict", _0)]
    UnexpectedKey(String),
    /// The underlying raw string contains garbage (should not happen in theory)
    #[error(display = "Garbage in underlying data")]
    Garbage,
}

impl From<std::str::Utf8Error> for TypeError {
    fn from(_x: std::str::Utf8Error) -> TypeError {
        TypeError::Garbage
    }
}

// ----

/// The error kind returned by the `decode` function.
#[derive(Eq, PartialEq)]
pub enum DecodeError<'a> {
    /// Indicates that there is trailing garbage at the end of the decoded string
    Garbage(&'a [u8]),
    /// Indicates that the entered string does not represent a complete nettext term
    IncompleteInput,
    /// Indicates a syntax error in the decoded term
    NomError(&'a [u8], nom::error::ErrorKind),
}

impl<'a> std::fmt::Display for DecodeError<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        match self {
            DecodeError::Garbage(g) => write!(f, "Garbage: `{}`", debug(g)),
            DecodeError::IncompleteInput => write!(f, "Incomplete input"),
            DecodeError::NomError(s, e) => write!(f, "Nom: {:?}, at: `{}`", e, debug(s)),
        }
    }
}

impl<'a> std::fmt::Debug for DecodeError<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        std::fmt::Display::fmt(self, f)
    }
}

impl<'a> std::error::Error for DecodeError<'a> {}

impl<'a> From<nom::Err<nom::error::Error<&'a [u8]>>> for DecodeError<'a> {
    fn from(e: nom::Err<nom::error::Error<&'a [u8]>>) -> DecodeError<'a> {
        match e {
            nom::Err::Incomplete(_) => DecodeError::IncompleteInput,
            nom::Err::Error(e) | nom::Err::Failure(e) => DecodeError::NomError(e.input, e.code),
        }
    }
}