diff --git a/src/error.rs b/src/error.rs index 2b037db..e1aec77 100644 --- a/src/error.rs +++ b/src/error.rs @@ -105,6 +105,23 @@ pub enum DecodeError { }, } +impl DecodeError { + /// If the current error is `InvalidIntegerType`, change the `expected` and + /// `found` values from `Ux` to `Ix`. This is needed to have correct error + /// reporting in src/varint/decode_signed.rs since this calls + /// src/varint/decode_unsigned.rs and needs to correct the `expected` and + /// `found` types. + pub(crate) fn change_integer_type_to_signed(self) -> DecodeError { + match self { + Self::InvalidIntegerType { expected, found } => Self::InvalidIntegerType { + expected: expected.into_signed(), + found: found.into_signed(), + }, + other => other, + } + } +} + /// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors. #[non_exhaustive] #[derive(Debug)] @@ -124,3 +141,20 @@ pub enum IntegerType { I128, Isize, } + +impl IntegerType { + /// Change the `Ux` value to the associated `Ix` value. + /// Returns the old value if `self` is already `Ix`. + pub(crate) fn into_signed(self) -> Self { + match self { + Self::U8 => Self::I8, + Self::U16 => Self::I16, + Self::U32 => Self::I32, + Self::U64 => Self::I64, + Self::U128 => Self::I128, + Self::Usize => Self::Isize, + + other => other, + } + } +} diff --git a/src/varint/decode_signed.rs b/src/varint/decode_signed.rs index b372d54..d670493 100644 --- a/src/varint/decode_signed.rs +++ b/src/varint/decode_signed.rs @@ -1,7 +1,12 @@ -use crate::{config::Endian, de::read::Reader, error::DecodeError}; +use crate::{ + config::Endian, + de::read::Reader, + error::{DecodeError, IntegerType}, +}; pub fn varint_decode_i16(read: &mut R, endian: Endian) -> Result { - let n = super::varint_decode_u16(read, endian)?; + let n = super::varint_decode_u16(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; Ok(if n % 2 == 0 { // positive number (n / 2) as _ @@ -17,7 +22,8 @@ pub fn varint_decode_i16(read: &mut R, endian: Endian) -> Result(read: &mut R, endian: Endian) -> Result { - let n = super::varint_decode_u32(read, endian)?; + let n = super::varint_decode_u32(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; Ok(if n % 2 == 0 { // positive number (n / 2) as _ @@ -33,7 +39,8 @@ pub fn varint_decode_i32(read: &mut R, endian: Endian) -> Result(read: &mut R, endian: Endian) -> Result { - let n = super::varint_decode_u64(read, endian)?; + let n = super::varint_decode_u64(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; Ok(if n % 2 == 0 { // positive number (n / 2) as _ @@ -49,7 +56,8 @@ pub fn varint_decode_i64(read: &mut R, endian: Endian) -> Result(read: &mut R, endian: Endian) -> Result { - let n = super::varint_decode_u128(read, endian)?; + let n = super::varint_decode_u128(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; Ok(if n % 2 == 0 { // positive number (n / 2) as _ @@ -65,5 +73,14 @@ pub fn varint_decode_i128(read: &mut R, endian: Endian) -> Result(read: &mut R, endian: Endian) -> Result { - varint_decode_i64(read, endian).map(|v| v as isize) + match varint_decode_i64(read, endian) { + Ok(val) => Ok(val as isize), + Err(DecodeError::InvalidIntegerType { found, .. }) => { + Err(DecodeError::InvalidIntegerType { + expected: IntegerType::Isize, + found: found.into_signed(), + }) + } + Err(e) => Err(e), + } }