From e8205bcb6749fce6dd1f56ede38128076820bffd Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Tue, 12 Sep 2023 20:14:54 +0900 Subject: [PATCH] feat: simplify encoding logic --- crates/stef-build/src/encode.rs | 54 ++---- crates/stef/src/lib.rs | 285 +++++++++++++++++++++++++++++++- 2 files changed, 300 insertions(+), 39 deletions(-) diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index 6db57f1..3bee68a 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -150,7 +150,7 @@ fn compile_variant( let field_names = unnamed .iter() .enumerate() - .map(|(idx, _)| Ident::new(&format!("unnamed_{idx}"), Span::call_site())); + .map(|(idx, _)| Ident::new(&format!("n{idx}"), Span::call_site())); quote! { Self::#name(#(#field_names,)*) => { @@ -194,7 +194,7 @@ fn compile_variant_fields(fields: &Fields<'_>) -> TokenStream { .enumerate() .map(|(idx, UnnamedField { ty, id })| { let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = Ident::new(&format!("unnamed_{idx}"), Span::call_site()); + let name = Ident::new(&format!("n{idx}"), Span::call_site()); let ty = compile_data_type(ty, name.to_token_stream()); quote! { ::stef::write_field(w, #id, |w| { #ty }); } @@ -206,6 +206,7 @@ fn compile_variant_fields(fields: &Fields<'_>) -> TokenStream { } } +#[allow(clippy::needless_pass_by_value)] fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { match ty { DataType::Bool => quote! { ::stef::encode_bool(w, #name) }, @@ -227,36 +228,20 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::HashMap(_kv) => quote! { ::stef::encode_hash_map(w, #name) }, DataType::HashSet(_ty) => quote! { ::stef::encode_hash_set(w, #name) }, DataType::Option(_ty) => quote! { ::stef::encode_option(w, #name) }, - DataType::NonZero(ty) => match **ty { - DataType::U8 => quote! { ::stef::encode_u8(w, #name.get()) }, - DataType::U16 => quote! { ::stef::encode_u16(w, #name.get()) }, - DataType::U32 => quote! { ::stef::encode_u32(w, #name.get()) }, - DataType::U64 => quote! { ::stef::encode_u64(w, #name.get()) }, - DataType::U128 => quote! { ::stef::encode_u128(w, #name.get()) }, - DataType::I8 => quote! { ::stef::encode_i8(w, #name.get()) }, - DataType::I16 => quote! { ::stef::encode_i16(w, #name.get()) }, - DataType::I32 => quote! { ::stef::encode_i32(w, #name.get()) }, - DataType::I64 => quote! { ::stef::encode_i64(w, #name.get()) }, - DataType::I128 => quote! { ::stef::encode_i128(w, #name.get()) }, - _ => compile_data_type(ty, name), - }, DataType::BoxString => quote! { ::stef::encode_string(w, &*#name) }, DataType::BoxBytes => quote! { ::stef::encode_bytes(w, &*#name) }, - DataType::Tuple(types) => { - let calls = types.iter().enumerate().map(|(idx, ty)| { - let idx = proc_macro2::Literal::usize_unsuffixed(idx); - compile_data_type(ty, quote! { #name.#idx }) - }); - quote! { #(#calls;)* } - } + DataType::Tuple(types) => match types.len() { + size @ 1..=12 => { + let fn_name = Ident::new(&format!("write_tuple{size}"), Span::call_site()); + quote! { ::stef::#fn_name(w, &#name) } + } + 0 => panic!("tuple with zero elements"), + _ => panic!("tuple with more than 12 elements"), + }, DataType::Array(_ty, _size) => { quote! { ::stef::encode_array(w, &#name) } } - DataType::External(ExternalType { - path: _, - name: _, - generics: _, - }) => { + DataType::NonZero(_) | DataType::External(_) => { quote! { #name.encode(w) } } } @@ -310,14 +295,7 @@ mod tests { fn encode(&self, w: &mut impl ::stef::BufMut) { ::stef::write_field(w, 1, |w| { ::stef::encode_u32(w, self.field1) }); ::stef::write_field(w, 2, |w| { ::stef::encode_bytes(w, &self.field2) }); - ::stef::write_field( - w, - 3, - |w| { - ::stef::encode_bool(w, self.field3.0); - ::stef::encode_array(w, &self.field3.1); - }, - ); + ::stef::write_field(w, 3, |w| { ::stef::write_tuple2(w, &self.field3) }); } } "#}; @@ -345,10 +323,10 @@ mod tests { Self::Variant1 => { ::stef::write_id(w, 1); } - Self::Variant2(unnamed_0, unnamed_1) => { + Self::Variant2(n0, n1) => { ::stef::write_id(w, 2); - ::stef::write_field(w, 1, |w| { ::stef::encode_u32(w, unnamed_0) }); - ::stef::write_field(w, 2, |w| { ::stef::encode_u8(w, unnamed_1) }); + ::stef::write_field(w, 1, |w| { ::stef::encode_u32(w, n0) }); + ::stef::write_field(w, 2, |w| { ::stef::encode_u8(w, n1) }); } Self::Variant3 { field1, field2 } => { ::stef::write_id(w, 3); diff --git a/crates/stef/src/lib.rs b/crates/stef/src/lib.rs index d437ba9..23c1483 100644 --- a/crates/stef/src/lib.rs +++ b/crates/stef/src/lib.rs @@ -86,7 +86,7 @@ macro_rules! forward { }; ($($ty:ty),+ $(,)?) => { $(forward!($ty);)+ - } + }; } forward!(bool); @@ -101,6 +101,13 @@ impl<'a> Encode for &'a str { } } +impl Encode for Box { + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_string(w, self) + } +} + impl<'a> Encode for &'a [u8] { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { @@ -108,6 +115,13 @@ impl<'a> Encode for &'a [u8] { } } +impl Encode for Box<[u8]> { + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_bytes(w, self) + } +} + pub fn encode_vec(w: &mut impl BufMut, vec: &Vec) { encode_u64(w, vec.len() as u64); @@ -116,6 +130,16 @@ pub fn encode_vec(w: &mut impl BufMut, vec: &Vec) { } } +impl Encode for Vec +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_vec(w, self) + } +} + pub fn encode_hash_map(w: &mut impl BufMut, map: &HashMap) { encode_u64(w, map.len() as u64); @@ -125,6 +149,17 @@ pub fn encode_hash_map(w: &mut impl BufMut, map: &HashMap< } } +impl Encode for HashMap +where + K: Encode, + V: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_hash_map(w, self) + } +} + pub fn encode_hash_set(w: &mut impl BufMut, set: &HashSet) { encode_u64(w, set.len() as u64); @@ -133,12 +168,32 @@ pub fn encode_hash_set(w: &mut impl BufMut, set: &HashSet) { } } +impl Encode for HashSet +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_hash_set(w, self) + } +} + pub fn encode_option(w: &mut impl BufMut, option: &Option) { if let Some(value) = option { value.encode(w); } } +impl Encode for Option +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_option(w, self) + } +} + // TODO: NonZero pub fn encode_array(w: &mut impl BufMut, array: &[T; N]) { @@ -149,6 +204,16 @@ pub fn encode_array(w: &mut impl BufMut, array: &[T; } } +impl Encode for [T; N] +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + encode_array(w, self) + } +} + pub fn write_tuple1(w: &mut impl BufMut, tuple: &(T0,)) where T0: Encode, @@ -156,6 +221,16 @@ where tuple.0.encode(w); } +impl Encode for (T0,) +where + T0: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple1(w, self) + } +} + pub fn write_tuple2(w: &mut impl BufMut, tuple: &(T0, T1)) where T0: Encode, @@ -165,6 +240,17 @@ where tuple.1.encode(w); } +impl Encode for (T0, T1) +where + T0: Encode, + T1: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple2(w, self) + } +} + pub fn write_tuple3(w: &mut impl BufMut, tuple: &(T0, T1, T2)) where T0: Encode, @@ -176,6 +262,18 @@ where tuple.2.encode(w); } +impl Encode for (T0, T1, T2) +where + T0: Encode, + T1: Encode, + T2: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple3(w, self) + } +} + pub fn write_tuple4(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3)) where T0: Encode, @@ -189,6 +287,19 @@ where tuple.3.encode(w); } +impl Encode for (T0, T1, T2, T3) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple4(w, self) + } +} + pub fn write_tuple5(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4)) where T0: Encode, @@ -204,6 +315,20 @@ where tuple.4.encode(w); } +impl Encode for (T0, T1, T2, T3, T4) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple5(w, self) + } +} + pub fn write_tuple6(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5)) where T0: Encode, @@ -221,6 +346,21 @@ where tuple.5.encode(w); } +impl Encode for (T0, T1, T2, T3, T4, T5) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple6(w, self) + } +} + pub fn write_tuple7( w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5, T6), @@ -242,6 +382,22 @@ pub fn write_tuple7( tuple.6.encode(w); } +impl Encode for (T0, T1, T2, T3, T4, T5, T6) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple7(w, self) + } +} + pub fn write_tuple8( w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5, T6, T7), @@ -265,6 +421,23 @@ pub fn write_tuple8( tuple.7.encode(w); } +impl Encode for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, + T7: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple8(w, self) + } +} + pub fn write_tuple9( w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5, T6, T7, T8), @@ -290,6 +463,24 @@ pub fn write_tuple9( tuple.8.encode(w); } +impl Encode for (T0, T1, T2, T3, T4, T5, T6, T7, T8) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, + T7: Encode, + T8: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple9(w, self) + } +} + pub fn write_tuple10( w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), @@ -317,6 +508,25 @@ pub fn write_tuple10( tuple.9.encode(w); } +impl Encode for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, + T7: Encode, + T8: Encode, + T9: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple10(w, self) + } +} + pub fn write_tuple11( w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), @@ -346,6 +556,27 @@ pub fn write_tuple11( tuple.10.encode(w); } +impl Encode + for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, + T7: Encode, + T8: Encode, + T9: Encode, + T10: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple11(w, self) + } +} + #[allow(clippy::type_complexity)] pub fn write_tuple12( w: &mut impl BufMut, @@ -378,6 +609,28 @@ pub fn write_tuple12( tuple.11.encode(w); } +impl Encode + for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) +where + T0: Encode, + T1: Encode, + T2: Encode, + T3: Encode, + T4: Encode, + T5: Encode, + T6: Encode, + T7: Encode, + T8: Encode, + T9: Encode, + T10: Encode, + T11: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + write_tuple12(w, self) + } +} + impl Encode for NonZeroU8 { fn encode(&self, w: &mut impl BufMut) { encode_u8(w, self.get()); @@ -438,6 +691,36 @@ impl Encode for NonZeroI128 { } } +impl<'a, T> Encode for std::borrow::Cow<'a, T> +where + T: Clone + Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + T::encode(self, w) + } +} + +impl Encode for std::rc::Rc +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + T::encode(self, w) + } +} + +impl Encode for std::sync::Arc +where + T: Encode, +{ + #[inline(always)] + fn encode(&self, w: &mut impl BufMut) { + T::encode(self, w) + } +} + #[inline(always)] pub fn write_field(w: &mut W, id: u32, encode: E) where