From 5cc3c2fab4cb6cc7645c7b7c51f2bf734dfa384b Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Mon, 11 Dec 2023 15:32:37 +0900 Subject: [PATCH] feat(go): generate new `Size` interface The newly defined `Size` interface allows to calculate the encoded size of an instance and pre-allocate a byte vector. It can be helful for significantly large payloads that would do several re-allocations of a buffer otherwise. --- crates/stef-go/src/definition.rs | 14 +- crates/stef-go/src/encode.rs | 2 +- crates/stef-go/src/lib.rs | 1 + crates/stef-go/src/size.rs | 369 ++++++++++++++++++ .../render__render@attribute_multi.stef.snap | 7 + .../render__render@attribute_single.stef.snap | 7 + .../render__render@attribute_unit.stef.snap | 7 + .../render__render@attributes.stef.snap | 7 + ...render__render@attributes_min_ws.stef.snap | 7 + .../render__render@enum_basic.stef.snap | 35 ++ .../render__render@enum_generics.stef.snap | 35 ++ .../render__render@enum_many_ws.stef.snap | 35 ++ .../render__render@enum_min_ws.stef.snap | 41 ++ .../render__render@module_basic.stef.snap | 21 + .../render__render@schema_basic.stef.snap | 49 +++ .../render__render@struct_basic.stef.snap | 14 + .../render__render@struct_generics.stef.snap | 14 + .../render__render@struct_many_ws.stef.snap | 17 + .../render__render@struct_min_ws.stef.snap | 17 + .../render__render@struct_tuple.stef.snap | 14 + .../render__render@types_basic.stef.snap | 79 ++++ .../render__render@types_generic.stef.snap | 72 +++- .../render__render@types_nested.stef.snap | 23 ++ .../render__render@types_non_zero.stef.snap | 65 +++ .../render__render@types_ref.stef.snap | 35 ++ 25 files changed, 981 insertions(+), 6 deletions(-) create mode 100644 crates/stef-go/src/size.rs diff --git a/crates/stef-go/src/definition.rs b/crates/stef-go/src/definition.rs index e0f7843..804bb55 100644 --- a/crates/stef-go/src/definition.rs +++ b/crates/stef-go/src/definition.rs @@ -5,7 +5,7 @@ use stef_parser::{ Schema, Struct, Type, TypeAlias, Variant, }; -use crate::{decode, encode, Opts, Output}; +use crate::{decode, encode, size, Opts, Output}; /// Take a single schema and convert it into Go source code (which can result in multiple files). #[must_use] @@ -68,9 +68,10 @@ fn render_definition<'a>(buf: &mut String, definition: &'a Definition<'_>) -> Op .unwrap(); writeln!( buf, - "\n{}\n{}", + "\n{}\n{}\n{}", encode::RenderStruct(s), - decode::RenderStruct(s) + decode::RenderStruct(s), + size::RenderStruct(s), ) .unwrap(); } @@ -709,7 +710,7 @@ impl Display for RenderEnumVariant<'_> { write!( f, - "\n{}\n{}", + "\n{}\n{}\n{}", encode::RenderEnumVariant { enum_name: self.enum_name, generics: self.generics, @@ -720,6 +721,11 @@ impl Display for RenderEnumVariant<'_> { generics: self.generics, variant: self.variant, }, + size::RenderEnumVariant { + enum_name: self.enum_name, + generics: self.generics, + variant: self.variant, + }, ) } } diff --git a/crates/stef-go/src/encode.rs b/crates/stef-go/src/encode.rs index 75e00ca..648b3f3 100644 --- a/crates/stef-go/src/encode.rs +++ b/crates/stef-go/src/encode.rs @@ -110,7 +110,7 @@ impl Display for RenderFields<'_> { writeln!( f, "\tw = buf.EncodeFieldOption[{}](w, {}, &v.F{idx}, func (w []byte, v \ - {0}) [] byte {{\n\t\treturn {}\n\t}})", + {0}) []byte {{\n\t\treturn {}\n\t}})", definition::RenderType(ty), field.id.get(), RenderType { diff --git a/crates/stef-go/src/lib.rs b/crates/stef-go/src/lib.rs index 6293fbd..9e11c7e 100644 --- a/crates/stef-go/src/lib.rs +++ b/crates/stef-go/src/lib.rs @@ -5,6 +5,7 @@ pub use definition::render_schema; mod decode; mod definition; mod encode; +mod size; /// Options for the code generator that can modify the way the code is generated. #[derive(Default)] diff --git a/crates/stef-go/src/size.rs b/crates/stef-go/src/size.rs new file mode 100644 index 0000000..d9935c8 --- /dev/null +++ b/crates/stef-go/src/size.rs @@ -0,0 +1,369 @@ +#![allow(clippy::too_many_lines)] + +use std::fmt::{self, Display}; + +use stef_parser::{DataType, Fields, Generics, Struct, Type, Variant}; + +use crate::definition::{self, RenderGenericNames}; + +pub(super) struct RenderStruct<'a>(pub(super) &'a Struct<'a>); + +impl Display for RenderStruct<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!( + f, + "var _ buf.Size = (*{}{})(nil)\n", + heck::AsUpperCamelCase(&self.0.name), + RenderGenericNames { + generics: &self.0.generics, + fields_filter: None, + } + )?; + + writeln!( + f, + "func (v *{}{}) Size() int {{", + heck::AsUpperCamelCase(&self.0.name), + RenderGenericNames { + generics: &self.0.generics, + fields_filter: None, + } + )?; + writeln!(f, "\tsize := 0")?; + writeln!(f, "{}\treturn size\n}}", RenderFields(&self.0.fields)) + } +} + +pub(super) struct RenderEnumVariant<'a> { + pub(super) enum_name: &'a str, + pub(super) generics: &'a Generics<'a>, + pub(super) variant: &'a Variant<'a>, +} + +impl Display for RenderEnumVariant<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!( + f, + "var _ buf.Size = (*{}_{}{})(nil)\n", + heck::AsUpperCamelCase(self.enum_name), + heck::AsUpperCamelCase(&self.variant.name), + RenderGenericNames { + generics: self.generics, + fields_filter: Some(&self.variant.fields), + } + )?; + + writeln!( + f, + "func (v *{}_{}{}) Size() int {{", + heck::AsUpperCamelCase(self.enum_name), + heck::AsUpperCamelCase(&self.variant.name), + RenderGenericNames { + generics: self.generics, + fields_filter: Some(&self.variant.fields), + } + )?; + writeln!(f, "\tsize := 0")?; + writeln!(f, "{}\treturn size\n}}", RenderFields(&self.variant.fields)) + } +} + +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, + }, + )?; + } + } + + writeln!(f, "\tsize += buf.SizeU32(buf.EndMarker)")?; + } + Fields::Unit => {} + } + + Ok(()) + } +} + +struct RenderType<'a, T> { + ty: &'a Type<'a>, + name: T, + indent: usize, +} + +impl Display for RenderType<'_, T> +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 => { + write!(f, "buf.SizeString({})", self.name) + } + DataType::Bytes | DataType::BytesRef | DataType::BoxBytes => { + write!(f, "buf.SizeBytes({})", self.name) + } + DataType::Vec(ty) => { + writeln!( + f, + "buf.SizeVec[{}]({}, func(v {0}) int {{", + definition::RenderType(ty), + self.name + )?; + writeln!( + f, + "{:\t { + writeln!( + f, + "buf.SizeHashMap[{}, {}](", + definition::RenderType(&kv.0), + definition::RenderType(&kv.1) + )?; + writeln!( + f, + "{:\t { + writeln!( + f, + "buf.SizeHashSet[{}]({}, func(v {0}) int {{", + definition::RenderType(ty), + self.name + )?; + writeln!( + f, + "{:\t { + writeln!( + f, + "buf.SizeOption[{}]({}, func(v {0}) int {{", + definition::RenderType(ty), + self.name + )?; + writeln!( + 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!( + f, + "{}", + RenderType { + ty, + name: format_args!("{}.Get()", self.name), + indent: self.indent, + } + ), + ty => todo!("compiler should catch invalid {ty:?} type"), + }, + DataType::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 { + 1..=32 => { + writeln!( + f, + "buf.SizeArray{size}[{}]({}, func(v {0}) int {{", + definition::RenderType(ty), + self.name + )?; + writeln!( + f, + "{:\t todo!("arrays with larger ({n}) sizes"), + }, + DataType::External(_) => write!(f, "{}.Size()", self.name), + } + } +} diff --git a/crates/stef-go/tests/snapshots/render__render@attribute_multi.stef.snap b/crates/stef-go/tests/snapshots/render__render@attribute_multi.stef.snap index 965c847..d31e073 100644 --- a/crates/stef-go/tests/snapshots/render__render@attribute_multi.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@attribute_multi.stef.snap @@ -47,4 +47,11 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@attribute_single.stef.snap b/crates/stef-go/tests/snapshots/render__render@attribute_single.stef.snap index a1a6836..9b63ca7 100644 --- a/crates/stef-go/tests/snapshots/render__render@attribute_single.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@attribute_single.stef.snap @@ -47,4 +47,11 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@attribute_unit.stef.snap b/crates/stef-go/tests/snapshots/render__render@attribute_unit.stef.snap index 1f3ce5e..b4cf8bd 100644 --- a/crates/stef-go/tests/snapshots/render__render@attribute_unit.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@attribute_unit.stef.snap @@ -47,4 +47,11 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@attributes.stef.snap b/crates/stef-go/tests/snapshots/render__render@attributes.stef.snap index d0824c4..afef042 100644 --- a/crates/stef-go/tests/snapshots/render__render@attributes.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@attributes.stef.snap @@ -47,4 +47,11 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@attributes_min_ws.stef.snap b/crates/stef-go/tests/snapshots/render__render@attributes_min_ws.stef.snap index 7879e83..0205577 100644 --- a/crates/stef-go/tests/snapshots/render__render@attributes_min_ws.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@attributes_min_ws.stef.snap @@ -47,4 +47,11 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + return size +} + 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 cf0bee4..8ea3484 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 @@ -56,6 +56,13 @@ func (v *Sample_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_One)(nil) + +func (v *Sample_One) Size() int { + size := 0 + return size +} + // Second variant type Sample_Two struct { F0 uint32 @@ -138,6 +145,20 @@ func (v *Sample_Two) Decode(r []byte) ([]byte, error) { return r, nil } +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) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU64(v.F1) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type Sample_Three struct { Field1 uint32 // Second field of third variant @@ -220,4 +241,18 @@ func (v *Sample_Three) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_Three)(nil) + +func (v *Sample_Three) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.Field1) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.Field2) + }) + 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 1cd4c9c..be912c0 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 @@ -56,6 +56,13 @@ func (v *Sample_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_One)(nil) + +func (v *Sample_One) Size() int { + size := 0 + return size +} + type Sample_Two[A any, B any] struct { F0 A F1 B @@ -145,6 +152,20 @@ func (v *Sample_Two[A, B]) Decode(r []byte) ([]byte, error) { return r, nil } +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() + }) + size += buf.SizeField(2, func() int { + return v.F1.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type Sample_Three[C any, D any] struct { Field1 C Field2 D @@ -234,4 +255,18 @@ func (v *Sample_Three[C, D]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_Three[C, D])(nil) + +func (v *Sample_Three[C, D]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return v.Field1.Size() + }) + size += buf.SizeField(2, func() int { + return v.Field2.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 d336365..a4d54bf 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 @@ -56,6 +56,13 @@ func (v *Sample_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_One)(nil) + +func (v *Sample_One) Size() int { + size := 0 + return size +} + type Sample_Two struct { F0 uint32 F1 uint64 @@ -137,6 +144,20 @@ func (v *Sample_Two) Decode(r []byte) ([]byte, error) { return r, nil } +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) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU64(v.F1) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type Sample_Three struct { Field1 uint32 Field2 bool @@ -218,4 +239,18 @@ func (v *Sample_Three) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_Three)(nil) + +func (v *Sample_Three) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.Field1) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.Field2) + }) + 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 533031e..61a01d0 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 @@ -55,6 +55,13 @@ func (v *Sample_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_One)(nil) + +func (v *Sample_One) Size() int { + size := 0 + return size +} + type Sample_Two[T any] struct { F0 uint32 F1 uint64 @@ -161,6 +168,23 @@ func (v *Sample_Two[T]) Decode(r []byte) ([]byte, error) { return r, nil } +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) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU64(v.F1) + }) + size += buf.SizeField(3, func() int { + return v.F2.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type Sample_Three[T any] struct { Field1 uint32 Field2 bool @@ -267,4 +291,21 @@ func (v *Sample_Three[T]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_Three[T])(nil) + +func (v *Sample_Three[T]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.Field1) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.Field2) + }) + size += buf.SizeField(3, func() int { + return v.Field3.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@module_basic.stef.snap b/crates/stef-go/tests/snapshots/render__render@module_basic.stef.snap index edca2ae..c6fb7af 100644 --- a/crates/stef-go/tests/snapshots/render__render@module_basic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@module_basic.stef.snap @@ -103,6 +103,20 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.Value) + }) + size += buf.SizeField(2, func() int { + return v.Inner.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + --- sample/a/b.go // Code generated by stef-go (v0.1.0). DO NOT EDIT. @@ -151,4 +165,11 @@ func (v *Sample_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample_One)(nil) + +func (v *Sample_One) Size() int { + size := 0 + return size +} + 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 a41ca15..3bb9270 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 @@ -94,6 +94,20 @@ func (v *SampleStruct) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*SampleStruct)(nil) + +func (v *SampleStruct) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.A) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.B) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type SampleEnumVariant interface { sealed() } @@ -136,6 +150,13 @@ func (v *SampleEnum_One) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*SampleEnum_One)(nil) + +func (v *SampleEnum_One) Size() int { + size := 0 + return size +} + type SampleEnum_Two struct { F0 uint32 F1 uint64 @@ -217,6 +238,20 @@ func (v *SampleEnum_Two) Decode(r []byte) ([]byte, error) { return r, nil } +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) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU64(v.F1) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type SampleEnum_Three struct { Field1 uint32 Field2 bool @@ -298,4 +333,18 @@ func (v *SampleEnum_Three) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*SampleEnum_Three)(nil) + +func (v *SampleEnum_Three) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.Field1) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.Field2) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@struct_basic.stef.snap b/crates/stef-go/tests/snapshots/render__render@struct_basic.stef.snap index d611a39..ff9ce42 100644 --- a/crates/stef-go/tests/snapshots/render__render@struct_basic.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@struct_basic.stef.snap @@ -95,4 +95,18 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.A) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.B) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@struct_generics.stef.snap b/crates/stef-go/tests/snapshots/render__render@struct_generics.stef.snap index e03e7a5..28784c4 100644 --- a/crates/stef-go/tests/snapshots/render__render@struct_generics.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@struct_generics.stef.snap @@ -102,4 +102,18 @@ func (v *KeyValue[K, V]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*KeyValue[K, V])(nil) + +func (v *KeyValue[K, V]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return v.Key.Size() + }) + size += buf.SizeField(2, func() int { + return v.Value.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@struct_many_ws.stef.snap b/crates/stef-go/tests/snapshots/render__render@struct_many_ws.stef.snap index cd01dbe..68ec252 100644 --- a/crates/stef-go/tests/snapshots/render__render@struct_many_ws.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@struct_many_ws.stef.snap @@ -119,4 +119,21 @@ func (v *Sample[T]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample[T])(nil) + +func (v *Sample[T]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.A) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.B) + }) + size += buf.SizeField(3, func() int { + return v.C.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@struct_min_ws.stef.snap b/crates/stef-go/tests/snapshots/render__render@struct_min_ws.stef.snap index eabec00..5dc18ca 100644 --- a/crates/stef-go/tests/snapshots/render__render@struct_min_ws.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@struct_min_ws.stef.snap @@ -118,4 +118,21 @@ func (v *Sample[T]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample[T])(nil) + +func (v *Sample[T]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.A) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.B) + }) + size += buf.SizeField(3, func() int { + return v.C.Size() + }) + 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 1f9a2d8..35fccd1 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 @@ -94,4 +94,18 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU32(v.F0) + }) + size += buf.SizeField(2, func() int { + return buf.SizeBool(v.F1) + }) + 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 c09a863..6802c77 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 @@ -521,4 +521,83 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeBool(v.F01) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU8(v.F02) + }) + size += buf.SizeField(3, func() int { + return buf.SizeU16(v.F03) + }) + size += buf.SizeField(4, func() int { + return buf.SizeU32(v.F04) + }) + size += buf.SizeField(5, func() int { + return buf.SizeU64(v.F05) + }) + size += buf.SizeField(6, func() int { + return buf.SizeU128(v.F06) + }) + size += buf.SizeField(7, func() int { + return buf.SizeI8(v.F07) + }) + size += buf.SizeField(8, func() int { + return buf.SizeI16(v.F08) + }) + size += buf.SizeField(9, func() int { + return buf.SizeI32(v.F09) + }) + size += buf.SizeField(10, func() int { + return buf.SizeI64(v.F10) + }) + size += buf.SizeField(11, func() int { + return buf.SizeI128(v.F11) + }) + size += buf.SizeField(12, func() int { + return buf.SizeF32(v.F12) + }) + size += buf.SizeField(13, func() int { + return buf.SizeF64(v.F13) + }) + size += buf.SizeField(14, func() int { + return buf.SizeString(v.F14) + }) + size += buf.SizeField(15, func() int { + return buf.SizeString(v.F15) + }) + size += buf.SizeField(16, func() int { + return buf.SizeBytes(v.F16) + }) + size += buf.SizeField(17, func() int { + return buf.SizeBytes(v.F17) + }) + size += buf.SizeField(18, func() int { + return buf.SizeString(v.F18) + }) + size += buf.SizeField(19, func() int { + return buf.SizeBytes(v.F19) + }) + size += buf.SizeField(20, func() int { + return func() int { + size := 0 + size += buf.SizeU32(v.F20.F0) + size += buf.SizeU32(v.F20.F1) + size += buf.SizeU32(v.F20.F2) + return size + }(size) + }) + size += buf.SizeField(21, func() int { + return buf.SizeArray12[uint32](v.F21, func(v uint32) int { + return buf.SizeU32(v) + }) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + 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 a1fc0e7..263dd78 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 @@ -182,6 +182,41 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeVec[uint32](v.F1, func(v uint32) int { + return buf.SizeU32(v) + }) + }) + size += buf.SizeField(2, func() int { + return buf.SizeHashMap[uint32, string]( + v.F2, + func(k uint32) int { + return buf.SizeU32(k) + }, + func(v string) int { + return buf.SizeString(v) + }, + ) + }) + size += buf.SizeField(3, func() int { + return buf.SizeHashSet[uint32](v.F3, func(v uint32) int { + return buf.SizeU32(v) + }) + }) + size += buf.SizeFieldOption[uint32](4, &v.F4, func (v uint32) []byte { + return buf.SizeU32(v) + }) + size += buf.SizeField(5, func() int { + return buf.SizeU32(v.F5.Get()) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type SampleUnnamed struct { F0 []uint32 F1 map[uint32]string @@ -230,7 +265,7 @@ func (v *SampleUnnamed) Encode(w []byte) []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.F3, func (w []byte, v uint32) []byte { return buf.EncodeU32(w, v) }) w = buf.EncodeField(w, 5, func (w []byte) []byte { @@ -350,4 +385,39 @@ func (v *SampleUnnamed) Decode(r []byte) ([]byte, error) { return r, nil } +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.SizeU32(v) + }) + }) + size += buf.SizeField(2, func() int { + return buf.SizeHashMap[uint32, string]( + v.F1, + func(k uint32) int { + return buf.SizeU32(k) + }, + func(v string) int { + return buf.SizeString(v) + }, + ) + }) + size += buf.SizeField(3, func() int { + return buf.SizeHashSet[uint32](v.F2, func(v uint32) int { + return buf.SizeU32(v) + }) + }) + size += buf.SizeFieldOption[uint32](4, &v.F3, func (v uint32) int { + return buf.SizeU32(v) + }) + size += buf.SizeField(5, func() int { + return buf.SizeU32(v.F4.Get()) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@types_nested.stef.snap b/crates/stef-go/tests/snapshots/render__render@types_nested.stef.snap index c5f291a..5bc48a6 100644 --- a/crates/stef-go/tests/snapshots/render__render@types_nested.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@types_nested.stef.snap @@ -96,4 +96,27 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeVec[*stef.NonZeroHashMap[int64, string]](v.Value, func(v *stef.NonZeroHashMap[int64, string]) int { + return buf.SizeOption[stef.NonZeroHashMap[int64, string]](v, func(v stef.NonZeroHashMap[int64, string]) int { + return buf.SizeHashMap[int64, string]( + v.Get(), + func(k int64) int { + return buf.SizeI64(k) + }, + func(v string) int { + return buf.SizeString(v) + }, + ) + }) + }) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@types_non_zero.stef.snap b/crates/stef-go/tests/snapshots/render__render@types_non_zero.stef.snap index 218389f..0bca174 100644 --- a/crates/stef-go/tests/snapshots/render__render@types_non_zero.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@types_non_zero.stef.snap @@ -390,4 +390,69 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return buf.SizeU8(v.F01.Get()) + }) + size += buf.SizeField(2, func() int { + return buf.SizeU16(v.F02.Get()) + }) + size += buf.SizeField(3, func() int { + return buf.SizeU32(v.F03.Get()) + }) + size += buf.SizeField(4, func() int { + return buf.SizeU64(v.F04.Get()) + }) + size += buf.SizeField(5, func() int { + return buf.SizeU128(v.F05.Get()) + }) + size += buf.SizeField(6, func() int { + return buf.SizeI8(v.F06.Get()) + }) + size += buf.SizeField(7, func() int { + return buf.SizeI16(v.F07.Get()) + }) + size += buf.SizeField(8, func() int { + return buf.SizeI32(v.F08.Get()) + }) + size += buf.SizeField(9, func() int { + return buf.SizeI64(v.F09.Get()) + }) + size += buf.SizeField(10, func() int { + return buf.SizeI128(v.F10.Get()) + }) + size += buf.SizeField(11, func() int { + return buf.SizeString(v.F11.Get()) + }) + size += buf.SizeField(12, func() int { + return buf.SizeBytes(v.F12.Get()) + }) + size += buf.SizeField(13, func() int { + return buf.SizeVec[string](v.F13.Get(), func(v string) int { + return buf.SizeString(v) + }) + }) + size += buf.SizeField(14, func() int { + return buf.SizeHashMap[string, []byte]( + v.F14.Get(), + func(k string) int { + return buf.SizeString(k) + }, + func(v []byte) int { + return buf.SizeBytes(v) + }, + ) + }) + size += buf.SizeField(15, func() int { + return buf.SizeHashSet[string](v.F15.Get(), func(v string) int { + return buf.SizeString(v) + }) + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + diff --git a/crates/stef-go/tests/snapshots/render__render@types_ref.stef.snap b/crates/stef-go/tests/snapshots/render__render@types_ref.stef.snap index 1b11c7e..8beb71f 100644 --- a/crates/stef-go/tests/snapshots/render__render@types_ref.stef.snap +++ b/crates/stef-go/tests/snapshots/render__render@types_ref.stef.snap @@ -101,6 +101,20 @@ func (v *Sample) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Sample)(nil) + +func (v *Sample) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return v.Basic.Size() + }) + size += buf.SizeField(2, func() int { + return v.WithGenerics.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} + type Test123Variant interface { sealed() } @@ -142,6 +156,13 @@ func (v *Test123_Value) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*Test123_Value)(nil) + +func (v *Test123_Value) Size() int { + size := 0 + return size +} + type KeyValue[K any, V any] struct { Key K Value V @@ -229,4 +250,18 @@ func (v *KeyValue[K, V]) Decode(r []byte) ([]byte, error) { return r, nil } +var _ buf.Size = (*KeyValue[K, V])(nil) + +func (v *KeyValue[K, V]) Size() int { + size := 0 + size += buf.SizeField(1, func() int { + return v.Key.Size() + }) + size += buf.SizeField(2, func() int { + return v.Value.Size() + }) + size += buf.SizeU32(buf.EndMarker) + return size +} +