From 131e7b46c252a8080c83a292a323c719a4a9fca7 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Thu, 28 Dec 2023 10:48:02 +0900 Subject: [PATCH] feat(compiler): introduce a simplified schema for easier codegen The parser's data structures can be a bit hard to use in the code generator, and some upcoming features would need to be rebuilt in every code generator. By introducing a simplified version of the schema data structures, common conversion logic can be moved into the compiler and overall make the data structures more convenient to use. --- Cargo.lock | 45 ++ crates/stef-benches/benches/compiler.rs | 9 + crates/stef-build/src/decode.rs | 256 ++++----- crates/stef-build/src/definition.rs | 229 ++++---- crates/stef-build/src/encode.rs | 496 +++++------------- crates/stef-build/src/lib.rs | 7 +- crates/stef-build/src/size.rs | 411 +++++---------- crates/stef-build/tests/compiler.rs | 2 + ...ompiler__compile@attribute_multi.stef.snap | 7 +- ...mpiler__compile@attribute_single.stef.snap | 7 +- ...compiler__compile@attribute_unit.stef.snap | 7 +- .../compiler__compile@attributes.stef.snap | 7 +- ...piler__compile@attributes_min_ws.stef.snap | 7 +- .../compiler__compile@enum_basic.stef.snap | 18 +- .../compiler__compile@enum_generics.stef.snap | 26 +- .../compiler__compile@enum_many_ws.stef.snap | 18 +- .../compiler__compile@enum_min_ws.stef.snap | 30 +- .../compiler__compile@mixed.stef.snap | 109 ++-- .../compiler__compile@module_basic.stef.snap | 14 +- .../compiler__compile@schema_basic.stef.snap | 30 +- .../compiler__compile@struct_basic.stef.snap | 12 +- ...ompiler__compile@struct_generics.stef.snap | 12 +- ...compiler__compile@struct_many_ws.stef.snap | 16 +- .../compiler__compile@struct_min_ws.stef.snap | 16 +- .../compiler__compile@struct_tuple.stef.snap | 12 +- .../compiler__compile@types_basic.stef.snap | 145 +++-- .../compiler__compile@types_generic.stef.snap | 70 ++- .../compiler__compile@types_nested.stef.snap | 24 +- ...compiler__compile@types_non_zero.stef.snap | 127 +++-- .../compiler__compile@types_ref.stef.snap | 26 +- .../compiler__compile_extra@enum.stef.snap | 25 +- .../compiler__compile_extra@struct.stef.snap | 27 +- crates/stef-compiler/Cargo.toml | 4 + crates/stef-compiler/src/lib.rs | 2 + crates/stef-compiler/src/simplify.rs | 443 ++++++++++++++++ crates/stef-derive/src/debug.rs | 6 +- crates/stef-derive/src/lib.rs | 2 +- crates/stef-go/src/decode.rs | 201 +++---- crates/stef-go/src/definition.rs | 396 ++++++-------- crates/stef-go/src/encode.rs | 182 +++---- crates/stef-go/src/size.rs | 180 +++---- crates/stef-go/tests/render.rs | 1 + .../render__render@enum_basic.stef.snap | 36 +- .../render__render@enum_generics.stef.snap | 36 +- .../render__render@enum_many_ws.stef.snap | 36 +- .../render__render@enum_min_ws.stef.snap | 54 +- .../snapshots/render__render@mixed.stef.snap | 44 +- .../render__render@schema_basic.stef.snap | 36 +- .../render__render@struct_tuple.stef.snap | 36 +- .../render__render@types_basic.stef.snap | 4 +- .../render__render@types_generic.stef.snap | 92 ++-- crates/stef-parser/src/lib.rs | 4 +- crates/stef-playground/src/lib.rs | 4 + 53 files changed, 2080 insertions(+), 1966 deletions(-) create mode 100644 crates/stef-compiler/src/simplify.rs diff --git a/Cargo.lock b/Cargo.lock index 70c9f02..744e9d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -403,6 +403,12 @@ dependencies = [ "syn 2.0.42", ] +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + [[package]] name = "either" version = "1.9.0" @@ -1057,6 +1063,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1083,6 +1113,17 @@ dependencies = [ "syn 2.0.42", ] +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_fmt" version = "1.0.3" @@ -1203,6 +1244,9 @@ dependencies = [ "insta", "miette", "owo-colors", + "schemars", + "serde", + "serde_json", "stef-parser", "thiserror", ] @@ -1416,6 +1460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] diff --git a/crates/stef-benches/benches/compiler.rs b/crates/stef-benches/benches/compiler.rs index d5ee4ee..c4ab87a 100644 --- a/crates/stef-benches/benches/compiler.rs +++ b/crates/stef-benches/benches/compiler.rs @@ -28,3 +28,12 @@ fn resolve_large_schema(bencher: Bencher<'_, '_>) { bencher.bench(|| stef_compiler::resolve_schemas(black_box(list))); } + +#[divan::bench(consts = [1, 10, 100, 1000])] +fn simplify_large_schema(bencher: Bencher<'_, '_>) { + let schema = stef_benches::generate_schema(N); + let schema = stef_parser::Schema::parse(&schema, None).unwrap(); + let _ = stef_compiler::simplify_schema(&schema); + + bencher.bench(|| stef_compiler::simplify_schema(black_box(&schema))); +} diff --git a/crates/stef-build/src/decode.rs b/crates/stef-build/src/decode.rs index 043bc9c..39118ba 100644 --- a/crates/stef-build/src/decode.rs +++ b/crates/stef-build/src/decode.rs @@ -1,7 +1,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; -use stef_parser::{ - DataType, Enum, ExternalType, Fields, Generics, NamedField, Struct, Type, UnnamedField, Variant, +use stef_compiler::simplify::{ + Enum, ExternalType, Field, FieldKind, Fields, Struct, Type, Variant, }; use crate::{BytesType, Opts}; @@ -10,19 +10,18 @@ pub(super) fn compile_struct( opts: &Opts, Struct { comment: _, - attributes: _, name, generics, fields, }: &Struct<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); - let field_vars = compile_field_vars(opts, fields); + let field_vars = compile_field_vars(opts, &fields.fields); let field_matches = compile_field_matches(opts, fields); let field_assigns = compile_field_assigns(fields); - let body = if matches!(fields, Fields::Unit) { + let body = if fields.kind == FieldKind::Unit { quote! { Ok(Self) } } else { quote! { @@ -56,13 +55,12 @@ pub(super) fn compile_enum( opts: &Opts, Enum { comment: _, - attributes: _, name, generics, variants, }: &Enum<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); let variants = variants.iter().map(|v| compile_variant(opts, v)); @@ -90,13 +88,13 @@ fn compile_variant( .. }: &Variant<'_>, ) -> TokenStream { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = Ident::new(name.get(), Span::call_site()); - let field_vars = compile_field_vars(opts, fields); + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = Ident::new(name, Span::call_site()); + let field_vars = compile_field_vars(opts, &fields.fields); let field_matches = compile_field_matches(opts, fields); let field_assigns = compile_field_assigns(fields); - if matches!(fields, Fields::Unit) { + if fields.kind == FieldKind::Unit { quote! { #id => Ok(Self::#name) } } else { quote! { @@ -118,23 +116,16 @@ fn compile_variant( } } -fn compile_field_vars(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - let vars: Box> = match fields { - Fields::Named(named) => Box::new(named.iter().map(|named| { - let name = Ident::new(named.name.get(), Span::call_site()); - (name, &named.ty) - })), - Fields::Unnamed(unnamed) => Box::new(unnamed.iter().enumerate().map(|(idx, unnamed)| { - let name = Ident::new(&format!("n{idx}"), Span::call_site()); - (name, &unnamed.ty) - })), - Fields::Unit => return quote! {}, - }; +fn compile_field_vars(opts: &Opts, fields: &[Field<'_>]) -> TokenStream { + let vars = fields.iter().map(|field| { + let name = Ident::new(&field.name, Span::call_site()); + (name, &field.ty) + }); let vars = vars.map(|(name, ty)| { let ty_ident = super::definition::compile_data_type(opts, ty); - if matches!(ty.value, DataType::Option(_)) { + if matches!(ty, Type::Option(_)) { quote! { let mut #name: #ty_ident = None; } } else { quote! { let mut #name: Option<#ty_ident> = None; } @@ -145,107 +136,58 @@ fn compile_field_vars(opts: &Opts, fields: &Fields<'_>) -> TokenStream { } fn compile_field_matches(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let calls = named.iter().map( - |NamedField { - comment: _, - name, - ty, - id, - .. - }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - let ty = compile_data_type( - opts, - if let DataType::Option(ty) = &ty.value { - ty - } else { - ty - }, - true, - ); - - quote! { #id => #name = Some(#ty?) } - }, - ); + let calls = fields.fields.iter().map(|Field { name, ty, id, .. }| { + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = proc_macro2::Ident::new(name, Span::call_site()); + let ty = compile_data_type(opts, if let Type::Option(ty) = &ty { ty } else { ty }, true); - quote! { #(#calls,)* } - } - Fields::Unnamed(unnamed) => { - let calls = unnamed - .iter() - .enumerate() - .map(|(idx, UnnamedField { ty, id, .. })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = Ident::new(&format!("n{idx}"), Span::call_site()); - let ty = compile_data_type( - opts, - if let DataType::Option(ty) = &ty.value { - ty - } else { - ty - }, - true, - ); - - quote! { #id => #name = Some(#ty?) } - }); + quote! { #id => #name = Some(#ty?) } + }); - quote! { #(#calls,)* } - } - Fields::Unit => quote! {}, - } + quote! { #(#calls,)* } } fn compile_field_assigns(fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let assigns = named.iter().map(|named| { - let name = Ident::new(named.name.get(), Span::call_site()); - let name_lit = proc_macro2::Literal::string(named.name.get()); - let id = proc_macro2::Literal::u32_unsuffixed(named.id.get()); - - if matches!(named.ty.value, DataType::Option(_)) { - quote! { #name } - } else { - quote! { #name: #name.ok_or(::stef::buf::Error::MissingField { - id: #id, - name: Some(#name_lit), - })? } - } - }); + let assigns = fields.fields.iter().map(|Field { name, ty, id, .. }| { + let name_lit = if fields.kind == FieldKind::Named { + let lit = proc_macro2::Literal::string(name); + quote! { Some(#lit)} + } else { + quote! { None } + }; + let name = Ident::new(name, Span::call_site()); + let id = proc_macro2::Literal::u32_unsuffixed(*id); - quote! { {#(#assigns,)*} } + if matches!(ty, Type::Option(_)) { + quote! { #name } + } else if fields.kind == FieldKind::Named { + quote! { + #name: #name.ok_or(::stef::buf::Error::MissingField { + id: #id, + name: #name_lit, + })? + } + } else { + quote! { + #name.ok_or(::stef::buf::Error::MissingField { + id: #id, + name: #name_lit, + })? + } } - Fields::Unnamed(unnamed) => { - let assigns = unnamed.iter().enumerate().map(|(idx, unnamed)| { - let name = Ident::new(&format!("n{idx}"), Span::call_site()); - let id = proc_macro2::Literal::u32_unsuffixed(unnamed.id.get()); - - if matches!(unnamed.ty.value, DataType::Option(_)) { - quote! { #name } - } else { - quote! { #name.ok_or(::stef::buf::Error::MissingField { - id: #id, - name: None, - })? } - } - }); + }); - quote! { (#(#assigns,)*) } - } - Fields::Unit => quote! {}, + if fields.kind == FieldKind::Named { + quote! { { #(#assigns,)* } } + } else { + quote! { (#(#assigns,)*) } } } -fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream) { +fn compile_generics(types: &[&str]) -> (TokenStream, TokenStream) { (!types.is_empty()) .then(|| { - let types = types - .iter() - .map(|ty| Ident::new(ty.get(), Span::call_site())); + let types = types.iter().map(|ty| Ident::new(ty, Span::call_site())); let types2 = types.clone(); ( @@ -258,57 +200,57 @@ fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream #[allow(clippy::needless_pass_by_value, clippy::too_many_lines)] fn compile_data_type(opts: &Opts, ty: &Type<'_>, root: bool) -> TokenStream { - match &ty.value { - DataType::Bool => quote! { ::stef::buf::decode_bool(r) }, - DataType::U8 => quote! { ::stef::buf::decode_u8(r) }, - DataType::U16 => quote! { ::stef::buf::decode_u16(r) }, - DataType::U32 => quote! { ::stef::buf::decode_u32(r) }, - DataType::U64 => quote! { ::stef::buf::decode_u64(r) }, - DataType::U128 => quote! { ::stef::buf::decode_u128(r) }, - DataType::I8 => quote! { ::stef::buf::decode_i8(r) }, - DataType::I16 => quote! { ::stef::buf::decode_i16(r) }, - DataType::I32 => quote! { ::stef::buf::decode_i32(r) }, - DataType::I64 => quote! { ::stef::buf::decode_i64(r) }, - DataType::I128 => quote! { ::stef::buf::decode_i128(r) }, - DataType::F32 => quote! { ::stef::buf::decode_f32(r) }, - DataType::F64 => quote! { ::stef::buf::decode_f64(r) }, - DataType::String | DataType::StringRef => quote! { ::stef::buf::decode_string(r) }, - DataType::Bytes | DataType::BytesRef => match opts.bytes_type { + match ty { + Type::Bool => quote! { ::stef::buf::decode_bool(r) }, + Type::U8 => quote! { ::stef::buf::decode_u8(r) }, + Type::U16 => quote! { ::stef::buf::decode_u16(r) }, + Type::U32 => quote! { ::stef::buf::decode_u32(r) }, + Type::U64 => quote! { ::stef::buf::decode_u64(r) }, + Type::U128 => quote! { ::stef::buf::decode_u128(r) }, + Type::I8 => quote! { ::stef::buf::decode_i8(r) }, + Type::I16 => quote! { ::stef::buf::decode_i16(r) }, + Type::I32 => quote! { ::stef::buf::decode_i32(r) }, + Type::I64 => quote! { ::stef::buf::decode_i64(r) }, + Type::I128 => quote! { ::stef::buf::decode_i128(r) }, + Type::F32 => quote! { ::stef::buf::decode_f32(r) }, + Type::F64 => quote! { ::stef::buf::decode_f64(r) }, + Type::String | Type::StringRef => quote! { ::stef::buf::decode_string(r) }, + Type::Bytes | Type::BytesRef => match opts.bytes_type { BytesType::VecU8 => quote! { ::stef::buf::decode_bytes_std(r) }, BytesType::Bytes => quote! { ::stef::buf::decode_bytes_bytes(r) }, }, - DataType::Vec(ty) => { + Type::Vec(ty) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_vec(r, |r| { #ty }) } } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { let ty_k = compile_data_type(opts, &kv.0, false); let ty_v = compile_data_type(opts, &kv.1, false); quote! { ::stef::buf::decode_hash_map(r, |r| { #ty_k }, |r| { #ty_v }) } } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_hash_set(r, |r| { #ty }) } } - DataType::Option(ty) => { + Type::Option(ty) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_option(r, |r| { #ty }) } } - DataType::NonZero(ty) => match &ty.value { - 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 => { + Type::NonZero(ty) => match &**ty { + Type::U8 => quote! { ::stef::buf::decode_non_zero_u8(r) }, + Type::U16 => quote! { ::stef::buf::decode_non_zero_u16(r) }, + Type::U32 => quote! { ::stef::buf::decode_non_zero_u32(r) }, + Type::U64 => quote! { ::stef::buf::decode_non_zero_u64(r) }, + Type::U128 => quote! { ::stef::buf::decode_non_zero_u128(r) }, + Type::I8 => quote! { ::stef::buf::decode_non_zero_i8(r) }, + Type::I16 => quote! { ::stef::buf::decode_non_zero_i16(r) }, + Type::I32 => quote! { ::stef::buf::decode_non_zero_i32(r) }, + Type::I64 => quote! { ::stef::buf::decode_non_zero_i64(r) }, + Type::I128 => quote! { ::stef::buf::decode_non_zero_i128(r) }, + Type::String | Type::StringRef => { quote! { ::stef::buf::decode_non_zero_string(r) } } - DataType::Bytes | DataType::BytesRef => match opts.bytes_type { + Type::Bytes | Type::BytesRef => match opts.bytes_type { BytesType::VecU8 => { quote! { ::stef::buf::decode_non_zero_bytes_std(r) } } @@ -316,24 +258,24 @@ fn compile_data_type(opts: &Opts, ty: &Type<'_>, root: bool) -> TokenStream { quote! { ::stef::buf::decode_non_zero_bytes_bytes(r) } } }, - DataType::Vec(ty) => { + Type::Vec(ty) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_non_zero_vec(r, |r| { #ty }) } } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { let ty_k = compile_data_type(opts, &kv.0, false); let ty_v = compile_data_type(opts, &kv.1, false); quote! { ::stef::buf::decode_non_zero_hash_map(r, |r| { #ty_k }, |r| { #ty_v }) } } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_non_zero_hash_set(r, |r| { #ty }) } } ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::BoxString => quote! { Box::::decode(r) }, - DataType::BoxBytes => quote! { Box::<[u8]>::decode(r) }, - DataType::Tuple(types) => match types.len() { + Type::BoxString => quote! { Box::::decode(r) }, + Type::BoxBytes => quote! { Box::<[u8]>::decode(r) }, + Type::Tuple(types) => match types.len() { 2..=12 => { let types = types.iter().map(|ty| compile_data_type(opts, ty, false)); let length = root.then_some(quote! { ::stef::buf::decode_u64(r)?; }); @@ -344,19 +286,17 @@ fn compile_data_type(opts: &Opts, ty: &Type<'_>, root: bool) -> TokenStream { } n => todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, _size) => { + Type::Array(ty, _size) => { let ty = compile_data_type(opts, ty, false); quote! { ::stef::buf::decode_array(r, |r| { #ty }) } } - DataType::External(ExternalType { + Type::External(ExternalType { path, name, generics, }) => { - let path = path - .iter() - .map(|part| Ident::new(part.get(), Span::call_site())); - let ty = Ident::new(name.get(), Span::call_site()); + let path = path.iter().map(|part| Ident::new(part, Span::call_site())); + let ty = Ident::new(name, Span::call_site()); let generics = (!generics.is_empty()).then(|| { let types = generics .iter() diff --git a/crates/stef-build/src/definition.rs b/crates/stef-build/src/definition.rs index 9e39a89..2a1f562 100644 --- a/crates/stef-build/src/definition.rs +++ b/crates/stef-build/src/definition.rs @@ -1,8 +1,8 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; -use stef_parser::{ - Comment, Const, DataType, Definition, Enum, ExternalType, Fields, Generics, Import, Literal, - LiteralValue, Module, NamedField, Schema, Struct, Type, TypeAlias, UnnamedField, Variant, +use stef_compiler::simplify::{ + Const, Definition, Enum, ExternalType, Field, FieldKind, Fields, Import, Literal, Module, + Schema, Struct, Type, TypeAlias, Variant, }; use super::{decode, encode, size}; @@ -64,7 +64,7 @@ fn compile_module( }: &Module<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let definitions = definitions.iter().map(|def| compile_definition(opts, def)); quote! { @@ -82,22 +82,22 @@ fn compile_struct( opts: &Opts, Struct { comment, - attributes: _, name, generics, fields, }: &Struct<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let generics = compile_generics(generics); + let semicolon = (fields.kind != FieldKind::Named).then_some(quote! {;}); let fields = compile_fields(opts, fields, true); quote! { #comment #[derive(Clone, Debug, PartialEq)] #[allow(clippy::module_name_repetitions, clippy::option_option)] - pub struct #name #generics #fields + pub struct #name #generics #fields #semicolon } } @@ -105,14 +105,13 @@ fn compile_enum( opts: &Opts, Enum { comment, - attributes: _, name, generics, variants, }: &Enum<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let generics = compile_generics(generics); let variants = variants.iter().map(|v| compile_variant(opts, v)); @@ -136,7 +135,7 @@ fn compile_variant( }: &Variant<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let fields = compile_fields(opts, fields, false); quote! { @@ -155,7 +154,7 @@ fn compile_alias( }: &TypeAlias<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let generics = compile_generics(generics); let target = compile_data_type(opts, target); @@ -175,7 +174,7 @@ fn compile_const( }: &Const<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let ty = compile_const_data_type(ty); let value = compile_literal(value); @@ -192,7 +191,7 @@ fn compile_import( }: &Import<'_>, ) -> TokenStream { let segments = segments.iter().enumerate().map(|(i, segment)| { - let segment = Ident::new(segment.get(), Span::call_site()); + let segment = Ident::new(segment, Span::call_site()); if i > 0 { quote! {::#segment} } else { @@ -200,7 +199,7 @@ fn compile_import( } }); let element = element.as_ref().map(|element| { - let element = Ident::new(element.get(), Span::call_site()); + let element = Ident::new(element, Span::call_site()); quote! { ::#element} }); @@ -210,153 +209,133 @@ fn compile_import( } } -fn compile_comment(Comment(lines): &Comment<'_>) -> TokenStream { - let lines = lines.iter().map(|line| format!(" {}", line.value)); +fn compile_comment(lines: &[&str]) -> TokenStream { + let lines = lines.iter().map(|line| format!(" {line}")); quote! { #(#[doc = #lines])* } } -fn compile_generics(Generics(types): &Generics<'_>) -> Option { +fn compile_generics(types: &[&str]) -> Option { (!types.is_empty()).then(|| { - let types = types - .iter() - .map(|ty| Ident::new(ty.get(), Span::call_site())); + let types = types.iter().map(|ty| Ident::new(ty, Span::call_site())); quote! { <#(#types,)*> } }) } fn compile_fields(opts: &Opts, fields: &Fields<'_>, for_struct: bool) -> TokenStream { - match fields { - Fields::Named(named) => { - let fields = named.iter().map( - |NamedField { - comment, name, ty, .. - }| { - let comment = compile_comment(comment); - let public = for_struct.then(|| quote! { pub }); - let name = Ident::new(name.get(), Span::call_site()); - let ty = compile_data_type(opts, ty); - quote! { - #comment - #public #name: #ty - } - }, - ); - - quote! { { - #(#fields,)* - } } - } - Fields::Unnamed(unnamed) => { - let fields = unnamed.iter().map(|UnnamedField { ty, .. }| { - let public = for_struct.then(|| quote! { pub }); - let ty = compile_data_type(opts, ty); - quote! { #public #ty } - }); + let values = fields.fields.iter().map( + |Field { + comment, name, ty, .. + }| { + let public = for_struct.then(|| quote! { pub }); + let ty = compile_data_type(opts, ty); - if for_struct { - quote! { (#(#fields,)*); } - } else { - quote! { (#(#fields,)*) } - } - } - Fields::Unit => { - if for_struct { - quote! { ; } + if fields.kind == FieldKind::Named { + let comment = compile_comment(comment); + let name = Ident::new(name, Span::call_site()); + + quote! { + #comment + #public #name: #ty + } } else { - quote! {} + quote! { #public #ty } } - } + }, + ); + + match fields.kind { + FieldKind::Named => quote! { {#(#values,)*} }, + FieldKind::Unnamed => quote! { (#(#values,)*) }, + FieldKind::Unit => quote! {}, } } pub(super) fn compile_data_type(opts: &Opts, ty: &Type<'_>) -> TokenStream { - match &ty.value { - DataType::Bool => quote! { bool }, - DataType::U8 => quote! { u8 }, - DataType::U16 => quote! { u16 }, - DataType::U32 => quote! { u32 }, - DataType::U64 => quote! { u64 }, - DataType::U128 => quote! { u128 }, - DataType::I8 => quote! { i8 }, - DataType::I16 => quote! { i16 }, - DataType::I32 => quote! { i32 }, - DataType::I64 => quote! { i64 }, - DataType::I128 => quote! { i128 }, - DataType::F32 => quote! { f32 }, - DataType::F64 => quote! { f64 }, - DataType::String | DataType::StringRef => quote! { String }, - DataType::Bytes | DataType::BytesRef => match opts.bytes_type { + match &ty { + Type::Bool => quote! { bool }, + Type::U8 => quote! { u8 }, + Type::U16 => quote! { u16 }, + Type::U32 => quote! { u32 }, + Type::U64 => quote! { u64 }, + Type::U128 => quote! { u128 }, + Type::I8 => quote! { i8 }, + Type::I16 => quote! { i16 }, + Type::I32 => quote! { i32 }, + Type::I64 => quote! { i64 }, + Type::I128 => quote! { i128 }, + Type::F32 => quote! { f32 }, + Type::F64 => quote! { f64 }, + Type::String | Type::StringRef => quote! { String }, + Type::Bytes | Type::BytesRef => match opts.bytes_type { BytesType::VecU8 => quote! { Vec }, BytesType::Bytes => quote! { ::stef::buf::Bytes }, }, - DataType::Vec(ty) => { + Type::Vec(ty) => { let ty = compile_data_type(opts, ty); quote! { Vec<#ty> } } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { let k = compile_data_type(opts, &kv.0); let v = compile_data_type(opts, &kv.1); quote! { ::std::collections::HashMap<#k, #v> } } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { let ty = compile_data_type(opts, ty); quote! { ::std::collections::HashSet<#ty> } } - DataType::Option(ty) => { + Type::Option(ty) => { let ty = compile_data_type(opts, ty); quote! { Option<#ty> } } - DataType::NonZero(ty) => match &ty.value { - DataType::U8 => quote! { ::std::num::NonZeroU8 }, - DataType::U16 => quote! { ::std::num::NonZeroU16 }, - DataType::U32 => quote! { ::std::num::NonZeroU32 }, - DataType::U64 => quote! { ::std::num::NonZeroU64 }, - DataType::U128 => quote! { ::std::num::NonZeroU128 }, - DataType::I8 => quote! { ::std::num::NonZeroI8 }, - DataType::I16 => quote! { ::std::num::NonZeroI16 }, - DataType::I32 => quote! { ::std::num::NonZeroI32 }, - DataType::I64 => quote! { ::std::num::NonZeroI64 }, - DataType::I128 => quote! { ::std::num::NonZeroI128 }, - DataType::String | DataType::StringRef => quote! { ::stef::NonZeroString }, - DataType::Bytes | DataType::BytesRef => match opts.bytes_type { + Type::NonZero(ty) => match &**ty { + Type::U8 => quote! { ::std::num::NonZeroU8 }, + Type::U16 => quote! { ::std::num::NonZeroU16 }, + Type::U32 => quote! { ::std::num::NonZeroU32 }, + Type::U64 => quote! { ::std::num::NonZeroU64 }, + Type::U128 => quote! { ::std::num::NonZeroU128 }, + Type::I8 => quote! { ::std::num::NonZeroI8 }, + Type::I16 => quote! { ::std::num::NonZeroI16 }, + Type::I32 => quote! { ::std::num::NonZeroI32 }, + Type::I64 => quote! { ::std::num::NonZeroI64 }, + Type::I128 => quote! { ::std::num::NonZeroI128 }, + Type::String | Type::StringRef => quote! { ::stef::NonZeroString }, + Type::Bytes | Type::BytesRef => match opts.bytes_type { BytesType::VecU8 => quote! { ::stef::NonZeroBytes }, BytesType::Bytes => quote! { ::stef::NonZero<::stef::buf::Bytes> }, }, - DataType::Vec(ty) => { + Type::Vec(ty) => { let ty = compile_data_type(opts, ty); quote! { ::stef::NonZeroVec<#ty> } } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { let k = compile_data_type(opts, &kv.0); let v = compile_data_type(opts, &kv.1); quote! { ::stef::NonZeroHashMap<#k, #v> } } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { let ty = compile_data_type(opts, ty); quote! { ::stef::NonZeroHashSet<#ty> } } ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::BoxString => quote! { Box }, - DataType::BoxBytes => quote! { Box<[u8]> }, - DataType::Tuple(types) => { + Type::BoxString => quote! { Box }, + Type::BoxBytes => quote! { Box<[u8]> }, + Type::Tuple(types) => { let types = types.iter().map(|ty| compile_data_type(opts, ty)); quote! { (#(#types,)*) } } - DataType::Array(ty, size) => { + Type::Array(ty, size) => { let ty = compile_data_type(opts, ty); let size = proc_macro2::Literal::u32_unsuffixed(*size); quote! { [#ty; #size] } } - DataType::External(ExternalType { + Type::External(ExternalType { path, name, generics, }) => { - let path = path - .iter() - .map(|part| Ident::new(part.get(), Span::call_site())); - let name = Ident::new(name.get(), Span::call_site()); + let path = path.iter().map(|part| Ident::new(part, Span::call_site())); + let name = Ident::new(name, Span::call_site()); let generics = (!generics.is_empty()).then(|| { let types = generics.iter().map(|ty| compile_data_type(opts, ty)); quote! { <#(#types,)*> } @@ -370,32 +349,32 @@ pub(super) fn compile_data_type(opts: &Opts, ty: &Type<'_>) -> TokenStream { } fn compile_const_data_type(ty: &Type<'_>) -> TokenStream { - match &ty.value { - DataType::Bool => quote! { bool }, - DataType::U8 => quote! { u8 }, - DataType::U16 => quote! { u16 }, - DataType::U32 => quote! { u32 }, - DataType::U64 => quote! { u64 }, - DataType::U128 => quote! { u128 }, - DataType::I8 => quote! { i8 }, - DataType::I16 => quote! { i16 }, - DataType::I32 => quote! { i32 }, - DataType::I64 => quote! { i64 }, - DataType::I128 => quote! { i128 }, - DataType::F32 => quote! { f32 }, - DataType::F64 => quote! { f64 }, - DataType::String | DataType::StringRef => quote! { &str }, - DataType::Bytes | DataType::BytesRef => quote! { &[u8] }, + match &ty { + Type::Bool => quote! { bool }, + Type::U8 => quote! { u8 }, + Type::U16 => quote! { u16 }, + Type::U32 => quote! { u32 }, + Type::U64 => quote! { u64 }, + Type::U128 => quote! { u128 }, + Type::I8 => quote! { i8 }, + Type::I16 => quote! { i16 }, + Type::I32 => quote! { i32 }, + Type::I64 => quote! { i64 }, + Type::I128 => quote! { i128 }, + Type::F32 => quote! { f32 }, + Type::F64 => quote! { f64 }, + Type::String | Type::StringRef => quote! { &str }, + Type::Bytes | Type::BytesRef => quote! { &[u8] }, _ => panic!("invalid data type for const"), } } fn compile_literal(literal: &Literal) -> TokenStream { - match &literal.value { - LiteralValue::Bool(b) => quote! { #b }, - LiteralValue::Int(i) => proc_macro2::Literal::i128_unsuffixed(*i).into_token_stream(), - LiteralValue::Float(f) => proc_macro2::Literal::f64_unsuffixed(*f).into_token_stream(), - LiteralValue::String(s) => proc_macro2::Literal::string(s).into_token_stream(), - LiteralValue::Bytes(b) => proc_macro2::Literal::byte_string(b).into_token_stream(), + match &literal { + Literal::Bool(b) => quote! { #b }, + Literal::Int(i) => proc_macro2::Literal::i128_unsuffixed(*i).into_token_stream(), + Literal::Float(f) => proc_macro2::Literal::f64_unsuffixed(*f).into_token_stream(), + Literal::String(s) => proc_macro2::Literal::string(s).into_token_stream(), + Literal::Bytes(b) => proc_macro2::Literal::byte_string(b).into_token_stream(), } } diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index 6fd7663..53b9ff5 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -1,8 +1,6 @@ use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use stef_parser::{ - DataType, Enum, Fields, Generics, NamedField, Struct, Type, UnnamedField, Variant, -}; +use quote::{quote, ToTokens}; +use stef_compiler::simplify::{Enum, Field, FieldKind, Fields, Struct, Type, Variant}; use crate::{BytesType, Opts}; @@ -10,110 +8,53 @@ pub(super) fn compile_struct( opts: &Opts, Struct { comment: _, - attributes: _, name, generics, fields, }: &Struct<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let names = fields + .fields + .iter() + .map(|field| Ident::new(&field.name, Span::call_site())); + let names = match fields.kind { + FieldKind::Named => quote! { {#(#names,)*} }, + FieldKind::Unnamed => quote! { (#(#names,)*) }, + FieldKind::Unit => quote! {}, + }; + + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); - let fields = compile_struct_fields(opts, fields); + let fields = compile_fields(opts, fields); quote! { #[automatically_derived] impl #generics ::stef::Encode for #name #generics #generics_where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self #names = self; #fields } } } } -fn compile_struct_fields(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let calls = named.iter().map( - |NamedField { - comment: _, - name, - ty, - id, - .. - }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - - if let DataType::Option(ty) = &ty.value { - let (enc, ty) = compile_data_type(opts, ty, if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, true); - let id = quote! { ::stef::FieldId::new(#id, #enc) }; - quote! { ::stef::buf::encode_field_option(w, #id, &self.#name, |w, v| { #ty; }); } - } else { - let (enc, ty) = compile_data_type(opts, ty, quote! { self.#name }, true); - let id = quote! { ::stef::FieldId::new(#id, #enc) }; - quote! { ::stef::buf::encode_field(w, #id, |w| { #ty; }); } - } - }, - ); - - quote! { - #(#calls)* - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } - } - Fields::Unnamed(unnamed) => { - let calls = unnamed - .iter() - .enumerate() - .map(|(idx, UnnamedField { ty, id, .. })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let idx = proc_macro2::Literal::usize_unsuffixed(idx); - - if let DataType::Option(ty) = &ty.value { - let (enc, ty) = compile_data_type(opts, ty, if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, true); - let id = quote !{ ::stef::FieldId::new(#id, #enc) }; - quote! { ::stef::buf::encode_field_option(w, #id, &self.#idx, |w, v| { #ty; }); } - }else{ - let (enc, ty) = compile_data_type(opts, ty, quote! { self.#idx }, true); - let id = quote !{ ::stef::FieldId::new(#id, #enc) }; - quote! { ::stef::buf::encode_field(w, #id, |w| { #ty; }); } - } - }); - - quote! { - #(#calls)* - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } - } - Fields::Unit => quote! {}, - } -} - pub(super) fn compile_enum( opts: &Opts, Enum { comment: _, - attributes: _, name, generics, variants, }: &Enum<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); let variants = variants.iter().map(|v| compile_variant(opts, v)); @@ -122,6 +63,7 @@ pub(super) fn compile_enum( impl #generics ::stef::Encode for #name #generics #generics_where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -144,103 +86,66 @@ fn compile_variant( .. }: &Variant<'_>, ) -> TokenStream { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); + let id = proc_macro2::Literal::u32_unsuffixed(*id); let id = quote! { ::stef::VariantId::new(#id) }; - let name = Ident::new(name.get(), Span::call_site()); - let fields_body = compile_variant_fields(opts, fields); - - match fields { - Fields::Named(named) => { - let field_names = named - .iter() - .map(|NamedField { name, .. }| Ident::new(name.get(), Span::call_site())); + let name = Ident::new(name, Span::call_site()); + let fields_body = compile_fields(opts, fields); + let field_names = fields + .fields + .iter() + .map(|field| Ident::new(&field.name, Span::call_site())); - quote! { - Self::#name{ #(#field_names,)* } => { - ::stef::buf::encode_variant_id(w, #id); - #fields_body - } + match fields.kind { + FieldKind::Named => quote! { + Self::#name{ #(#field_names,)* } => { + ::stef::buf::encode_variant_id(w, #id); + #fields_body } - } - Fields::Unnamed(unnamed) => { - let field_names = unnamed - .iter() - .enumerate() - .map(|(idx, _)| Ident::new(&format!("n{idx}"), Span::call_site())); - - quote! { - Self::#name(#(#field_names,)*) => { - ::stef::buf::encode_variant_id(w, #id); - #fields_body - } + }, + FieldKind::Unnamed => quote! { + Self::#name(#(#field_names,)*) => { + ::stef::buf::encode_variant_id(w, #id); + #fields_body } - } - Fields::Unit => quote! { + }, + FieldKind::Unit => quote! { Self::#name => { ::stef::buf::encode_variant_id(w, #id); - #fields_body } }, } } -fn compile_variant_fields(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let calls = named.iter().map( - |NamedField { - comment: _, - name, - ty, - id, - .. - }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = proc_macro2::Ident::new(name.get(), Span::call_site()); +fn compile_fields(opts: &Opts, fields: &Fields<'_>) -> TokenStream { + if fields.kind == FieldKind::Unit { + quote! {} + } else { + let calls = fields.fields.iter().map(|Field { name, ty, id, .. }| { + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = proc_macro2::Ident::new(name, Span::call_site()); - if matches!(ty.value, DataType::Option(_)) { - quote! { ::stef::buf::encode_field_option(w, #id, &#name); } - } else { - let (enc, ty) = compile_data_type(opts, ty, quote! { *#name }, true); - let id = quote! { ::stef::FieldId::new(#id, #enc) }; - quote! { ::stef::buf::encode_field(w, #id, |w| { #ty }); } - } - }, - ); - - quote! { - #(#calls)* - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); + if let Type::Option(ty) = &ty { + let (enc, ty) = compile_data_type(opts, ty, quote! { v }, true); + let id = quote! { ::stef::FieldId::new(#id, #enc) }; + quote! { ::stef::buf::encode_field_option(w, #id, #name, |w, v| { #ty; }); } + } else { + let (enc, ty) = compile_data_type(opts, ty, name.into_token_stream(), true); + let id = quote! { ::stef::FieldId::new(#id, #enc) }; + quote! { ::stef::buf::encode_field(w, #id, |w| { #ty; }); } } - } - Fields::Unnamed(unnamed) => { - let calls = unnamed - .iter() - .enumerate() - .map(|(idx, UnnamedField { ty, id, .. })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = Ident::new(&format!("n{idx}"), Span::call_site()); - let (enc, ty) = compile_data_type(opts, ty, quote! { *#name }, true); - let id = quote! { ::stef::FieldId::new(#id, #enc) }; + }); - quote! { ::stef::buf::encode_field(w, #id, |w| { #ty }); } - }); - - quote! { - #(#calls)* - ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); - } + quote! { + #(#calls)* + ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } - Fields::Unit => quote! {}, } } -fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream) { +fn compile_generics(types: &[&str]) -> (TokenStream, TokenStream) { (!types.is_empty()) .then(|| { - let types = types - .iter() - .map(|ty| Ident::new(ty.get(), Span::call_site())); + let types = types.iter().map(|ty| Ident::new(ty, Span::call_site())); let types2 = types.clone(); ( @@ -251,25 +156,6 @@ fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream .unwrap_or_default() } -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( opts: &Opts, @@ -277,142 +163,91 @@ fn compile_data_type( name: TokenStream, root: bool, ) -> (TokenStream, TokenStream) { - match &ty.value { - DataType::Bool => ( + match &ty { + Type::Bool => ( quote! { ::stef::FieldEncoding::Fixed1 }, - quote! { ::stef::buf::encode_bool(w, #name) }, + quote! { ::stef::buf::encode_bool(w, *#name) }, ), - DataType::U8 => ( + Type::U8 => ( quote! { ::stef::FieldEncoding::Fixed1 }, - quote! { ::stef::buf::encode_u8(w, #name) }, + quote! { ::stef::buf::encode_u8(w, *#name) }, ), - DataType::U16 => ( + Type::U16 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_u16(w, #name) }, + quote! { ::stef::buf::encode_u16(w, *#name) }, ), - DataType::U32 => ( + Type::U32 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_u32(w, #name) }, + quote! { ::stef::buf::encode_u32(w, *#name) }, ), - DataType::U64 => ( + Type::U64 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_u64(w, #name) }, + quote! { ::stef::buf::encode_u64(w, *#name) }, ), - DataType::U128 => ( + Type::U128 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_u128(w, #name) }, + quote! { ::stef::buf::encode_u128(w, *#name) }, ), - DataType::I8 => ( + Type::I8 => ( quote! { ::stef::FieldEncoding::Fixed1 }, - quote! { ::stef::buf::encode_i8(w, #name) }, + quote! { ::stef::buf::encode_i8(w, *#name) }, ), - DataType::I16 => ( + Type::I16 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_i16(w, #name) }, + quote! { ::stef::buf::encode_i16(w, *#name) }, ), - DataType::I32 => ( + Type::I32 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_i32(w, #name) }, + quote! { ::stef::buf::encode_i32(w, *#name) }, ), - DataType::I64 => ( + Type::I64 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_i64(w, #name) }, + quote! { ::stef::buf::encode_i64(w, *#name) }, ), - DataType::I128 => ( + Type::I128 => ( quote! { ::stef::FieldEncoding::Varint }, - quote! { ::stef::buf::encode_i128(w, #name) }, + quote! { ::stef::buf::encode_i128(w, *#name) }, ), - DataType::F32 => ( + Type::F32 => ( quote! { ::stef::FieldEncoding::Fixed4 }, - quote! { ::stef::buf::encode_f32(w, #name) }, + quote! { ::stef::buf::encode_f32(w, *#name) }, ), - DataType::F64 => ( + Type::F64 => ( quote! { ::stef::FieldEncoding::Fixed8 }, - quote! { ::stef::buf::encode_f64(w, #name) }, + quote! { ::stef::buf::encode_f64(w, *#name) }, ), - DataType::String | DataType::StringRef | DataType::BoxString => ( + Type::String | Type::StringRef | Type::BoxString => ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_string(w, &#name) }, + quote! { ::stef::buf::encode_string(w, #name) }, ), - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => match opts.bytes_type { + Type::Bytes | Type::BytesRef | Type::BoxBytes => match opts.bytes_type { BytesType::VecU8 => ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_bytes_std(w, &#name) }, + quote! { ::stef::buf::encode_bytes_std(w, #name) }, ), BytesType::Bytes => ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_bytes_bytes(w, &#name) }, + quote! { ::stef::buf::encode_bytes_bytes(w, #name) }, ), }, - DataType::Vec(ty) => { - let size = super::size::compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - let (_, encode) = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - false, - ); + Type::Vec(ty) => { + let size = super::size::compile_data_type(opts, ty, quote! { v }); + let (_, encode) = compile_data_type(opts, ty, quote! { v }, false); (quote! { ::stef::FieldEncoding::LengthPrefixed }, { - quote! { ::stef::buf::encode_vec(w, &#name, |v| { #size }, |w, v| { #encode; }) } + quote! { ::stef::buf::encode_vec(w, #name, |v| { #size }, |w, v| { #encode; }) } }) } - DataType::HashMap(kv) => { - let size_k = super::size::compile_data_type( - opts, - &kv.0, - if is_copy(&kv.0.value) { - quote! { *k } - } else { - quote! { k } - }, - ); - let size_v = super::size::compile_data_type( - opts, - &kv.1, - if is_copy(&kv.1.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - let (_, encode_k) = compile_data_type( - opts, - &kv.0, - if is_copy(&kv.0.value) { - quote! { *k } - } else { - quote! { k } - }, - false, - ); - let (_, encode_v) = compile_data_type( - opts, - &kv.1, - if is_copy(&kv.1.value) { - quote! { *v } - } else { - quote! { v } - }, - false, - ); + Type::HashMap(kv) => { + let size_k = super::size::compile_data_type(opts, &kv.0, quote! { k }); + let size_v = super::size::compile_data_type(opts, &kv.1, quote! { v }); + let (_, encode_k) = compile_data_type(opts, &kv.0, quote! { k }, false); + let (_, encode_v) = compile_data_type(opts, &kv.1, quote! { v }, false); ( quote! { ::stef::FieldEncoding::LengthPrefixed }, quote! { ::stef::buf::encode_hash_map( w, - &#name, + #name, |k| { #size_k }, |v| { #size_v }, |w, k| { #encode_k; }, @@ -421,129 +256,83 @@ fn compile_data_type( }, ) } - DataType::HashSet(ty) => { - let size = super::size::compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - let (_, encode) = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - false, - ); + Type::HashSet(ty) => { + let size = super::size::compile_data_type(opts, ty, quote! { v }); + let (_, encode) = compile_data_type(opts, ty, quote! { v }, false); ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_hash_set(w, &#name, |v| { #size }, |w, v| { #encode; }) }, + quote! { ::stef::buf::encode_hash_set(w, #name, |v| { #size }, |w, v| { #encode; }) }, ) } - DataType::Option(ty) => { - let (_, encode) = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - false, - ); + Type::Option(ty) => { + let (_, encode) = compile_data_type(opts, ty, quote! { v }, false); ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_option(w, &#name, |w, v| { #encode; }) }, + quote! { ::stef::buf::encode_option(w, #name, |w, v| { #encode; }) }, ) } - DataType::NonZero(ty) => match &ty.value { - DataType::U8 => ( + Type::NonZero(ty) => match &**ty { + Type::U8 => ( quote! { ::stef::FieldEncoding::Fixed1 }, quote! { ::stef::buf::encode_u8(w, #name.get()) }, ), - DataType::U16 => ( + Type::U16 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_u16(w, #name.get()) }, ), - DataType::U32 => ( + Type::U32 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_u32(w, #name.get()) }, ), - DataType::U64 => ( + Type::U64 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_u64(w, #name.get()) }, ), - DataType::U128 => ( + Type::U128 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_u128(w, #name.get()) }, ), - DataType::I8 => ( + Type::I8 => ( quote! { ::stef::FieldEncoding::Fixed1 }, quote! { ::stef::buf::encode_i8(w, #name.get()) }, ), - DataType::I16 => ( + Type::I16 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_i16(w, #name.get()) }, ), - DataType::I32 => ( + Type::I32 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_i32(w, #name.get()) }, ), - DataType::I64 => ( + Type::I64 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_i64(w, #name.get()) }, ), - DataType::I128 => ( + Type::I128 => ( quote! { ::stef::FieldEncoding::Varint }, quote! { ::stef::buf::encode_i128(w, #name.get()) }, ), - DataType::String - | DataType::StringRef - | DataType::Bytes - | DataType::BytesRef - | DataType::Vec(_) - | DataType::HashMap(_) - | DataType::HashSet(_) => compile_data_type(opts, ty, quote! { #name.get() }, false), + Type::String + | Type::StringRef + | Type::Bytes + | Type::BytesRef + | Type::Vec(_) + | Type::HashMap(_) + | Type::HashSet(_) => compile_data_type(opts, ty, quote! { #name.get() }, false), ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => match types.len() { + Type::Tuple(types) => match types.len() { 2..=12 => { let encode = types.iter().enumerate().map(|(idx, ty)| { let idx = proc_macro2::Literal::usize_unsuffixed(idx); - - compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { #name.#idx } - } else { - quote! { &(#name.#idx) } - }, - false, - ) - .1 + compile_data_type(opts, ty, quote! { &#name.#idx }, false).1 }); ( quote! { ::stef::FieldEncoding::LengthPrefixed }, if root { let size = types.iter().enumerate().map(|(idx, ty)| { let idx = proc_macro2::Literal::usize_unsuffixed(idx); - - super::size::compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { #name.#idx } - } else { - quote! { &(#name.#idx) } - }, - ) + super::size::compile_data_type(opts, ty, quote! { &#name.#idx }) }); quote! { ::stef::buf::encode_tuple(w, || { #(#size)+* }, |w| { #(#encode;)* }) } @@ -554,34 +343,17 @@ fn compile_data_type( } n => todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, _size) => { - let size = super::size::compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - let (_, encode) = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - false, - ); + Type::Array(ty, _size) => { + let size = super::size::compile_data_type(opts, ty, quote! { v }); + let (_, encode) = compile_data_type(opts, ty, quote! { v }, false); ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { ::stef::buf::encode_array(w, &#name, |v| { #size }, |w, v| { #encode; }) }, + quote! { ::stef::buf::encode_array(w, #name, |v| { #size }, |w, v| { #encode; }) }, ) } - DataType::External(_) => ( + Type::External(_) => ( quote! { ::stef::FieldEncoding::LengthPrefixed }, - quote! { (#name).encode(w) }, + quote! { #name.encode(w) }, ), } } diff --git a/crates/stef-build/src/lib.rs b/crates/stef-build/src/lib.rs index adcd88c..853f287 100644 --- a/crates/stef-build/src/lib.rs +++ b/crates/stef-build/src/lib.rs @@ -136,8 +136,11 @@ impl Compiler { }; for (stem, schema) in validated { - let code = definition::compile_schema(&opts, schema); - let code = prettyplease::unparse(&syn::parse2(code).unwrap()); + let schema = stef_compiler::simplify_schema(schema); + let code = definition::compile_schema(&opts, &schema); + let code = prettyplease::unparse( + &syn::parse2(code.clone()).unwrap_or_else(|_| panic!("{code}")), + ); let out_file = out_dir.join(format!("{stem}.rs",)); diff --git a/crates/stef-build/src/size.rs b/crates/stef-build/src/size.rs index 4dd2d25..e9b7938 100644 --- a/crates/stef-build/src/size.rs +++ b/crates/stef-build/src/size.rs @@ -1,8 +1,6 @@ use proc_macro2::{Ident, Span, TokenStream}; -use quote::quote; -use stef_parser::{ - DataType, Enum, Fields, Generics, NamedField, Struct, Type, UnnamedField, Variant, -}; +use quote::{quote, ToTokens}; +use stef_compiler::simplify::{Enum, Field, FieldKind, Fields, Struct, Type, Variant}; use crate::{BytesType, Opts}; @@ -10,13 +8,22 @@ pub(super) fn compile_struct( opts: &Opts, Struct { comment: _, - attributes: _, name, generics, fields, }: &Struct<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let names = fields + .fields + .iter() + .map(|field| Ident::new(&field.name, Span::call_site())); + let names = match fields.kind { + FieldKind::Named => quote! { {#(#names,)*} }, + FieldKind::Unnamed => quote! { (#(#names,)*) }, + FieldKind::Unit => quote! {}, + }; + + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); let fields = compile_struct_fields(opts, fields); @@ -25,11 +32,13 @@ pub(super) fn compile_struct( impl #generics ::stef::buf::Size for #name #generics #generics_where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self #names = self; #fields } } @@ -37,77 +46,28 @@ pub(super) fn compile_struct( } fn compile_struct_fields(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let calls = named.iter().map( - |NamedField { - comment: _, - name, - ty, - id, - .. - }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - - if let DataType::Option(ty) = &ty.value { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { - ::stef::buf::size_field_option(#id, self.#name.as_ref(), |v| { #ty }) - } - } else { - let ty = compile_data_type(opts, ty, quote! { self.#name }); - quote! { ::stef::buf::size_field(#id, || { #ty }) } - } - }, - ); + if fields.kind == FieldKind::Unit { + quote! { 0 } + } else { + let calls = fields.fields.iter().map(|Field { name, ty, id, .. }| { + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = proc_macro2::Ident::new(name, Span::call_site()); - quote! { - #(#calls +)* - ::stef::buf::size_u32(::stef::buf::END_MARKER) + if let Type::Option(ty) = &ty { + let ty = compile_data_type(opts, ty, quote! { v }); + quote! { + ::stef::buf::size_field_option(#id, #name.as_ref(), |v| { #ty }) + } + } else { + let ty = compile_data_type(opts, ty, name.into_token_stream()); + quote! { ::stef::buf::size_field(#id, || { #ty }) } } - } - Fields::Unnamed(unnamed) => { - let calls = unnamed - .iter() - .enumerate() - .map(|(idx, UnnamedField { ty, id, .. })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let idx = proc_macro2::Literal::usize_unsuffixed(idx); - - if let DataType::Option(ty) = &ty.value { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { - ::stef::buf::size_field_option(#id, self.#idx.as_ref(), |v| { #ty }) - } - } else { - let ty = compile_data_type(opts, ty, quote! { self.#idx }); - quote! { ::stef::buf::size_field(#id, || { #ty }) } - } - }); + }); - quote! { - #(#calls +)* - ::stef::buf::size_u32(::stef::buf::END_MARKER) - } + quote! { + #(#calls +)* + ::stef::buf::size_u32(::stef::buf::END_MARKER) } - Fields::Unit => quote! { 0 }, } } @@ -115,13 +75,12 @@ pub(super) fn compile_enum( opts: &Opts, Enum { comment: _, - attributes: _, name, generics, variants, }: &Enum<'_>, ) -> TokenStream { - let name = Ident::new(name.get(), Span::call_site()); + let name = Ident::new(name, Span::call_site()); let (generics, generics_where) = compile_generics(generics); let variants = variants.iter().map(|v| compile_variant(opts, v)); @@ -130,6 +89,7 @@ pub(super) fn compile_enum( impl #generics ::stef::buf::Size for #name #generics #generics_where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -152,37 +112,28 @@ fn compile_variant( .. }: &Variant<'_>, ) -> TokenStream { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = Ident::new(name.get(), Span::call_site()); + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = Ident::new(name, Span::call_site()); let fields_body = compile_variant_fields(opts, fields); + let field_names = fields + .fields + .iter() + .map(|field| Ident::new(&field.name, Span::call_site())); - match fields { - Fields::Named(named) => { - let field_names = named - .iter() - .map(|NamedField { name, .. }| Ident::new(name.get(), Span::call_site())); - - quote! { - Self::#name{ #(#field_names,)* } => { - ::stef::buf::size_id(#id) + - #fields_body - } + match fields.kind { + FieldKind::Named => quote! { + Self::#name{ #(#field_names,)* } => { + ::stef::buf::size_id(#id) + + #fields_body } - } - Fields::Unnamed(unnamed) => { - let field_names = unnamed - .iter() - .enumerate() - .map(|(idx, _)| Ident::new(&format!("n{idx}"), Span::call_site())); - - quote! { - Self::#name(#(#field_names,)*) => { - ::stef::buf::size_id(#id) + - #fields_body - } + }, + FieldKind::Unnamed => quote! { + Self::#name(#(#field_names,)*) => { + ::stef::buf::size_id(#id) + + #fields_body } - } - Fields::Unit => quote! { + }, + FieldKind::Unit => quote! { Self::#name => { ::stef::buf::size_id(#id) } @@ -191,64 +142,35 @@ fn compile_variant( } fn compile_variant_fields(opts: &Opts, fields: &Fields<'_>) -> TokenStream { - match fields { - Fields::Named(named) => { - let calls = named.iter().map( - |NamedField { - comment: _, - name, - ty, - id, - .. - }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - - if matches!(ty.value, DataType::Option(_)) { - quote! { ::stef::buf::size_field_option(#id, #name.as_ref()) } - } else { - let ty = compile_data_type(opts, ty, quote! { *#name }); - quote! { ::stef::buf::size_field(#id, || { #ty }) } - } - }, - ); + if fields.kind == FieldKind::Unit { + quote! { 0 } + } else { + let calls = fields.fields.iter().map(|Field { name, ty, id, .. }| { + let id = proc_macro2::Literal::u32_unsuffixed(*id); + let name = proc_macro2::Ident::new(name, Span::call_site()); - quote! { - #(#calls +)* - ::stef::buf::size_u32(::stef::buf::END_MARKER) + if let Type::Option(ty) = &ty { + let ty = compile_data_type(opts, ty, quote! { v }); + quote! { + ::stef::buf::size_field_option(#id, #name.as_ref(), |v| { #ty }) + } + } else { + let ty = compile_data_type(opts, ty, name.into_token_stream()); + quote! { ::stef::buf::size_field(#id, || { #ty }) } } - } - Fields::Unnamed(unnamed) => { - let calls = unnamed - .iter() - .enumerate() - .map(|(idx, UnnamedField { ty, id, .. })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.get()); - let name = Ident::new(&format!("n{idx}"), Span::call_site()); - - if matches!(ty.value, DataType::Option(_)) { - quote! { ::stef::buf::size_field_option(#id, #name.as_ref()) } - } else { - let ty = compile_data_type(opts, ty, quote! { *#name }); - quote! { ::stef::buf::size_field(#id, || { #ty }) } - } - }); + }); - quote! { - #(#calls +)* - ::stef::buf::size_u32(::stef::buf::END_MARKER) - } + quote! { + #(#calls +)* + ::stef::buf::size_u32(::stef::buf::END_MARKER) } - Fields::Unit => quote! { 0 }, } } -fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream) { +fn compile_generics(types: &[&str]) -> (TokenStream, TokenStream) { (!types.is_empty()) .then(|| { - let types = types - .iter() - .map(|ty| Ident::new(ty.get(), Span::call_site())); + let types = types.iter().map(|ty| Ident::new(ty, Span::call_site())); let types2 = types.clone(); ( @@ -259,157 +181,82 @@ fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream .unwrap_or_default() } -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)] pub(crate) fn compile_data_type(opts: &Opts, ty: &Type<'_>, name: TokenStream) -> TokenStream { - match &ty.value { - DataType::Bool => quote! { ::stef::buf::size_bool(#name) }, - DataType::U8 => quote! { ::stef::buf::size_u8(#name) }, - DataType::U16 => quote! { ::stef::buf::size_u16(#name) }, - DataType::U32 => quote! { ::stef::buf::size_u32(#name) }, - DataType::U64 => quote! { ::stef::buf::size_u64(#name) }, - DataType::U128 => quote! { ::stef::buf::size_u128(#name) }, - DataType::I8 => quote! { ::stef::buf::size_i8(#name) }, - DataType::I16 => quote! { ::stef::buf::size_i16(#name) }, - DataType::I32 => quote! { ::stef::buf::size_i32(#name) }, - DataType::I64 => quote! { ::stef::buf::size_i64(#name) }, - DataType::I128 => quote! { ::stef::buf::size_i128(#name) }, - DataType::F32 => quote! { ::stef::buf::size_f32(#name) }, - DataType::F64 => quote! { ::stef::buf::size_f64(#name) }, - DataType::String | DataType::StringRef | DataType::BoxString => { - quote! { ::stef::buf::size_string(&#name) } + match &ty { + Type::Bool => quote! { ::stef::buf::size_bool(*#name) }, + Type::U8 => quote! { ::stef::buf::size_u8(*#name) }, + Type::U16 => quote! { ::stef::buf::size_u16(*#name) }, + Type::U32 => quote! { ::stef::buf::size_u32(*#name) }, + Type::U64 => quote! { ::stef::buf::size_u64(*#name) }, + Type::U128 => quote! { ::stef::buf::size_u128(*#name) }, + Type::I8 => quote! { ::stef::buf::size_i8(*#name) }, + Type::I16 => quote! { ::stef::buf::size_i16(*#name) }, + Type::I32 => quote! { ::stef::buf::size_i32(*#name) }, + Type::I64 => quote! { ::stef::buf::size_i64(*#name) }, + Type::I128 => quote! { ::stef::buf::size_i128(*#name) }, + Type::F32 => quote! { ::stef::buf::size_f32(*#name) }, + Type::F64 => quote! { ::stef::buf::size_f64(*#name) }, + Type::String | Type::StringRef | Type::BoxString => { + quote! { ::stef::buf::size_string(#name) } } - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => match opts.bytes_type { - BytesType::VecU8 => quote! { ::stef::buf::size_bytes_std(&#name) }, - BytesType::Bytes => quote! { ::stef::buf::size_bytes_bytes(&#name) }, + Type::Bytes | Type::BytesRef | Type::BoxBytes => match opts.bytes_type { + BytesType::VecU8 => quote! { ::stef::buf::size_bytes_std(#name) }, + BytesType::Bytes => quote! { ::stef::buf::size_bytes_bytes(#name) }, }, - DataType::Vec(ty) => { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { ::stef::buf::size_vec(&#name, |v| { #ty }) } + Type::Vec(ty) => { + let ty = compile_data_type(opts, ty, quote! { v }); + quote! { ::stef::buf::size_vec(#name, |v| { #ty }) } } - DataType::HashMap(kv) => { - let ty_k = compile_data_type( - opts, - &kv.0, - if is_copy(&kv.0.value) { - quote! { *k } - } else { - quote! { k } - }, - ); - let ty_v = compile_data_type( - opts, - &kv.1, - if is_copy(&kv.1.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { ::stef::buf::size_hash_map(&#name, |k| { #ty_k }, |v| { #ty_v }) } + Type::HashMap(kv) => { + let ty_k = compile_data_type(opts, &kv.0, quote! { k }); + let ty_v = compile_data_type(opts, &kv.1, quote! { v }); + quote! { ::stef::buf::size_hash_map(#name, |k| { #ty_k }, |v| { #ty_v }) } } - DataType::HashSet(ty) => { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { ::stef::buf::size_hash_set(&#name, |v| { #ty }) } + Type::HashSet(ty) => { + let ty = compile_data_type(opts, ty, quote! { v }); + quote! { ::stef::buf::size_hash_set(#name, |v| { #ty }) } } - DataType::Option(ty) => { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); + Type::Option(ty) => { + let ty = compile_data_type(opts, ty, quote! { v }); quote! { ::stef::buf::size_option(#name.as_ref(), |v| { #ty }) } } - DataType::NonZero(ty) => match &ty.value { - DataType::U8 => quote! { ::stef::buf::size_u8(#name.get()) }, - DataType::U16 => quote! { ::stef::buf::size_u16(#name.get()) }, - DataType::U32 => quote! { ::stef::buf::size_u32(#name.get()) }, - DataType::U64 => quote! { ::stef::buf::size_u64(#name.get()) }, - DataType::U128 => quote! { ::stef::buf::size_u128(#name.get()) }, - DataType::I8 => quote! { ::stef::buf::size_i8(#name.get()) }, - DataType::I16 => quote! { ::stef::buf::size_i16(#name.get()) }, - DataType::I32 => quote! { ::stef::buf::size_i32(#name.get()) }, - DataType::I64 => quote! { ::stef::buf::size_i64(#name.get()) }, - DataType::I128 => quote! { ::stef::buf::size_i128(#name.get()) }, - DataType::String - | DataType::StringRef - | DataType::Bytes - | DataType::BytesRef - | DataType::Vec(_) - | DataType::HashMap(_) - | DataType::HashSet(_) => compile_data_type(opts, ty, quote! { #name.get() }), + Type::NonZero(ty) => match &**ty { + Type::U8 => quote! { ::stef::buf::size_u8(#name.get()) }, + Type::U16 => quote! { ::stef::buf::size_u16(#name.get()) }, + Type::U32 => quote! { ::stef::buf::size_u32(#name.get()) }, + Type::U64 => quote! { ::stef::buf::size_u64(#name.get()) }, + Type::U128 => quote! { ::stef::buf::size_u128(#name.get()) }, + Type::I8 => quote! { ::stef::buf::size_i8(#name.get()) }, + Type::I16 => quote! { ::stef::buf::size_i16(#name.get()) }, + Type::I32 => quote! { ::stef::buf::size_i32(#name.get()) }, + Type::I64 => quote! { ::stef::buf::size_i64(#name.get()) }, + Type::I128 => quote! { ::stef::buf::size_i128(#name.get()) }, + Type::String + | Type::StringRef + | Type::Bytes + | Type::BytesRef + | Type::Vec(_) + | Type::HashMap(_) + | Type::HashSet(_) => compile_data_type(opts, ty, quote! { #name.get() }), ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => match types.len() { + Type::Tuple(types) => match types.len() { 2..=12 => { let types = types.iter().enumerate().map(|(idx, ty)| { let idx = proc_macro2::Literal::usize_unsuffixed(idx); - compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { #name.#idx } - } else { - quote! { &(#name.#idx) } - }, - ) + compile_data_type(opts, ty, quote! { &#name.#idx }) }); quote! { #(#types)+* } } n => todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, _size) => { - let ty = compile_data_type( - opts, - ty, - if is_copy(&ty.value) { - quote! { *v } - } else { - quote! { v } - }, - ); - quote! { ::stef::buf::size_array(&#name, |v| { #ty }) } + Type::Array(ty, _size) => { + let ty = compile_data_type(opts, ty, quote! { v }); + quote! { ::stef::buf::size_array(#name, |v| { #ty }) } } - DataType::External(_) => { - quote! { (#name).size() } + Type::External(_) => { + quote! { #name.size() } } } } diff --git a/crates/stef-build/tests/compiler.rs b/crates/stef-build/tests/compiler.rs index 3fe2ff0..c5b529a 100644 --- a/crates/stef-build/tests/compiler.rs +++ b/crates/stef-build/tests/compiler.rs @@ -19,6 +19,7 @@ fn compile_schema() { glob!("inputs/*.stef", |path| { let input = fs::read_to_string(path).unwrap(); let value = Schema::parse(input.as_str(), Some(&strip_path(path))).unwrap(); + let value = stef_compiler::simplify_schema(&value); let value = stef_build::compile_schema(&Opts::default(), &value); let value = prettyplease::unparse(&syn::parse2(value.clone()).unwrap()); @@ -36,6 +37,7 @@ fn compile_schema_extra() { glob!("inputs_extra/*.stef", |path| { let input = fs::read_to_string(path).unwrap(); let value = Schema::parse(input.as_str(), Some(&strip_path(path))).unwrap(); + let value = stef_compiler::simplify_schema(&value); let value = stef_build::compile_schema(&Opts::default(), &value); let value = prettyplease::unparse(&syn::parse2(value.clone()).unwrap()); 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 8983104..77f5e82 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 @@ -12,11 +12,14 @@ pub struct Sample; impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] - fn encode(&self, w: &mut impl ::stef::BufMut) {} + fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self = self; + } } #[automatically_derived] impl ::stef::Decode for Sample { @@ -29,11 +32,13 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self = self; 0 } } 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 7ec9f01..ee5bb3a 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 @@ -12,11 +12,14 @@ pub struct Sample; impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] - fn encode(&self, w: &mut impl ::stef::BufMut) {} + fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self = self; + } } #[automatically_derived] impl ::stef::Decode for Sample { @@ -29,11 +32,13 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self = self; 0 } } 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 263fdd9..ec5e2fe 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 @@ -12,11 +12,14 @@ pub struct Sample; impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] - fn encode(&self, w: &mut impl ::stef::BufMut) {} + fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self = self; + } } #[automatically_derived] impl ::stef::Decode for Sample { @@ -29,11 +32,13 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self = self; 0 } } 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 c6edb7a..cd2aee2 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@attributes.stef.snap @@ -12,11 +12,14 @@ pub struct Sample; impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] - fn encode(&self, w: &mut impl ::stef::BufMut) {} + fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self = self; + } } #[automatically_derived] impl ::stef::Decode for Sample { @@ -29,11 +32,13 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self = self; 0 } } 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 303c993..970c9a9 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 @@ -12,11 +12,14 @@ pub struct Sample; impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] - fn encode(&self, w: &mut impl ::stef::BufMut) {} + fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self = self; + } } #[automatically_derived] impl ::stef::Decode for Sample { @@ -29,11 +32,13 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self = self; 0 } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@enum_basic.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@enum_basic.stef.snap index 7dd6cf9..e3ac1c5 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@enum_basic.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@enum_basic.stef.snap @@ -22,6 +22,7 @@ pub enum Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -35,12 +36,16 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *n0) }, + |w| { + ::stef::buf::encode_u32(w, *n0); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u64(w, *n1) }, + |w| { + ::stef::buf::encode_u64(w, *n1); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -49,12 +54,16 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *field1) }, + |w| { + ::stef::buf::encode_u32(w, *field1); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_bool(w, *field2) }, + |w| { + ::stef::buf::encode_bool(w, *field2); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -127,6 +136,7 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@enum_generics.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@enum_generics.stef.snap index f9bab3d..4ad4a0d 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@enum_generics.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@enum_generics.stef.snap @@ -23,6 +23,7 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -36,12 +37,16 @@ where ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*n0).encode(w) }, + |w| { + n0.encode(w); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*n1).encode(w) }, + |w| { + n1.encode(w); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -50,12 +55,16 @@ where ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*field1).encode(w) }, + |w| { + field1.encode(w); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*field2).encode(w) }, + |w| { + field2.encode(w); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -140,6 +149,7 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -147,14 +157,14 @@ where match self { Self::One => ::stef::buf::size_id(1), Self::Two(n0, n1) => { - ::stef::buf::size_id(2) + ::stef::buf::size_field(1, || { (*n0).size() }) - + ::stef::buf::size_field(2, || { (*n1).size() }) + ::stef::buf::size_id(2) + ::stef::buf::size_field(1, || { n0.size() }) + + ::stef::buf::size_field(2, || { n1.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } Self::Three { field1, field2 } => { ::stef::buf::size_id(3) - + ::stef::buf::size_field(1, || { (*field1).size() }) - + ::stef::buf::size_field(2, || { (*field2).size() }) + + ::stef::buf::size_field(1, || { field1.size() }) + + ::stef::buf::size_field(2, || { field2.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@enum_many_ws.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@enum_many_ws.stef.snap index c5fea89..d703df2 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@enum_many_ws.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@enum_many_ws.stef.snap @@ -17,6 +17,7 @@ pub enum Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -30,12 +31,16 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *n0) }, + |w| { + ::stef::buf::encode_u32(w, *n0); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u64(w, *n1) }, + |w| { + ::stef::buf::encode_u64(w, *n1); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -44,12 +49,16 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *field1) }, + |w| { + ::stef::buf::encode_u32(w, *field1); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_bool(w, *field2) }, + |w| { + ::stef::buf::encode_bool(w, *field2); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -122,6 +131,7 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] diff --git a/crates/stef-build/tests/snapshots/compiler__compile@enum_min_ws.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@enum_min_ws.stef.snap index 3200202..cb03dc0 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@enum_min_ws.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@enum_min_ws.stef.snap @@ -19,6 +19,7 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -32,17 +33,23 @@ where ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *n0) }, + |w| { + ::stef::buf::encode_u32(w, *n0); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u64(w, *n1) }, + |w| { + ::stef::buf::encode_u64(w, *n1); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*n2).encode(w) }, + |w| { + n2.encode(w); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -51,17 +58,23 @@ where ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *field1) }, + |w| { + ::stef::buf::encode_u32(w, *field1); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_bool(w, *field2) }, + |w| { + ::stef::buf::encode_bool(w, *field2); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*field3).encode(w) }, + |w| { + field3.encode(w); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -154,6 +167,7 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -164,14 +178,14 @@ where ::stef::buf::size_id(2) + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*n0) }) + ::stef::buf::size_field(2, || { ::stef::buf::size_u64(*n1) }) - + ::stef::buf::size_field(3, || { (*n2).size() }) + + ::stef::buf::size_field(3, || { n2.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } Self::Three { field1, field2, field3 } => { ::stef::buf::size_id(3) + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*field1) }) + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*field2) }) - + ::stef::buf::size_field(3, || { (*field3).size() }) + + ::stef::buf::size_field(3, || { field3.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile@mixed.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile@mixed.stef.snap index 6e01b34..bef11d7 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile@mixed.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile@mixed.stef.snap @@ -1,6 +1,6 @@ --- source: crates/stef-build/tests/compiler.rs -description: "/// Basic user information.\n///\n/// Uses various other `structs` and `enums` to compose the information\n/// in a **type safe** way.\nstruct User {\n name: FullName @1,\n /// Physical address, might not be specified by the user.\n address: option
@2,\n age: u8 @3,\n birthday: birthday::DayOfBirth @4,\n}\n\n/// Full name of a user.\nstruct FullName {\n first: string @1,\n middle: option @2,\n last: string @3,\n}\n\n/// Simple alias for convenience.\n///\n/// - Might be easier to remember.\n/// - Often referenced as this.\ntype Name = FullName;\n\nstruct Address {\n /// Street name.\n street: string @1,\n /// Number of the house in the street.\n house_no: HouseNumber @2,\n city: string @3,\n}\n\n/// The number on the house.\n///\n/// More details can be found at [Wikipedia](https://en.wikipedia.org/wiki/House_numbering).\nenum HouseNumber {\n /// Digit only number.\n Digit(u16 @1) @1,\n /// Mixed _number_ with characters like `1a`.\n Text(string @1) @2,\n}\n\n/// Probably the max age of a human, currently.\nconst MAX_AGE: u8 = 120;\n\n\n/// Details for defining birthdays.\nmod birthday {\n /// As the name suggests, specifies details about birthdays.\n enum DayOfBirth {\n Specific {\n year: u16 @1,\n month: Month @2,\n day: u8 @3,\n } @1,\n /// The user didn't want to say.\n Secret {\n /// Optional info from the user about why they didn't want to\n /// reveal their birthday.\n reason: option @1,\n } @2,\n /// We never asked and nobody knows.\n Unknown @3,\n }\n\n /// Let's assume we only have details of people born **after** this year.\n const MIN_YEAR: u16 = 1900;\n\n /// Absolute maximum for a day, but might be even less depending\n /// on the month.\n const MAX_DAY: u8 = 31;\n\n /// The month of the year.\n enum Month {\n January @1,\n February @2,\n March @3,\n April @4,\n May @5,\n June @6,\n July @7,\n August @8,\n September @9,\n October @10,\n November @11,\n December @12,\n }\n}" +description: "/// Schema with a bit of everything, to try out more complex scenarios.\n\n/// Basic user information.\n///\n/// Uses various other `structs` and `enums` to compose the information\n/// in a **type safe** way.\nstruct User {\n name: FullName @1,\n /// Physical address, might not be specified by the user.\n address: option
@2,\n age: u8 @3,\n birthday: birthday::DayOfBirth @4,\n}\n\n/// Full name of a user.\nstruct FullName {\n first: string @1,\n middle: option @2,\n last: string @3,\n}\n\n/// Simple alias for convenience.\n///\n/// - Might be easier to remember.\n/// - Often referenced as this.\ntype Name = FullName;\n\nstruct Address {\n /// Street name.\n street: string @1,\n /// Number of the house in the street.\n house_no: HouseNumber @2,\n city: string @3,\n}\n\n/// The number on the house.\n///\n/// More details can be found at [Wikipedia](https://en.wikipedia.org/wiki/House_numbering).\nenum HouseNumber {\n /// Digit only number.\n Digit(u16 @1) @1,\n /// Mixed _number_ with characters like `1a`.\n Text(string @1) @2,\n}\n\n/// Probably the max age of a human, currently.\nconst MAX_AGE: u8 = 120;\n\n\n/// Details for defining birthdays.\nmod birthday {\n /// As the name suggests, specifies details about birthdays.\n enum DayOfBirth {\n Specific {\n year: u16 @1,\n month: Month @2,\n day: u8 @3,\n } @1,\n /// The user didn't want to say.\n Secret {\n /// Optional info from the user about why they didn't want to\n /// reveal their birthday.\n reason: option @1,\n } @2,\n /// We never asked and nobody knows.\n Unknown @3,\n }\n\n /// Let's assume we only have details of people born **after** this year.\n const MIN_YEAR: u16 = 1900;\n\n /// Absolute maximum for a day, but might be even less depending\n /// on the month.\n const MAX_DAY: u8 = 31;\n\n /// The month of the year.\n enum Month {\n January @1,\n February @2,\n March @3,\n April @4,\n May @5,\n June @6,\n July @7,\n August @8,\n September @9,\n October @10,\n November @11,\n December @12,\n }\n}" input_file: crates/stef-parser/tests/inputs/mixed.stef --- #[allow(unused_imports)] @@ -22,38 +22,40 @@ pub struct User { impl ::stef::Encode for User { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { name, address, age, birthday } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.name).encode(w); + name.encode(w); }, ); ::stef::buf::encode_field_option( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), - &self.address, + address, |w, v| { - (v).encode(w); + v.encode(w); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_u8(w, self.age); + ::stef::buf::encode_u8(w, *age); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(4, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.birthday).encode(w); + birthday.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -102,18 +104,17 @@ impl ::stef::Decode for User { impl ::stef::buf::Size for User { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { (self.name).size() }) - + ::stef::buf::size_field_option( - 2, - self.address.as_ref(), - |v| { (v).size() }, - ) + ::stef::buf::size_field(3, || { ::stef::buf::size_u8(self.age) }) - + ::stef::buf::size_field(4, || { (self.birthday).size() }) + let Self { name, address, age, birthday } = self; + ::stef::buf::size_field(1, || { name.size() }) + + ::stef::buf::size_field_option(2, address.as_ref(), |v| { v.size() }) + + ::stef::buf::size_field(3, || { ::stef::buf::size_u8(*age) }) + + ::stef::buf::size_field(4, || { birthday.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -129,31 +130,33 @@ pub struct FullName { impl ::stef::Encode for FullName { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { first, middle, last } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.first); + ::stef::buf::encode_string(w, first); }, ); ::stef::buf::encode_field_option( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), - &self.middle, + middle, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.last); + ::stef::buf::encode_string(w, last); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -195,17 +198,19 @@ impl ::stef::Decode for FullName { impl ::stef::buf::Size for FullName { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_string(&self.first) }) + let Self { first, middle, last } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_string(first) }) + ::stef::buf::size_field_option( 2, - self.middle.as_ref(), - |v| { ::stef::buf::size_string(&v) }, - ) + ::stef::buf::size_field(3, || { ::stef::buf::size_string(&self.last) }) + middle.as_ref(), + |v| { ::stef::buf::size_string(v) }, + ) + ::stef::buf::size_field(3, || { ::stef::buf::size_string(last) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -228,30 +233,32 @@ pub struct Address { impl ::stef::Encode for Address { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { street, house_no, city } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.street); + ::stef::buf::encode_string(w, street); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.house_no).encode(w); + house_no.encode(w); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.city); + ::stef::buf::encode_string(w, city); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -297,14 +304,16 @@ impl ::stef::Decode for Address { impl ::stef::buf::Size for Address { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_string(&self.street) }) - + ::stef::buf::size_field(2, || { (self.house_no).size() }) - + ::stef::buf::size_field(3, || { ::stef::buf::size_string(&self.city) }) + let Self { street, house_no, city } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_string(street) }) + + ::stef::buf::size_field(2, || { house_no.size() }) + + ::stef::buf::size_field(3, || { ::stef::buf::size_string(city) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -323,6 +332,7 @@ pub enum HouseNumber { impl ::stef::Encode for HouseNumber { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -333,7 +343,9 @@ impl ::stef::Encode for HouseNumber { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u16(w, *n0) }, + |w| { + ::stef::buf::encode_u16(w, *n0); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -342,7 +354,9 @@ impl ::stef::Encode for HouseNumber { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), - |w| { ::stef::buf::encode_string(w, &*n0) }, + |w| { + ::stef::buf::encode_string(w, n0); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -402,6 +416,7 @@ impl ::stef::Decode for HouseNumber { impl ::stef::buf::Size for HouseNumber { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -414,7 +429,7 @@ impl ::stef::buf::Size for HouseNumber { } Self::Text(n0) => { ::stef::buf::size_id(2) - + ::stef::buf::size_field(1, || { ::stef::buf::size_string(&*n0) }) + + ::stef::buf::size_field(1, || { ::stef::buf::size_string(n0) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -445,6 +460,7 @@ pub mod birthday { impl ::stef::Encode for DayOfBirth { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -455,23 +471,36 @@ pub mod birthday { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u16(w, *year) }, + |w| { + ::stef::buf::encode_u16(w, *year); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), - |w| { (*month).encode(w) }, + |w| { + month.encode(w); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_u8(w, *day) }, + |w| { + ::stef::buf::encode_u8(w, *day); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } Self::Secret { reason } => { ::stef::buf::encode_variant_id(w, ::stef::VariantId::new(2)); - ::stef::buf::encode_field_option(w, 1, &reason); + ::stef::buf::encode_field_option( + w, + ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), + reason, + |w, v| { + ::stef::buf::encode_string(w, v); + }, + ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } Self::Unknown => { @@ -538,6 +567,7 @@ pub mod birthday { impl ::stef::buf::Size for DayOfBirth { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -546,14 +576,17 @@ pub mod birthday { Self::Specific { year, month, day } => { ::stef::buf::size_id(1) + ::stef::buf::size_field(1, || { ::stef::buf::size_u16(*year) }) - + ::stef::buf::size_field(2, || { (*month).size() }) + + ::stef::buf::size_field(2, || { month.size() }) + ::stef::buf::size_field(3, || { ::stef::buf::size_u8(*day) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } Self::Secret { reason } => { ::stef::buf::size_id(2) - + ::stef::buf::size_field_option(1, reason.as_ref()) - + ::stef::buf::size_u32(::stef::buf::END_MARKER) + + ::stef::buf::size_field_option( + 1, + reason.as_ref(), + |v| { ::stef::buf::size_string(v) }, + ) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } Self::Unknown => ::stef::buf::size_id(3), } @@ -587,6 +620,7 @@ pub mod birthday { impl ::stef::Encode for Month { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -656,6 +690,7 @@ pub mod birthday { impl ::stef::buf::Size for Month { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] 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 1d0f857..fe0f831 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 @@ -21,6 +21,7 @@ pub mod a { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -46,6 +47,7 @@ pub mod a { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -66,23 +68,25 @@ pub mod a { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { value, inner } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.value); + ::stef::buf::encode_u32(w, *value); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.inner).encode(w); + inner.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -121,13 +125,15 @@ pub mod a { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.value) }) - + ::stef::buf::size_field(2, || { (self.inner).size() }) + let Self { value, inner } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*value) }) + + ::stef::buf::size_field(2, || { inner.size() }) + ::stef::buf::size_u32(::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 41c6aae..27feb8b 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 @@ -16,23 +16,25 @@ pub struct SampleStruct { impl ::stef::Encode for SampleStruct { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { a, b } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.a); + ::stef::buf::encode_u32(w, *a); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.b); + ::stef::buf::encode_bool(w, *b); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -71,13 +73,15 @@ impl ::stef::Decode for SampleStruct { impl ::stef::buf::Size for SampleStruct { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.a) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(self.b) }) + let Self { a, b } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*a) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*b) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -93,6 +97,7 @@ pub enum SampleEnum { impl ::stef::Encode for SampleEnum { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -106,12 +111,16 @@ impl ::stef::Encode for SampleEnum { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *n0) }, + |w| { + ::stef::buf::encode_u32(w, *n0); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u64(w, *n1) }, + |w| { + ::stef::buf::encode_u64(w, *n1); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -120,12 +129,16 @@ impl ::stef::Encode for SampleEnum { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *field1) }, + |w| { + ::stef::buf::encode_u32(w, *field1); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_bool(w, *field2) }, + |w| { + ::stef::buf::encode_bool(w, *field2); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -198,6 +211,7 @@ impl ::stef::Decode for SampleEnum { impl ::stef::buf::Size for SampleEnum { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] 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 16d26e6..b9e6ac2 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 @@ -17,23 +17,25 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { a, b } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.a); + ::stef::buf::encode_u32(w, *a); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.b); + ::stef::buf::encode_bool(w, *b); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -72,13 +74,15 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.a) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(self.b) }) + let Self { a, b } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*a) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*b) }) + ::stef::buf::size_u32(::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 8f79390..c6a1e57 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 @@ -20,23 +20,25 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { key, value } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.key).encode(w); + key.encode(w); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.value).encode(w); + value.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -83,13 +85,15 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { (self.key).size() }) - + ::stef::buf::size_field(2, || { (self.value).size() }) + let Self { key, value } = self; + ::stef::buf::size_field(1, || { key.size() }) + + ::stef::buf::size_field(2, || { value.size() }) + ::stef::buf::size_u32(::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 b1df045..968d820 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 @@ -20,30 +20,32 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { a, b, c } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.a); + ::stef::buf::encode_u32(w, *a); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.b); + ::stef::buf::encode_bool(w, *b); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.c).encode(w); + c.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -95,14 +97,16 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.a) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(self.b) }) - + ::stef::buf::size_field(3, || { (self.c).size() }) + let Self { a, b, c } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*a) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*b) }) + + ::stef::buf::size_field(3, || { c.size() }) + ::stef::buf::size_u32(::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 a041faf..1fa6591 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 @@ -19,30 +19,32 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { a, b, c } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.a); + ::stef::buf::encode_u32(w, *a); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.b); + ::stef::buf::encode_bool(w, *b); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.c).encode(w); + c.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -94,14 +96,16 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.a) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(self.b) }) - + ::stef::buf::size_field(3, || { (self.c).size() }) + let Self { a, b, c } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*a) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*b) }) + + ::stef::buf::size_field(3, || { c.size() }) + ::stef::buf::size_u32(::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 d8789a1..2511fc3 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 @@ -13,23 +13,25 @@ pub struct Sample(pub u32, pub bool); impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self(n0, n1) = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.0); + ::stef::buf::encode_u32(w, *n0); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.1); + ::stef::buf::encode_bool(w, *n1); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -70,13 +72,15 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.0) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(self.1) }) + let Self(n0, n1) = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*n0) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bool(*n1) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } 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 f6020e8..0fab124 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 @@ -34,142 +34,166 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { + f01, + f02, + f03, + f04, + f05, + f06, + f07, + f08, + f09, + f10, + f11, + f12, + f13, + f14, + f15, + f16, + f17, + f18, + f19, + f20, + f21, + } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_bool(w, self.f01); + ::stef::buf::encode_bool(w, *f01); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_u8(w, self.f02); + ::stef::buf::encode_u8(w, *f02); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u16(w, self.f03); + ::stef::buf::encode_u16(w, *f03); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(4, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.f04); + ::stef::buf::encode_u32(w, *f04); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(5, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u64(w, self.f05); + ::stef::buf::encode_u64(w, *f05); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(6, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u128(w, self.f06); + ::stef::buf::encode_u128(w, *f06); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(7, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_i8(w, self.f07); + ::stef::buf::encode_i8(w, *f07); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(8, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i16(w, self.f08); + ::stef::buf::encode_i16(w, *f08); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(9, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i32(w, self.f09); + ::stef::buf::encode_i32(w, *f09); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(10, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i64(w, self.f10); + ::stef::buf::encode_i64(w, *f10); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(11, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i128(w, self.f11); + ::stef::buf::encode_i128(w, *f11); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(12, ::stef::FieldEncoding::Fixed4), |w| { - ::stef::buf::encode_f32(w, self.f12); + ::stef::buf::encode_f32(w, *f12); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(13, ::stef::FieldEncoding::Fixed8), |w| { - ::stef::buf::encode_f64(w, self.f13); + ::stef::buf::encode_f64(w, *f13); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(14, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.f14); + ::stef::buf::encode_string(w, f14); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(15, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.f15); + ::stef::buf::encode_string(w, f15); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(16, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_bytes_std(w, &self.f16); + ::stef::buf::encode_bytes_std(w, f16); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(17, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_bytes_std(w, &self.f17); + ::stef::buf::encode_bytes_std(w, f17); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(18, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.f18); + ::stef::buf::encode_string(w, f18); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(19, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_bytes_std(w, &self.f19); + ::stef::buf::encode_bytes_std(w, f19); }, ); ::stef::buf::encode_field( @@ -179,14 +203,13 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_tuple( w, || { - ::stef::buf::size_u32(self.f20.0) - + ::stef::buf::size_u32(self.f20.1) - + ::stef::buf::size_u32(self.f20.2) + ::stef::buf::size_u32(*&f20.0) + ::stef::buf::size_u32(*&f20.1) + + ::stef::buf::size_u32(*&f20.2) }, |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_u32(w, *&f20.0); + ::stef::buf::encode_u32(w, *&f20.1); + ::stef::buf::encode_u32(w, *&f20.2); }, ); }, @@ -197,7 +220,7 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_array( w, - &self.f21, + f21, |v| { ::stef::buf::size_u32(*v) }, |w, v| { ::stef::buf::encode_u32(w, *v); @@ -392,42 +415,64 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_bool(self.f01) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_u8(self.f02) }) - + ::stef::buf::size_field(3, || { ::stef::buf::size_u16(self.f03) }) - + ::stef::buf::size_field(4, || { ::stef::buf::size_u32(self.f04) }) - + ::stef::buf::size_field(5, || { ::stef::buf::size_u64(self.f05) }) - + ::stef::buf::size_field(6, || { ::stef::buf::size_u128(self.f06) }) - + ::stef::buf::size_field(7, || { ::stef::buf::size_i8(self.f07) }) - + ::stef::buf::size_field(8, || { ::stef::buf::size_i16(self.f08) }) - + ::stef::buf::size_field(9, || { ::stef::buf::size_i32(self.f09) }) - + ::stef::buf::size_field(10, || { ::stef::buf::size_i64(self.f10) }) - + ::stef::buf::size_field(11, || { ::stef::buf::size_i128(self.f11) }) - + ::stef::buf::size_field(12, || { ::stef::buf::size_f32(self.f12) }) - + ::stef::buf::size_field(13, || { ::stef::buf::size_f64(self.f13) }) - + ::stef::buf::size_field(14, || { ::stef::buf::size_string(&self.f14) }) - + ::stef::buf::size_field(15, || { ::stef::buf::size_string(&self.f15) }) - + ::stef::buf::size_field(16, || { ::stef::buf::size_bytes_std(&self.f16) }) - + ::stef::buf::size_field(17, || { ::stef::buf::size_bytes_std(&self.f17) }) - + ::stef::buf::size_field(18, || { ::stef::buf::size_string(&self.f18) }) - + ::stef::buf::size_field(19, || { ::stef::buf::size_bytes_std(&self.f19) }) + let Self { + f01, + f02, + f03, + f04, + f05, + f06, + f07, + f08, + f09, + f10, + f11, + f12, + f13, + f14, + f15, + f16, + f17, + f18, + f19, + f20, + f21, + } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_bool(*f01) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_u8(*f02) }) + + ::stef::buf::size_field(3, || { ::stef::buf::size_u16(*f03) }) + + ::stef::buf::size_field(4, || { ::stef::buf::size_u32(*f04) }) + + ::stef::buf::size_field(5, || { ::stef::buf::size_u64(*f05) }) + + ::stef::buf::size_field(6, || { ::stef::buf::size_u128(*f06) }) + + ::stef::buf::size_field(7, || { ::stef::buf::size_i8(*f07) }) + + ::stef::buf::size_field(8, || { ::stef::buf::size_i16(*f08) }) + + ::stef::buf::size_field(9, || { ::stef::buf::size_i32(*f09) }) + + ::stef::buf::size_field(10, || { ::stef::buf::size_i64(*f10) }) + + ::stef::buf::size_field(11, || { ::stef::buf::size_i128(*f11) }) + + ::stef::buf::size_field(12, || { ::stef::buf::size_f32(*f12) }) + + ::stef::buf::size_field(13, || { ::stef::buf::size_f64(*f13) }) + + ::stef::buf::size_field(14, || { ::stef::buf::size_string(f14) }) + + ::stef::buf::size_field(15, || { ::stef::buf::size_string(f15) }) + + ::stef::buf::size_field(16, || { ::stef::buf::size_bytes_std(f16) }) + + ::stef::buf::size_field(17, || { ::stef::buf::size_bytes_std(f17) }) + + ::stef::buf::size_field(18, || { ::stef::buf::size_string(f18) }) + + ::stef::buf::size_field(19, || { ::stef::buf::size_bytes_std(f19) }) + ::stef::buf::size_field( 20, || { - ::stef::buf::size_u32(self.f20.0) + ::stef::buf::size_u32(self.f20.1) - + ::stef::buf::size_u32(self.f20.2) + ::stef::buf::size_u32(*&f20.0) + ::stef::buf::size_u32(*&f20.1) + + ::stef::buf::size_u32(*&f20.2) }, ) + ::stef::buf::size_field( 21, - || { - ::stef::buf::size_array(&self.f21, |v| { ::stef::buf::size_u32(*v) }) - }, + || { ::stef::buf::size_array(f21, |v| { ::stef::buf::size_u32(*v) }) }, ) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } 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 0729505..5afb8fb 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 @@ -18,18 +18,20 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { f1, f2, f3, f4, f5 } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { ::stef::buf::encode_vec( w, - &self.f1, + f1, |v| { ::stef::buf::size_u32(*v) }, |w, v| { ::stef::buf::encode_u32(w, *v); @@ -43,14 +45,14 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_hash_map( w, - &self.f2, + f2, |k| { ::stef::buf::size_u32(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, |w, k| { ::stef::buf::encode_u32(w, *k); }, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); }, @@ -61,7 +63,7 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_hash_set( w, - &self.f3, + f3, |v| { ::stef::buf::size_u32(*v) }, |w, v| { ::stef::buf::encode_u32(w, *v); @@ -72,7 +74,7 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field_option( w, ::stef::FieldId::new(4, ::stef::FieldEncoding::Varint), - &self.f4, + f4, |w, v| { ::stef::buf::encode_u32(w, *v); }, @@ -81,7 +83,7 @@ impl ::stef::Encode for Sample { w, ::stef::FieldId::new(5, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.f5.get()); + ::stef::buf::encode_u32(w, f5.get()); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -156,39 +158,36 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self { f1, f2, f3, f4, f5 } = self; ::stef::buf::size_field( 1, - || { ::stef::buf::size_vec(&self.f1, |v| { ::stef::buf::size_u32(*v) }) }, + || { ::stef::buf::size_vec(f1, |v| { ::stef::buf::size_u32(*v) }) }, ) + ::stef::buf::size_field( 2, || { ::stef::buf::size_hash_map( - &self.f2, + f2, |k| { ::stef::buf::size_u32(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, ) }, ) + ::stef::buf::size_field( 3, - || { - ::stef::buf::size_hash_set( - &self.f3, - |v| { ::stef::buf::size_u32(*v) }, - ) - }, + || { ::stef::buf::size_hash_set(f3, |v| { ::stef::buf::size_u32(*v) }) }, ) + ::stef::buf::size_field_option( 4, - self.f4.as_ref(), + f4.as_ref(), |v| { ::stef::buf::size_u32(*v) }, - ) + ::stef::buf::size_field(5, || { ::stef::buf::size_u32(self.f5.get()) }) + ) + ::stef::buf::size_field(5, || { ::stef::buf::size_u32(f5.get()) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -205,18 +204,20 @@ pub struct SampleUnnamed( impl ::stef::Encode for SampleUnnamed { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self(n0, n1, n2, n3, n4) = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { ::stef::buf::encode_vec( w, - &self.0, + n0, |v| { ::stef::buf::size_u32(*v) }, |w, v| { ::stef::buf::encode_u32(w, *v); @@ -230,14 +231,14 @@ impl ::stef::Encode for SampleUnnamed { |w| { ::stef::buf::encode_hash_map( w, - &self.1, + n1, |k| { ::stef::buf::size_u32(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, |w, k| { ::stef::buf::encode_u32(w, *k); }, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); }, @@ -248,7 +249,7 @@ impl ::stef::Encode for SampleUnnamed { |w| { ::stef::buf::encode_hash_set( w, - &self.2, + n2, |v| { ::stef::buf::size_u32(*v) }, |w, v| { ::stef::buf::encode_u32(w, *v); @@ -259,7 +260,7 @@ impl ::stef::Encode for SampleUnnamed { ::stef::buf::encode_field_option( w, ::stef::FieldId::new(4, ::stef::FieldEncoding::Varint), - &self.3, + n3, |w, v| { ::stef::buf::encode_u32(w, *v); }, @@ -268,7 +269,7 @@ impl ::stef::Encode for SampleUnnamed { w, ::stef::FieldId::new(5, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.4.get()); + ::stef::buf::encode_u32(w, n4.get()); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -345,39 +346,36 @@ impl ::stef::Decode for SampleUnnamed { impl ::stef::buf::Size for SampleUnnamed { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self(n0, n1, n2, n3, n4) = self; ::stef::buf::size_field( 1, - || { ::stef::buf::size_vec(&self.0, |v| { ::stef::buf::size_u32(*v) }) }, + || { ::stef::buf::size_vec(n0, |v| { ::stef::buf::size_u32(*v) }) }, ) + ::stef::buf::size_field( 2, || { ::stef::buf::size_hash_map( - &self.1, + n1, |k| { ::stef::buf::size_u32(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, ) }, ) + ::stef::buf::size_field( 3, - || { - ::stef::buf::size_hash_set( - &self.2, - |v| { ::stef::buf::size_u32(*v) }, - ) - }, + || { ::stef::buf::size_hash_set(n2, |v| { ::stef::buf::size_u32(*v) }) }, ) + ::stef::buf::size_field_option( 4, - self.3.as_ref(), + n3.as_ref(), |v| { ::stef::buf::size_u32(*v) }, - ) + ::stef::buf::size_field(5, || { ::stef::buf::size_u32(self.4.get()) }) + ) + ::stef::buf::size_field(5, || { ::stef::buf::size_u32(n4.get()) }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } 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 0fac5dd..810f4f5 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 @@ -14,26 +14,28 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { value } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { ::stef::buf::encode_vec( w, - &self.value, + value, |v| { ::stef::buf::size_option( v.as_ref(), |v| { ::stef::buf::size_hash_map( - &v.get(), + v.get(), |k| { ::stef::buf::size_i64(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, ) }, ) @@ -41,18 +43,18 @@ impl ::stef::Encode for Sample { |w, v| { ::stef::buf::encode_option( w, - &v, + v, |w, v| { ::stef::buf::encode_hash_map( w, - &v.get(), + v.get(), |k| { ::stef::buf::size_i64(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, |w, k| { ::stef::buf::encode_i64(w, *k); }, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); }, @@ -108,24 +110,26 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { + let Self { value } = self; ::stef::buf::size_field( 1, || { ::stef::buf::size_vec( - &self.value, + value, |v| { ::stef::buf::size_option( v.as_ref(), |v| { ::stef::buf::size_hash_map( - &v.get(), + v.get(), |k| { ::stef::buf::size_i64(*k) }, - |v| { ::stef::buf::size_string(&v) }, + |v| { ::stef::buf::size_string(v) }, ) }, ) 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 215e161..c6243d7 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 @@ -28,93 +28,111 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { + f01, + f02, + f03, + f04, + f05, + f06, + f07, + f08, + f09, + f10, + f11, + f12, + f13, + f14, + f15, + } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_u8(w, self.f01.get()); + ::stef::buf::encode_u8(w, f01.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u16(w, self.f02.get()); + ::stef::buf::encode_u16(w, f02.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(3, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.f03.get()); + ::stef::buf::encode_u32(w, f03.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(4, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u64(w, self.f04.get()); + ::stef::buf::encode_u64(w, f04.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(5, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u128(w, self.f05.get()); + ::stef::buf::encode_u128(w, f05.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(6, ::stef::FieldEncoding::Fixed1), |w| { - ::stef::buf::encode_i8(w, self.f06.get()); + ::stef::buf::encode_i8(w, f06.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(7, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i16(w, self.f07.get()); + ::stef::buf::encode_i16(w, f07.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(8, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i32(w, self.f08.get()); + ::stef::buf::encode_i32(w, f08.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(9, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i64(w, self.f09.get()); + ::stef::buf::encode_i64(w, f09.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(10, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_i128(w, self.f10.get()); + ::stef::buf::encode_i128(w, f10.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(11, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_string(w, &self.f11.get()); + ::stef::buf::encode_string(w, f11.get()); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(12, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_bytes_std(w, &self.f12.get()); + ::stef::buf::encode_bytes_std(w, f12.get()); }, ); ::stef::buf::encode_field( @@ -123,10 +141,10 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_vec( w, - &self.f13.get(), - |v| { ::stef::buf::size_string(&v) }, + f13.get(), + |v| { ::stef::buf::size_string(v) }, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); }, @@ -137,14 +155,14 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_hash_map( w, - &self.f14.get(), - |k| { ::stef::buf::size_string(&k) }, - |v| { ::stef::buf::size_bytes_std(&v) }, + f14.get(), + |k| { ::stef::buf::size_string(k) }, + |v| { ::stef::buf::size_bytes_std(v) }, |w, k| { - ::stef::buf::encode_string(w, &k); + ::stef::buf::encode_string(w, k); }, |w, v| { - ::stef::buf::encode_bytes_std(w, &v); + ::stef::buf::encode_bytes_std(w, v); }, ); }, @@ -155,10 +173,10 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_hash_set( w, - &self.f15.get(), - |v| { ::stef::buf::size_string(&v) }, + f15.get(), + |v| { ::stef::buf::size_string(v) }, |w, v| { - ::stef::buf::encode_string(w, &v); + ::stef::buf::encode_string(w, v); }, ); }, @@ -312,45 +330,54 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u8(self.f01.get()) }) - + ::stef::buf::size_field(2, || { ::stef::buf::size_u16(self.f02.get()) }) - + ::stef::buf::size_field(3, || { ::stef::buf::size_u32(self.f03.get()) }) - + ::stef::buf::size_field(4, || { ::stef::buf::size_u64(self.f04.get()) }) - + ::stef::buf::size_field(5, || { ::stef::buf::size_u128(self.f05.get()) }) - + ::stef::buf::size_field(6, || { ::stef::buf::size_i8(self.f06.get()) }) - + ::stef::buf::size_field(7, || { ::stef::buf::size_i16(self.f07.get()) }) - + ::stef::buf::size_field(8, || { ::stef::buf::size_i32(self.f08.get()) }) - + ::stef::buf::size_field(9, || { ::stef::buf::size_i64(self.f09.get()) }) - + ::stef::buf::size_field(10, || { ::stef::buf::size_i128(self.f10.get()) }) - + ::stef::buf::size_field( - 11, - || { ::stef::buf::size_string(&self.f11.get()) }, - ) - + ::stef::buf::size_field( - 12, - || { ::stef::buf::size_bytes_std(&self.f12.get()) }, - ) + let Self { + f01, + f02, + f03, + f04, + f05, + f06, + f07, + f08, + f09, + f10, + f11, + f12, + f13, + f14, + f15, + } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u8(f01.get()) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_u16(f02.get()) }) + + ::stef::buf::size_field(3, || { ::stef::buf::size_u32(f03.get()) }) + + ::stef::buf::size_field(4, || { ::stef::buf::size_u64(f04.get()) }) + + ::stef::buf::size_field(5, || { ::stef::buf::size_u128(f05.get()) }) + + ::stef::buf::size_field(6, || { ::stef::buf::size_i8(f06.get()) }) + + ::stef::buf::size_field(7, || { ::stef::buf::size_i16(f07.get()) }) + + ::stef::buf::size_field(8, || { ::stef::buf::size_i32(f08.get()) }) + + ::stef::buf::size_field(9, || { ::stef::buf::size_i64(f09.get()) }) + + ::stef::buf::size_field(10, || { ::stef::buf::size_i128(f10.get()) }) + + ::stef::buf::size_field(11, || { ::stef::buf::size_string(f11.get()) }) + + ::stef::buf::size_field(12, || { ::stef::buf::size_bytes_std(f12.get()) }) + ::stef::buf::size_field( 13, || { - ::stef::buf::size_vec( - &self.f13.get(), - |v| { ::stef::buf::size_string(&v) }, - ) + ::stef::buf::size_vec(f13.get(), |v| { ::stef::buf::size_string(v) }) }, ) + ::stef::buf::size_field( 14, || { ::stef::buf::size_hash_map( - &self.f14.get(), - |k| { ::stef::buf::size_string(&k) }, - |v| { ::stef::buf::size_bytes_std(&v) }, + f14.get(), + |k| { ::stef::buf::size_string(k) }, + |v| { ::stef::buf::size_bytes_std(v) }, ) }, ) @@ -358,8 +385,8 @@ impl ::stef::buf::Size for Sample { 15, || { ::stef::buf::size_hash_set( - &self.f15.get(), - |v| { ::stef::buf::size_string(&v) }, + f15.get(), + |v| { ::stef::buf::size_string(v) }, ) }, ) + ::stef::buf::size_u32(::stef::buf::END_MARKER) 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 63e7865..1645fed 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 @@ -15,23 +15,25 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { basic, with_generics } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.basic).encode(w); + basic.encode(w); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.with_generics).encode(w); + with_generics.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -70,13 +72,15 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { (self.basic).size() }) - + ::stef::buf::size_field(2, || { (self.with_generics).size() }) + let Self { basic, with_generics } = self; + ::stef::buf::size_field(1, || { basic.size() }) + + ::stef::buf::size_field(2, || { with_generics.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } @@ -89,6 +93,7 @@ pub enum Test123 { impl ::stef::Encode for Test123 { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -114,6 +119,7 @@ impl ::stef::Decode for Test123 { impl ::stef::buf::Size for Test123 { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -137,23 +143,25 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { key, value } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.key).encode(w); + key.encode(w); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - (self.value).encode(w); + value.encode(w); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -200,13 +208,15 @@ where { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { (self.key).size() }) - + ::stef::buf::size_field(2, || { (self.value).size() }) + let Self { key, value } = self; + ::stef::buf::size_field(1, || { key.size() }) + + ::stef::buf::size_field(2, || { value.size() }) + ::stef::buf::size_u32(::stef::buf::END_MARKER) } } diff --git a/crates/stef-build/tests/snapshots/compiler__compile_extra@enum.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile_extra@enum.stef.snap index 1d69532..6b1f977 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile_extra@enum.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile_extra@enum.stef.snap @@ -17,6 +17,7 @@ pub enum Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -30,12 +31,16 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), - |w| { ::stef::buf::encode_u32(w, *n0) }, + |w| { + ::stef::buf::encode_u32(w, *n0); + }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::Fixed1), - |w| { ::stef::buf::encode_u8(w, *n1) }, + |w| { + ::stef::buf::encode_u8(w, *n1); + }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); } @@ -44,7 +49,9 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::LengthPrefixed), - |w| { ::stef::buf::encode_string(w, &*field1) }, + |w| { + ::stef::buf::encode_string(w, field1); + }, ); ::stef::buf::encode_field( w, @@ -52,12 +59,12 @@ impl ::stef::Encode for Sample { |w| { ::stef::buf::encode_vec( w, - &*field2, + field2, |v| { ::stef::buf::size_bool(*v) }, |w, v| { ::stef::buf::encode_bool(w, *v); }, - ) + ); }, ); ::stef::buf::encode_u32(w, ::stef::buf::END_MARKER); @@ -138,6 +145,7 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::semicolon_if_nothing_returned, clippy::too_many_lines, )] @@ -152,15 +160,12 @@ impl ::stef::buf::Size for Sample { } Self::Variant3 { field1, field2 } => { ::stef::buf::size_id(3) - + ::stef::buf::size_field( - 1, - || { ::stef::buf::size_string(&*field1) }, - ) + + ::stef::buf::size_field(1, || { ::stef::buf::size_string(field1) }) + ::stef::buf::size_field( 2, || { ::stef::buf::size_vec( - &*field2, + field2, |v| { ::stef::buf::size_bool(*v) }, ) }, diff --git a/crates/stef-build/tests/snapshots/compiler__compile_extra@struct.stef.snap b/crates/stef-build/tests/snapshots/compiler__compile_extra@struct.stef.snap index 1acc02d..b7135ec 100644 --- a/crates/stef-build/tests/snapshots/compiler__compile_extra@struct.stef.snap +++ b/crates/stef-build/tests/snapshots/compiler__compile_extra@struct.stef.snap @@ -17,23 +17,25 @@ pub struct Sample { impl ::stef::Encode for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn encode(&self, w: &mut impl ::stef::BufMut) { + let Self { field1, field2, field3 } = self; ::stef::buf::encode_field( w, ::stef::FieldId::new(1, ::stef::FieldEncoding::Varint), |w| { - ::stef::buf::encode_u32(w, self.field1); + ::stef::buf::encode_u32(w, *field1); }, ); ::stef::buf::encode_field( w, ::stef::FieldId::new(2, ::stef::FieldEncoding::LengthPrefixed), |w| { - ::stef::buf::encode_bytes_std(w, &self.field2); + ::stef::buf::encode_bytes_std(w, field2); }, ); ::stef::buf::encode_field( @@ -43,17 +45,17 @@ impl ::stef::Encode for Sample { ::stef::buf::encode_tuple( w, || { - ::stef::buf::size_bool(self.field3.0) + ::stef::buf::size_bool(*&field3.0) + ::stef::buf::size_array( - &&(self.field3.1), + &field3.1, |v| { ::stef::buf::size_i16(*v) }, ) }, |w| { - ::stef::buf::encode_bool(w, self.field3.0); + ::stef::buf::encode_bool(w, *&field3.0); ::stef::buf::encode_array( w, - &&(self.field3.1), + &field3.1, |v| { ::stef::buf::size_i16(*v) }, |w, v| { ::stef::buf::encode_i16(w, *v); @@ -122,22 +124,21 @@ impl ::stef::Decode for Sample { impl ::stef::buf::Size for Sample { #[allow( clippy::borrow_deref_ref, + clippy::deref_addrof, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::too_many_lines, )] fn size(&self) -> usize { - ::stef::buf::size_field(1, || { ::stef::buf::size_u32(self.field1) }) - + ::stef::buf::size_field( - 2, - || { ::stef::buf::size_bytes_std(&self.field2) }, - ) + let Self { field1, field2, field3 } = self; + ::stef::buf::size_field(1, || { ::stef::buf::size_u32(*field1) }) + + ::stef::buf::size_field(2, || { ::stef::buf::size_bytes_std(field2) }) + ::stef::buf::size_field( 3, || { - ::stef::buf::size_bool(self.field3.0) + ::stef::buf::size_bool(*&field3.0) + ::stef::buf::size_array( - &&(self.field3.1), + &field3.1, |v| { ::stef::buf::size_i16(*v) }, ) }, diff --git a/crates/stef-compiler/Cargo.toml b/crates/stef-compiler/Cargo.toml index eea598f..f33a817 100644 --- a/crates/stef-compiler/Cargo.toml +++ b/crates/stef-compiler/Cargo.toml @@ -12,6 +12,9 @@ license.workspace = true [dependencies] miette.workspace = true owo-colors.workspace = true +schemars = { version = "0.8.16", optional = true } +serde = { version = "1.0.193", features = ["derive"], optional = true } +serde_json = { version = "1.0.108", optional = true } stef-parser = { path = "../stef-parser" } thiserror.workspace = true @@ -21,6 +24,7 @@ miette = { workspace = true, features = ["fancy-no-backtrace"] } [features] debug = [] +json = ["dep:schemars", "dep:serde", "dep:serde_json"] [lints] workspace = true diff --git a/crates/stef-compiler/src/lib.rs b/crates/stef-compiler/src/lib.rs index 8416727..2f453c4 100644 --- a/crates/stef-compiler/src/lib.rs +++ b/crates/stef-compiler/src/lib.rs @@ -21,8 +21,10 @@ #![allow(clippy::missing_errors_doc, clippy::module_name_repetitions)] pub use resolve::schemas as resolve_schemas; +pub use simplify::schema as simplify_schema; pub use validate::schema as validate_schema; mod highlight; pub mod resolve; +pub mod simplify; pub mod validate; diff --git a/crates/stef-compiler/src/simplify.rs b/crates/stef-compiler/src/simplify.rs new file mode 100644 index 0000000..0bcddae --- /dev/null +++ b/crates/stef-compiler/src/simplify.rs @@ -0,0 +1,443 @@ +//! Reduce the complexity of the schema types that are used by the parser, making it easier for code +//! generators to operate on and reducing the amount of duplicate calculations that can be done in +//! the compiler instead. + +use std::borrow::Cow; + +/// Uppermost element, describing a single schema file. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Schema<'a> { + /// Optional schema-level comment. + pub comment: Box<[&'a str]>, + /// List of all the definitions that make up the schema. + pub definitions: Box<[Definition<'a>]>, +} + +impl Schema<'_> { + /// Render the [JSON Schema](https://json-schema.org/draft-07/json-schema-release-notes) of the complete schema, which can help external tools to understand the structure or derive types from it. + #[cfg(feature = "json")] + pub fn json_schema() -> serde_json::Result { + let schema = schemars::schema_for!(Schema<'_>); + serde_json::to_string_pretty(&schema) + } +} + +/// Possible elements that can appear inside a [`Schema`] or [`Module`]. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub enum Definition<'a> { + /// Module declaration to organize other definitions into scopes. + Module(Module<'a>), + /// Data structure. + Struct(Struct<'a>), + /// Enum definition. + Enum(Enum<'a>), + /// Type aliasing definition. + TypeAlias(TypeAlias<'a>), + /// Const value declaration. + Const(Const<'a>), + /// Import declaration of other schemas. + Import(Import<'a>), +} + +/// Scoping mechanism to categorize elements. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Module<'a> { + /// Optional module-level comment. + pub comment: Box<[&'a str]>, + /// Unique name of the module, within the current scope. + pub name: &'a str, + /// List of definitions that are scoped within this module. + pub definitions: Box<[Definition<'a>]>, +} + +/// Rust-ish struct. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Struct<'a> { + /// Optional struct-level comment. + pub comment: Box<[&'a str]>, + /// Unique name for this struct (within its scope). + pub name: &'a str, + /// Potential generics. + pub generics: Box<[&'a str]>, + /// Fields of the struct, if any. + pub fields: Fields<'a>, +} + +/// Rust-ish enum. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Enum<'a> { + /// Optional enum-level comment. + pub comment: Box<[&'a str]>, + /// Unique name for this enum, within its current scope. + pub name: &'a str, + /// Potential generics. + pub generics: Box<[&'a str]>, + /// List of possible variants that the enum can represent. + pub variants: Vec>, +} + +/// Single variant of an enum. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Variant<'a> { + /// Optional variant-level comment. + pub comment: Box<[&'a str]>, + /// Unique for this variant, within the enum it belongs to. + pub name: &'a str, + /// Fields of this variant, if any. + pub fields: Fields<'a>, + /// Identifier for this variant, that must be unique within the current enum. + pub id: u32, +} + +/// Fields of a struct or enum that define its structure. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Fields<'a> { + /// List of contained fields. + pub fields: Box<[Field<'a>]>, + /// The way how the fields are defined, like named or unnamed. + pub kind: FieldKind, +} + +/// Single unified field that might be named or unnamed. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Field<'a> { + /// Optional field-level comment. + pub comment: Box<[&'a str]>, + /// Unique name for this field, within the current element. + pub name: Cow<'a, str>, + /// Data type that defines the shape of the contained data. + pub ty: Type<'a>, + /// Identifier for this field, that must be unique within the current element. + pub id: u32, +} + +/// Possible kinds in which the fields of a struct or enum variant can be represented. +#[derive(Eq, PartialEq)] +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub enum FieldKind { + /// Named fields. + Named, + /// Types without an explicit name. + Unnamed, + /// No attached value. + Unit, +} + +/// Alias (re-name) from one type to another. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct TypeAlias<'a> { + /// Optional element-level comment. + pub comment: Box<[&'a str]>, + /// Unique name of the type alias within the current scope. + pub name: &'a str, + /// Potential generic type arguments. + pub generics: Box<[&'a str]>, + /// Original type that is being aliased. + pub target: Type<'a>, +} + +/// Declaration of a constant value. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Const<'a> { + /// Optional element-level comment. + pub comment: Box<[&'a str]>, + /// Unique identifier of this constant. + pub name: &'a str, + /// Type of the value. + pub ty: Type<'a>, + /// Literal value that this declaration represents. + pub value: Literal, +} + +/// In-schema definition of a literal value +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub enum Literal { + /// Boolean `true` or `false` value. + Bool(bool), + /// Integer number. + Int(i128), + /// Floating point number. + Float(f64), + /// UTF-8 encoded string. + String(Box), + /// Raw vector of bytes. + Bytes(Box<[u8]>), +} + +/// Import declaration for an external schema. +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct Import<'a> { + /// Individual elements that form the import path. + pub segments: Box<[&'a str]>, + /// Optional final element that allows to fully import the type, making it look as it would be + /// defined in the current schema. + pub element: Option>, +} + +/// Possible data type that describes the shape of a field. +#[derive(Debug, Eq, PartialEq)] +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub enum Type<'a> { + /// Boolean `true` or `false`. + Bool, + /// 8-bit unsigned integer. + U8, + /// 16-bit unsigned integer. + U16, + /// 32-bit unsigned integer. + U32, + /// 64-bit unsigned integer. + U64, + /// 128-bit unsigned integer. + U128, + /// 8-bit signed integer. + I8, + /// 16-bit signed integer. + I16, + /// 32-bit signed integer. + I32, + /// 64-bit signed integer. + I64, + /// 128-bit signed integer. + I128, + /// 32-bit floating point number. + F32, + /// 64-bit floating point number. + F64, + /// UTF-8 encoded string. + String, + /// Reference version of an UTF-8 encoded string. + StringRef, + /// Vector of `u8` bytes. + Bytes, + /// Reference version (slice) of `u8` bytes. + BytesRef, + /// Vector of another data type. + Vec(Box>), + /// Key-value hash map of data types. + HashMap(Box<(Type<'a>, Type<'a>)>), + /// Hash set of data types (each entry is unique). + HashSet(Box>), + /// Optional value. + Option(Box>), + /// Non-zero value. + /// - Integers: `n > 0` + /// - Collections: `len() > 0` + NonZero(Box>), + /// Boxed version of a string that is immutable. + BoxString, + /// Boxed version of a byte vector that is immutable. + BoxBytes, + /// Fixed size list of up to 12 types. + Tuple(Box<[Type<'a>]>), + /// Continuous list of values with a single time and known length. + Array(Box>, u32), + /// Any external, non-standard data type (like a user defined struct or enum). + External(ExternalType<'a>), +} + +/// Type that is not part of the built-in list of types. +#[derive(Debug, Eq, PartialEq)] +#[cfg_attr(feature = "json", derive(schemars::JsonSchema, serde::Serialize))] +pub struct ExternalType<'a> { + /// Optional path, if the type wasn't fully imported with a `use` statement. + pub path: Box<[&'a str]>, + /// Unique name of the type within the current scope (or the module if prefixed with a path). + pub name: &'a str, + /// Potential generic type arguments. + pub generics: Vec>, +} + +/// Transform the schema into a simpler form, which has less but still enough details to generate +/// language implementations for a schema. +#[must_use] +pub fn schema<'a>(schema: &'a stef_parser::Schema<'_>) -> Schema<'a> { + Schema { + comment: comment(&schema.comment), + definitions: definitions(&schema.definitions), + } +} + +#[inline] +fn comment<'a>(item: &'a stef_parser::Comment<'_>) -> Box<[&'a str]> { + item.0.iter().map(|line| line.value).collect() +} + +#[inline] +fn generics<'a>(item: &'a stef_parser::Generics<'_>) -> Box<[&'a str]> { + item.0.iter().map(stef_parser::Name::get).collect() +} + +#[inline] +fn definitions<'a>(item: &'a [stef_parser::Definition<'_>]) -> Box<[Definition<'a>]> { + item.iter().map(|def| definition(def)).collect() +} + +fn definition<'a>(item: &'a stef_parser::Definition<'_>) -> Definition<'a> { + match item { + stef_parser::Definition::Module(m) => Definition::Module(simplify_module(m)), + stef_parser::Definition::Struct(s) => Definition::Struct(simplify_struct(s)), + stef_parser::Definition::Enum(e) => Definition::Enum(simplify_enum(e)), + stef_parser::Definition::TypeAlias(a) => Definition::TypeAlias(simplify_alias(a)), + stef_parser::Definition::Const(c) => Definition::Const(simplify_const(c)), + stef_parser::Definition::Import(i) => Definition::Import(simplify_import(i)), + } +} + +fn simplify_module<'a>(item: &'a stef_parser::Module<'_>) -> Module<'a> { + Module { + comment: comment(&item.comment), + name: item.name.get(), + definitions: definitions(&item.definitions), + } +} + +fn simplify_struct<'a>(item: &'a stef_parser::Struct<'_>) -> Struct<'a> { + Struct { + comment: comment(&item.comment), + name: item.name.get(), + generics: generics(&item.generics), + fields: simplify_fields(&item.fields), + } +} + +fn simplify_enum<'a>(item: &'a stef_parser::Enum<'_>) -> Enum<'a> { + Enum { + comment: comment(&item.comment), + name: item.name.get(), + generics: generics(&item.generics), + variants: item + .variants + .iter() + .map(|variant| simplify_variant(variant)) + .collect(), + } +} + +fn simplify_variant<'a>(item: &'a stef_parser::Variant<'_>) -> Variant<'a> { + Variant { + comment: comment(&item.comment), + name: item.name.get(), + fields: simplify_fields(&item.fields), + id: item.id.get(), + } +} + +fn simplify_fields<'a>(item: &'a stef_parser::Fields<'_>) -> Fields<'a> { + match item { + stef_parser::Fields::Named(named) => Fields { + fields: named + .iter() + .map(|field| Field { + comment: comment(&field.comment), + name: field.name.get().into(), + ty: simplify_type(&field.ty), + id: field.id.get(), + }) + .collect(), + kind: FieldKind::Named, + }, + stef_parser::Fields::Unnamed(unnamed) => Fields { + fields: unnamed + .iter() + .enumerate() + .map(|(i, field)| Field { + comment: Box::default(), + name: format!("n{i}").into(), + ty: simplify_type(&field.ty), + id: field.id.get(), + }) + .collect(), + kind: FieldKind::Unnamed, + }, + stef_parser::Fields::Unit => Fields { + fields: Box::default(), + kind: FieldKind::Unit, + }, + } +} + +fn simplify_type<'a>(item: &'a stef_parser::Type<'_>) -> Type<'a> { + match item.value { + stef_parser::DataType::Bool => Type::Bool, + stef_parser::DataType::U8 => Type::U8, + stef_parser::DataType::U16 => Type::U16, + stef_parser::DataType::U32 => Type::U32, + stef_parser::DataType::U64 => Type::U64, + stef_parser::DataType::U128 => Type::U128, + stef_parser::DataType::I8 => Type::I8, + stef_parser::DataType::I16 => Type::I16, + stef_parser::DataType::I32 => Type::I32, + stef_parser::DataType::I64 => Type::I64, + stef_parser::DataType::I128 => Type::I128, + stef_parser::DataType::F32 => Type::F32, + stef_parser::DataType::F64 => Type::F64, + stef_parser::DataType::String => Type::String, + stef_parser::DataType::StringRef => Type::StringRef, + stef_parser::DataType::Bytes => Type::Bytes, + stef_parser::DataType::BytesRef => Type::BytesRef, + stef_parser::DataType::Vec(ref ty) => Type::Vec(simplify_type(ty).into()), + stef_parser::DataType::HashMap(ref kv) => { + Type::HashMap((simplify_type(&kv.0), simplify_type(&kv.1)).into()) + } + stef_parser::DataType::HashSet(ref ty) => Type::HashSet(simplify_type(ty).into()), + stef_parser::DataType::Option(ref ty) => Type::Option(simplify_type(ty).into()), + stef_parser::DataType::NonZero(ref ty) => Type::NonZero(simplify_type(ty).into()), + stef_parser::DataType::BoxString => Type::BoxString, + stef_parser::DataType::BoxBytes => Type::BoxBytes, + stef_parser::DataType::Tuple(ref types) => { + Type::Tuple(types.iter().map(|ty| simplify_type(ty)).collect()) + } + stef_parser::DataType::Array(ref ty, size) => Type::Array(simplify_type(ty).into(), size), + stef_parser::DataType::External(ref ty) => Type::External(ExternalType { + path: ty.path.iter().map(stef_parser::Name::get).collect(), + name: ty.name.get(), + generics: ty.generics.iter().map(|ty| simplify_type(ty)).collect(), + }), + } +} + +fn simplify_alias<'a>(item: &'a stef_parser::TypeAlias<'_>) -> TypeAlias<'a> { + TypeAlias { + comment: comment(&item.comment), + name: item.name.get(), + generics: generics(&item.generics), + target: simplify_type(&item.target), + } +} + +fn simplify_const<'a>(item: &'a stef_parser::Const<'_>) -> Const<'a> { + Const { + comment: comment(&item.comment), + name: item.name.get(), + ty: simplify_type(&item.ty), + value: simplify_literal(&item.value), + } +} + +fn simplify_literal(item: &stef_parser::Literal) -> Literal { + match item.value { + stef_parser::LiteralValue::Bool(b) => Literal::Bool(b), + stef_parser::LiteralValue::Int(i) => Literal::Int(i), + stef_parser::LiteralValue::Float(f) => Literal::Float(f), + stef_parser::LiteralValue::String(ref s) => Literal::String(s.clone().into()), + stef_parser::LiteralValue::Bytes(ref b) => Literal::Bytes(b.clone().into()), + } +} + +fn simplify_import<'a>(item: &'a stef_parser::Import<'_>) -> Import<'a> { + Import { + segments: item.segments.iter().map(stef_parser::Name::get).collect(), + element: item.element.as_ref().map(|element| element.get().into()), + } +} + +#[cfg(test)] +mod tests { + + #[cfg(feature = "json")] + #[test] + fn json_schema() { + super::Schema::json_schema().unwrap(); + } +} diff --git a/crates/stef-derive/src/debug.rs b/crates/stef-derive/src/debug.rs index f8c3d10..4b7bdf3 100644 --- a/crates/stef-derive/src/debug.rs +++ b/crates/stef-derive/src/debug.rs @@ -15,7 +15,7 @@ pub fn expand(derive: DeriveInput) -> syn::Result { match derive.data { Data::Struct(data) => { - let fields= expand_fields(name, &data.fields); + let fields = expand_fields(&name, &data.fields); Ok(quote! { impl #generics ::core::fmt::Debug for #ident #generics { @@ -30,7 +30,7 @@ pub fn expand(derive: DeriveInput) -> syn::Result { Data::Enum(data) => { let variants = data.variants.iter().map(|variant| { let ident = &variant.ident; - let fields = expand_fields(Literal::string(&ident.to_string()), &variant.fields); + let fields = expand_fields(&Literal::string(&ident.to_string()), &variant.fields); quote! { Self::#ident #fields @@ -51,7 +51,7 @@ pub fn expand(derive: DeriveInput) -> syn::Result { } } -fn expand_fields(name: Literal, fields: &Fields) -> TokenStream { +fn expand_fields(name: &Literal, fields: &Fields) -> TokenStream { match fields { Fields::Named(fields) => { let names = fields.named.iter().map(|field| { diff --git a/crates/stef-derive/src/lib.rs b/crates/stef-derive/src/lib.rs index b072556..b22aebf 100644 --- a/crates/stef-derive/src/lib.rs +++ b/crates/stef-derive/src/lib.rs @@ -9,8 +9,8 @@ use syn::{parse_macro_input, DeriveInput}; mod attributes; mod cause; -mod error; mod debug; +mod error; #[proc_macro_derive(ParserError, attributes(err, rename))] pub fn parser_error(input: proc_macro::TokenStream) -> proc_macro::TokenStream { diff --git a/crates/stef-go/src/decode.rs b/crates/stef-go/src/decode.rs index 70f3b2d..3c5ed9f 100644 --- a/crates/stef-go/src/decode.rs +++ b/crates/stef-go/src/decode.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display}; -use stef_parser::{DataType, Fields, Generics, Struct, Type, Variant}; +use stef_compiler::simplify::{FieldKind, Fields, Struct, Type, Variant}; use crate::definition::{self, RenderGenericNames}; @@ -49,7 +49,7 @@ impl Display for RenderStruct<'_> { pub(super) struct RenderEnumVariant<'a> { pub(super) enum_name: &'a str, - pub(super) generics: &'a Generics<'a>, + pub(super) generics: &'a [&'a str], pub(super) variant: &'a Variant<'a>, } @@ -98,18 +98,8 @@ struct RenderFieldVars<'a>(&'a Fields<'a>); impl Display for RenderFieldVars<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - for field in named { - writeln!(f, "\tfound{} := false", heck::AsUpperCamelCase(&field.name))?; - } - } - Fields::Unnamed(unnamed) => { - for (idx, _) in unnamed.iter().enumerate() { - writeln!(f, "\tfoundF{idx} := false")?; - } - } - Fields::Unit => {} + for field in &*self.0.fields { + writeln!(f, "\tfound{} := false", heck::AsUpperCamelCase(&field.name))?; } Ok(()) @@ -120,28 +110,21 @@ struct RenderFoundChecks<'a>(&'a Fields<'a>); impl Display for RenderFoundChecks<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - for field in named { - writeln!(f, "\tif !found{} {{", heck::AsUpperCamelCase(&field.name))?; - writeln!(f, "\t\treturn nil, buf.MissingFieldError{{")?; - writeln!(f, "\t\t\tID: {}", field.id.get())?; - writeln!(f, "\t\t\tField: \"{}\"", &field.name)?; - writeln!(f, "\t\t}}")?; - writeln!(f, "\t}}")?; + for field in &*self.0.fields { + writeln!(f, "\tif !found{} {{", heck::AsUpperCamelCase(&field.name))?; + writeln!(f, "\t\treturn nil, buf.MissingFieldError{{")?; + writeln!(f, "\t\t\tID: {}", field.id)?; + writeln!( + f, + "\t\t\tField: \"{}\"", + if self.0.kind == FieldKind::Named { + &field.name + } else { + "" } - } - Fields::Unnamed(unnamed) => { - for (idx, field) in unnamed.iter().enumerate() { - writeln!(f, "\tif !foundF{idx} {{")?; - writeln!(f, "\t\treturn nil, buf.MissingFieldError{{")?; - writeln!(f, "\t\t\tID: {}", field.id.get())?; - writeln!(f, "\t\t\tField: \"\"")?; - writeln!(f, "\t\t}}")?; - writeln!(f, "\t}}")?; - } - } - Fields::Unit => {} + )?; + writeln!(f, "\t\t}}")?; + writeln!(f, "\t}}")?; } Ok(()) @@ -152,54 +135,30 @@ struct RenderFields<'a>(&'a Fields<'a>); impl Display for RenderFields<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - for field in named { - writeln!(f, "\t\t\tcase {}:", field.id.get())?; - writeln!( - f, - "\t\t\t\tr2, value, err := {}", - RenderType { - ty: &field.ty, - indent: 4 - } - )?; - writeln!(f, "\t\t\t\tif err != nil {{")?; - writeln!(f, "\t\t\t\t\treturn nil, err")?; - writeln!(f, "\t\t\t\t}}")?; - writeln!(f, "\t\t\t\tr = r2")?; - writeln!( - f, - "\t\t\t\tv.{} = value", - heck::AsUpperCamelCase(&field.name) - )?; - writeln!( - f, - "\t\t\t\tfound{} = true", - heck::AsUpperCamelCase(&field.name) - )?; + for field in &*self.0.fields { + writeln!(f, "\t\t\tcase {}:", field.id)?; + writeln!( + f, + "\t\t\t\tr2, value, err := {}", + RenderType { + ty: &field.ty, + indent: 4 } - } - Fields::Unnamed(unnamed) => { - for (idx, field) in unnamed.iter().enumerate() { - writeln!(f, "\t\t\tcase {}:", field.id.get())?; - writeln!( - f, - "\t\t\t\tr2, value, err := {}", - RenderType { - ty: &field.ty, - indent: 4 - } - )?; - writeln!(f, "\t\t\t\tif err != nil {{")?; - writeln!(f, "\t\t\t\t\treturn nil, err")?; - writeln!(f, "\t\t\t\t}}")?; - writeln!(f, "\t\t\t\tr = r2")?; - writeln!(f, "\t\t\t\tv.F{idx} = value")?; - writeln!(f, "\t\t\t\tfoundF{idx} = true")?; - } - } - Fields::Unit => {} + )?; + writeln!(f, "\t\t\t\tif err != nil {{")?; + writeln!(f, "\t\t\t\t\treturn nil, err")?; + writeln!(f, "\t\t\t\t}}")?; + writeln!(f, "\t\t\t\tr = r2")?; + writeln!( + f, + "\t\t\t\tv.{} = value", + heck::AsUpperCamelCase(&field.name) + )?; + writeln!( + f, + "\t\t\t\tfound{} = true", + heck::AsUpperCamelCase(&field.name) + )?; } Ok(()) @@ -213,27 +172,27 @@ struct RenderType<'a> { impl Display for RenderType<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.ty.value { - DataType::Bool => write!(f, "buf.DecodeBool(r)"), - DataType::U8 => write!(f, "buf.DecodeU8(r)"), - DataType::U16 => write!(f, "buf.DecodeU16(r)"), - DataType::U32 => write!(f, "buf.DecodeU32(r)"), - DataType::U64 => write!(f, "buf.DecodeU64(r)"), - DataType::U128 => write!(f, "buf.DecodeU128(r)"), - DataType::I8 => write!(f, "buf.DecodeI8(r)"), - DataType::I16 => write!(f, "buf.DecodeI16(r)"), - DataType::I32 => write!(f, "buf.DecodeI32(r)"), - DataType::I64 => write!(f, "buf.DecodeI64(r)"), - DataType::I128 => write!(f, "buf.DecodeI128(r)"), - DataType::F32 => write!(f, "buf.DecodeF32(r)"), - DataType::F64 => write!(f, "buf.DecodeF64(r)"), - DataType::String | DataType::StringRef | DataType::BoxString => { + match self.ty { + Type::Bool => write!(f, "buf.DecodeBool(r)"), + Type::U8 => write!(f, "buf.DecodeU8(r)"), + Type::U16 => write!(f, "buf.DecodeU16(r)"), + Type::U32 => write!(f, "buf.DecodeU32(r)"), + Type::U64 => write!(f, "buf.DecodeU64(r)"), + Type::U128 => write!(f, "buf.DecodeU128(r)"), + Type::I8 => write!(f, "buf.DecodeI8(r)"), + Type::I16 => write!(f, "buf.DecodeI16(r)"), + Type::I32 => write!(f, "buf.DecodeI32(r)"), + Type::I64 => write!(f, "buf.DecodeI64(r)"), + Type::I128 => write!(f, "buf.DecodeI128(r)"), + Type::F32 => write!(f, "buf.DecodeF32(r)"), + Type::F64 => write!(f, "buf.DecodeF64(r)"), + Type::String | Type::StringRef | Type::BoxString => { write!(f, "buf.DecodeString(r)") } - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => { + Type::Bytes | Type::BytesRef | Type::BoxBytes => { write!(f, "buf.DecodeBytes(r)") } - DataType::Vec(ty) => { + Type::Vec(ty) => { write!( f, "{}", @@ -244,7 +203,7 @@ impl Display for RenderType<'_> { } ) } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { write!( f, "{}", @@ -255,7 +214,7 @@ impl Display for RenderType<'_> { } ) } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { write!( f, "{}", @@ -266,7 +225,7 @@ impl Display for RenderType<'_> { } ) } - DataType::Option(ty) => { + Type::Option(ty) => { write!( f, "{}", @@ -277,20 +236,20 @@ impl Display for RenderType<'_> { } ) } - DataType::NonZero(ty) => match &ty.value { - DataType::U8 => write!(f, "buf.DecodeNonZeroU8(r)"), - DataType::U16 => write!(f, "buf.DecodeNonZeroU16(r)"), - DataType::U32 => write!(f, "buf.DecodeNonZeroU32(r)"), - DataType::U64 => write!(f, "buf.DecodeNonZeroU64(r)"), - DataType::U128 => write!(f, "buf.DecodeNonZeroU128(r)"), - DataType::I8 => write!(f, "buf.DecodeNonZeroI8(r)"), - DataType::I16 => write!(f, "buf.DecodeNonZeroI16(r)"), - DataType::I32 => write!(f, "buf.DecodeNonZeroI32(r)"), - DataType::I64 => write!(f, "buf.DecodeNonZeroI64(r)"), - DataType::I128 => write!(f, "buf.DecodeNonZeroI128(r)"), - DataType::String | DataType::StringRef => write!(f, "buf.DecodeNonZeroString(r)"), - DataType::Bytes | DataType::BytesRef => write!(f, "buf.DecodeNonZeroBytes(r)"), - DataType::Vec(ty) => { + Type::NonZero(ty) => match &**ty { + Type::U8 => write!(f, "buf.DecodeNonZeroU8(r)"), + Type::U16 => write!(f, "buf.DecodeNonZeroU16(r)"), + Type::U32 => write!(f, "buf.DecodeNonZeroU32(r)"), + Type::U64 => write!(f, "buf.DecodeNonZeroU64(r)"), + Type::U128 => write!(f, "buf.DecodeNonZeroU128(r)"), + Type::I8 => write!(f, "buf.DecodeNonZeroI8(r)"), + Type::I16 => write!(f, "buf.DecodeNonZeroI16(r)"), + Type::I32 => write!(f, "buf.DecodeNonZeroI32(r)"), + Type::I64 => write!(f, "buf.DecodeNonZeroI64(r)"), + Type::I128 => write!(f, "buf.DecodeNonZeroI128(r)"), + Type::String | Type::StringRef => write!(f, "buf.DecodeNonZeroString(r)"), + Type::Bytes | Type::BytesRef => write!(f, "buf.DecodeNonZeroBytes(r)"), + Type::Vec(ty) => { write!( f, "{}", @@ -301,7 +260,7 @@ impl Display for RenderType<'_> { } ) } - DataType::HashMap(kv) => { + Type::HashMap(kv) => { write!( f, "{}", @@ -312,7 +271,7 @@ impl Display for RenderType<'_> { } ) } - DataType::HashSet(ty) => { + Type::HashSet(ty) => { write!( f, "{}", @@ -325,7 +284,7 @@ impl Display for RenderType<'_> { } ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => match types.len() { + Type::Tuple(types) => match types.len() { n @ 2..=12 => { writeln!(f, "func (r []byte) ([]byte, buf.Tuple{n}, error) {{")?; for (idx, ty) in types.iter().enumerate() { @@ -370,7 +329,7 @@ impl Display for RenderType<'_> { } n => todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, size) => match *size { + Type::Array(ty, size) => match *size { 1..=32 => { writeln!( f, @@ -391,7 +350,7 @@ impl Display for RenderType<'_> { } n => todo!("arrays with larger ({n}) sizes"), }, - DataType::External(_) => { + Type::External(_) => { writeln!( f, "func(r []byte) ([]byte, {}, error) {{", diff --git a/crates/stef-go/src/definition.rs b/crates/stef-go/src/definition.rs index 9ff17b6..657ac17 100644 --- a/crates/stef-go/src/definition.rs +++ b/crates/stef-go/src/definition.rs @@ -1,8 +1,8 @@ use std::fmt::{self, Display, Write}; -use stef_parser::{ - Comment, Const, DataType, Definition, Enum, ExternalType, Fields, Generics, Literal, - LiteralValue, Name, Schema, Struct, Type, TypeAlias, Variant, +use stef_compiler::simplify::{ + Const, Definition, Enum, ExternalType, Fields, Literal, Schema, Struct, Type, TypeAlias, + Variant, }; use crate::{decode, encode, size, Opts, Output}; @@ -38,7 +38,7 @@ fn render_definition<'a>(buf: &mut String, definition: &'a Definition<'_>) -> Op let mut content = format!( "{}{}", RenderHeader, - RenderPackage(m.name.get(), Some(&m.comment)) + RenderPackage(m.name, Some(&m.comment)) ); let modules = m @@ -48,7 +48,7 @@ fn render_definition<'a>(buf: &mut String, definition: &'a Definition<'_>) -> Op .collect(); return Some(Output { - name: m.name.get(), + name: m.name, content, modules, }); @@ -97,7 +97,7 @@ impl Display for RenderHeader { } } -struct RenderPackage<'a>(&'a str, Option<&'a Comment<'a>>); +struct RenderPackage<'a>(&'a str, Option<&'a [&'a str]>); impl Display for RenderPackage<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -143,7 +143,7 @@ impl Display for RenderStruct<'_> { struct RenderNewFunc<'a, T> { name: T, - generics: &'a Generics<'a>, + generics: &'a [&'a str], fields: &'a Fields<'a>, filter_generics: bool, } @@ -182,7 +182,7 @@ where } struct RenderGenerics<'a> { - generics: &'a Generics<'a>, + generics: &'a [&'a str], fields_filter: Option<&'a Fields<'a>>, } @@ -190,12 +190,12 @@ impl Display for RenderGenerics<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.fields_filter { Some(fields) => { - if !self.generics.0.iter().any(|gen| uses_generic(gen, fields)) { + if !self.generics.iter().any(|gen| uses_generic(gen, fields)) { return Ok(()); } } None => { - if self.generics.0.is_empty() { + if self.generics.is_empty() { return Ok(()); } } @@ -204,7 +204,6 @@ impl Display for RenderGenerics<'_> { f.write_char('[')?; for (i, value) in self .generics - .0 .iter() .filter(|gen| match self.fields_filter { Some(fields) => uses_generic(gen, fields), @@ -222,7 +221,7 @@ impl Display for RenderGenerics<'_> { } pub(super) struct RenderGenericNames<'a> { - pub(super) generics: &'a Generics<'a>, + pub(super) generics: &'a [&'a str], pub(super) fields_filter: Option<&'a Fields<'a>>, } @@ -230,12 +229,12 @@ impl Display for RenderGenericNames<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.fields_filter { Some(fields) => { - if !self.generics.0.iter().any(|gen| uses_generic(gen, fields)) { + if !self.generics.iter().any(|gen| uses_generic(gen, fields)) { return Ok(()); } } None => { - if self.generics.0.is_empty() { + if self.generics.is_empty() { return Ok(()); } } @@ -244,7 +243,6 @@ impl Display for RenderGenericNames<'_> { f.write_char('[')?; for (i, value) in self .generics - .0 .iter() .filter(|gen| match self.fields_filter { Some(fields) => uses_generic(gen, fields), @@ -284,43 +282,25 @@ struct RenderFields<'a>(&'a Fields<'a>); impl Display for RenderFields<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - if named.is_empty() { - write!(f, "struct{{}}") - } else { - writeln!(f, "struct {{")?; - - for field in named { - writeln!( - f, - "{}\t{} {}", - RenderComment { - indent: 1, - comment: &field.comment - }, - heck::AsUpperCamelCase(&field.name), - RenderType(&field.ty) - )?; - } + if self.0.fields.is_empty() { + write!(f, "struct{{}}") + } else { + writeln!(f, "struct {{")?; - write!(f, "}}") - } + for field in &*self.0.fields { + writeln!( + f, + "{}\t{} {}", + RenderComment { + indent: 1, + comment: &field.comment + }, + heck::AsUpperCamelCase(&field.name), + RenderType(&field.ty) + )?; } - Fields::Unnamed(unnamed) => { - if unnamed.is_empty() { - write!(f, "struct{{}}") - } else { - writeln!(f, "struct {{")?; - - for (i, field) in unnamed.iter().enumerate() { - writeln!(f, "\tF{i} {}", RenderType(&field.ty))?; - } - write!(f, "}}") - } - } - Fields::Unit => write!(f, "struct{{}}"), + write!(f, "}}") } } } @@ -329,31 +309,17 @@ struct RenderParameters<'a>(&'a Fields<'a>); impl Display for RenderParameters<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - if !named.is_empty() { - writeln!(f)?; - } - - for field in named { - writeln!( - f, - "\t{} {},", - heck::AsLowerCamelCase(&field.name), - RenderType(&field.ty), - )?; - } - } - Fields::Unnamed(unnamed) => { - if !unnamed.is_empty() { - writeln!(f)?; - } + if !self.0.fields.is_empty() { + writeln!(f)?; + } - for (i, field) in unnamed.iter().enumerate() { - writeln!(f, "\tf{i} {},", RenderType(&field.ty))?; - } - } - Fields::Unit => {} + for field in &*self.0.fields { + writeln!( + f, + "\t{} {},", + heck::AsLowerCamelCase(&field.name), + RenderType(&field.ty), + )?; } Ok(()) @@ -364,39 +330,21 @@ struct RenderConstructor<'a>(&'a Fields<'a>); impl Display for RenderConstructor<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - if named.is_empty() { - write!(f, "{{}}") - } else { - writeln!(f, "{{")?; - - for field in named { - writeln!( - f, - "\t\t{}: {},", - heck::AsUpperCamelCase(&field.name), - heck::AsLowerCamelCase(&field.name) - )?; - } + if self.0.fields.is_empty() { + write!(f, "{{}}") + } else { + writeln!(f, "{{")?; - write!(f, "\t}}") - } + for field in &*self.0.fields { + writeln!( + f, + "\t\t{}: {},", + heck::AsUpperCamelCase(&field.name), + heck::AsLowerCamelCase(&field.name) + )?; } - Fields::Unnamed(unnamed) => { - if unnamed.is_empty() { - write!(f, "{{}}") - } else { - writeln!(f, "{{")?; - - for (i, _) in unnamed.iter().enumerate() { - writeln!(f, "\t\tF{i}: f{i},")?; - } - write!(f, "\t}}") - } - } - Fields::Unit => write!(f, "{{}}"), + write!(f, "\t}}") } } } @@ -420,13 +368,13 @@ impl Display for RenderAlias<'_> { struct RenderComment<'a> { indent: usize, - comment: &'a Comment<'a>, + comment: &'a [&'a str], } impl Display for RenderComment<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for line in &self.comment.0 { - writeln!(f, "{:\t(pub(super) &'a Type<'a>); impl Display for RenderType<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.0.value { - DataType::Bool => write!(f, "bool"), - DataType::U8 => write!(f, "uint8"), - DataType::U16 => write!(f, "uint16"), - DataType::U32 => write!(f, "uint32"), - DataType::U64 => write!(f, "uint64"), - DataType::U128 | DataType::I128 => write!(f, "*big.Int"), - DataType::I8 => write!(f, "int8"), - DataType::I16 => write!(f, "int16"), - DataType::I32 => write!(f, "int32"), - DataType::I64 => write!(f, "int64"), - DataType::F32 => write!(f, "float32"), - DataType::F64 => write!(f, "float64"), - DataType::String | DataType::StringRef | DataType::BoxString => write!(f, "string"), - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => write!(f, "[]byte"), - DataType::Vec(ty) => write!(f, "[]{}", RenderType(ty)), - DataType::HashMap(kv) => write!(f, "map[{}]{}", RenderType(&kv.0), RenderType(&kv.1)), - DataType::HashSet(ty) => write!(f, "map[{}]struct{{}}", RenderType(ty)), - DataType::Option(ty) => write!(f, "*{}", RenderType(ty)), - DataType::NonZero(ty) => match &ty.value { - DataType::U8 => write!(f, "stef.NonZeroU8"), - DataType::U16 => write!(f, "stef.NonZeroU16"), - DataType::U32 => write!(f, "stef.NonZeroU32"), - DataType::U64 => write!(f, "stef.NonZeroU64"), - DataType::U128 => write!(f, "stef.NonZeroU128"), - DataType::I8 => write!(f, "stef.NonZeroI8"), - DataType::I16 => write!(f, "stef.NonZeroI16"), - DataType::I32 => write!(f, "stef.NonZeroI32"), - DataType::I64 => write!(f, "stef.NonZeroI64"), - DataType::I128 => write!(f, "stef.NonZeroI128"), - DataType::F32 => write!(f, "stef.NonZeroF32"), - DataType::F64 => write!(f, "stef.NonZeroF64"), - DataType::String | DataType::StringRef => write!(f, "stef.NonZeroString"), - DataType::Bytes | DataType::BytesRef => write!(f, "stef.NonZeroBytes"), - DataType::Vec(ty) => write!(f, "stef.NonZeroVec[{}]", RenderType(ty)), - DataType::HashMap(kv) => write!( + match self.0 { + Type::Bool => write!(f, "bool"), + Type::U8 => write!(f, "uint8"), + Type::U16 => write!(f, "uint16"), + Type::U32 => write!(f, "uint32"), + Type::U64 => write!(f, "uint64"), + Type::U128 | Type::I128 => write!(f, "*big.Int"), + Type::I8 => write!(f, "int8"), + Type::I16 => write!(f, "int16"), + Type::I32 => write!(f, "int32"), + Type::I64 => write!(f, "int64"), + Type::F32 => write!(f, "float32"), + Type::F64 => write!(f, "float64"), + Type::String | Type::StringRef | Type::BoxString => write!(f, "string"), + Type::Bytes | Type::BytesRef | Type::BoxBytes => write!(f, "[]byte"), + Type::Vec(ty) => write!(f, "[]{}", RenderType(ty)), + Type::HashMap(kv) => write!(f, "map[{}]{}", RenderType(&kv.0), RenderType(&kv.1)), + Type::HashSet(ty) => write!(f, "map[{}]struct{{}}", RenderType(ty)), + Type::Option(ty) => write!(f, "*{}", RenderType(ty)), + Type::NonZero(ty) => match &**ty { + Type::U8 => write!(f, "stef.NonZeroU8"), + Type::U16 => write!(f, "stef.NonZeroU16"), + Type::U32 => write!(f, "stef.NonZeroU32"), + Type::U64 => write!(f, "stef.NonZeroU64"), + Type::U128 => write!(f, "stef.NonZeroU128"), + Type::I8 => write!(f, "stef.NonZeroI8"), + Type::I16 => write!(f, "stef.NonZeroI16"), + Type::I32 => write!(f, "stef.NonZeroI32"), + Type::I64 => write!(f, "stef.NonZeroI64"), + Type::I128 => write!(f, "stef.NonZeroI128"), + Type::F32 => write!(f, "stef.NonZeroF32"), + Type::F64 => write!(f, "stef.NonZeroF64"), + Type::String | Type::StringRef => write!(f, "stef.NonZeroString"), + Type::Bytes | Type::BytesRef => write!(f, "stef.NonZeroBytes"), + Type::Vec(ty) => write!(f, "stef.NonZeroVec[{}]", RenderType(ty)), + Type::HashMap(kv) => write!( f, "stef.NonZeroHashMap[{}, {}]", RenderType(&kv.0), RenderType(&kv.1) ), - DataType::HashSet(ty) => write!(f, "stef.NonZeroHashSet[{}]", RenderType(ty)), + Type::HashSet(ty) => write!(f, "stef.NonZeroHashSet[{}]", RenderType(ty)), ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => write!(f, "stef.Tuple{}{}", types.len(), Concat(types)), - DataType::Array(ty, size) => write!(f, "[{size}]{}", RenderType(ty)), - DataType::External(ExternalType { + Type::Tuple(types) => write!(f, "stef.Tuple{}{}", types.len(), Concat(types)), + Type::Array(ty, size) => write!(f, "[{size}]{}", RenderType(ty)), + Type::External(ExternalType { path, name, generics, @@ -512,32 +460,29 @@ struct RenderConstType<'a>(&'a Type<'a>); impl Display for RenderConstType<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.0.value { - DataType::Bool => write!(f, "bool"), - DataType::U8 => write!(f, "uint8"), - DataType::U16 => write!(f, "uint16"), - DataType::U32 => write!(f, "uint32"), - DataType::U64 => write!(f, "uint64"), - DataType::U128 | DataType::I128 => write!(f, "*big.Int"), - DataType::I8 => write!(f, "int8"), - DataType::I16 => write!(f, "int16"), - DataType::I32 => write!(f, "int32"), - DataType::I64 => write!(f, "int64"), - DataType::F32 => write!(f, "float32"), - DataType::F64 => write!(f, "float64"), - DataType::String | DataType::StringRef => write!(f, "string"), - DataType::Bytes | DataType::BytesRef => write!(f, "[]byte"), + match self.0 { + Type::Bool => write!(f, "bool"), + Type::U8 => write!(f, "uint8"), + Type::U16 => write!(f, "uint16"), + Type::U32 => write!(f, "uint32"), + Type::U64 => write!(f, "uint64"), + Type::U128 | Type::I128 => write!(f, "*big.Int"), + Type::I8 => write!(f, "int8"), + Type::I16 => write!(f, "int16"), + Type::I32 => write!(f, "int32"), + Type::I64 => write!(f, "int64"), + Type::F32 => write!(f, "float32"), + Type::F64 => write!(f, "float64"), + Type::String | Type::StringRef => write!(f, "string"), + Type::Bytes | Type::BytesRef => write!(f, "[]byte"), _ => panic!("invalid data type for const"), } } } -struct Concat<'a, T>(&'a [T]); +struct Concat<'a>(&'a [Type<'a>]); -impl Display for Concat<'_, T> -where - T: Display, -{ +impl Display for Concat<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.0.is_empty() { return Ok(()); @@ -548,7 +493,7 @@ where if i > 0 { f.write_str(", ")?; } - value.fmt(f)?; + RenderType(value).fmt(f)?; } f.write_char(']') } @@ -559,20 +504,20 @@ struct RenderConst<'a>(&'a Const<'a>); impl Display for RenderConst<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let kind = if matches!( - self.0.ty.value, - DataType::Bool - | DataType::U8 - | DataType::U16 - | DataType::U32 - | DataType::U64 - | DataType::I8 - | DataType::I16 - | DataType::I32 - | DataType::I64 - | DataType::F32 - | DataType::F64 - | DataType::String - | DataType::StringRef + self.0.ty, + Type::Bool + | Type::U8 + | Type::U16 + | Type::U32 + | Type::U64 + | Type::I8 + | Type::I16 + | Type::I32 + | Type::I64 + | Type::F32 + | Type::F64 + | Type::String + | Type::StringRef ) { "const" } else { @@ -597,12 +542,12 @@ struct RenderLiteral<'a>(&'a Literal); impl Display for RenderLiteral<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.0.value { - LiteralValue::Bool(b) => write!(f, "{b}"), - LiteralValue::Int(i) => write!(f, "{i}"), - LiteralValue::Float(f2) => write!(f, "{f2}"), - LiteralValue::String(s) => write!(f, "{s:?}"), - LiteralValue::Bytes(b) => { + match &self.0 { + Literal::Bool(b) => write!(f, "{b}"), + Literal::Int(i) => write!(f, "{i}"), + Literal::Float(f2) => write!(f, "{f2}"), + Literal::String(s) => write!(f, "{s:?}"), + Literal::Bytes(b) => { if b.is_empty() { return Ok(()); } @@ -647,7 +592,7 @@ impl Display for RenderEnum<'_> { f, "\n{}", RenderEnumVariant { - enum_name: self.0.name.get(), + enum_name: self.0.name, generics: &self.0.generics, variant } @@ -660,7 +605,7 @@ impl Display for RenderEnum<'_> { struct RenderEnumVariant<'a> { enum_name: &'a str, - generics: &'a Generics<'a>, + generics: &'a [&'a str], variant: &'a Variant<'a>, } @@ -730,50 +675,45 @@ impl Display for RenderEnumVariant<'_> { } } -fn uses_generic(generic: &Name<'_>, fields: &Fields<'_>) -> bool { +fn uses_generic(generic: &str, fields: &Fields<'_>) -> bool { fn visit_external(ty: &Type<'_>, visit: &impl Fn(&ExternalType<'_>) -> bool) -> bool { - match &ty.value { - 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 - | DataType::String - | DataType::StringRef - | DataType::Bytes - | DataType::BytesRef - | DataType::BoxString - | DataType::BoxBytes => false, - DataType::Vec(ty) - | DataType::HashSet(ty) - | DataType::Option(ty) - | DataType::NonZero(ty) - | DataType::Array(ty, _) => visit_external(ty, visit), - DataType::HashMap(kv) => visit_external(&kv.0, visit) || visit_external(&kv.1, visit), - DataType::Tuple(types) => types.iter().any(|ty| visit_external(ty, visit)), - DataType::External(ty) => visit(ty), + match ty { + Type::Bool + | Type::U8 + | Type::U16 + | Type::U32 + | Type::U64 + | Type::U128 + | Type::I8 + | Type::I16 + | Type::I32 + | Type::I64 + | Type::I128 + | Type::F32 + | Type::F64 + | Type::String + | Type::StringRef + | Type::Bytes + | Type::BytesRef + | Type::BoxString + | Type::BoxBytes => false, + Type::Vec(ty) + | Type::HashSet(ty) + | Type::Option(ty) + | Type::NonZero(ty) + | Type::Array(ty, _) => visit_external(ty, visit), + Type::HashMap(kv) => visit_external(&kv.0, visit) || visit_external(&kv.1, visit), + Type::Tuple(types) => types.iter().any(|ty| visit_external(ty, visit)), + Type::External(ty) => visit(ty), } } let matches = |ext: &ExternalType<'_>| { - ext.path.is_empty() && ext.generics.is_empty() && ext.name.get() == generic.get() + ext.path.is_empty() && ext.generics.is_empty() && ext.name == generic }; - match fields { - Fields::Named(named) => named - .iter() - .any(|field| visit_external(&field.ty, &matches)), - Fields::Unnamed(unnamed) => unnamed - .iter() - .any(|field| visit_external(&field.ty, &matches)), - Fields::Unit => false, - } + fields + .fields + .iter() + .any(|field| visit_external(&field.ty, &matches)) } diff --git a/crates/stef-go/src/encode.rs b/crates/stef-go/src/encode.rs index 648b3f3..88c85dd 100644 --- a/crates/stef-go/src/encode.rs +++ b/crates/stef-go/src/encode.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display}; -use stef_parser::{DataType, Fields, Generics, Struct, Type, Variant}; +use stef_compiler::simplify::{FieldKind, Fields, Struct, Type, Variant}; use crate::definition::{self, RenderGenericNames}; @@ -35,7 +35,7 @@ impl Display for RenderStruct<'_> { pub(super) struct RenderEnumVariant<'a> { pub(super) enum_name: &'a str, - pub(super) generics: &'a Generics<'a>, + pub(super) generics: &'a [&'a str], pub(super) variant: &'a Variant<'a>, } @@ -70,76 +70,40 @@ struct RenderFields<'a>(&'a Fields<'a>); impl Display for RenderFields<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - for field in named { - if let DataType::Option(ty) = &field.ty.value { - writeln!( - f, - "\tw = buf.EncodeFieldOption[{}](w, {}, &v.{}, func (w []byte, v {0}) \ - []byte {{\n\t\treturn {}\n\t}})", - definition::RenderType(ty), - field.id.get(), - heck::AsUpperCamelCase(&field.name), - RenderType { - ty, - name: "v", - indent: 2, - }, - )?; - } else { - writeln!( - f, - "\tw = buf.EncodeField(w, {}, func (w []byte) []byte {{\n\t\treturn \ - {}\n\t}})", - field.id.get(), - RenderType { - ty: &field.ty, - name: format_args!("v.{}", heck::AsUpperCamelCase(&field.name)), - indent: 2, - }, - )?; - } - } - - writeln!(f, "\tw = buf.EncodeU32(w, buf.EndMarker)")?; - } - Fields::Unnamed(unnamed) => { - for (idx, field) in unnamed.iter().enumerate() { - if let DataType::Option(ty) = &field.ty.value { - writeln!( - f, - "\tw = buf.EncodeFieldOption[{}](w, {}, &v.F{idx}, func (w []byte, v \ - {0}) []byte {{\n\t\treturn {}\n\t}})", - definition::RenderType(ty), - field.id.get(), - RenderType { - ty, - name: "v", - indent: 2, - }, - )?; - } else { - writeln!( - f, - "\tw = buf.EncodeField(w, {}, func (w []byte) []byte {{\n\t\treturn \ - {}\n\t}})", - field.id.get(), - RenderType { - ty: &field.ty, - name: format_args!("v.F{idx}"), - indent: 2, - }, - )?; - } - } + if self.0.kind == FieldKind::Unit { + return Ok(()); + } - writeln!(f, "\tw = buf.EncodeU32(w, buf.EndMarker)")?; + for field in &*self.0.fields { + if let Type::Option(ty) = &field.ty { + writeln!( + f, + "\tw = buf.EncodeFieldOption[{}](w, {}, &v.{}, func (w []byte, v {0}) []byte \ + {{\n\t\treturn {}\n\t}})", + definition::RenderType(ty), + field.id, + heck::AsUpperCamelCase(&field.name), + RenderType { + ty, + name: "v", + indent: 2, + }, + )?; + } else { + writeln!( + f, + "\tw = buf.EncodeField(w, {}, func (w []byte) []byte {{\n\t\treturn {}\n\t}})", + field.id, + RenderType { + ty: &field.ty, + name: format_args!("v.{}", heck::AsUpperCamelCase(&field.name)), + indent: 2, + }, + )?; } - Fields::Unit => {} } - Ok(()) + writeln!(f, "\tw = buf.EncodeU32(w, buf.EndMarker)") } } @@ -154,27 +118,27 @@ where T: Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.ty.value { - DataType::Bool => write!(f, "buf.EncodeBool(w, {})", self.name), - DataType::U8 => write!(f, "buf.EncodeU8(w, {})", self.name), - DataType::U16 => write!(f, "buf.EncodeU16(w, {})", self.name), - DataType::U32 => write!(f, "buf.EncodeU32(w, {})", self.name), - DataType::U64 => write!(f, "buf.EncodeU64(w, {})", self.name), - DataType::U128 => write!(f, "buf.EncodeU128(w, {})", self.name), - DataType::I8 => write!(f, "buf.EncodeI8(w, {})", self.name), - DataType::I16 => write!(f, "buf.EncodeI16(w, {})", self.name), - DataType::I32 => write!(f, "buf.EncodeI32(w, {})", self.name), - DataType::I64 => write!(f, "buf.EncodeI64(w, {})", self.name), - DataType::I128 => write!(f, "buf.EncodeI128(w, {})", self.name), - DataType::F32 => write!(f, "buf.EncodeF32(w, {})", self.name), - DataType::F64 => write!(f, "buf.EncodeF64(w, {})", self.name), - DataType::String | DataType::StringRef | DataType::BoxString => { + match self.ty { + Type::Bool => write!(f, "buf.EncodeBool(w, {})", self.name), + Type::U8 => write!(f, "buf.EncodeU8(w, {})", self.name), + Type::U16 => write!(f, "buf.EncodeU16(w, {})", self.name), + Type::U32 => write!(f, "buf.EncodeU32(w, {})", self.name), + Type::U64 => write!(f, "buf.EncodeU64(w, {})", self.name), + Type::U128 => write!(f, "buf.EncodeU128(w, {})", self.name), + Type::I8 => write!(f, "buf.EncodeI8(w, {})", self.name), + Type::I16 => write!(f, "buf.EncodeI16(w, {})", self.name), + Type::I32 => write!(f, "buf.EncodeI32(w, {})", self.name), + Type::I64 => write!(f, "buf.EncodeI64(w, {})", self.name), + Type::I128 => write!(f, "buf.EncodeI128(w, {})", self.name), + Type::F32 => write!(f, "buf.EncodeF32(w, {})", self.name), + Type::F64 => write!(f, "buf.EncodeF64(w, {})", self.name), + Type::String | Type::StringRef | Type::BoxString => { write!(f, "buf.EncodeString(w, {})", self.name) } - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => { + Type::Bytes | Type::BytesRef | Type::BoxBytes => { write!(f, "buf.EncodeBytes(w, {})", self.name) } - DataType::Vec(ty) => { + Type::Vec(ty) => { writeln!( f, "buf.EncodeVec[{}](w, {}, func(w []byte, v {0}) []byte {{", @@ -194,7 +158,7 @@ where )?; write!(f, "{:\t { + Type::HashMap(kv) => { writeln!( f, "buf.EncodeHashMap[{}, {}](", @@ -250,7 +214,7 @@ where writeln!(f, "{:\t { + Type::HashSet(ty) => { writeln!( f, "buf.EncodeHashSet[{}](w, {}, func(w []byte, v {0}) []byte {{", @@ -270,7 +234,7 @@ where )?; write!(f, "{:\t { + Type::Option(ty) => { writeln!( f, "buf.EncodeOption[{}](w, {}, func(w []byte, v {0}) []byte {{", @@ -290,24 +254,24 @@ where )?; write!(f, "{:\t match &ty.value { - DataType::U8 => write!(f, "buf.EncodeU8(w, {}.Get())", self.name), - DataType::U16 => write!(f, "buf.EncodeU16(w, {}.Get())", self.name), - DataType::U32 => write!(f, "buf.EncodeU32(w, {}.Get())", self.name), - DataType::U64 => write!(f, "buf.EncodeU64(w, {}.Get())", self.name), - DataType::U128 => write!(f, "buf.EncodeU128(w, {}.Get())", self.name), - DataType::I8 => write!(f, "buf.EncodeI8(w, {}.Get())", self.name), - DataType::I16 => write!(f, "buf.EncodeI16(w, {}.Get())", self.name), - DataType::I32 => write!(f, "buf.EncodeI32(w, {}.Get())", self.name), - DataType::I64 => write!(f, "buf.EncodeI64(w, {}.Get())", self.name), - DataType::I128 => write!(f, "buf.EncodeI128(w, {}.Get())", self.name), - DataType::String - | DataType::StringRef - | DataType::Bytes - | DataType::BytesRef - | DataType::Vec(_) - | DataType::HashMap(_) - | DataType::HashSet(_) => write!( + Type::NonZero(ty) => match &**ty { + Type::U8 => write!(f, "buf.EncodeU8(w, {}.Get())", self.name), + Type::U16 => write!(f, "buf.EncodeU16(w, {}.Get())", self.name), + Type::U32 => write!(f, "buf.EncodeU32(w, {}.Get())", self.name), + Type::U64 => write!(f, "buf.EncodeU64(w, {}.Get())", self.name), + Type::U128 => write!(f, "buf.EncodeU128(w, {}.Get())", self.name), + Type::I8 => write!(f, "buf.EncodeI8(w, {}.Get())", self.name), + Type::I16 => write!(f, "buf.EncodeI16(w, {}.Get())", self.name), + Type::I32 => write!(f, "buf.EncodeI32(w, {}.Get())", self.name), + Type::I64 => write!(f, "buf.EncodeI64(w, {}.Get())", self.name), + Type::I128 => write!(f, "buf.EncodeI128(w, {}.Get())", self.name), + Type::String + | Type::StringRef + | Type::Bytes + | Type::BytesRef + | Type::Vec(_) + | Type::HashMap(_) + | Type::HashSet(_) => write!( f, "{}", RenderType { @@ -318,7 +282,7 @@ where ), ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => match types.len() { + Type::Tuple(types) => match types.len() { 2..=12 => { writeln!(f, "func (w []byte) []byte {{")?; for (idx, ty) in types.iter().enumerate() { @@ -339,7 +303,7 @@ where } n => todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, size) => match *size { + Type::Array(ty, size) => match *size { 1..=32 => { writeln!( f, @@ -362,7 +326,7 @@ where } n => todo!("arrays with larger ({n}) sizes"), }, - DataType::External(_) => write!(f, "{}.Encode(w)", self.name), + Type::External(_) => write!(f, "{}.Encode(w)", self.name), } } } diff --git a/crates/stef-go/src/size.rs b/crates/stef-go/src/size.rs index d9935c8..5f569f6 100644 --- a/crates/stef-go/src/size.rs +++ b/crates/stef-go/src/size.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display}; -use stef_parser::{DataType, Fields, Generics, Struct, Type, Variant}; +use stef_compiler::simplify::{FieldKind, Fields, Struct, Type, Variant}; use crate::definition::{self, RenderGenericNames}; @@ -36,7 +36,7 @@ impl Display for RenderStruct<'_> { pub(super) struct RenderEnumVariant<'a> { pub(super) enum_name: &'a str, - pub(super) generics: &'a Generics<'a>, + pub(super) generics: &'a [&'a str], pub(super) variant: &'a Variant<'a>, } @@ -72,74 +72,40 @@ struct RenderFields<'a>(&'a Fields<'a>); impl Display for RenderFields<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Fields::Named(named) => { - for field in named { - if let DataType::Option(ty) = &field.ty.value { - writeln!( - f, - "\tsize += buf.SizeFieldOption[{}]({}, &v.{}, func (v {0}) []byte \ - {{\n\t\treturn {}\n\t}})", - definition::RenderType(ty), - field.id.get(), - heck::AsUpperCamelCase(&field.name), - RenderType { - ty, - name: "v", - indent: 2, - }, - )?; - } else { - writeln!( - f, - "\tsize += buf.SizeField({}, func() int {{\n\t\treturn {}\n\t}})", - field.id.get(), - RenderType { - ty: &field.ty, - name: format_args!("v.{}", heck::AsUpperCamelCase(&field.name)), - indent: 2, - }, - )?; - } - } - - writeln!(f, "\tsize += buf.SizeU32(buf.EndMarker)")?; - } - Fields::Unnamed(unnamed) => { - for (idx, field) in unnamed.iter().enumerate() { - if let DataType::Option(ty) = &field.ty.value { - writeln!( - f, - "\tsize += buf.SizeFieldOption[{}]({}, &v.F{idx}, func (v {0}) int \ - {{\n\t\treturn {}\n\t}})", - definition::RenderType(ty), - field.id.get(), - RenderType { - ty, - name: "v", - indent: 2, - }, - )?; - } else { - writeln!( - f, - "\tsize += buf.SizeField({}, func() int {{\n\t\treturn {}\n\t}})", - field.id.get(), - RenderType { - ty: &field.ty, - name: format_args!("v.F{idx}"), - indent: 2, - }, - )?; - } - } + if self.0.kind == FieldKind::Unit { + return Ok(()); + } - writeln!(f, "\tsize += buf.SizeU32(buf.EndMarker)")?; + for field in &*self.0.fields { + if let Type::Option(ty) = &field.ty { + writeln!( + f, + "\tsize += buf.SizeFieldOption[{}]({}, &v.{}, func (v {0}) int {{\n\t\treturn \ + {}\n\t}})", + definition::RenderType(ty), + field.id, + heck::AsUpperCamelCase(&field.name), + RenderType { + ty, + name: "v", + indent: 2, + }, + )?; + } else { + writeln!( + f, + "\tsize += buf.SizeField({}, func() int {{\n\t\treturn {}\n\t}})", + field.id, + RenderType { + ty: &field.ty, + name: format_args!("v.{}", heck::AsUpperCamelCase(&field.name)), + indent: 2, + }, + )?; } - Fields::Unit => {} } - Ok(()) + writeln!(f, "\tsize += buf.SizeU32(buf.EndMarker)") } } @@ -154,27 +120,27 @@ where T: Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.ty.value { - DataType::Bool => write!(f, "buf.SizeBool({})", self.name), - DataType::U8 => write!(f, "buf.SizeU8({})", self.name), - DataType::U16 => write!(f, "buf.SizeU16({})", self.name), - DataType::U32 => write!(f, "buf.SizeU32({})", self.name), - DataType::U64 => write!(f, "buf.SizeU64({})", self.name), - DataType::U128 => write!(f, "buf.SizeU128({})", self.name), - DataType::I8 => write!(f, "buf.SizeI8({})", self.name), - DataType::I16 => write!(f, "buf.SizeI16({})", self.name), - DataType::I32 => write!(f, "buf.SizeI32({})", self.name), - DataType::I64 => write!(f, "buf.SizeI64({})", self.name), - DataType::I128 => write!(f, "buf.SizeI128({})", self.name), - DataType::F32 => write!(f, "buf.SizeF32({})", self.name), - DataType::F64 => write!(f, "buf.SizeF64({})", self.name), - DataType::String | DataType::StringRef | DataType::BoxString => { + match self.ty { + Type::Bool => write!(f, "buf.SizeBool({})", self.name), + Type::U8 => write!(f, "buf.SizeU8({})", self.name), + Type::U16 => write!(f, "buf.SizeU16({})", self.name), + Type::U32 => write!(f, "buf.SizeU32({})", self.name), + Type::U64 => write!(f, "buf.SizeU64({})", self.name), + Type::U128 => write!(f, "buf.SizeU128({})", self.name), + Type::I8 => write!(f, "buf.SizeI8({})", self.name), + Type::I16 => write!(f, "buf.SizeI16({})", self.name), + Type::I32 => write!(f, "buf.SizeI32({})", self.name), + Type::I64 => write!(f, "buf.SizeI64({})", self.name), + Type::I128 => write!(f, "buf.SizeI128({})", self.name), + Type::F32 => write!(f, "buf.SizeF32({})", self.name), + Type::F64 => write!(f, "buf.SizeF64({})", self.name), + Type::String | Type::StringRef | Type::BoxString => { write!(f, "buf.SizeString({})", self.name) } - DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => { + Type::Bytes | Type::BytesRef | Type::BoxBytes => { write!(f, "buf.SizeBytes({})", self.name) } - DataType::Vec(ty) => { + Type::Vec(ty) => { writeln!( f, "buf.SizeVec[{}]({}, func(v {0}) int {{", @@ -194,7 +160,7 @@ where )?; write!(f, "{:\t { + Type::HashMap(kv) => { writeln!( f, "buf.SizeHashMap[{}, {}](", @@ -250,7 +216,7 @@ where writeln!(f, "{:\t { + Type::HashSet(ty) => { writeln!( f, "buf.SizeHashSet[{}]({}, func(v {0}) int {{", @@ -270,7 +236,7 @@ where )?; write!(f, "{:\t { + Type::Option(ty) => { writeln!( f, "buf.SizeOption[{}]({}, func(v {0}) int {{", @@ -290,24 +256,24 @@ where )?; write!(f, "{:\t match &ty.value { - DataType::U8 => write!(f, "buf.SizeU8({}.Get())", self.name), - DataType::U16 => write!(f, "buf.SizeU16({}.Get())", self.name), - DataType::U32 => write!(f, "buf.SizeU32({}.Get())", self.name), - DataType::U64 => write!(f, "buf.SizeU64({}.Get())", self.name), - DataType::U128 => write!(f, "buf.SizeU128({}.Get())", self.name), - DataType::I8 => write!(f, "buf.SizeI8({}.Get())", self.name), - DataType::I16 => write!(f, "buf.SizeI16({}.Get())", self.name), - DataType::I32 => write!(f, "buf.SizeI32({}.Get())", self.name), - DataType::I64 => write!(f, "buf.SizeI64({}.Get())", self.name), - DataType::I128 => write!(f, "buf.SizeI128({}.Get())", self.name), - DataType::String - | DataType::StringRef - | DataType::Bytes - | DataType::BytesRef - | DataType::Vec(_) - | DataType::HashMap(_) - | DataType::HashSet(_) => write!( + Type::NonZero(ty) => match &**ty { + Type::U8 => write!(f, "buf.SizeU8({}.Get())", self.name), + Type::U16 => write!(f, "buf.SizeU16({}.Get())", self.name), + Type::U32 => write!(f, "buf.SizeU32({}.Get())", self.name), + Type::U64 => write!(f, "buf.SizeU64({}.Get())", self.name), + Type::U128 => write!(f, "buf.SizeU128({}.Get())", self.name), + Type::I8 => write!(f, "buf.SizeI8({}.Get())", self.name), + Type::I16 => write!(f, "buf.SizeI16({}.Get())", self.name), + Type::I32 => write!(f, "buf.SizeI32({}.Get())", self.name), + Type::I64 => write!(f, "buf.SizeI64({}.Get())", self.name), + Type::I128 => write!(f, "buf.SizeI128({}.Get())", self.name), + Type::String + | Type::StringRef + | Type::Bytes + | Type::BytesRef + | Type::Vec(_) + | Type::HashMap(_) + | Type::HashSet(_) => write!( f, "{}", RenderType { @@ -318,7 +284,7 @@ where ), ty => todo!("compiler should catch invalid {ty:?} type"), }, - DataType::Tuple(types) => match types.len() { + Type::Tuple(types) => match types.len() { 2..=12 => { writeln!(f, "func() int {{")?; writeln!(f, "{:\t todo!("compiler should catch invalid tuple with {n} elements"), }, - DataType::Array(ty, size) => match *size { + Type::Array(ty, size) => match *size { 1..=32 => { writeln!( f, @@ -363,7 +329,7 @@ where } n => todo!("arrays with larger ({n}) sizes"), }, - DataType::External(_) => write!(f, "{}.Size()", self.name), + Type::External(_) => write!(f, "{}.Size()", self.name), } } } diff --git a/crates/stef-go/tests/render.rs b/crates/stef-go/tests/render.rs index 4616a8a..f01bcb9 100644 --- a/crates/stef-go/tests/render.rs +++ b/crates/stef-go/tests/render.rs @@ -29,6 +29,7 @@ fn render_schema() { glob!("inputs/*.stef", |path| { let input = fs::read_to_string(path).unwrap(); let value = Schema::parse(input.as_str(), Some(&strip_path(path))).unwrap(); + let value = stef_compiler::simplify_schema(&value); let value = stef_go::render_schema(&Opts { package: "sample" }, &value); let mut merged = String::new(); diff --git a/crates/stef-go/tests/snapshots/render__render@enum_basic.stef.snap b/crates/stef-go/tests/snapshots/render__render@enum_basic.stef.snap index 8ea3484..eb6d569 100644 --- a/crates/stef-go/tests/snapshots/render__render@enum_basic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@enum_basic.stef.snap @@ -65,19 +65,19 @@ func (v *Sample_One) Size() int { // Second variant type Sample_Two struct { - F0 uint32 - F1 uint64 + N0 uint32 + N1 uint64 } func (v Sample_Two) sealed() {} func NewSample_Two( - f0 uint32, - f1 uint64, + n0 uint32, + n1 uint64, ) Sample_Two { return Sample_Two{ - F0: f0, - F1: f1, + N0: n0, + N1: n1, } } @@ -85,10 +85,10 @@ var _ buf.Encode = (*Sample_Two)(nil) func (v *Sample_Two) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU32(w, v.F0) + return buf.EncodeU32(w, v.N0) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return buf.EncodeU64(w, v.F1) + return buf.EncodeU64(w, v.N1) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -97,8 +97,8 @@ func (v *Sample_Two) Encode(w []byte) []byte { var _ buf.Decode = (*Sample_Two)(nil) func (v *Sample_Two) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false + foundN0 := false + foundN1 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -114,28 +114,28 @@ func (v *Sample_Two) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeU64(r) if err != nil { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" @@ -150,10 +150,10 @@ var _ buf.Size = (*Sample_Two)(nil) func (v *Sample_Two) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU32(v.F0) + return buf.SizeU32(v.N0) }) size += buf.SizeField(2, func() int { - return buf.SizeU64(v.F1) + return buf.SizeU64(v.N1) }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@enum_generics.stef.snap b/crates/stef-go/tests/snapshots/render__render@enum_generics.stef.snap index be912c0..98878d4 100644 --- a/crates/stef-go/tests/snapshots/render__render@enum_generics.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@enum_generics.stef.snap @@ -64,19 +64,19 @@ func (v *Sample_One) Size() int { } type Sample_Two[A any, B any] struct { - F0 A - F1 B + N0 A + N1 B } func (v Sample_Two[A, B]) sealed() {} func NewSample_Two[A any, B any]( - f0 A, - f1 B, + n0 A, + n1 B, ) Sample_Two[A, B] { return Sample_Two[A, B]{ - F0: f0, - F1: f1, + N0: n0, + N1: n1, } } @@ -84,10 +84,10 @@ var _ buf.Encode = (*Sample_Two[A, B])(nil) func (v *Sample_Two[A, B]) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return v.F0.Encode(w) + return v.N0.Encode(w) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return v.F1.Encode(w) + return v.N1.Encode(w) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -96,8 +96,8 @@ func (v *Sample_Two[A, B]) Encode(w []byte) []byte { var _ buf.Decode = (*Sample_Two[A, B])(nil) func (v *Sample_Two[A, B]) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false + foundN0 := false + foundN1 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -117,8 +117,8 @@ func (v *Sample_Two[A, B]) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := func(r []byte) ([]byte, B, error) { var value B @@ -129,20 +129,20 @@ func (v *Sample_Two[A, B]) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" @@ -157,10 +157,10 @@ var _ buf.Size = (*Sample_Two[A, B])(nil) func (v *Sample_Two[A, B]) Size() int { size := 0 size += buf.SizeField(1, func() int { - return v.F0.Size() + return v.N0.Size() }) size += buf.SizeField(2, func() int { - return v.F1.Size() + return v.N1.Size() }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@enum_many_ws.stef.snap b/crates/stef-go/tests/snapshots/render__render@enum_many_ws.stef.snap index a4d54bf..190096e 100644 --- a/crates/stef-go/tests/snapshots/render__render@enum_many_ws.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@enum_many_ws.stef.snap @@ -64,19 +64,19 @@ func (v *Sample_One) Size() int { } type Sample_Two struct { - F0 uint32 - F1 uint64 + N0 uint32 + N1 uint64 } func (v Sample_Two) sealed() {} func NewSample_Two( - f0 uint32, - f1 uint64, + n0 uint32, + n1 uint64, ) Sample_Two { return Sample_Two{ - F0: f0, - F1: f1, + N0: n0, + N1: n1, } } @@ -84,10 +84,10 @@ var _ buf.Encode = (*Sample_Two)(nil) func (v *Sample_Two) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU32(w, v.F0) + return buf.EncodeU32(w, v.N0) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return buf.EncodeU64(w, v.F1) + return buf.EncodeU64(w, v.N1) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -96,8 +96,8 @@ func (v *Sample_Two) Encode(w []byte) []byte { var _ buf.Decode = (*Sample_Two)(nil) func (v *Sample_Two) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false + foundN0 := false + foundN1 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -113,28 +113,28 @@ func (v *Sample_Two) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeU64(r) if err != nil { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" @@ -149,10 +149,10 @@ var _ buf.Size = (*Sample_Two)(nil) func (v *Sample_Two) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU32(v.F0) + return buf.SizeU32(v.N0) }) size += buf.SizeField(2, func() int { - return buf.SizeU64(v.F1) + return buf.SizeU64(v.N1) }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@enum_min_ws.stef.snap b/crates/stef-go/tests/snapshots/render__render@enum_min_ws.stef.snap index 61a01d0..c838224 100644 --- a/crates/stef-go/tests/snapshots/render__render@enum_min_ws.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@enum_min_ws.stef.snap @@ -63,22 +63,22 @@ func (v *Sample_One) Size() int { } type Sample_Two[T any] struct { - F0 uint32 - F1 uint64 - F2 T + N0 uint32 + N1 uint64 + N2 T } func (v Sample_Two[T]) sealed() {} func NewSample_Two[T any]( - f0 uint32, - f1 uint64, - f2 T, + n0 uint32, + n1 uint64, + n2 T, ) Sample_Two[T] { return Sample_Two[T]{ - F0: f0, - F1: f1, - F2: f2, + N0: n0, + N1: n1, + N2: n2, } } @@ -86,13 +86,13 @@ var _ buf.Encode = (*Sample_Two[T])(nil) func (v *Sample_Two[T]) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU32(w, v.F0) + return buf.EncodeU32(w, v.N0) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return buf.EncodeU64(w, v.F1) + return buf.EncodeU64(w, v.N1) }) w = buf.EncodeField(w, 3, func (w []byte) []byte { - return v.F2.Encode(w) + return v.N2.Encode(w) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -101,9 +101,9 @@ func (v *Sample_Two[T]) Encode(w []byte) []byte { var _ buf.Decode = (*Sample_Two[T])(nil) func (v *Sample_Two[T]) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false - foundF2 := false + foundN0 := false + foundN1 := false + foundN2 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -119,16 +119,16 @@ func (v *Sample_Two[T]) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeU64(r) if err != nil { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case 3: r2, value, err := func(r []byte) ([]byte, T, error) { var value T @@ -139,26 +139,26 @@ func (v *Sample_Two[T]) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F2 = value - foundF2 = true + v.N2 = value + foundN2 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" } } - if !foundF2 { + if !foundN2 { return nil, buf.MissingFieldError{ ID: 3 Field: "" @@ -173,13 +173,13 @@ var _ buf.Size = (*Sample_Two[T])(nil) func (v *Sample_Two[T]) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU32(v.F0) + return buf.SizeU32(v.N0) }) size += buf.SizeField(2, func() int { - return buf.SizeU64(v.F1) + return buf.SizeU64(v.N1) }) size += buf.SizeField(3, func() int { - return v.F2.Size() + return v.N2.Size() }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@mixed.stef.snap b/crates/stef-go/tests/snapshots/render__render@mixed.stef.snap index 762f189..a6aeaa7 100644 --- a/crates/stef-go/tests/snapshots/render__render@mixed.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@mixed.stef.snap @@ -1,6 +1,6 @@ --- source: crates/stef-go/tests/render.rs -description: "/// Basic user information.\n///\n/// Uses various other `structs` and `enums` to compose the information\n/// in a **type safe** way.\nstruct User {\n name: FullName @1,\n /// Physical address, might not be specified by the user.\n address: option
@2,\n age: u8 @3,\n birthday: birthday::DayOfBirth @4,\n}\n\n/// Full name of a user.\nstruct FullName {\n first: string @1,\n middle: option @2,\n last: string @3,\n}\n\n/// Simple alias for convenience.\n///\n/// - Might be easier to remember.\n/// - Often referenced as this.\ntype Name = FullName;\n\nstruct Address {\n /// Street name.\n street: string @1,\n /// Number of the house in the street.\n house_no: HouseNumber @2,\n city: string @3,\n}\n\n/// The number on the house.\n///\n/// More details can be found at [Wikipedia](https://en.wikipedia.org/wiki/House_numbering).\nenum HouseNumber {\n /// Digit only number.\n Digit(u16 @1) @1,\n /// Mixed _number_ with characters like `1a`.\n Text(string @1) @2,\n}\n\n/// Probably the max age of a human, currently.\nconst MAX_AGE: u8 = 120;\n\n\n/// Details for defining birthdays.\nmod birthday {\n /// As the name suggests, specifies details about birthdays.\n enum DayOfBirth {\n Specific {\n year: u16 @1,\n month: Month @2,\n day: u8 @3,\n } @1,\n /// The user didn't want to say.\n Secret {\n /// Optional info from the user about why they didn't want to\n /// reveal their birthday.\n reason: option @1,\n } @2,\n /// We never asked and nobody knows.\n Unknown @3,\n }\n\n /// Let's assume we only have details of people born **after** this year.\n const MIN_YEAR: u16 = 1900;\n\n /// Absolute maximum for a day, but might be even less depending\n /// on the month.\n const MAX_DAY: u8 = 31;\n\n /// The month of the year.\n enum Month {\n January @1,\n February @2,\n March @3,\n April @4,\n May @5,\n June @6,\n July @7,\n August @8,\n September @9,\n October @10,\n November @11,\n December @12,\n }\n}" +description: "/// Schema with a bit of everything, to try out more complex scenarios.\n\n/// Basic user information.\n///\n/// Uses various other `structs` and `enums` to compose the information\n/// in a **type safe** way.\nstruct User {\n name: FullName @1,\n /// Physical address, might not be specified by the user.\n address: option
@2,\n age: u8 @3,\n birthday: birthday::DayOfBirth @4,\n}\n\n/// Full name of a user.\nstruct FullName {\n first: string @1,\n middle: option @2,\n last: string @3,\n}\n\n/// Simple alias for convenience.\n///\n/// - Might be easier to remember.\n/// - Often referenced as this.\ntype Name = FullName;\n\nstruct Address {\n /// Street name.\n street: string @1,\n /// Number of the house in the street.\n house_no: HouseNumber @2,\n city: string @3,\n}\n\n/// The number on the house.\n///\n/// More details can be found at [Wikipedia](https://en.wikipedia.org/wiki/House_numbering).\nenum HouseNumber {\n /// Digit only number.\n Digit(u16 @1) @1,\n /// Mixed _number_ with characters like `1a`.\n Text(string @1) @2,\n}\n\n/// Probably the max age of a human, currently.\nconst MAX_AGE: u8 = 120;\n\n\n/// Details for defining birthdays.\nmod birthday {\n /// As the name suggests, specifies details about birthdays.\n enum DayOfBirth {\n Specific {\n year: u16 @1,\n month: Month @2,\n day: u8 @3,\n } @1,\n /// The user didn't want to say.\n Secret {\n /// Optional info from the user about why they didn't want to\n /// reveal their birthday.\n reason: option @1,\n } @2,\n /// We never asked and nobody knows.\n Unknown @3,\n }\n\n /// Let's assume we only have details of people born **after** this year.\n const MIN_YEAR: u16 = 1900;\n\n /// Absolute maximum for a day, but might be even less depending\n /// on the month.\n const MAX_DAY: u8 = 31;\n\n /// The month of the year.\n enum Month {\n January @1,\n February @2,\n March @3,\n April @4,\n May @5,\n June @6,\n July @7,\n August @8,\n September @9,\n October @10,\n November @11,\n December @12,\n }\n}" input_file: crates/stef-parser/tests/inputs/mixed.stef --- --- sample.go @@ -161,7 +161,7 @@ func (v *User) Size() int { size += buf.SizeField(1, func() int { return v.Name.Size() }) - size += buf.SizeFieldOption[Address](2, &v.Address, func (v Address) []byte { + size += buf.SizeFieldOption[Address](2, &v.Address, func (v Address) int { return v.Size() }) size += buf.SizeField(3, func() int { @@ -284,7 +284,7 @@ func (v *FullName) Size() int { size += buf.SizeField(1, func() int { return buf.SizeString(v.First) }) - size += buf.SizeFieldOption[string](2, &v.Middle, func (v string) []byte { + size += buf.SizeFieldOption[string](2, &v.Middle, func (v string) int { return buf.SizeString(v) }) size += buf.SizeField(3, func() int { @@ -434,16 +434,16 @@ type HouseNumber HouseNumberVariant // Digit only number. type HouseNumber_Digit struct { - F0 uint16 + N0 uint16 } func (v HouseNumber_Digit) sealed() {} func NewHouseNumber_Digit( - f0 uint16, + n0 uint16, ) HouseNumber_Digit { return HouseNumber_Digit{ - F0: f0, + N0: n0, } } @@ -451,7 +451,7 @@ var _ buf.Encode = (*HouseNumber_Digit)(nil) func (v *HouseNumber_Digit) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU16(w, v.F0) + return buf.EncodeU16(w, v.N0) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -460,7 +460,7 @@ func (v *HouseNumber_Digit) Encode(w []byte) []byte { var _ buf.Decode = (*HouseNumber_Digit)(nil) func (v *HouseNumber_Digit) Decode(r []byte) ([]byte, error) { - foundF0 := false + foundN0 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -476,14 +476,14 @@ func (v *HouseNumber_Digit) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" @@ -498,7 +498,7 @@ var _ buf.Size = (*HouseNumber_Digit)(nil) func (v *HouseNumber_Digit) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU16(v.F0) + return buf.SizeU16(v.N0) }) size += buf.SizeU32(buf.EndMarker) return size @@ -506,16 +506,16 @@ func (v *HouseNumber_Digit) Size() int { // Mixed _number_ with characters like `1a`. type HouseNumber_Text struct { - F0 string + N0 string } func (v HouseNumber_Text) sealed() {} func NewHouseNumber_Text( - f0 string, + n0 string, ) HouseNumber_Text { return HouseNumber_Text{ - F0: f0, + N0: n0, } } @@ -523,7 +523,7 @@ var _ buf.Encode = (*HouseNumber_Text)(nil) func (v *HouseNumber_Text) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeString(w, v.F0) + return buf.EncodeString(w, v.N0) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -532,7 +532,7 @@ func (v *HouseNumber_Text) Encode(w []byte) []byte { var _ buf.Decode = (*HouseNumber_Text)(nil) func (v *HouseNumber_Text) Decode(r []byte) ([]byte, error) { - foundF0 := false + foundN0 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -548,14 +548,14 @@ func (v *HouseNumber_Text) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" @@ -570,7 +570,7 @@ var _ buf.Size = (*HouseNumber_Text)(nil) func (v *HouseNumber_Text) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeString(v.F0) + return buf.SizeString(v.N0) }) size += buf.SizeU32(buf.EndMarker) return size @@ -784,7 +784,7 @@ var _ buf.Size = (*DayOfBirth_Secret)(nil) func (v *DayOfBirth_Secret) Size() int { size := 0 - size += buf.SizeFieldOption[string](1, &v.Reason, func (v string) []byte { + size += buf.SizeFieldOption[string](1, &v.Reason, func (v string) int { return buf.SizeString(v) }) size += buf.SizeU32(buf.EndMarker) diff --git a/crates/stef-go/tests/snapshots/render__render@schema_basic.stef.snap b/crates/stef-go/tests/snapshots/render__render@schema_basic.stef.snap index 3bb9270..1cbc0c8 100644 --- a/crates/stef-go/tests/snapshots/render__render@schema_basic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@schema_basic.stef.snap @@ -158,19 +158,19 @@ func (v *SampleEnum_One) Size() int { } type SampleEnum_Two struct { - F0 uint32 - F1 uint64 + N0 uint32 + N1 uint64 } func (v SampleEnum_Two) sealed() {} func NewSampleEnum_Two( - f0 uint32, - f1 uint64, + n0 uint32, + n1 uint64, ) SampleEnum_Two { return SampleEnum_Two{ - F0: f0, - F1: f1, + N0: n0, + N1: n1, } } @@ -178,10 +178,10 @@ var _ buf.Encode = (*SampleEnum_Two)(nil) func (v *SampleEnum_Two) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU32(w, v.F0) + return buf.EncodeU32(w, v.N0) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return buf.EncodeU64(w, v.F1) + return buf.EncodeU64(w, v.N1) }) w = buf.EncodeU32(w, buf.EndMarker) return nil @@ -190,8 +190,8 @@ func (v *SampleEnum_Two) Encode(w []byte) []byte { var _ buf.Decode = (*SampleEnum_Two)(nil) func (v *SampleEnum_Two) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false + foundN0 := false + foundN1 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -207,28 +207,28 @@ func (v *SampleEnum_Two) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeU64(r) if err != nil { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" @@ -243,10 +243,10 @@ var _ buf.Size = (*SampleEnum_Two)(nil) func (v *SampleEnum_Two) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU32(v.F0) + return buf.SizeU32(v.N0) }) size += buf.SizeField(2, func() int { - return buf.SizeU64(v.F1) + return buf.SizeU64(v.N1) }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@struct_tuple.stef.snap b/crates/stef-go/tests/snapshots/render__render@struct_tuple.stef.snap index 35fccd1..a67e990 100644 --- a/crates/stef-go/tests/snapshots/render__render@struct_tuple.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@struct_tuple.stef.snap @@ -16,17 +16,17 @@ package sample // Basic struct. type Sample struct { - F0 uint32 - F1 bool + N0 uint32 + N1 bool } func NewSample( - f0 uint32, - f1 bool, + n0 uint32, + n1 bool, ) Sample { return Sample{ - F0: f0, - F1: f1, + N0: n0, + N1: n1, } } @@ -34,10 +34,10 @@ var _ buf.Encode = (*Sample)(nil) func (v *Sample) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeU32(w, v.F0) + return buf.EncodeU32(w, v.N0) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { - return buf.EncodeBool(w, v.F1) + return buf.EncodeBool(w, v.N1) }) w = buf.EncodeU32(w, buf.EndMarker) return w @@ -46,8 +46,8 @@ func (v *Sample) Encode(w []byte) []byte { var _ buf.Decode = (*Sample)(nil) func (v *Sample) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false + foundN0 := false + foundN1 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -63,28 +63,28 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeBool(r) if err != nil { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" @@ -99,10 +99,10 @@ var _ buf.Size = (*Sample)(nil) func (v *Sample) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeU32(v.F0) + return buf.SizeU32(v.N0) }) size += buf.SizeField(2, func() int { - return buf.SizeBool(v.F1) + return buf.SizeBool(v.N1) }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-go/tests/snapshots/render__render@types_basic.stef.snap b/crates/stef-go/tests/snapshots/render__render@types_basic.stef.snap index 6802c77..8940a5c 100644 --- a/crates/stef-go/tests/snapshots/render__render@types_basic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@types_basic.stef.snap @@ -34,7 +34,7 @@ type Sample struct { F17 []byte F18 string F19 []byte - F20 stef.Tuple3[u32, u32, u32] + F20 stef.Tuple3[uint32, uint32, uint32] F21 [12]uint32 } @@ -58,7 +58,7 @@ func NewSample( f17 []byte, f18 string, f19 []byte, - f20 stef.Tuple3[u32, u32, u32], + f20 stef.Tuple3[uint32, uint32, uint32], f21 [12]uint32, ) Sample { return Sample{ diff --git a/crates/stef-go/tests/snapshots/render__render@types_generic.stef.snap b/crates/stef-go/tests/snapshots/render__render@types_generic.stef.snap index 263dd78..999f609 100644 --- a/crates/stef-go/tests/snapshots/render__render@types_generic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@types_generic.stef.snap @@ -207,7 +207,7 @@ func (v *Sample) Size() int { return buf.SizeU32(v) }) }) - size += buf.SizeFieldOption[uint32](4, &v.F4, func (v uint32) []byte { + size += buf.SizeFieldOption[uint32](4, &v.F4, func (v uint32) int { return buf.SizeU32(v) }) size += buf.SizeField(5, func() int { @@ -218,26 +218,26 @@ func (v *Sample) Size() int { } type SampleUnnamed struct { - F0 []uint32 - F1 map[uint32]string - F2 map[uint32]struct{} - F3 *uint32 - F4 stef.NonZeroU32 + N0 []uint32 + N1 map[uint32]string + N2 map[uint32]struct{} + N3 *uint32 + N4 stef.NonZeroU32 } func NewSampleUnnamed( - f0 []uint32, - f1 map[uint32]string, - f2 map[uint32]struct{}, - f3 *uint32, - f4 stef.NonZeroU32, + n0 []uint32, + n1 map[uint32]string, + n2 map[uint32]struct{}, + n3 *uint32, + n4 stef.NonZeroU32, ) SampleUnnamed { return SampleUnnamed{ - F0: f0, - F1: f1, - F2: f2, - F3: f3, - F4: f4, + N0: n0, + N1: n1, + N2: n2, + N3: n3, + N4: n4, } } @@ -245,13 +245,13 @@ var _ buf.Encode = (*SampleUnnamed)(nil) func (v *SampleUnnamed) Encode(w []byte) []byte { w = buf.EncodeField(w, 1, func (w []byte) []byte { - return buf.EncodeVec[uint32](w, v.F0, func(w []byte, v uint32) []byte { + return buf.EncodeVec[uint32](w, v.N0, func(w []byte, v uint32) []byte { return buf.EncodeU32(w, v) }) }) w = buf.EncodeField(w, 2, func (w []byte) []byte { return buf.EncodeHashMap[uint32, string]( - w, v.F1, + w, v.N1, func(w []byte, k uint32) []byte { return buf.EncodeU32(w, k) }, @@ -261,15 +261,15 @@ func (v *SampleUnnamed) Encode(w []byte) []byte { ) }) w = buf.EncodeField(w, 3, func (w []byte) []byte { - return buf.EncodeHashSet[uint32](w, v.F2, func(w []byte, v uint32) []byte { + return buf.EncodeHashSet[uint32](w, v.N2, func(w []byte, v uint32) []byte { return buf.EncodeU32(w, v) }) }) - w = buf.EncodeFieldOption[uint32](w, 4, &v.F3, func (w []byte, v uint32) []byte { + w = buf.EncodeFieldOption[uint32](w, 4, &v.N3, func (w []byte, v uint32) []byte { return buf.EncodeU32(w, v) }) w = buf.EncodeField(w, 5, func (w []byte) []byte { - return buf.EncodeU32(w, v.F4.Get()) + return buf.EncodeU32(w, v.N4.Get()) }) w = buf.EncodeU32(w, buf.EndMarker) return w @@ -278,11 +278,11 @@ func (v *SampleUnnamed) Encode(w []byte) []byte { var _ buf.Decode = (*SampleUnnamed)(nil) func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { - foundF0 := false - foundF1 := false - foundF2 := false - foundF3 := false - foundF4 := false + foundN0 := false + foundN1 := false + foundN2 := false + foundN3 := false + foundN4 := false for len(r) > 0 { r2, id, err := buf.DecodeID(r) @@ -300,8 +300,8 @@ func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F0 = value - foundF0 = true + v.N0 = value + foundN0 = true case 2: r2, value, err := buf.DecodeHashMap[uint32, string]( r, @@ -316,8 +316,8 @@ func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F1 = value - foundF1 = true + v.N1 = value + foundN1 = true case 3: r2, value, err := buf.DecodeHashSet[uint32](r, func(r []byte) ([]byte, uint32, error) { return buf.DecodeU32(r) @@ -326,8 +326,8 @@ func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F2 = value - foundF2 = true + v.N2 = value + foundN2 = true case 4: r2, value, err := buf.DecodeOption[uint32](r, func(r []byte) ([]byte, uint32, error) { return buf.DecodeU32(r) @@ -336,46 +336,46 @@ func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { return nil, err } r = r2 - v.F3 = value - foundF3 = true + v.N3 = value + foundN3 = true case 5: r2, value, err := buf.DecodeNonZeroU32(r) if err != nil { return nil, err } r = r2 - v.F4 = value - foundF4 = true + v.N4 = value + foundN4 = true case buf.EndMarker: break } } - if !foundF0 { + if !foundN0 { return nil, buf.MissingFieldError{ ID: 1 Field: "" } } - if !foundF1 { + if !foundN1 { return nil, buf.MissingFieldError{ ID: 2 Field: "" } } - if !foundF2 { + if !foundN2 { return nil, buf.MissingFieldError{ ID: 3 Field: "" } } - if !foundF3 { + if !foundN3 { return nil, buf.MissingFieldError{ ID: 4 Field: "" } } - if !foundF4 { + if !foundN4 { return nil, buf.MissingFieldError{ ID: 5 Field: "" @@ -390,13 +390,13 @@ var _ buf.Size = (*SampleUnnamed)(nil) func (v *SampleUnnamed) Size() int { size := 0 size += buf.SizeField(1, func() int { - return buf.SizeVec[uint32](v.F0, func(v uint32) int { + return buf.SizeVec[uint32](v.N0, func(v uint32) int { return buf.SizeU32(v) }) }) size += buf.SizeField(2, func() int { return buf.SizeHashMap[uint32, string]( - v.F1, + v.N1, func(k uint32) int { return buf.SizeU32(k) }, @@ -406,15 +406,15 @@ func (v *SampleUnnamed) Size() int { ) }) size += buf.SizeField(3, func() int { - return buf.SizeHashSet[uint32](v.F2, func(v uint32) int { + return buf.SizeHashSet[uint32](v.N2, func(v uint32) int { return buf.SizeU32(v) }) }) - size += buf.SizeFieldOption[uint32](4, &v.F3, func (v uint32) int { + size += buf.SizeFieldOption[uint32](4, &v.N3, func (v uint32) int { return buf.SizeU32(v) }) size += buf.SizeField(5, func() int { - return buf.SizeU32(v.F4.Get()) + return buf.SizeU32(v.N4.Get()) }) size += buf.SizeU32(buf.EndMarker) return size diff --git a/crates/stef-parser/src/lib.rs b/crates/stef-parser/src/lib.rs index 6baec25..0e00c37 100644 --- a/crates/stef-parser/src/lib.rs +++ b/crates/stef-parser/src/lib.rs @@ -442,7 +442,7 @@ impl Display for Variant<'_> { /// ``` #[derive(Debug, Eq, PartialEq)] pub struct TypeAlias<'a> { - /// Optional comment. + /// Optional element-level comment. pub comment: Comment<'a>, /// Unique name of the type alias within the current scope. pub name: Name<'a>, @@ -474,7 +474,7 @@ impl Display for TypeAlias<'_> { } } -/// Possible kinds in which a the fields of a struct or enum variant can be represented. +/// Possible kinds in which the fields of a struct or enum variant can be represented. #[derive(Debug, Eq, PartialEq)] pub enum Fields<'a> { /// List of named fields. diff --git a/crates/stef-playground/src/lib.rs b/crates/stef-playground/src/lib.rs index fce9502..6a70e9f 100644 --- a/crates/stef-playground/src/lib.rs +++ b/crates/stef-playground/src/lib.rs @@ -61,6 +61,10 @@ mod schemas { stef::include!("import_basic"); } + mod mixed { + stef::include!("mixed"); + } + mod other { stef::include!("other"); }