From 3d64436501d5e395ba27e9acc51bd82aa312a8d8 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Sat, 14 Oct 2023 17:10:52 +0900 Subject: [PATCH] feat: unroll container type en-/decoding Instead of relying on generic implementations for the Rust generated code that en- or decodes the data, these are defined as closures. The main benefit is that it allows optimized calls that would not be possible through the trait system (for example a fast encoding of `Vec` instead of the regular `Vec` encoding that would write the bytes one-by-one). --- crates/stef-build/src/decode.rs | 34 +- crates/stef-build/src/definition.rs | 60 ++- crates/stef-build/src/encode.rs | 117 ++++- ...ompiler__compile@attribute-multi.stef.snap | 1 + ...mpiler__compile@attribute-single.stef.snap | 1 + ...compiler__compile@attribute-unit.stef.snap | 1 + ...piler__compile@attributes-min-ws.stef.snap | 1 + .../compiler__compile@attributes.stef.snap | 1 + .../compiler__compile@module-basic.stef.snap | 5 +- .../compiler__compile@schema-basic.stef.snap | 17 +- .../compiler__compile@struct-basic.stef.snap | 17 +- ...ompiler__compile@struct-generics.stef.snap | 17 +- ...compiler__compile@struct-many-ws.stef.snap | 17 +- .../compiler__compile@struct-min-ws.stef.snap | 25 +- .../compiler__compile@struct-tuple.stef.snap | 1 + .../compiler__compile@types-basic.stef.snap | 166 +++++- .../compiler__compile@types-generic.stef.snap | 80 ++- .../compiler__compile@types-nested.stef.snap | 30 +- .../compiler__compile@types-ref.stef.snap | 17 +- crates/stef/src/buf/decode.rs | 476 ++--------------- crates/stef/src/buf/encode.rs | 479 ++---------------- 21 files changed, 628 insertions(+), 935 deletions(-) diff --git a/crates/stef-build/src/decode.rs b/crates/stef-build/src/decode.rs index b2fdffe..7fc478b 100644 --- a/crates/stef-build/src/decode.rs +++ b/crates/stef-build/src/decode.rs @@ -251,10 +251,23 @@ fn compile_data_type(ty: &DataType<'_>) -> TokenStream { DataType::F64 => quote! { ::stef::buf::decode_f64(r) }, DataType::String | DataType::StringRef => quote! { ::stef::buf::decode_string(r) }, DataType::Bytes | DataType::BytesRef => quote! { ::stef::buf::decode_bytes(r) }, - DataType::Vec(_ty) => quote! { ::stef::buf::decode_vec(r) }, - DataType::HashMap(_kv) => quote! { ::stef::buf::decode_hash_map(r) }, - DataType::HashSet(_ty) => quote! { ::stef::buf::decode_hash_set(r) }, - DataType::Option(_ty) => quote! { ::stef::buf::decode_option(r) }, + DataType::Vec(ty) => { + let ty = compile_data_type(ty); + quote! { ::stef::buf::decode_vec(r, |r| { #ty }) } + } + DataType::HashMap(kv) => { + let ty_k = compile_data_type(&kv.0); + let ty_v = compile_data_type(&kv.1); + quote! { ::stef::buf::decode_hash_map(r, |r| { #ty_k }, |r| { #ty_v }) } + } + DataType::HashSet(ty) => { + let ty = compile_data_type(ty); + quote! { ::stef::buf::decode_hash_set(r, |r| { #ty }) } + } + DataType::Option(ty) => { + let ty = compile_data_type(ty); + quote! { ::stef::buf::decode_option(r, |r| { #ty }) } + } DataType::NonZero(ty) => match **ty { DataType::U8 => quote! { NonZeroU8::decode(r) }, DataType::U16 => quote! { NonZeroU16::decode(r) }, @@ -266,21 +279,22 @@ fn compile_data_type(ty: &DataType<'_>) -> TokenStream { DataType::I32 => quote! { NonZeroI32::decode(r) }, DataType::I64 => quote! { NonZeroI64::decode(r) }, DataType::I128 => quote! { NonZeroI128::decode(r) }, - _ => todo!(), + _ => quote! { todo!() }, }, DataType::BoxString => quote! { Box::decode(r) }, DataType::BoxBytes => quote! { Box<[u8]>::decode(r) }, DataType::Tuple(types) => match types.len() { - size @ 2..=12 => { - let fn_name = Ident::new(&format!("decode_tuple{size}"), Span::call_site()); - quote! { ::stef::buf::#fn_name(r) } + 2..=12 => { + let types = types.iter().map(|ty| compile_data_type(ty)); + quote! { { Ok::<_, ::stef::buf::Error>((#(#types?,)*)) } } } 0 => panic!("tuple with zero elements"), 1 => panic!("tuple with single element"), _ => panic!("tuple with more than 12 elements"), }, - DataType::Array(_ty, _size) => { - quote! { ::stef::buf::decode_array(r) } + DataType::Array(ty, _size) => { + let ty = compile_data_type(ty); + quote! { ::stef::buf::decode_array(r, |r| { #ty }) } } DataType::External(ty) => { let ty = Ident::new(ty.name, Span::call_site()); diff --git a/crates/stef-build/src/definition.rs b/crates/stef-build/src/definition.rs index d77648a..3aa817b 100644 --- a/crates/stef-build/src/definition.rs +++ b/crates/stef-build/src/definition.rs @@ -406,17 +406,35 @@ mod tests { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.field1) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.field1); + }, + ); ::stef::buf::encode_field( w, 2, - |w| { ::stef::buf::encode_bytes(w, &self.field2) }, + |w| { + ::stef::buf::encode_bytes(w, &self.field2); + }, ); ::stef::buf::encode_field( w, 3, - |w| { ::stef::buf::encode_tuple2(w, &self.field3) }, + |w| { + ::stef::buf::encode_bool(w, self.field3.0); + ::stef::buf::encode_array( + w, + &&(self.field3.1), + |w, v| { + ::stef::buf::encode_i16(w, *v); + }, + ); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -432,7 +450,22 @@ mod tests { ::stef::buf::END_MARKER => break, 1 => field1 = Some(::stef::buf::decode_u32(r)?), 2 => field2 = Some(::stef::buf::decode_bytes(r)?), - 3 => field3 = Some(::stef::buf::decode_tuple2(r)?), + 3 => { + field3 = Some( + { + Ok::< + _, + ::stef::buf::Error, + >(( + ::stef::buf::decode_bool(r)?, + ::stef::buf::decode_array( + r, + |r| { ::stef::buf::decode_i16(r) }, + )?, + )) + }?, + ); + } _ => continue, } } @@ -505,7 +538,15 @@ mod tests { ::stef::buf::encode_field( w, 2, - |w| { ::stef::buf::encode_vec(w, &*field2) }, + |w| { + ::stef::buf::encode_vec( + w, + &*field2, + |w, v| { + ::stef::buf::encode_bool(w, *v); + }, + ) + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -550,7 +591,14 @@ mod tests { match ::stef::buf::decode_id(r)? { ::stef::buf::END_MARKER => break, 1 => field1 = Some(::stef::buf::decode_string(r)?), - 2 => field2 = Some(::stef::buf::decode_vec(r)?), + 2 => { + field2 = Some( + ::stef::buf::decode_vec( + r, + |r| { ::stef::buf::decode_bool(r) }, + )?, + ); + } _ => continue, } } diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index 218609d..81ba0de 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -18,6 +18,7 @@ pub fn compile_struct( quote! { #[automatically_derived] impl #generics ::stef::Encode for #name #generics #generics_where { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { #fields } @@ -38,11 +39,16 @@ fn compile_struct_fields(fields: &Fields<'_>) -> TokenStream { let id = proc_macro2::Literal::u32_unsuffixed(id.0); let name = proc_macro2::Ident::new(name, Span::call_site()); - if matches!(ty, DataType::Option(_)) { - quote! { ::stef::buf::encode_field_option(w, #id, &self.#name); } + if let DataType::Option(ty) = ty { + let ty = compile_data_type(ty, if is_copy(ty) { + quote! { *v } + } else { + quote! { v } + }); + quote! { ::stef::buf::encode_field_option(w, #id, &self.#name, |w, v| { #ty; }); } } else { let ty = compile_data_type(ty, quote! { self.#name }); - quote! { ::stef::buf::encode_field(w, #id, |w| { #ty }); } + quote! { ::stef::buf::encode_field(w, #id, |w| { #ty; }); } } }, ); @@ -208,7 +214,26 @@ fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream .unwrap_or_default() } -#[allow(clippy::needless_pass_by_value)] +fn is_copy(ty: &DataType<'_>) -> bool { + matches!( + ty, + DataType::Bool + | DataType::U8 + | DataType::U16 + | DataType::U32 + | DataType::U64 + | DataType::U128 + | DataType::I8 + | DataType::I16 + | DataType::I32 + | DataType::I64 + | DataType::I128 + | DataType::F32 + | DataType::F64 + ) +} + +#[allow(clippy::needless_pass_by_value, clippy::too_many_lines)] fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { match ty { DataType::Bool => quote! { ::stef::buf::encode_bool(w, #name) }, @@ -226,23 +251,89 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::F64 => quote! { ::stef::buf::encode_f64(w, #name) }, DataType::String | DataType::StringRef => quote! { ::stef::buf::encode_string(w, &#name) }, DataType::Bytes | DataType::BytesRef => quote! { ::stef::buf::encode_bytes(w, &#name) }, - DataType::Vec(_ty) => quote! { ::stef::buf::encode_vec(w, &#name) }, - DataType::HashMap(_kv) => quote! { ::stef::buf::encode_hash_map(w, #name) }, - DataType::HashSet(_ty) => quote! { ::stef::buf::encode_hash_set(w, #name) }, - DataType::Option(_ty) => quote! { ::stef::buf::encode_option(w, &#name) }, + DataType::Vec(ty) => { + let ty = compile_data_type( + ty, + if is_copy(ty) { + quote! { *v } + } else { + quote! { v } + }, + ); + quote! { ::stef::buf::encode_vec(w, &#name, |w, v| { #ty; }) } + } + DataType::HashMap(kv) => { + let ty_k = compile_data_type( + &kv.0, + if is_copy(&kv.0) { + quote! { *k } + } else { + quote! { k } + }, + ); + let ty_v = compile_data_type( + &kv.1, + if is_copy(&kv.1) { + quote! { *v } + } else { + quote! { v } + }, + ); + quote! { ::stef::buf::encode_hash_map(w, #name, |w, k| { #ty_k; }, |w, v| { #ty_v; }) } + } + DataType::HashSet(ty) => { + let ty = compile_data_type( + ty, + if is_copy(ty) { + quote! { *v } + } else { + quote! { v } + }, + ); + quote! { ::stef::buf::encode_hash_set(w, #name, |w, v| { #ty; }) } + } + DataType::Option(ty) => { + let ty = compile_data_type( + ty, + if is_copy(ty) { + quote! { *v } + } else { + quote! { v } + }, + ); + quote! { ::stef::buf::encode_option(w, &#name, |w, v| { #ty; }) } + } DataType::BoxString => quote! { ::stef::buf::encode_string(w, &*#name) }, DataType::BoxBytes => quote! { ::stef::buf::encode_bytes(w, &*#name) }, DataType::Tuple(types) => match types.len() { - size @ 2..=12 => { - let fn_name = Ident::new(&format!("encode_tuple{size}"), Span::call_site()); - quote! { ::stef::buf::#fn_name(w, &#name) } + 2..=12 => { + let types = types.iter().enumerate().map(|(idx, ty)| { + let idx = proc_macro2::Literal::usize_unsuffixed(idx); + compile_data_type( + ty, + if is_copy(ty) { + quote! { #name.#idx } + } else { + quote! { &(#name.#idx) } + }, + ) + }); + quote! { #(#types;)* } } 0 => panic!("tuple with zero elements"), 1 => panic!("tuple with single element"), _ => panic!("tuple with more than 12 elements"), }, - DataType::Array(_ty, _size) => { - quote! { ::stef::buf::encode_array(w, &#name) } + DataType::Array(ty, _size) => { + let ty = compile_data_type( + ty, + if is_copy(ty) { + quote! { *v } + } else { + quote! { v } + }, + ); + quote! { ::stef::buf::encode_array(w, &#name, |w, v| { #ty; }) } } DataType::NonZero(_) | DataType::External(_) => { quote! { (#name).encode(w) } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@attribute-multi.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@attribute-multi.stef.snap index 6b72720..1fc0424 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attribute-multi.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attribute-multi.stef.snap @@ -7,6 +7,7 @@ input_file: crates/stef-parser/tests/inputs/attribute-multi.stef pub struct Sample; #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) {} } #[automatically_derived] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@attribute-single.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@attribute-single.stef.snap index 5ce3c37..a7a3392 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attribute-single.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attribute-single.stef.snap @@ -7,6 +7,7 @@ input_file: crates/stef-parser/tests/inputs/attribute-single.stef pub struct Sample; #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) {} } #[automatically_derived] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@attribute-unit.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@attribute-unit.stef.snap index d1f8db6..b2f0792 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attribute-unit.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attribute-unit.stef.snap @@ -7,6 +7,7 @@ input_file: crates/stef-parser/tests/inputs/attribute-unit.stef pub struct Sample; #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) {} } #[automatically_derived] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@attributes-min-ws.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@attributes-min-ws.stef.snap index 3a5fd73..31c67c5 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attributes-min-ws.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attributes-min-ws.stef.snap @@ -7,6 +7,7 @@ input_file: crates/stef-parser/tests/inputs/attributes-min-ws.stef pub struct Sample; #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) {} } #[automatically_derived] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap index eddcfea..aacddac 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap @@ -7,6 +7,7 @@ input_file: crates/stef-parser/tests/inputs/attributes.stef pub struct Sample; #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) {} } #[automatically_derived] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@module-basic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@module-basic.stef.snap index 0c6d863..b57fe1c 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@module-basic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@module-basic.stef.snap @@ -37,11 +37,14 @@ pub mod a { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { ::stef::buf::encode_field( w, 1, - |w| { ::stef::buf::encode_u32(w, self.value) }, + |w| { + ::stef::buf::encode_u32(w, self.value); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@schema-basic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@schema-basic.stef.snap index 56cbd73..7853546 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@schema-basic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@schema-basic.stef.snap @@ -11,9 +11,22 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.a) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_bool(w, self.b) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.a); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_bool(w, self.b); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@struct-basic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@struct-basic.stef.snap index e439dd4..69a4ae3 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@struct-basic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@struct-basic.stef.snap @@ -12,9 +12,22 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.a) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_bool(w, self.b) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.a); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_bool(w, self.b); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@struct-generics.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@struct-generics.stef.snap index 05a3107..ad0b06b 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@struct-generics.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@struct-generics.stef.snap @@ -15,9 +15,22 @@ where K: ::stef::buf::Encode, V: ::stef::buf::Encode, { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { (self.key).encode(w) }); - ::stef::buf::encode_field(w, 2, |w| { (self.value).encode(w) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + (self.key).encode(w); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + (self.value).encode(w); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@struct-many-ws.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@struct-many-ws.stef.snap index 41402d4..2c32760 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@struct-many-ws.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@struct-many-ws.stef.snap @@ -15,9 +15,22 @@ where A: ::stef::buf::Encode, B: ::stef::buf::Encode, { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.a) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_bool(w, self.b) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.a); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_bool(w, self.b); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@struct-min-ws.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@struct-min-ws.stef.snap index 7ce555e..a3e8bdf 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@struct-min-ws.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@struct-min-ws.stef.snap @@ -14,10 +14,29 @@ impl ::stef::Encode for Sample where T: ::stef::buf::Encode, { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.a) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_bool(w, self.b) }); - ::stef::buf::encode_field(w, 3, |w| { (self.c).encode(w) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_u32(w, self.a); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_bool(w, self.b); + }, + ); + ::stef::buf::encode_field( + w, + 3, + |w| { + (self.c).encode(w); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@struct-tuple.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@struct-tuple.stef.snap index 6e34243..aa7499f 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@struct-tuple.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@struct-tuple.stef.snap @@ -8,6 +8,7 @@ input_file: crates/stef-parser/tests/inputs/struct-tuple.stef pub struct Sample(u32, bool); #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_u32(w, self.0) }); ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_bool(w, self.1) }); diff --git a/crates/stef-build/tests/snapshots/compiler__compile@types-basic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@types-basic.stef.snap index 6580117..ccf5182 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@types-basic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@types-basic.stef.snap @@ -29,59 +29,162 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_bool(w, self.f01) }); - ::stef::buf::encode_field(w, 2, |w| { ::stef::buf::encode_u8(w, self.f02) }); - ::stef::buf::encode_field(w, 3, |w| { ::stef::buf::encode_u16(w, self.f03) }); - ::stef::buf::encode_field(w, 4, |w| { ::stef::buf::encode_u32(w, self.f04) }); - ::stef::buf::encode_field(w, 5, |w| { ::stef::buf::encode_u64(w, self.f05) }); - ::stef::buf::encode_field(w, 6, |w| { ::stef::buf::encode_u128(w, self.f06) }); - ::stef::buf::encode_field(w, 7, |w| { ::stef::buf::encode_i8(w, self.f07) }); - ::stef::buf::encode_field(w, 8, |w| { ::stef::buf::encode_i16(w, self.f08) }); - ::stef::buf::encode_field(w, 9, |w| { ::stef::buf::encode_i32(w, self.f09) }); - ::stef::buf::encode_field(w, 10, |w| { ::stef::buf::encode_i64(w, self.f10) }); - ::stef::buf::encode_field(w, 11, |w| { ::stef::buf::encode_i128(w, self.f11) }); - ::stef::buf::encode_field(w, 12, |w| { ::stef::buf::encode_f32(w, self.f12) }); - ::stef::buf::encode_field(w, 13, |w| { ::stef::buf::encode_f64(w, self.f13) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_bool(w, self.f01); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + ::stef::buf::encode_u8(w, self.f02); + }, + ); + ::stef::buf::encode_field( + w, + 3, + |w| { + ::stef::buf::encode_u16(w, self.f03); + }, + ); + ::stef::buf::encode_field( + w, + 4, + |w| { + ::stef::buf::encode_u32(w, self.f04); + }, + ); + ::stef::buf::encode_field( + w, + 5, + |w| { + ::stef::buf::encode_u64(w, self.f05); + }, + ); + ::stef::buf::encode_field( + w, + 6, + |w| { + ::stef::buf::encode_u128(w, self.f06); + }, + ); + ::stef::buf::encode_field( + w, + 7, + |w| { + ::stef::buf::encode_i8(w, self.f07); + }, + ); + ::stef::buf::encode_field( + w, + 8, + |w| { + ::stef::buf::encode_i16(w, self.f08); + }, + ); + ::stef::buf::encode_field( + w, + 9, + |w| { + ::stef::buf::encode_i32(w, self.f09); + }, + ); + ::stef::buf::encode_field( + w, + 10, + |w| { + ::stef::buf::encode_i64(w, self.f10); + }, + ); + ::stef::buf::encode_field( + w, + 11, + |w| { + ::stef::buf::encode_i128(w, self.f11); + }, + ); + ::stef::buf::encode_field( + w, + 12, + |w| { + ::stef::buf::encode_f32(w, self.f12); + }, + ); + ::stef::buf::encode_field( + w, + 13, + |w| { + ::stef::buf::encode_f64(w, self.f13); + }, + ); ::stef::buf::encode_field( w, 14, - |w| { ::stef::buf::encode_string(w, &self.f14) }, + |w| { + ::stef::buf::encode_string(w, &self.f14); + }, ); ::stef::buf::encode_field( w, 15, - |w| { ::stef::buf::encode_string(w, &self.f15) }, + |w| { + ::stef::buf::encode_string(w, &self.f15); + }, ); ::stef::buf::encode_field( w, 16, - |w| { ::stef::buf::encode_bytes(w, &self.f16) }, + |w| { + ::stef::buf::encode_bytes(w, &self.f16); + }, ); ::stef::buf::encode_field( w, 17, - |w| { ::stef::buf::encode_bytes(w, &self.f17) }, + |w| { + ::stef::buf::encode_bytes(w, &self.f17); + }, ); ::stef::buf::encode_field( w, 18, - |w| { ::stef::buf::encode_string(w, &*self.f18) }, + |w| { + ::stef::buf::encode_string(w, &*self.f18); + }, ); ::stef::buf::encode_field( w, 19, - |w| { ::stef::buf::encode_bytes(w, &*self.f19) }, + |w| { + ::stef::buf::encode_bytes(w, &*self.f19); + }, ); ::stef::buf::encode_field( w, 20, - |w| { ::stef::buf::encode_tuple3(w, &self.f20) }, + |w| { + ::stef::buf::encode_u32(w, self.f20.0); + ::stef::buf::encode_u32(w, self.f20.1); + ::stef::buf::encode_u32(w, self.f20.2); + }, ); ::stef::buf::encode_field( w, 21, - |w| { ::stef::buf::encode_array(w, &self.f21) }, + |w| { + ::stef::buf::encode_array( + w, + &self.f21, + |w, v| { + ::stef::buf::encode_u32(w, *v); + }, + ); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -132,8 +235,25 @@ impl ::stef::Decode for Sample { 17 => f17 = Some(::stef::buf::decode_bytes(r)?), 18 => f18 = Some(Box < str > ::decode(r)?), 19 => f19 = Some(Box < [u8] > ::decode(r)?), - 20 => f20 = Some(::stef::buf::decode_tuple3(r)?), - 21 => f21 = Some(::stef::buf::decode_array(r)?), + 20 => { + f20 = Some( + { + Ok::< + _, + ::stef::buf::Error, + >(( + ::stef::buf::decode_u32(r)?, + ::stef::buf::decode_u32(r)?, + ::stef::buf::decode_u32(r)?, + )) + }?, + ); + } + 21 => { + f21 = Some( + ::stef::buf::decode_array(r, |r| { ::stef::buf::decode_u32(r) })?, + ); + } _ => continue, } } 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 fbefd8d..10a7f9f 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 @@ -13,20 +13,65 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_vec(w, &self.f1) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_vec( + w, + &self.f1, + |w, v| { + ::stef::buf::encode_u32(w, *v); + }, + ); + }, + ); ::stef::buf::encode_field( w, 2, - |w| { ::stef::buf::encode_hash_map(w, self.f2) }, + |w| { + ::stef::buf::encode_hash_map( + w, + self.f2, + |w, k| { + ::stef::buf::encode_u32(w, *k); + }, + |w, v| { + ::stef::buf::encode_string(w, &v); + }, + ); + }, ); ::stef::buf::encode_field( w, 3, - |w| { ::stef::buf::encode_hash_set(w, self.f3) }, + |w| { + ::stef::buf::encode_hash_set( + w, + self.f3, + |w, v| { + ::stef::buf::encode_u32(w, *v); + }, + ); + }, + ); + ::stef::buf::encode_field_option( + w, + 4, + &self.f4, + |w, v| { + ::stef::buf::encode_u32(w, *v); + }, + ); + ::stef::buf::encode_field( + w, + 5, + |w| { + (self.f5).encode(w); + }, ); - ::stef::buf::encode_field_option(w, 4, &self.f4); - ::stef::buf::encode_field(w, 5, |w| { (self.f5).encode(w) }); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } @@ -41,9 +86,28 @@ impl ::stef::Decode for Sample { loop { match ::stef::buf::decode_id(r)? { ::stef::buf::END_MARKER => break, - 1 => f1 = Some(::stef::buf::decode_vec(r)?), - 2 => f2 = Some(::stef::buf::decode_hash_map(r)?), - 3 => f3 = Some(::stef::buf::decode_hash_set(r)?), + 1 => { + f1 = Some( + ::stef::buf::decode_vec(r, |r| { ::stef::buf::decode_u32(r) })?, + ); + } + 2 => { + f2 = Some( + ::stef::buf::decode_hash_map( + r, + |r| { ::stef::buf::decode_u32(r) }, + |r| { ::stef::buf::decode_string(r) }, + )?, + ); + } + 3 => { + f3 = Some( + ::stef::buf::decode_hash_set( + r, + |r| { ::stef::buf::decode_u32(r) }, + )?, + ); + } 4 => f4 = Some(::stef::buf::decode_u32(r)?), 5 => f5 = Some(NonZeroU32::decode(r)?), _ => continue, diff --git a/crates/stef-build/tests/snapshots/compiler__compile@types-nested.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@types-nested.stef.snap index 1f047f5..6855ce7 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@types-nested.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@types-nested.stef.snap @@ -9,8 +9,27 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { ::stef::buf::encode_vec(w, &self.value) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + ::stef::buf::encode_vec( + w, + &self.value, + |w, v| { + ::stef::buf::encode_option( + w, + &v, + |w, v| { + (v).encode(w); + }, + ); + }, + ); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } @@ -21,7 +40,14 @@ impl ::stef::Decode for Sample { loop { match ::stef::buf::decode_id(r)? { ::stef::buf::END_MARKER => break, - 1 => value = Some(::stef::buf::decode_vec(r)?), + 1 => { + value = Some( + ::stef::buf::decode_vec( + r, + |r| { ::stef::buf::decode_option(r, |r| { todo!() }) }, + )?, + ); + } _ => continue, } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@types-ref.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@types-ref.stef.snap index 2d88029..9f4b753 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@types-ref.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@types-ref.stef.snap @@ -10,9 +10,22 @@ pub struct Sample { } #[automatically_derived] impl ::stef::Encode for Sample { + #[allow(clippy::needless_borrow)] fn encode(&self, w: &mut impl ::stef::BufMut) { - ::stef::buf::encode_field(w, 1, |w| { (self.basic).encode(w) }); - ::stef::buf::encode_field(w, 2, |w| { (self.with_generics).encode(w) }); + ::stef::buf::encode_field( + w, + 1, + |w| { + (self.basic).encode(w); + }, + ); + ::stef::buf::encode_field( + w, + 2, + |w| { + (self.with_generics).encode(w); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } } diff --git a/crates/stef/src/buf/decode.rs b/crates/stef/src/buf/decode.rs index 7c6e54f..0e35f92 100644 --- a/crates/stef/src/buf/decode.rs +++ b/crates/stef/src/buf/decode.rs @@ -98,46 +98,72 @@ pub fn decode_bytes(r: &mut impl Buf) -> Result> { Ok(r.copy_to_bytes(len as usize).to_vec()) } -pub fn decode_vec(r: &mut impl Buf) -> Result> { +pub fn decode_vec(r: &mut R, decode: D) -> Result> +where + R: Buf, + D: Fn(&mut R) -> Result, +{ let len = decode_u64(r)?; - (0..len).map(|_| T::decode(r)).collect() + (0..len).map(|_| decode(r)).collect() } -pub fn decode_hash_map( - r: &mut impl Buf, -) -> Result> { +pub fn decode_hash_map( + r: &mut R, + decode_key: DK, + decode_value: DV, +) -> Result> +where + R: Buf, + K: Hash + Eq, + DK: Fn(&mut R) -> Result, + DV: Fn(&mut R) -> Result, +{ let len = decode_u64(r)?; (0..len) - .map(|_| Ok((K::decode(r)?, V::decode(r)?))) + .map(|_| Ok((decode_key(r)?, decode_value(r)?))) .collect() } -pub fn decode_hash_set(r: &mut impl Buf) -> Result> { +pub fn decode_hash_set(r: &mut R, decode: D) -> Result> +where + R: Buf, + T: Hash + Eq, + D: Fn(&mut R) -> Result, +{ let len = decode_u64(r)?; - (0..len).map(|_| T::decode(r)).collect() + (0..len).map(|_| decode(r)).collect() } -pub fn decode_option(r: &mut impl Buf) -> Result> { +pub fn decode_option(r: &mut R, decode: D) -> Result> +where + R: Buf, + D: Fn(&mut R) -> Result, +{ let some = decode_u8(r)? == 1; if some { - T::decode(r).map(Some) + decode(r).map(Some) } else { Ok(None) } } -pub fn decode_array(r: &mut impl Buf) -> Result<[T; N]> { +pub fn decode_array(r: &mut R, decode: D) -> Result<[T; N]> +where + R: Buf, + T: Debug, + D: Fn(&mut R) -> Result, +{ let len = decode_u64(r)?; if (len as usize) < N { return Err(Error::InsufficentData); } - let buf = (0..N).map(|_| T::decode(r)).collect::>>()?; + let buf = (0..N).map(|_| decode(r)).collect::>>()?; // read any remaining values, in case the old array definition was larger. // still have to decode the values to advance the buffer accordingly. for _ in N..len as usize { - T::decode(r)?; + decode(r)?; } // SAFETY: we can unwrap here, because we ensured the Vec exactly matches @@ -145,242 +171,6 @@ pub fn decode_array(r: &mut impl Buf) -> Resu Ok(buf.try_into().unwrap()) } -pub fn decode_tuple2(r: &mut impl Buf) -> Result<(T0, T1)> -where - T0: Decode, - T1: Decode, -{ - Ok((T0::decode(r)?, T1::decode(r)?)) -} - -pub fn decode_tuple3(r: &mut impl Buf) -> Result<(T0, T1, T2)> -where - T0: Decode, - T1: Decode, - T2: Decode, -{ - Ok((T0::decode(r)?, T1::decode(r)?, T2::decode(r)?)) -} - -pub fn decode_tuple4(r: &mut impl Buf) -> Result<(T0, T1, T2, T3)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - )) -} - -pub fn decode_tuple5(r: &mut impl Buf) -> Result<(T0, T1, T2, T3, T4)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - )) -} - -pub fn decode_tuple6(r: &mut impl Buf) -> Result<(T0, T1, T2, T3, T4, T5)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - )) -} - -pub fn decode_tuple7( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - )) -} - -pub fn decode_tuple8( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6, T7)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - T7::decode(r)?, - )) -} - -pub fn decode_tuple9( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6, T7, T8)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - T7::decode(r)?, - T8::decode(r)?, - )) -} - -pub fn decode_tuple10( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - T7::decode(r)?, - T8::decode(r)?, - T9::decode(r)?, - )) -} - -pub fn decode_tuple11( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, - T10: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - T7::decode(r)?, - T8::decode(r)?, - T9::decode(r)?, - T10::decode(r)?, - )) -} - -pub fn decode_tuple12( - r: &mut impl Buf, -) -> Result<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, - T10: Decode, - T11: Decode, -{ - Ok(( - T0::decode(r)?, - T1::decode(r)?, - T2::decode(r)?, - T3::decode(r)?, - T4::decode(r)?, - T5::decode(r)?, - T6::decode(r)?, - T7::decode(r)?, - T8::decode(r)?, - T9::decode(r)?, - T10::decode(r)?, - T11::decode(r)?, - )) -} - #[inline(always)] pub fn decode_id(r: &mut impl Buf) -> Result { decode_u32(r) @@ -438,7 +228,7 @@ where { #[inline(always)] fn decode(r: &mut impl Buf) -> Result { - decode_vec(r) + decode_vec(r, T::decode) } } @@ -449,7 +239,7 @@ where { #[inline(always)] fn decode(r: &mut impl Buf) -> Result { - decode_hash_map(r) + decode_hash_map(r, K::decode, V::decode) } } @@ -459,7 +249,7 @@ where { #[inline(always)] fn decode(r: &mut impl Buf) -> Result { - decode_hash_set(r) + decode_hash_set(r, T::decode) } } @@ -469,7 +259,7 @@ where { #[inline(always)] fn decode(r: &mut impl Buf) -> Result { - decode_option(r) + decode_option(r, T::decode) } } @@ -479,185 +269,7 @@ where { #[inline(always)] fn decode(r: &mut impl Buf) -> Result { - decode_array(r) - } -} - -impl Decode for (T0, T1) -where - T0: Decode, - T1: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple2(r) - } -} - -impl Decode for (T0, T1, T2) -where - T0: Decode, - T1: Decode, - T2: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple3(r) - } -} - -impl Decode for (T0, T1, T2, T3) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple4(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple5(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4, T5) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple6(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4, T5, T6) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple7(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4, T5, T6, T7) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple8(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4, T5, T6, T7, T8) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple9(r) - } -} - -impl Decode for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple10(r) - } -} - -impl Decode - for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, - T10: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple11(r) - } -} - -impl Decode - for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -where - T0: Decode, - T1: Decode, - T2: Decode, - T3: Decode, - T4: Decode, - T5: Decode, - T6: Decode, - T7: Decode, - T8: Decode, - T9: Decode, - T10: Decode, - T11: Decode, -{ - #[inline(always)] - fn decode(r: &mut impl Buf) -> Result { - decode_tuple12(r) + decode_array(r, T::decode) } } diff --git a/crates/stef/src/buf/encode.rs b/crates/stef/src/buf/encode.rs index 92331a2..a52beca 100644 --- a/crates/stef/src/buf/encode.rs +++ b/crates/stef/src/buf/encode.rs @@ -56,270 +56,73 @@ pub fn encode_bytes(w: &mut impl BufMut, value: &[u8]) { w.put(value) } -pub fn encode_vec(w: &mut impl BufMut, vec: &[T]) { +pub fn encode_vec(w: &mut W, vec: &[T], encode: E) +where + W: BufMut, + E: Fn(&mut W, &T), +{ encode_u64(w, vec.len() as u64); for value in vec { - value.encode(w); + encode(w, value); } } -pub fn encode_hash_map(w: &mut impl BufMut, map: &HashMap) { +pub fn encode_hash_map( + w: &mut W, + map: &HashMap, + encode_key: EK, + encode_value: EV, +) where + W: BufMut, + EK: Fn(&mut W, &K), + EV: Fn(&mut W, &V), +{ encode_u64(w, map.len() as u64); for (key, value) in map { - key.encode(w); - value.encode(w); + encode_key(w, key); + encode_value(w, value); } } -pub fn encode_hash_set(w: &mut impl BufMut, set: &HashSet) { +pub fn encode_hash_set(w: &mut W, set: &HashSet, encode: E) +where + W: BufMut, + E: Fn(&mut W, &T), +{ encode_u64(w, set.len() as u64); for value in set { - value.encode(w); + encode(w, value); } } -pub fn encode_option(w: &mut impl BufMut, option: &Option) { +pub fn encode_option(w: &mut W, option: &Option, encode: E) +where + W: BufMut, + E: Fn(&mut W, &T), +{ if let Some(value) = option { w.put_u8(1); - value.encode(w); + encode(w, value); } else { w.put_u8(0); } } -pub fn encode_array(w: &mut impl BufMut, array: &[T; N]) { +pub fn encode_array(w: &mut W, array: &[T; N], encode: E) +where + W: BufMut, + E: Fn(&mut W, &T), +{ encode_u64(w, array.len() as u64); for value in array { - value.encode(w); + encode(w, value); } } -pub fn encode_tuple2(w: &mut impl BufMut, tuple: &(T0, T1)) -where - T0: Encode, - T1: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); -} - -pub fn encode_tuple3(w: &mut impl BufMut, tuple: &(T0, T1, T2)) -where - T0: Encode, - T1: Encode, - T2: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); -} - -pub fn encode_tuple4(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3)) -where - T0: Encode, - T1: Encode, - T2: Encode, - T3: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); -} - -pub fn encode_tuple5(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4)) -where - T0: Encode, - T1: Encode, - T2: Encode, - T3: Encode, - T4: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); -} - -pub fn encode_tuple6(w: &mut impl BufMut, tuple: &(T0, T1, T2, T3, T4, T5)) -where - T0: Encode, - T1: Encode, - T2: Encode, - T3: Encode, - T4: Encode, - T5: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); -} - -pub fn encode_tuple7( - w: &mut impl BufMut, - tuple: &(T0, T1, T2, T3, T4, T5, T6), -) where - T0: Encode, - T1: Encode, - T2: Encode, - T3: Encode, - T4: Encode, - T5: Encode, - T6: Encode, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); -} - -pub fn encode_tuple8( - w: &mut impl BufMut, - tuple: &(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, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); - tuple.7.encode(w); -} - -pub fn encode_tuple9( - w: &mut impl BufMut, - tuple: &(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, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); - tuple.7.encode(w); - tuple.8.encode(w); -} - -pub fn encode_tuple10( - w: &mut impl BufMut, - tuple: &(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, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); - tuple.7.encode(w); - tuple.8.encode(w); - tuple.9.encode(w); -} - -pub fn encode_tuple11( - w: &mut impl BufMut, - tuple: &(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, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); - tuple.7.encode(w); - tuple.8.encode(w); - tuple.9.encode(w); - tuple.10.encode(w); -} - -#[allow(clippy::type_complexity)] -pub fn encode_tuple12( - w: &mut impl BufMut, - tuple: &(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, -{ - tuple.0.encode(w); - tuple.1.encode(w); - tuple.2.encode(w); - tuple.3.encode(w); - tuple.4.encode(w); - tuple.5.encode(w); - tuple.6.encode(w); - tuple.7.encode(w); - tuple.8.encode(w); - tuple.9.encode(w); - tuple.10.encode(w); - tuple.11.encode(w); -} - #[inline(always)] pub fn encode_id(w: &mut impl BufMut, id: u32) { encode_u32(w, id) @@ -336,14 +139,14 @@ where } #[inline(always)] -pub fn encode_field_option(w: &mut W, id: u32, option: &Option) +pub fn encode_field_option(w: &mut W, id: u32, option: &Option, encode: E) where W: BufMut, - T: Encode, + E: Fn(&mut W, &T), { if let Some(value) = option { encode_id(w, id); - value.encode(w); + encode(w, value); } } @@ -357,7 +160,7 @@ macro_rules! forward { impl Encode for $ty { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - [](w, *self) + [](w, *self); } } } @@ -375,21 +178,21 @@ forward!(f32, f64); impl Encode for String { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_string(w, self) + encode_string(w, self); } } impl Encode for Box { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_string(w, self) + encode_string(w, self); } } impl Encode for Box<[u8]> { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_bytes(w, self) + encode_bytes(w, self); } } @@ -399,7 +202,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_vec(w, self) + encode_vec(w, self, |w, v| v.encode(w)); } } @@ -409,7 +212,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_vec(w, self) + encode_vec(w, self, |w, v| v.encode(w)); } } @@ -420,7 +223,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_hash_map(w, self) + encode_hash_map(w, self, |w, k| k.encode(w), |w, v| v.encode(w)); } } @@ -430,7 +233,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_hash_set(w, self) + encode_hash_set(w, self, |w, v| v.encode(w)); } } @@ -440,7 +243,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_option(w, self) + encode_option(w, self, |w, v| v.encode(w)); } } @@ -450,185 +253,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - encode_array(w, self) - } -} - -impl Encode for (T0, T1) -where - T0: Encode, - T1: Encode, -{ - #[inline(always)] - fn encode(&self, w: &mut impl BufMut) { - encode_tuple2(w, self) - } -} - -impl Encode for (T0, T1, T2) -where - T0: Encode, - T1: Encode, - T2: Encode, -{ - #[inline(always)] - fn encode(&self, w: &mut impl BufMut) { - encode_tuple3(w, self) - } -} - -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) { - encode_tuple4(w, self) - } -} - -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) { - encode_tuple5(w, self) - } -} - -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) { - encode_tuple6(w, self) - } -} - -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) { - encode_tuple7(w, self) - } -} - -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) { - encode_tuple8(w, self) - } -} - -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) { - encode_tuple9(w, self) - } -} - -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) { - encode_tuple10(w, self) - } -} - -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) { - encode_tuple11(w, self) - } -} - -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) { - encode_tuple12(w, self) + encode_array(w, self, |w, v| v.encode(w)); } } @@ -698,7 +323,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - T::encode(self, w) + T::encode(self, w); } } @@ -708,7 +333,7 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - T::encode(self, w) + T::encode(self, w); } } @@ -718,6 +343,6 @@ where { #[inline(always)] fn encode(&self, w: &mut impl BufMut) { - T::encode(self, w) + T::encode(self, w); } }