From bd07adea66674a7e15b934474b87d95c3776e552 Mon Sep 17 00:00:00 2001 From: Maciej Hirsz <1096222+maciejhirsz@users.noreply.github.com> Date: Wed, 15 Jun 2022 19:50:09 +0100 Subject: [PATCH] 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 --- derive/src/derive_enum.rs | 4 ++-- src/de/impls.rs | 8 ++++---- src/de/mod.rs | 2 +- src/error.rs | 8 ++++---- src/features/impl_std.rs | 11 ++++++----- tests/derive.rs | 2 +- tests/error_size.rs | 15 +++++++++++++++ tests/issues/issue_498.rs | 2 +- 8 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 tests/error_size.rs diff --git a/derive/src/derive_enum.rs b/derive/src/derive_enum.rs index 0f21e8c..8c8daf1 100644 --- a/derive/src/derive_enum.rs +++ b/derive/src/derive_enum.rs @@ -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 ))?; diff --git a/src/de/impls.rs b/src/de/impls.rs index 7902ce5..7228d42 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -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::>(), }), } @@ -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::>(), }), } @@ -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::>(), }), @@ -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::>(), }), diff --git a/src/de/mod.rs b/src/de/mod.rs index 9348cb2..d603782 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -265,7 +265,7 @@ pub(crate) fn decode_option_variant( 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, }), } diff --git a/src/error.rs b/src/error.rs index ac897db..a544f0c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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, }, #[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 diff --git a/src/features/impl_std.rs b/src/features/impl_std.rs index 84e242c..72330ed 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -144,7 +144,9 @@ impl Encode for CString { impl Decode for CString { fn decode(decoder: &mut D) -> Result { 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::(), }), @@ -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::(), }), @@ -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, } } diff --git a/tests/derive.rs b/tests/derive.rs index 2ef7a70..bdbbb26 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -285,7 +285,7 @@ fn test_c_style_enum() { fn expected_err(idx: u32) -> Result { 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, }) } diff --git a/tests/error_size.rs b/tests/error_size.rs new file mode 100644 index 0000000..9949d67 --- /dev/null +++ b/tests/error_size.rs @@ -0,0 +1,15 @@ +#![cfg(target_pointer_width = "64")] + +#[test] +fn decode_error_size() { + assert_eq!(std::mem::size_of::(), 32); +} + +#[test] +fn encode_error_size() { + #[cfg(any(feature = "std", feature = "alloc"))] + assert_eq!(std::mem::size_of::(), 32); + + #[cfg(not(any(feature = "std", feature = "alloc")))] + assert_eq!(std::mem::size_of::(), 24); +} diff --git a/tests/issues/issue_498.rs b/tests/issues/issue_498.rs index a60fec8..f301c4b 100644 --- a/tests/issues/issue_498.rs +++ b/tests/issues/issue_498.rs @@ -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), } }