diff --git a/src/buf/decode.rs b/src/buf/decode.rs index 39dd6c0..2e6465d 100644 --- a/src/buf/decode.rs +++ b/src/buf/decode.rs @@ -5,13 +5,6 @@ use crate::{ use super::*; -#[derive(Debug)] -pub enum ParseError { - IncompleteInput, - DuplicateKey(Pos), - Garbage(Pos), -} - pub fn decode(input: &[u8]) -> Result<(Buf<'_>, ITerm), ParseError> { let mut buf = Buf { bytes: input.into(), @@ -62,7 +55,7 @@ impl<'a> Buf<'a> { let rest = self.take_whitespace(rest); if rest.start < raw.end { - return Err(ParseError::Garbage(rest.start)); + return Err(ParseError::UnexpectedInput(rest.start as usize)); } Ok(term) @@ -181,7 +174,7 @@ impl<'a> Buf<'a> { .zip(self.dicts[dict_start + 1..].iter()) { if self.get_bytes(*k1) == self.get_bytes(*k2) { - return Err(ParseError::DuplicateKey(k1.start)); + return Err(ParseError::DuplicateKey(String::from_utf8(self.get_bytes(*k1).to_vec()).unwrap())); } } @@ -265,7 +258,7 @@ impl<'a> Buf<'a> { if raw.start >= raw.end { Err(ParseError::IncompleteInput) } else if self.bytes[raw.start as usize] != c { - Err(ParseError::Garbage(raw.start)) + Err(ParseError::UnexpectedInput(raw.start as usize)) } else { Ok(IRaw { start: raw.start + 1, @@ -294,7 +287,7 @@ impl<'a> Buf<'a> { #[inline] fn error_at(&self, raw: IRaw) -> ParseError { if raw.start < raw.end { - ParseError::Garbage(raw.start) + ParseError::UnexpectedInput(raw.start as usize) } else { ParseError::IncompleteInput } diff --git a/src/buf/error.rs b/src/buf/error.rs new file mode 100644 index 0000000..c3e06bf --- /dev/null +++ b/src/buf/error.rs @@ -0,0 +1,39 @@ +use err_derive::Error; + +use super::*; + +#[derive(Debug, Error)] +pub enum ParseError { + #[error(display = "Incomplete input")] + IncompleteInput, + #[error(display = "UnexpectedInput at position {}", _0)] + UnexpectedInput(usize), + #[error(display = "Duplicate dictionnary key: {}", _0)] + DuplicateKey(String), +} + +#[derive(Debug, Error)] +pub enum TermError { + #[error(display = "Invalid term index ({:?})", _0)] + InvalidIndex(ITerm), + #[error(display = "Wrong type, expected {}, got {}", _0, _1)] + WrongType(&'static str, &'static str), + #[error(display = "Wrong length, expected {}, got {}", _0, _1)] + WrongLength(usize, usize), + #[error(display = "Wrong dictionnary keys")] + WrongKeys, + #[error(display = "Term does not have a raw representation")] + NoRawRepresentation, +} + +#[derive(Debug, Error)] +pub enum ValueError { + #[error(display = "Invalid term index ({:?})", _0)] + InvalidIndex(ITerm), + #[error(display = "Duplicate dictionary key")] + DuplicateKey, + #[error(display = "Bad string (contains invalid characters)")] + BadString, + #[error(display = "Nested sequence")] + SeqInSeq, +} diff --git a/src/buf/mod.rs b/src/buf/mod.rs index 24c4409..7f3ae26 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -1,9 +1,11 @@ mod decode; +mod error; use std::borrow::Cow; use crate::is_string_char; +pub use error::*; pub use decode::*; pub(crate) const STR_INLINE_MAX: usize = 18; @@ -51,23 +53,6 @@ pub struct Buf<'a> { terms: Vec, } -#[derive(Debug)] -pub enum TermError { - InvalidIndex(ITerm), - WrongType(&'static str, &'static str), - WrongLength(usize, usize), - WrongKeys, - NoRawRepresentation, -} - -#[derive(Debug)] -pub enum ValueError { - InvalidIndex(ITerm), - DuplicateKey, - BadString, - SeqInSeq, -} - impl<'a> Buf<'a> { pub fn new() -> Self { Self { @@ -350,7 +335,11 @@ impl<'a> Buf<'a> { self.terms.truncate(terms_len); } - result + if let Err(ParseError::UnexpectedInput(pos)) = result { + Err(ParseError::UnexpectedInput(pos - bytes_len)) + } else { + result + } } // ==== Internal ====