From f165d618e91a70ab805a9f23f1139177150db4f4 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Thu, 26 Oct 2023 12:17:43 +0900 Subject: [PATCH] feat: en-/decode non-zero integers directly Instead of driving the encoding and decoding of non-zero integer types through the Encode/Decode trait, use direct function calls which allows for specialized calls with better performance. --- crates/stef-build/src/decode.rs | 20 +++--- crates/stef-build/src/encode.rs | 20 +++--- .../compiler__compile@types-generic.stef.snap | 4 +- ...compiler__compile@types-non-zero.stef.snap | 40 +++++------ crates/stef/src/buf/decode.rs | 38 +++++------ crates/stef/src/buf/encode.rs | 68 +------------------ 6 files changed, 62 insertions(+), 128 deletions(-) diff --git a/crates/stef-build/src/decode.rs b/crates/stef-build/src/decode.rs index 627b8f1..a100bbd 100644 --- a/crates/stef-build/src/decode.rs +++ b/crates/stef-build/src/decode.rs @@ -275,16 +275,16 @@ fn compile_data_type(ty: &DataType<'_>) -> TokenStream { quote! { ::stef::buf::decode_option(r, |r| { #ty }) } } DataType::NonZero(ty) => match &**ty { - DataType::U8 => quote! { ::std::num::NonZeroU8::decode(r) }, - DataType::U16 => quote! { ::std::num::NonZeroU16::decode(r) }, - DataType::U32 => quote! { ::std::num::NonZeroU32::decode(r) }, - DataType::U64 => quote! { ::std::num::NonZeroU64::decode(r) }, - DataType::U128 => quote! { ::std::num::NonZeroU128::decode(r) }, - DataType::I8 => quote! { ::std::num::NonZeroI8::decode(r) }, - DataType::I16 => quote! { ::std::num::NonZeroI16::decode(r) }, - DataType::I32 => quote! { ::std::num::NonZeroI32::decode(r) }, - DataType::I64 => quote! { ::std::num::NonZeroI64::decode(r) }, - DataType::I128 => quote! { ::std::num::NonZeroI128::decode(r) }, + DataType::U8 => quote! { ::stef::buf::decode_non_zero_u8(r) }, + DataType::U16 => quote! { ::stef::buf::decode_non_zero_u16(r) }, + DataType::U32 => quote! { ::stef::buf::decode_non_zero_u32(r) }, + DataType::U64 => quote! { ::stef::buf::decode_non_zero_u64(r) }, + DataType::U128 => quote! { ::stef::buf::decode_non_zero_u128(r) }, + DataType::I8 => quote! { ::stef::buf::decode_non_zero_i8(r) }, + DataType::I16 => quote! { ::stef::buf::decode_non_zero_i16(r) }, + DataType::I32 => quote! { ::stef::buf::decode_non_zero_i32(r) }, + DataType::I64 => quote! { ::stef::buf::decode_non_zero_i64(r) }, + DataType::I128 => quote! { ::stef::buf::decode_non_zero_i128(r) }, DataType::String | DataType::StringRef => { quote! { ::stef::buf::decode_non_zero_string(r) } } diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index 60b53aa..c79e61e 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -318,16 +318,16 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { quote! { ::stef::buf::encode_option(w, &#name, |w, v| { #ty; }) } } DataType::NonZero(ty) => match &**ty { - DataType::U8 - | DataType::U16 - | DataType::U32 - | DataType::U64 - | DataType::U128 - | DataType::I8 - | DataType::I16 - | DataType::I32 - | DataType::I64 - | DataType::I128 => quote! { (#name).encode(w) }, + DataType::U8 => quote! { ::stef::buf::encode_u8(w, #name.get()) }, + DataType::U16 => quote! { ::stef::buf::encode_u16(w, #name.get()) }, + DataType::U32 => quote! { ::stef::buf::encode_u32(w, #name.get()) }, + DataType::U64 => quote! { ::stef::buf::encode_u64(w, #name.get()) }, + DataType::U128 => quote! { ::stef::buf::encode_u128(w, #name.get()) }, + DataType::I8 => quote! { ::stef::buf::encode_i8(w, #name.get()) }, + DataType::I16 => quote! { ::stef::buf::encode_i16(w, #name.get()) }, + DataType::I32 => quote! { ::stef::buf::encode_i32(w, #name.get()) }, + DataType::I64 => quote! { ::stef::buf::encode_i64(w, #name.get()) }, + DataType::I128 => quote! { ::stef::buf::encode_i128(w, #name.get()) }, DataType::String | DataType::StringRef | DataType::Bytes diff --git a/crates/stef-build/tests/snapshots/compiler__compile@types-generic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@types-generic.stef.snap index 5a6d2df..a2735d6 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@types-generic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@types-generic.stef.snap @@ -77,7 +77,7 @@ impl ::stef::Encode for Sample { w, 5, |w| { - (self.f5).encode(w); + ::stef::buf::encode_u32(w, self.f5.get()); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -118,7 +118,7 @@ impl ::stef::Decode for Sample { ); } 4 => f4 = Some(::stef::buf::decode_u32(r)?), - 5 => f5 = Some(::std::num::NonZeroU32::decode(r)?), + 5 => f5 = Some(::stef::buf::decode_non_zero_u32(r)?), _ => continue, } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@types-non-zero.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@types-non-zero.stef.snap index 3581c17..2d5f97f 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@types-non-zero.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@types-non-zero.stef.snap @@ -37,70 +37,70 @@ impl ::stef::Encode for Sample { w, 1, |w| { - (self.f01).encode(w); + ::stef::buf::encode_u8(w, self.f01.get()); }, ); ::stef::buf::encode_field( w, 2, |w| { - (self.f02).encode(w); + ::stef::buf::encode_u16(w, self.f02.get()); }, ); ::stef::buf::encode_field( w, 3, |w| { - (self.f03).encode(w); + ::stef::buf::encode_u32(w, self.f03.get()); }, ); ::stef::buf::encode_field( w, 4, |w| { - (self.f04).encode(w); + ::stef::buf::encode_u64(w, self.f04.get()); }, ); ::stef::buf::encode_field( w, 5, |w| { - (self.f05).encode(w); + ::stef::buf::encode_u128(w, self.f05.get()); }, ); ::stef::buf::encode_field( w, 6, |w| { - (self.f06).encode(w); + ::stef::buf::encode_i8(w, self.f06.get()); }, ); ::stef::buf::encode_field( w, 7, |w| { - (self.f07).encode(w); + ::stef::buf::encode_i16(w, self.f07.get()); }, ); ::stef::buf::encode_field( w, 8, |w| { - (self.f08).encode(w); + ::stef::buf::encode_i32(w, self.f08.get()); }, ); ::stef::buf::encode_field( w, 9, |w| { - (self.f09).encode(w); + ::stef::buf::encode_i64(w, self.f09.get()); }, ); ::stef::buf::encode_field( w, 10, |w| { - (self.f10).encode(w); + ::stef::buf::encode_i128(w, self.f10.get()); }, ); ::stef::buf::encode_field( @@ -184,16 +184,16 @@ impl ::stef::Decode for Sample { loop { match ::stef::buf::decode_id(r)? { ::stef::buf::END_MARKER => break, - 1 => f01 = Some(::std::num::NonZeroU8::decode(r)?), - 2 => f02 = Some(::std::num::NonZeroU16::decode(r)?), - 3 => f03 = Some(::std::num::NonZeroU32::decode(r)?), - 4 => f04 = Some(::std::num::NonZeroU64::decode(r)?), - 5 => f05 = Some(::std::num::NonZeroU128::decode(r)?), - 6 => f06 = Some(::std::num::NonZeroI8::decode(r)?), - 7 => f07 = Some(::std::num::NonZeroI16::decode(r)?), - 8 => f08 = Some(::std::num::NonZeroI32::decode(r)?), - 9 => f09 = Some(::std::num::NonZeroI64::decode(r)?), - 10 => f10 = Some(::std::num::NonZeroI128::decode(r)?), + 1 => f01 = Some(::stef::buf::decode_non_zero_u8(r)?), + 2 => f02 = Some(::stef::buf::decode_non_zero_u16(r)?), + 3 => f03 = Some(::stef::buf::decode_non_zero_u32(r)?), + 4 => f04 = Some(::stef::buf::decode_non_zero_u64(r)?), + 5 => f05 = Some(::stef::buf::decode_non_zero_u128(r)?), + 6 => f06 = Some(::stef::buf::decode_non_zero_i8(r)?), + 7 => f07 = Some(::stef::buf::decode_non_zero_i16(r)?), + 8 => f08 = Some(::stef::buf::decode_non_zero_i32(r)?), + 9 => f09 = Some(::stef::buf::decode_non_zero_i64(r)?), + 10 => f10 = Some(::stef::buf::decode_non_zero_i128(r)?), 11 => f11 = Some(::stef::buf::decode_non_zero_string(r)?), 12 => f12 = Some(::stef::buf::decode_non_zero_bytes(r)?), 13 => { diff --git a/crates/stef/src/buf/decode.rs b/crates/stef/src/buf/decode.rs index bc5096f..97f8a1f 100644 --- a/crates/stef/src/buf/decode.rs +++ b/crates/stef/src/buf/decode.rs @@ -179,6 +179,25 @@ macro_rules! ensure_not_empty { }; } +macro_rules! decode_non_zero_int { + ($ty:ty) => { + paste::paste! { + pub fn []( + r: &mut impl Buf, + ) -> Result]> { + std::num::[]::new([](r)?) + .ok_or_else(|| Error::Zero) + } + } + }; + ($($ty:ty),+ $(,)?) => { + $(decode_non_zero_int!($ty);)+ + }; +} + +decode_non_zero_int!(u8, u16, u32, u64, u128); +decode_non_zero_int!(i8, i16, i32, i64, i128); + pub fn decode_non_zero_string(r: &mut impl Buf) -> Result> { String::from_utf8(decode_non_zero_bytes(r)?.into_inner()) .map(|v| NonZero::::new(v).unwrap()) @@ -344,25 +363,6 @@ where } } -macro_rules! non_zero { - ($ty:ty) => { - paste::paste! { - impl Decode for std::num::[] { - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - Self::new([](r)?).ok_or_else(|| Error::Zero) - } - } - } - }; - ($($ty:ty),+ $(,)?) => { - $(non_zero!($ty);)+ - }; -} - -non_zero!(u8, u16, u32, u64, u128); -non_zero!(i8, i16, i32, i64, i128); - impl<'a, T> Decode for std::borrow::Cow<'a, T> where T: Copy + Decode, diff --git a/crates/stef/src/buf/encode.rs b/crates/stef/src/buf/encode.rs index 936fd4b..0c9f51f 100644 --- a/crates/stef/src/buf/encode.rs +++ b/crates/stef/src/buf/encode.rs @@ -1,10 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, - num::{ - NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16, - NonZeroU32, NonZeroU64, NonZeroU8, - }, -}; +use std::collections::{HashMap, HashSet}; pub use bytes::BufMut; @@ -257,66 +251,6 @@ where } } -impl Encode for NonZeroU8 { - fn encode(&self, w: &mut impl BufMut) { - encode_u8(w, self.get()); - } -} - -impl Encode for NonZeroU16 { - fn encode(&self, w: &mut impl BufMut) { - encode_u16(w, self.get()); - } -} - -impl Encode for NonZeroU32 { - fn encode(&self, w: &mut impl BufMut) { - encode_u32(w, self.get()); - } -} - -impl Encode for NonZeroU64 { - fn encode(&self, w: &mut impl BufMut) { - encode_u64(w, self.get()); - } -} - -impl Encode for NonZeroU128 { - fn encode(&self, w: &mut impl BufMut) { - encode_u128(w, self.get()); - } -} - -impl Encode for NonZeroI8 { - fn encode(&self, w: &mut impl BufMut) { - encode_i8(w, self.get()); - } -} - -impl Encode for NonZeroI16 { - fn encode(&self, w: &mut impl BufMut) { - encode_i16(w, self.get()); - } -} - -impl Encode for NonZeroI32 { - fn encode(&self, w: &mut impl BufMut) { - encode_i32(w, self.get()); - } -} - -impl Encode for NonZeroI64 { - fn encode(&self, w: &mut impl BufMut) { - encode_i64(w, self.get()); - } -} - -impl Encode for NonZeroI128 { - fn encode(&self, w: &mut impl BufMut) { - encode_i128(w, self.get()); - } -} - impl Encode for NonZero where T: Encode,