Shrink `DecodeError` from 48 to 32 bytes on 64-bit arch (#553)

* Shrink `DecodeError` to 32 bytes on 64-bit arch

* Nul with a single l

* fmt

* Consider feature combinations for error sizes

* Remove superfluous `any`

* fmt

* Box SystemTime in EncodeError
This commit is contained in:
Maciej Hirsz 2022-06-15 19:50:09 +01:00 committed by GitHub
parent 229b597a84
commit bd07adea66
8 changed files with 34 additions and 18 deletions

View File

@ -185,7 +185,7 @@ impl DeriveEnum {
if self.variants.iter().any(|i| i.has_fixed_value()) {
// we have fixed values, implement AllowedEnumVariants::Allowed
variant_inner.push_parsed(format!(
"{}::error::AllowedEnumVariants::Allowed",
"&{}::error::AllowedEnumVariants::Allowed",
crate_name
))?;
variant_inner.group(Delimiter::Parenthesis, |allowed_inner| {
@ -204,7 +204,7 @@ impl DeriveEnum {
} else {
// no fixed values, implement a range
variant_inner.push_parsed(format!(
"{0}::error::AllowedEnumVariants::Range {{ min: 0, max: {1} }}",
"&{0}::error::AllowedEnumVariants::Range {{ min: 0, max: {1} }}",
crate_name,
self.variants.len() - 1
))?;

View File

@ -607,7 +607,7 @@ where
}
x => Err(DecodeError::UnexpectedVariant {
found: x as u32,
allowed: crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
type_name: core::any::type_name::<Result<T, U>>(),
}),
}
@ -632,7 +632,7 @@ where
}
x => Err(DecodeError::UnexpectedVariant {
found: x as u32,
allowed: crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
type_name: core::any::type_name::<Result<T, U>>(),
}),
}
@ -745,7 +745,7 @@ where
1 => Ok(Bound::Included(T::decode(decoder)?)),
2 => Ok(Bound::Excluded(T::decode(decoder)?)),
x => Err(DecodeError::UnexpectedVariant {
allowed: crate::error::AllowedEnumVariants::Range { max: 2, min: 0 },
allowed: &crate::error::AllowedEnumVariants::Range { max: 2, min: 0 },
found: x,
type_name: core::any::type_name::<Bound<T>>(),
}),
@ -763,7 +763,7 @@ where
1 => Ok(Bound::Included(T::borrow_decode(decoder)?)),
2 => Ok(Bound::Excluded(T::borrow_decode(decoder)?)),
x => Err(DecodeError::UnexpectedVariant {
allowed: crate::error::AllowedEnumVariants::Range { max: 2, min: 0 },
allowed: &crate::error::AllowedEnumVariants::Range { max: 2, min: 0 },
found: x,
type_name: core::any::type_name::<Bound<T>>(),
}),

View File

@ -265,7 +265,7 @@ pub(crate) fn decode_option_variant<D: Decoder>(
1 => Ok(Some(())),
x => Err(DecodeError::UnexpectedVariant {
found: x as u32,
allowed: crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
type_name,
}),
}

View File

@ -48,7 +48,7 @@ pub enum EncodeError {
/// The error that was thrown by the SystemTime
inner: std::time::SystemTimeError,
/// The SystemTime that caused the error
time: std::time::SystemTime,
time: std::boxed::Box<std::time::SystemTime>,
},
#[cfg(feature = "serde")]
@ -100,7 +100,7 @@ pub enum DecodeError {
type_name: &'static str,
/// The variants that are allowed
allowed: AllowedEnumVariants,
allowed: &'static AllowedEnumVariants,
/// The index of the enum that the decoder encountered
found: u32,
@ -160,8 +160,8 @@ pub enum DecodeError {
/// The decoder tried to decode a `CString`, but the incoming data contained a 0 byte
#[cfg(feature = "std")]
CStringNulError {
/// The inner exception
inner: std::ffi::NulError,
/// Nul byte position
position: usize,
},
/// An uncommon error occurred, see the inner text for more information

View File

@ -144,7 +144,9 @@ impl Encode for CString {
impl Decode for CString {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let vec = std::vec::Vec::decode(decoder)?;
CString::new(vec).map_err(|inner| DecodeError::CStringNulError { inner })
CString::new(vec).map_err(|inner| DecodeError::CStringNulError {
position: inner.nul_position(),
})
}
}
impl_borrow_decode!(CString);
@ -216,7 +218,7 @@ impl Encode for SystemTime {
let duration = self.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| {
EncodeError::InvalidSystemTime {
inner: e,
time: *self,
time: std::boxed::Box::new(*self),
}
})?;
duration.encode(encoder)
@ -285,7 +287,7 @@ impl Decode for IpAddr {
0 => Ok(IpAddr::V4(Ipv4Addr::decode(decoder)?)),
1 => Ok(IpAddr::V6(Ipv6Addr::decode(decoder)?)),
found => Err(DecodeError::UnexpectedVariant {
allowed: crate::error::AllowedEnumVariants::Range { min: 0, max: 1 },
allowed: &crate::error::AllowedEnumVariants::Range { min: 0, max: 1 },
found,
type_name: core::any::type_name::<IpAddr>(),
}),
@ -345,7 +347,7 @@ impl Decode for SocketAddr {
0 => Ok(SocketAddr::V4(SocketAddrV4::decode(decoder)?)),
1 => Ok(SocketAddr::V6(SocketAddrV6::decode(decoder)?)),
found => Err(DecodeError::UnexpectedVariant {
allowed: crate::error::AllowedEnumVariants::Range { min: 0, max: 1 },
allowed: &crate::error::AllowedEnumVariants::Range { min: 0, max: 1 },
found,
type_name: core::any::type_name::<SocketAddr>(),
}),
@ -400,7 +402,6 @@ impl std::error::Error for DecodeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Utf8 { inner } => Some(inner),
Self::CStringNulError { inner } => Some(inner),
_ => None,
}
}

View File

@ -285,7 +285,7 @@ fn test_c_style_enum() {
fn expected_err(idx: u32) -> Result<CStyleEnum, bincode::error::DecodeError> {
Err(bincode::error::DecodeError::UnexpectedVariant {
type_name: "CStyleEnum",
allowed: bincode::error::AllowedEnumVariants::Allowed(&[1, 2, 3, 5, 6]),
allowed: &bincode::error::AllowedEnumVariants::Allowed(&[1, 2, 3, 5, 6]),
found: idx,
})
}

15
tests/error_size.rs Normal file
View File

@ -0,0 +1,15 @@
#![cfg(target_pointer_width = "64")]
#[test]
fn decode_error_size() {
assert_eq!(std::mem::size_of::<bincode::error::DecodeError>(), 32);
}
#[test]
fn encode_error_size() {
#[cfg(any(feature = "std", feature = "alloc"))]
assert_eq!(std::mem::size_of::<bincode::error::EncodeError>(), 32);
#[cfg(not(any(feature = "std", feature = "alloc")))]
assert_eq!(std::mem::size_of::<bincode::error::EncodeError>(), 24);
}

View File

@ -11,7 +11,7 @@ fn test_issue_498() {
bincode::decode_from_slice(&bytes, bincode::config::legacy().with_limit::<1024>());
match out.unwrap_err() {
bincode::error::DecodeError::CStringNulError { inner: _ } => {}
bincode::error::DecodeError::CStringNulError { position: _ } => {}
err => panic!("Expected CStringNullErr, found {:?}", err),
}
}