diff --git a/.claude/agents/rust-code-reviewer.md b/.claude/agents/rust-code-reviewer.md index 089ca01..69008bb 100644 --- a/.claude/agents/rust-code-reviewer.md +++ b/.claude/agents/rust-code-reviewer.md @@ -2,7 +2,6 @@ name: rust-code-reviewer description: Expert Rust code reviewer. Reviews Rust code for quality, safety, idioms, performance, maintainability, readability, and API ergonomics. tools: Read, Glob, Grep -model: opus --- You are an expert Rust code reviewer with deep knowledge of: diff --git a/DESIGN.md b/DESIGN.md index d362e58..86815c2 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -39,7 +39,7 @@ The runtime library that generated code depends on. Contains: - **`MessageView` trait**: The trait for borrowed/zero-copy message views. - **`OwnedView`**: Self-referential container that pairs a `Bytes` buffer with a decoded view, producing a `'static + Send + Sync` type suitable for async and RPC frameworks. - **`MessageField`**: Ergonomic wrapper for optional message fields that dereferences to a default instance when unset. -- **`CachedSize`**: Per-message cached encoded size for linear-time serialization. +- **`SizeCache`**: External (non-field) pre-order cache of nested-message sizes, populated by `compute_size` and consumed by `write_to`. Keeps generated structs free of serialization plumbing. - **`EnumValue`**: Type-safe wrapper for open enum fields that preserves unknown values. - **Wire format codec**: Varint, fixed-width, length-delimited, and group encoding/decoding using `bytes::{Buf, BufMut}`. - **Unknown field storage**: Preserves unknown fields for round-trip fidelity. @@ -179,7 +179,6 @@ pub struct Person { pub address: buffa::MessageField
, // internal fields (excluded from Debug output): // __buffa_unknown_fields: buffa::UnknownFields, - // __buffa_cached_size: buffa::__private::CachedSize, } // Generated impls: Clone, PartialEq, Debug, Default, Message @@ -271,41 +270,40 @@ For **open enums** (default in editions), the field type is `EnumValue, // pre-order DFS slots + cursor: usize, // write-phase read position } ``` -Each generated message struct contains a `CachedSize` field. Serialization is a two-pass process: +Serialization is a two-pass process over the message tree: -1. **`compute_size()`** — walks the message tree, computes sizes bottom-up, caches each message's size in its `CachedSize` field. -2. **`write_to()`** — walks the tree again, writing bytes and using cached sizes for length-prefixed sub-message headers. +1. **`compute_size(&self, cache)`** — walks the tree bottom-up computing sizes, but records them in the cache in **pre-order** (reserve a slot on entry, fill it on exit). Each length-delimited nested message gets one slot. +2. **`write_to(&self, cache, buf)`** — walks the tree again in the same order, consuming cached sizes for length-delimited sub-message headers via `cache.next_size()`. -Both passes are O(n) in the total message size. The C++ protobuf implementation has used this approach from the start. +Both passes are O(n) in the total message size. The cache is transient — created inside the provided `encode` methods and discarded after — so generated structs contain no serialization state. Earlier designs stored an `AtomicU32` cached-size field in every message struct (as C++ protobuf and protobuf-go do); that worked but polluted exhaustive struct destructuring with an implementation-detail field. -**`AtomicU32` over `Cell`:** An earlier design used `Cell` on the assumption that avoiding atomics would be faster, since serialization is single-threaded. In practice, `Relaxed`-ordered atomic load/store compiles to identical machine instructions as a plain memory access on every major platform (x86/x86_64 TSO, ARM64, ARM32, RISC-V) — the only difference is a compiler reordering barrier, which has zero runtime cost. Switching to `AtomicU32` makes messages `Sync`, enabling `Arc` and read-sharing across threads, at no measurable overhead. The `DefaultInstance` trait requires `T: Sync` for its `static` lazy-initializer pattern; `!Sync` messages made it impossible to compile the generated `DefaultInstance` impl, which was the decisive factor. - -Serialization must still be sequenced: `compute_size()` and `write_to()` must be called in order without interleaving from another thread. `merge()` requires `&mut self`, so mutation is still exclusive. `Sync` enables shared read access to a fully-built message, not concurrent serialization. +Groups (start/end-tag delimited) thread the cache through to their children without reserving a slot for themselves, since they have no length prefix. The `Message` trait reflects this two-pass model: ```rust,ignore pub trait Message: DefaultInstance + Clone + PartialEq + Send + Sync { // Required methods (implemented by codegen per message type): - fn compute_size(&self) -> u32; // Pass 1: compute and cache - fn write_to(&self, buf: &mut impl BufMut); // Pass 2: write (infallible) + fn compute_size(&self, cache: &mut SizeCache) -> u32; // Pass 1: populate cache + fn write_to(&self, cache: &mut SizeCache, buf: &mut impl BufMut); // Pass 2: consume cache fn merge_field(&mut self, tag: Tag, buf: &mut impl Buf, depth: u32) -> Result<(), DecodeError>; // Per-field decode dispatch - fn cached_size(&self) -> u32; fn clear(&mut self); // Provided methods (default impls): - fn encode(&self, buf: &mut impl BufMut); + fn encode(&self, buf: &mut impl BufMut); // runs both passes with a fresh cache + fn encoded_len(&self) -> u32; // just the size (discards the cache) fn encode_to_vec(&self) -> Vec; fn encode_to_bytes(&self) -> Bytes; fn decode_from_slice(data: &[u8]) -> Result; diff --git a/benchmarks/buffa/benches/protobuf.rs b/benchmarks/buffa/benches/protobuf.rs index bbfc661..6174845 100644 --- a/benchmarks/buffa/benches/protobuf.rs +++ b/benchmarks/buffa/benches/protobuf.rs @@ -61,7 +61,7 @@ fn benchmark_decode(c: &mut Criterion, name: &str, dataset .collect(); b.iter(|| { for msg in &messages { - let size = msg.compute_size(); + let size = msg.encoded_len(); criterion::black_box(size); } }); diff --git a/buffa-codegen/src/impl_message.rs b/buffa-codegen/src/impl_message.rs index b9ea8b6..18c1446 100644 --- a/buffa-codegen/src/impl_message.rs +++ b/buffa-codegen/src/impl_message.rs @@ -531,8 +531,9 @@ pub fn generate_message_impl( /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; #size_decl #(#compute_stmts)* @@ -540,15 +541,15 @@ pub fn generate_message_impl( #(#oneof_compute_stmts)* #(#map_compute_stmts)* #unknown_fields_size_stmt - self.__buffa_cached_size.set(size); size } fn write_to( &self, + __cache: &mut ::buffa::SizeCache, #buf_param, - ) { - #[allow(unused_imports)] + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; #(#write_stmts)* #(#repeated_write_stmts)* @@ -577,17 +578,12 @@ pub fn generate_message_impl( ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } - fn clear(&mut self) { #(#scalar_clear_stmts)* #(#repeated_clear_stmts)* #(#oneof_clear_stmts)* #(#map_clear_stmts)* #unknown_fields_clear_stmt - self.__buffa_cached_size.set(0); } } @@ -985,7 +981,9 @@ fn scalar_compute_size_stmt( Type::TYPE_MESSAGE => { return Ok(quote! { if self.#ident.is_set() { - let inner_size = self.#ident.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.#ident.compute_size(__cache); + __cache.set(__slot, inner_size); size += #tag_len + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -996,7 +994,7 @@ fn scalar_compute_size_stmt( // Groups: start_tag + body + end_tag (no length prefix). return Ok(quote! { if self.#ident.is_set() { - let inner_size = self.#ident.compute_size(); + let inner_size = self.#ident.compute_size(__cache); size += #tag_len + inner_size + #tag_len; } }); @@ -1154,8 +1152,8 @@ fn scalar_write_to_stmt( #field_number, ::buffa::encoding::WireType::LengthDelimited, ).encode(buf); - ::buffa::encoding::encode_varint(self.#ident.cached_size() as u64, buf); - self.#ident.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.#ident.write_to(__cache, buf); } }); } @@ -1166,7 +1164,7 @@ fn scalar_write_to_stmt( #field_number, ::buffa::encoding::WireType::StartGroup, ).encode(buf); - self.#ident.write_to(buf); + self.#ident.write_to(__cache, buf); ::buffa::encoding::Tag::new( #field_number, ::buffa::encoding::WireType::EndGroup, @@ -1517,7 +1515,9 @@ fn repeated_compute_size_stmt( // Messages are always length-delimited (one tag per element). return Ok(quote! { for v in &self.#ident { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += #ld_tag_len + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -1528,7 +1528,7 @@ fn repeated_compute_size_stmt( // Groups: start_tag + body + end_tag per element (no length prefix). return Ok(quote! { for v in &self.#ident { - let inner_size = v.compute_size(); + let inner_size = v.compute_size(__cache); size += #elem_tag_len + inner_size + #elem_tag_len; } }); @@ -1610,8 +1610,8 @@ fn repeated_write_to_stmt( #field_number, ::buffa::encoding::WireType::LengthDelimited, ).encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } }); } @@ -1622,7 +1622,7 @@ fn repeated_write_to_stmt( #field_number, ::buffa::encoding::WireType::StartGroup, ).encode(buf); - v.write_to(buf); + v.write_to(__cache, buf); ::buffa::encoding::Tag::new( #field_number, ::buffa::encoding::WireType::EndGroup, @@ -2001,7 +2001,9 @@ fn oneof_size_arm( }, Type::TYPE_MESSAGE => quote! { #enum_ident::#variant_ident(x) => { - let inner = x.compute_size(); + let __slot = __cache.reserve(); + let inner = x.compute_size(__cache); + __cache.set(__slot, inner); size += #tag_len + ::buffa::encoding::varint_len(inner as u64) as u32 + inner; @@ -2009,7 +2011,7 @@ fn oneof_size_arm( }, Type::TYPE_GROUP => quote! { #enum_ident::#variant_ident(x) => { - let inner = x.compute_size(); + let inner = x.compute_size(__cache); size += #tag_len + inner + #tag_len; } }, @@ -2083,8 +2085,8 @@ fn oneof_write_arm( ::buffa::encoding::Tag::new( #field_number, ::buffa::encoding::WireType::LengthDelimited, ).encode(buf); - ::buffa::encoding::encode_varint(x.cached_size() as u64, buf); - x.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + x.write_to(__cache, buf); } }, Type::TYPE_GROUP => quote! { @@ -2092,7 +2094,7 @@ fn oneof_write_arm( ::buffa::encoding::Tag::new( #field_number, ::buffa::encoding::WireType::StartGroup, ).encode(buf); - x.write_to(buf); + x.write_to(__cache, buf); ::buffa::encoding::Tag::new( #field_number, ::buffa::encoding::WireType::EndGroup, ).encode(buf); @@ -2338,18 +2340,17 @@ pub(crate) fn find_map_entry_fields<'a>( /// Generate the encoded-byte-size expression for a single map entry element /// (key or value) bound to the variable named `var`. Uses `*var` for copy -/// scalars, `var` for string/bytes/enum, and `var.compute_size()` for messages. +/// scalars, `var` for string/bytes/enum, and `var.to_i32()` for enums. +/// +/// Message values are phase-dependent (compute reserves a cache slot, +/// write reads it) so callers handle them explicitly; keys cannot be +/// message-typed per the proto spec. fn map_element_size_expr(ty: Type, var: &Ident) -> TokenStream { match ty { Type::TYPE_STRING => quote! { ::buffa::types::string_encoded_len(#var) as u32 }, Type::TYPE_BYTES => quote! { ::buffa::types::bytes_encoded_len(#var) as u32 }, Type::TYPE_ENUM => quote! { ::buffa::types::int32_encoded_len(#var.to_i32()) as u32 }, - Type::TYPE_MESSAGE => quote! { - { - let inner = #var.compute_size(); - ::buffa::encoding::varint_len(inner as u64) as u32 + inner - } - }, + Type::TYPE_MESSAGE => unreachable!("message map values are handled per-phase by callers"), Type::TYPE_FIXED32 | Type::TYPE_SFIXED32 | Type::TYPE_FLOAT => { quote! { ::buffa::types::FIXED32_ENCODED_LEN as u32 } } @@ -2389,8 +2390,8 @@ fn map_element_encode_stmt(ty: Type, tag_num: u32, var: &Ident) -> TokenStream { Type::TYPE_ENUM => quote! { ::buffa::types::encode_int32(#var.to_i32(), buf); }, Type::TYPE_MESSAGE => { quote! { - ::buffa::encoding::encode_varint(#var.cached_size() as u64, buf); - #var.write_to(buf); + ::buffa::encoding::encode_varint(__v_len as u64, buf); + #var.write_to(__cache, buf); } } _ => { @@ -2466,11 +2467,28 @@ fn map_compute_size_stmt( let k = format_ident!("k"); let v = format_ident!("v"); let key_size = map_element_size_expr(key_ty, &k); - let val_size = map_element_size_expr(val_ty, &v); + let val_size = if val_ty == Type::TYPE_MESSAGE { + quote! { + { + let __slot = __cache.reserve(); + let inner = #v.compute_size(__cache); + __cache.set(__slot, inner); + ::buffa::encoding::varint_len(inner as u64) as u32 + inner + } + } + } else { + map_element_size_expr(val_ty, &v) + }; let key_const = map_element_size_is_constant(key_ty); let val_const = map_element_size_is_constant(val_ty); // Iterate only the side(s) whose size varies: avoids unused-variable // and clippy::for_kv_map lints for bool/fixed* map key or value types. + // + // The (true, false) arm uses `.values()` here while `map_write_to_stmt` + // uses `for (k, v) in &map`. Cache slot order must match between the two + // passes. For HashMap (both std and hashbrown), `.values()` and `.iter()` + // walk the same table slots in the same order — identical sequence for an + // unmodified instance, which `&self` guarantees across both passes. Ok(match (key_const, val_const) { (true, true) => quote! { { @@ -2527,11 +2545,19 @@ fn map_write_to_stmt( let k = format_ident!("k"); let v = format_ident!("v"); let key_size = map_element_size_expr(key_ty, &k); - let val_size = map_element_size_expr(val_ty, &v); + let (val_len_bind, val_size) = if val_ty == Type::TYPE_MESSAGE { + ( + quote! { let __v_len = __cache.next_size(); }, + quote! { (::buffa::encoding::varint_len(__v_len as u64) as u32 + __v_len) }, + ) + } else { + (quote! {}, map_element_size_expr(val_ty, &v)) + }; let encode_key = map_element_encode_stmt(key_ty, 1, &k); let encode_val = map_element_encode_stmt(val_ty, 2, &v); Ok(quote! { for (#k, #v) in &self.#ident { + #val_len_bind let entry_size: u32 = #key_tag_len + #key_size + #val_tag_len + #val_size; ::buffa::encoding::Tag::new( #field_number, diff --git a/buffa-codegen/src/lib.rs b/buffa-codegen/src/lib.rs index 3a8e019..6611e91 100644 --- a/buffa-codegen/src/lib.rs +++ b/buffa-codegen/src/lib.rs @@ -410,13 +410,9 @@ fn check_nested_type_oneof_conflicts(file: &FileDescriptorProto) -> Result<(), C // type names. Synthetic oneofs (created by proto3 `optional` fields) // never produce a Rust enum, so they cannot collide. for (idx, oneof) in msg.oneof_decl.iter().enumerate() { - let has_real_fields = msg - .field - .iter() - .any(|f| { - crate::impl_message::is_real_oneof_member(f) - && f.oneof_index == Some(idx as i32) - }); + let has_real_fields = msg.field.iter().any(|f| { + crate::impl_message::is_real_oneof_member(f) && f.oneof_index == Some(idx as i32) + }); if !has_real_fields { continue; } diff --git a/buffa-codegen/src/message.rs b/buffa-codegen/src/message.rs index 98836ae..a93c912 100644 --- a/buffa-codegen/src/message.rs +++ b/buffa-codegen/src/message.rs @@ -369,12 +369,6 @@ pub fn generate_message( quote! {} }; - let cached_size_serde_skip = if ctx.config.generate_json { - quote! { #[serde(skip)] } - } else { - quote! {} - }; - // Check if any non-optional field has a custom default value, which // requires a hand-written `impl Default` instead of `#[derive(Default)]`. let custom_default_impl = @@ -504,9 +498,6 @@ pub fn generate_message( #(#direct_fields)* #(#oneof_struct_fields)* #unknown_fields_field - #[doc(hidden)] - #cached_size_serde_skip - pub __buffa_cached_size: ::buffa::__private::CachedSize, } #debug_impl @@ -1725,7 +1716,6 @@ fn generate_custom_default( Self { #(#field_inits)* #unknown_fields_init - __buffa_cached_size: ::core::default::Default::default(), } } } diff --git a/buffa-codegen/src/tests/generation.rs b/buffa-codegen/src/tests/generation.rs index d3de07b..3334998 100644 --- a/buffa-codegen/src/tests/generation.rs +++ b/buffa-codegen/src/tests/generation.rs @@ -952,14 +952,19 @@ fn test_repeated_message_field() { content.contains("pub items: ::buffa::alloc::vec::Vec"), "missing items field: {content}" ); - // Uses two-pass size model for each element. + // Uses two-pass size model for each element: compute reserves a cache + // slot, write consumes it. assert!( content.contains("merge_length_delimited"), "missing merge_length_delimited for repeated msg: {content}" ); assert!( - content.contains("cached_size"), - "missing cached_size in write_to: {content}" + content.contains("__cache.reserve()"), + "missing cache slot reservation in compute_size: {content}" + ); + assert!( + content.contains("__cache.next_size()"), + "missing cache read in write_to: {content}" ); } diff --git a/buffa-codegen/src/tests/json_codegen.rs b/buffa-codegen/src/tests/json_codegen.rs index cdf6a90..b49b2e1 100644 --- a/buffa-codegen/src/tests/json_codegen.rs +++ b/buffa-codegen/src/tests/json_codegen.rs @@ -170,10 +170,10 @@ fn test_json_message_has_derive_and_field_attrs() { content.contains("is_zero_f32"), "missing skip_serializing_if for ratio: {content}" ); - // cached_size gets skip + // __buffa_unknown_fields gets skip (no extension ranges → no JSON wrapper) assert!( content.contains("serde(skip)"), - "missing serde(skip) for cached_size: {content}" + "missing serde(skip) for unknown_fields: {content}" ); } diff --git a/buffa-codegen/src/tests/naming.rs b/buffa-codegen/src/tests/naming.rs index 867d62f..1c268b0 100644 --- a/buffa-codegen/src/tests/naming.rs +++ b/buffa-codegen/src/tests/naming.rs @@ -6,7 +6,7 @@ use super::*; #[test] fn test_reserved_field_name_rejected() { let field = make_field( - "__buffa_cached_size", + "__buffa_unknown_fields", 1, Label::LABEL_OPTIONAL, Type::TYPE_INT32, @@ -25,7 +25,7 @@ fn test_reserved_field_name_rejected() { assert!(result.is_err()); let err = result.unwrap_err(); assert!( - err.to_string().contains("__buffa_cached_size"), + err.to_string().contains("__buffa_unknown_fields"), "error should mention the field name: {err}" ); assert!( @@ -280,8 +280,7 @@ fn test_proto3_optional_field_name_matches_nested_enum_no_conflict() { }], field: vec![{ let mut f = make_field("match_operator", 4, Label::LABEL_OPTIONAL, Type::TYPE_ENUM); - f.type_name = - Some(".minimal.StringFieldMatcher.MatchOperator".to_string()); + f.type_name = Some(".minimal.StringFieldMatcher.MatchOperator".to_string()); f.oneof_index = Some(0); f.proto3_optional = Some(true); f diff --git a/buffa-codegen/src/view.rs b/buffa-codegen/src/view.rs index d5b2a7d..975a97c 100644 --- a/buffa-codegen/src/view.rs +++ b/buffa-codegen/src/view.rs @@ -259,7 +259,6 @@ pub fn generate_view( use ::buffa::alloc::string::ToString as _; #owned_ident { #(#owned_fields)* - ..::core::default::Default::default() } } } diff --git a/buffa-codegen/tests/codegen_integration.rs b/buffa-codegen/tests/codegen_integration.rs index ab976f9..ec7f5a6 100644 --- a/buffa-codegen/tests/codegen_integration.rs +++ b/buffa-codegen/tests/codegen_integration.rs @@ -808,9 +808,10 @@ fn inline_empty_message() { assert!(content.contains("pub struct Empty")); // Empty message should still implement Message. assert!(content.contains("impl ::buffa::Message for Empty")); - // Should have internal fields but no user fields. + // Should have the unknown-fields internal but no user fields. assert!(content.contains("__buffa_unknown_fields")); - assert!(content.contains("__buffa_cached_size")); + // __buffa_cached_size no longer exists — sizes live in an external SizeCache. + assert!(!content.contains("__buffa_cached_size")); } #[test] diff --git a/buffa-descriptor/src/generated/google.protobuf.compiler.plugin.rs b/buffa-descriptor/src/generated/google.protobuf.compiler.plugin.rs index d714cb9..0490b80 100644 --- a/buffa-descriptor/src/generated/google.protobuf.compiler.plugin.rs +++ b/buffa-descriptor/src/generated/google.protobuf.compiler.plugin.rs @@ -17,8 +17,6 @@ pub struct Version { pub suffix: Option<::buffa::alloc::string::String>, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Version { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -49,8 +47,9 @@ impl ::buffa::Message for Version { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(v) = self.major { @@ -66,11 +65,14 @@ impl ::buffa::Message for Version { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.major { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -164,16 +166,12 @@ impl ::buffa::Message for Version { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.major = ::core::option::Option::None; self.minor = ::core::option::Option::None; self.patch = ::core::option::Option::None; self.suffix = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Version { @@ -232,8 +230,6 @@ pub struct CodeGeneratorRequest { pub compiler_version: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for CodeGeneratorRequest { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -265,15 +261,18 @@ impl ::buffa::Message for CodeGeneratorRequest { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.parameter { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.compiler_version.is_set() { - let inner_size = self.compiler_version.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.compiler_version.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -282,23 +281,30 @@ impl ::buffa::Message for CodeGeneratorRequest { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } for v in &self.proto_file { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.source_file_descriptors { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.parameter { ::buffa::encoding::Tag::new( @@ -314,11 +320,8 @@ impl ::buffa::Message for CodeGeneratorRequest { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.compiler_version.cached_size() as u64, - buf, - ); - self.compiler_version.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.compiler_version.write_to(__cache, buf); } for v in &self.file_to_generate { ::buffa::encoding::Tag::new( @@ -334,8 +337,8 @@ impl ::buffa::Message for CodeGeneratorRequest { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.source_file_descriptors { ::buffa::encoding::Tag::new( @@ -343,8 +346,8 @@ impl ::buffa::Message for CodeGeneratorRequest { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -429,9 +432,6 @@ impl ::buffa::Message for CodeGeneratorRequest { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.parameter = ::core::option::Option::None; self.compiler_version = ::buffa::MessageField::none(); @@ -439,7 +439,6 @@ impl ::buffa::Message for CodeGeneratorRequest { self.proto_file.clear(); self.source_file_descriptors.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for CodeGeneratorRequest { @@ -488,8 +487,6 @@ pub struct CodeGeneratorResponse { pub file: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for CodeGeneratorResponse { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -521,8 +518,9 @@ impl ::buffa::Message for CodeGeneratorResponse { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.error { @@ -538,17 +536,22 @@ impl ::buffa::Message for CodeGeneratorResponse { size += 1u32 + ::buffa::types::int32_encoded_len(v) as u32; } for v in &self.file { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.error { ::buffa::encoding::Tag::new( @@ -579,8 +582,8 @@ impl ::buffa::Message for CodeGeneratorResponse { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -663,9 +666,6 @@ impl ::buffa::Message for CodeGeneratorResponse { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.error = ::core::option::Option::None; self.supported_features = ::core::option::Option::None; @@ -673,7 +673,6 @@ impl ::buffa::Message for CodeGeneratorResponse { self.maximum_edition = ::core::option::Option::None; self.file.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for CodeGeneratorResponse { @@ -802,8 +801,6 @@ pub mod code_generator_response { pub generated_code_info: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for File { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -834,8 +831,9 @@ pub mod code_generator_response { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { @@ -848,17 +846,22 @@ pub mod code_generator_response { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.generated_code_info.is_set() { - let inner_size = self.generated_code_info.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.generated_code_info.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -890,11 +893,8 @@ pub mod code_generator_response { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.generated_code_info.cached_size() as u64, - buf, - ); - self.generated_code_info.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.generated_code_info.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -975,16 +975,12 @@ pub mod code_generator_response { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.insertion_point = ::core::option::Option::None; self.content = ::core::option::Option::None; self.generated_code_info = ::buffa::MessageField::none(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for File { diff --git a/buffa-descriptor/src/generated/google.protobuf.descriptor.rs b/buffa-descriptor/src/generated/google.protobuf.descriptor.rs index e86540d..8e8077d 100644 --- a/buffa-descriptor/src/generated/google.protobuf.descriptor.rs +++ b/buffa-descriptor/src/generated/google.protobuf.descriptor.rs @@ -161,8 +161,6 @@ pub struct FileDescriptorSet { pub file: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FileDescriptorSet { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -188,22 +186,28 @@ impl ::buffa::Message for FileDescriptorSet { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.file { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.file { ::buffa::encoding::Tag::new( @@ -211,8 +215,8 @@ impl ::buffa::Message for FileDescriptorSet { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -246,13 +250,9 @@ impl ::buffa::Message for FileDescriptorSet { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.file.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FileDescriptorSet { @@ -331,8 +331,6 @@ pub struct FileDescriptorProto { pub edition: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FileDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -373,8 +371,9 @@ impl ::buffa::Message for FileDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { @@ -384,13 +383,17 @@ impl ::buffa::Message for FileDescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } if self.source_code_info.is_set() { - let inner_size = self.source_code_info.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.source_code_info.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -414,35 +417,46 @@ impl ::buffa::Message for FileDescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } for v in &self.message_type { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.enum_type { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.service { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.extension { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -466,8 +480,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } if self.source_code_info.is_set() { ::buffa::encoding::Tag::new( @@ -475,11 +489,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.source_code_info.cached_size() as u64, - buf, - ); - self.source_code_info.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.source_code_info.write_to(__cache, buf); } if let Some(ref v) = self.syntax { ::buffa::encoding::Tag::new( @@ -526,8 +537,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.enum_type { ::buffa::encoding::Tag::new( @@ -535,8 +546,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.service { ::buffa::encoding::Tag::new( @@ -544,8 +555,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.extension { ::buffa::encoding::Tag::new( @@ -553,8 +564,8 @@ impl ::buffa::Message for FileDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -792,9 +803,6 @@ impl ::buffa::Message for FileDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.package = ::core::option::Option::None; @@ -811,7 +819,6 @@ impl ::buffa::Message for FileDescriptorProto { self.service.clear(); self.extension.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FileDescriptorProto { @@ -855,8 +862,6 @@ pub struct DescriptorProto { pub visibility: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for DescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -894,15 +899,18 @@ impl ::buffa::Message for DescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -911,43 +919,57 @@ impl ::buffa::Message for DescriptorProto { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } for v in &self.field { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.extension { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.nested_type { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.enum_type { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.extension_range { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.oneof_decl { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.reserved_range { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -956,11 +978,14 @@ impl ::buffa::Message for DescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -976,8 +1001,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } if let Some(ref v) = self.visibility { ::buffa::encoding::Tag::new(11u32, ::buffa::encoding::WireType::Varint) @@ -990,8 +1015,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.extension { ::buffa::encoding::Tag::new( @@ -999,8 +1024,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.nested_type { ::buffa::encoding::Tag::new( @@ -1008,8 +1033,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.enum_type { ::buffa::encoding::Tag::new( @@ -1017,8 +1042,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.extension_range { ::buffa::encoding::Tag::new( @@ -1026,8 +1051,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.oneof_decl { ::buffa::encoding::Tag::new( @@ -1035,8 +1060,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.reserved_range { ::buffa::encoding::Tag::new( @@ -1044,8 +1069,8 @@ impl ::buffa::Message for DescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.reserved_name { ::buffa::encoding::Tag::new( @@ -1217,9 +1242,6 @@ impl ::buffa::Message for DescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); @@ -1233,7 +1255,6 @@ impl ::buffa::Message for DescriptorProto { self.reserved_range.clear(); self.reserved_name.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for DescriptorProto { @@ -1262,8 +1283,6 @@ pub mod descriptor_proto { pub options: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ExtensionRange { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1293,8 +1312,9 @@ pub mod descriptor_proto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(v) = self.start { @@ -1304,17 +1324,22 @@ pub mod descriptor_proto { size += 1u32 + ::buffa::types::int32_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.start { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -1332,8 +1357,8 @@ pub mod descriptor_proto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -1393,15 +1418,11 @@ pub mod descriptor_proto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.start = ::core::option::Option::None; self.end = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ExtensionRange { @@ -1428,8 +1449,6 @@ pub mod descriptor_proto { pub end: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ReservedRange { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1458,8 +1477,9 @@ pub mod descriptor_proto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(v) = self.start { @@ -1469,11 +1489,14 @@ pub mod descriptor_proto { size += 1u32 + ::buffa::types::int32_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.start { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -1529,14 +1552,10 @@ pub mod descriptor_proto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.start = ::core::option::Option::None; self.end = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ReservedRange { @@ -1573,8 +1592,6 @@ pub struct ExtensionRangeOptions { pub verification: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ExtensionRangeOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1605,12 +1622,15 @@ impl ::buffa::Message for ExtensionRangeOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -1619,23 +1639,30 @@ impl ::buffa::Message for ExtensionRangeOptions { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.declaration { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.features.is_set() { ::buffa::encoding::Tag::new( @@ -1643,8 +1670,8 @@ impl ::buffa::Message for ExtensionRangeOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } if let Some(ref v) = self.verification { ::buffa::encoding::Tag::new(3u32, ::buffa::encoding::WireType::Varint) @@ -1657,8 +1684,8 @@ impl ::buffa::Message for ExtensionRangeOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.declaration { ::buffa::encoding::Tag::new( @@ -1666,8 +1693,8 @@ impl ::buffa::Message for ExtensionRangeOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -1748,16 +1775,12 @@ impl ::buffa::Message for ExtensionRangeOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.features = ::buffa::MessageField::none(); self.verification = ::core::option::Option::None; self.uninterpreted_option.clear(); self.declaration.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ExtensionRangeOptions { @@ -1840,8 +1863,6 @@ pub mod extension_range_options { pub repeated: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Declaration { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1873,8 +1894,9 @@ pub mod extension_range_options { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(v) = self.number { @@ -1893,11 +1915,14 @@ pub mod extension_range_options { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.number { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -2016,9 +2041,6 @@ pub mod extension_range_options { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.number = ::core::option::Option::None; self.full_name = ::core::option::Option::None; @@ -2026,7 +2048,6 @@ pub mod extension_range_options { self.reserved = ::core::option::Option::None; self.repeated = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Declaration { @@ -2113,8 +2134,6 @@ pub struct FieldDescriptorProto { pub proto3_optional: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FieldDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -2152,8 +2171,9 @@ impl ::buffa::Message for FieldDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { @@ -2184,7 +2204,9 @@ impl ::buffa::Message for FieldDescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -2193,11 +2215,14 @@ impl ::buffa::Message for FieldDescriptorProto { size += 2u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -2265,8 +2290,8 @@ impl ::buffa::Message for FieldDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } if let Some(v) = self.proto3_optional { ::buffa::encoding::Tag::new(17u32, ::buffa::encoding::WireType::Varint) @@ -2458,9 +2483,6 @@ impl ::buffa::Message for FieldDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.number = ::core::option::Option::None; @@ -2474,7 +2496,6 @@ impl ::buffa::Message for FieldDescriptorProto { self.options = ::buffa::MessageField::none(); self.proto3_optional = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FieldDescriptorProto { @@ -2658,8 +2679,6 @@ pub struct OneofDescriptorProto { pub options: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for OneofDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -2688,25 +2707,31 @@ impl ::buffa::Message for OneofDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -2722,8 +2747,8 @@ impl ::buffa::Message for OneofDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -2772,14 +2797,10 @@ impl ::buffa::Message for OneofDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for OneofDescriptorProto { @@ -2819,8 +2840,6 @@ pub struct EnumDescriptorProto { pub visibility: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EnumDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -2853,15 +2872,18 @@ impl ::buffa::Message for EnumDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -2870,13 +2892,17 @@ impl ::buffa::Message for EnumDescriptorProto { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } for v in &self.value { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.reserved_range { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -2885,11 +2911,14 @@ impl ::buffa::Message for EnumDescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -2905,8 +2934,8 @@ impl ::buffa::Message for EnumDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } if let Some(ref v) = self.visibility { ::buffa::encoding::Tag::new(6u32, ::buffa::encoding::WireType::Varint) @@ -2919,8 +2948,8 @@ impl ::buffa::Message for EnumDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.reserved_range { ::buffa::encoding::Tag::new( @@ -2928,8 +2957,8 @@ impl ::buffa::Message for EnumDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.reserved_name { ::buffa::encoding::Tag::new( @@ -3041,9 +3070,6 @@ impl ::buffa::Message for EnumDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); @@ -3052,7 +3078,6 @@ impl ::buffa::Message for EnumDescriptorProto { self.reserved_range.clear(); self.reserved_name.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EnumDescriptorProto { @@ -3085,8 +3110,6 @@ pub mod enum_descriptor_proto { pub end: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EnumReservedRange { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -3115,8 +3138,9 @@ pub mod enum_descriptor_proto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(v) = self.start { @@ -3126,11 +3150,14 @@ pub mod enum_descriptor_proto { size += 1u32 + ::buffa::types::int32_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.start { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -3186,14 +3213,10 @@ pub mod enum_descriptor_proto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.start = ::core::option::Option::None; self.end = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EnumReservedRange { @@ -3217,8 +3240,6 @@ pub struct EnumValueDescriptorProto { pub options: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EnumValueDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -3248,8 +3269,9 @@ impl ::buffa::Message for EnumValueDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { @@ -3259,17 +3281,22 @@ impl ::buffa::Message for EnumValueDescriptorProto { size += 1u32 + ::buffa::types::int32_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -3290,8 +3317,8 @@ impl ::buffa::Message for EnumValueDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -3352,15 +3379,11 @@ impl ::buffa::Message for EnumValueDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.number = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EnumValueDescriptorProto { @@ -3383,8 +3406,6 @@ pub struct ServiceDescriptorProto { pub options: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ServiceDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -3414,31 +3435,39 @@ impl ::buffa::Message for ServiceDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.method { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -3454,8 +3483,8 @@ impl ::buffa::Message for ServiceDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } for v in &self.method { ::buffa::encoding::Tag::new( @@ -3463,8 +3492,8 @@ impl ::buffa::Message for ServiceDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -3525,15 +3554,11 @@ impl ::buffa::Message for ServiceDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.options = ::buffa::MessageField::none(); self.method.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ServiceDescriptorProto { @@ -3569,8 +3594,6 @@ pub struct MethodDescriptorProto { pub server_streaming: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for MethodDescriptorProto { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -3603,8 +3626,9 @@ impl ::buffa::Message for MethodDescriptorProto { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.name { @@ -3617,7 +3641,9 @@ impl ::buffa::Message for MethodDescriptorProto { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.options.is_set() { - let inner_size = self.options.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.options.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -3629,11 +3655,14 @@ impl ::buffa::Message for MethodDescriptorProto { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.name { ::buffa::encoding::Tag::new( @@ -3665,8 +3694,8 @@ impl ::buffa::Message for MethodDescriptorProto { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.options.cached_size() as u64, buf); - self.options.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.options.write_to(__cache, buf); } if let Some(v) = self.client_streaming { ::buffa::encoding::Tag::new(5u32, ::buffa::encoding::WireType::Varint) @@ -3779,9 +3808,6 @@ impl ::buffa::Message for MethodDescriptorProto { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name = ::core::option::Option::None; self.input_type = ::core::option::Option::None; @@ -3790,7 +3816,6 @@ impl ::buffa::Message for MethodDescriptorProto { self.client_streaming = ::core::option::Option::None; self.server_streaming = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for MethodDescriptorProto { @@ -3968,8 +3993,6 @@ pub struct FileOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FileOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -4017,8 +4040,9 @@ impl ::buffa::Message for FileOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.java_package { @@ -4079,23 +4103,30 @@ impl ::buffa::Message for FileOptions { size += 2u32 + ::buffa::types::string_encoded_len(v) as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.java_package { ::buffa::encoding::Tag::new( @@ -4228,8 +4259,8 @@ impl ::buffa::Message for FileOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -4237,8 +4268,8 @@ impl ::buffa::Message for FileOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -4553,9 +4584,6 @@ impl ::buffa::Message for FileOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.java_package = ::core::option::Option::None; self.java_outer_classname = ::core::option::Option::None; @@ -4579,7 +4607,6 @@ impl ::buffa::Message for FileOptions { self.features = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FileOptions { @@ -4733,8 +4760,6 @@ pub struct MessageOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for MessageOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -4774,8 +4799,9 @@ impl ::buffa::Message for MessageOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.message_set_wire_format.is_some() { @@ -4794,23 +4820,30 @@ impl ::buffa::Message for MessageOptions { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.message_set_wire_format { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -4843,8 +4876,8 @@ impl ::buffa::Message for MessageOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -4852,8 +4885,8 @@ impl ::buffa::Message for MessageOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -4961,9 +4994,6 @@ impl ::buffa::Message for MessageOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.message_set_wire_format = ::core::option::Option::None; self.no_standard_descriptor_accessor = ::core::option::Option::None; @@ -4973,7 +5003,6 @@ impl ::buffa::Message for MessageOptions { self.features = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for MessageOptions { @@ -5090,8 +5119,6 @@ pub struct FieldOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FieldOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -5132,8 +5159,9 @@ impl ::buffa::Message for FieldOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.ctype { @@ -5164,13 +5192,17 @@ impl ::buffa::Message for FieldOptions { size += 2u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } if self.feature_support.is_set() { - let inner_size = self.feature_support.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.feature_support.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -5179,23 +5211,30 @@ impl ::buffa::Message for FieldOptions { size += 2u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } for v in &self.edition_defaults { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.ctype { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -5248,8 +5287,8 @@ impl ::buffa::Message for FieldOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } if self.feature_support.is_set() { ::buffa::encoding::Tag::new( @@ -5257,11 +5296,8 @@ impl ::buffa::Message for FieldOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.feature_support.cached_size() as u64, - buf, - ); - self.feature_support.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.feature_support.write_to(__cache, buf); } for v in &self.targets { ::buffa::encoding::Tag::new(19u32, ::buffa::encoding::WireType::Varint) @@ -5274,8 +5310,8 @@ impl ::buffa::Message for FieldOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -5283,8 +5319,8 @@ impl ::buffa::Message for FieldOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -5544,9 +5580,6 @@ impl ::buffa::Message for FieldOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.ctype = ::core::option::Option::None; self.packed = ::core::option::Option::None; @@ -5563,7 +5596,6 @@ impl ::buffa::Message for FieldOptions { self.edition_defaults.clear(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FieldOptions { @@ -5816,8 +5848,6 @@ pub mod field_options { pub value: Option<::buffa::alloc::string::String>, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EditionDefault { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -5846,8 +5876,9 @@ pub mod field_options { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.edition { @@ -5857,11 +5888,14 @@ pub mod field_options { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.edition { ::buffa::encoding::Tag::new(3u32, ::buffa::encoding::WireType::Varint) @@ -5932,14 +5966,10 @@ pub mod field_options { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.edition = ::core::option::Option::None; self.value = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EditionDefault { @@ -5978,8 +6008,6 @@ pub mod field_options { pub edition_removed: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FeatureSupport { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -6010,8 +6038,9 @@ pub mod field_options { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.edition_introduced { @@ -6027,11 +6056,14 @@ pub mod field_options { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.edition_introduced { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -6154,16 +6186,12 @@ pub mod field_options { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.edition_introduced = ::core::option::Option::None; self.edition_deprecated = ::core::option::Option::None; self.deprecation_warning = ::core::option::Option::None; self.edition_removed = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FeatureSupport { @@ -6191,8 +6219,6 @@ pub struct OneofOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for OneofOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -6221,28 +6247,36 @@ impl ::buffa::Message for OneofOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.features.is_set() { ::buffa::encoding::Tag::new( @@ -6250,8 +6284,8 @@ impl ::buffa::Message for OneofOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -6259,8 +6293,8 @@ impl ::buffa::Message for OneofOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -6308,14 +6342,10 @@ impl ::buffa::Message for OneofOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.features = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for OneofOptions { @@ -6363,8 +6393,6 @@ pub struct EnumOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EnumOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -6399,8 +6427,9 @@ impl ::buffa::Message for EnumOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.allow_alias.is_some() { @@ -6413,23 +6442,30 @@ impl ::buffa::Message for EnumOptions { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.allow_alias { ::buffa::encoding::Tag::new(2u32, ::buffa::encoding::WireType::Varint) @@ -6452,8 +6488,8 @@ impl ::buffa::Message for EnumOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -6461,8 +6497,8 @@ impl ::buffa::Message for EnumOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -6546,9 +6582,6 @@ impl ::buffa::Message for EnumOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.allow_alias = ::core::option::Option::None; self.deprecated = ::core::option::Option::None; @@ -6556,7 +6589,6 @@ impl ::buffa::Message for EnumOptions { self.features = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EnumOptions { @@ -6600,8 +6632,6 @@ pub struct EnumValueOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for EnumValueOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -6633,15 +6663,18 @@ impl ::buffa::Message for EnumValueOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.deprecated.is_some() { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -6650,23 +6683,30 @@ impl ::buffa::Message for EnumValueOptions { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } if self.feature_support.is_set() { - let inner_size = self.feature_support.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.feature_support.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.deprecated { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -6679,8 +6719,8 @@ impl ::buffa::Message for EnumValueOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } if let Some(v) = self.debug_redact { ::buffa::encoding::Tag::new(3u32, ::buffa::encoding::WireType::Varint) @@ -6693,11 +6733,8 @@ impl ::buffa::Message for EnumValueOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.feature_support.cached_size() as u64, - buf, - ); - self.feature_support.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.feature_support.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -6705,8 +6742,8 @@ impl ::buffa::Message for EnumValueOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -6792,9 +6829,6 @@ impl ::buffa::Message for EnumValueOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.deprecated = ::core::option::Option::None; self.features = ::buffa::MessageField::none(); @@ -6802,7 +6836,6 @@ impl ::buffa::Message for EnumValueOptions { self.feature_support = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for EnumValueOptions { @@ -6841,8 +6874,6 @@ pub struct ServiceOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ServiceOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -6872,12 +6903,15 @@ impl ::buffa::Message for ServiceOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -6886,17 +6920,22 @@ impl ::buffa::Message for ServiceOptions { size += 2u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.features.is_set() { ::buffa::encoding::Tag::new( @@ -6904,8 +6943,8 @@ impl ::buffa::Message for ServiceOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } if let Some(v) = self.deprecated { ::buffa::encoding::Tag::new(33u32, ::buffa::encoding::WireType::Varint) @@ -6918,8 +6957,8 @@ impl ::buffa::Message for ServiceOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -6979,15 +7018,11 @@ impl ::buffa::Message for ServiceOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.features = ::buffa::MessageField::none(); self.deprecated = ::core::option::Option::None; self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ServiceOptions { @@ -7028,8 +7063,6 @@ pub struct MethodOptions { pub uninterpreted_option: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for MethodOptions { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -7060,8 +7093,9 @@ impl ::buffa::Message for MethodOptions { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.deprecated.is_some() { @@ -7071,23 +7105,30 @@ impl ::buffa::Message for MethodOptions { size += 2u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } if self.features.is_set() { - let inner_size = self.features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } for v in &self.uninterpreted_option { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 2u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(v) = self.deprecated { ::buffa::encoding::Tag::new(33u32, ::buffa::encoding::WireType::Varint) @@ -7105,8 +7146,8 @@ impl ::buffa::Message for MethodOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.features.cached_size() as u64, buf); - self.features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.features.write_to(__cache, buf); } for v in &self.uninterpreted_option { ::buffa::encoding::Tag::new( @@ -7114,8 +7155,8 @@ impl ::buffa::Message for MethodOptions { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -7196,16 +7237,12 @@ impl ::buffa::Message for MethodOptions { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.deprecated = ::core::option::Option::None; self.idempotency_level = ::core::option::Option::None; self.features = ::buffa::MessageField::none(); self.uninterpreted_option.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for MethodOptions { @@ -7295,8 +7332,6 @@ pub struct UninterpretedOption { pub aggregate_value: Option<::buffa::alloc::string::String>, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for UninterpretedOption { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -7330,8 +7365,9 @@ impl ::buffa::Message for UninterpretedOption { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.identifier_value { @@ -7353,17 +7389,22 @@ impl ::buffa::Message for UninterpretedOption { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } for v in &self.name { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.identifier_value { ::buffa::encoding::Tag::new( @@ -7410,8 +7451,8 @@ impl ::buffa::Message for UninterpretedOption { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -7524,9 +7565,6 @@ impl ::buffa::Message for UninterpretedOption { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.identifier_value = ::core::option::Option::None; self.positive_int_value = ::core::option::Option::None; @@ -7536,7 +7574,6 @@ impl ::buffa::Message for UninterpretedOption { self.aggregate_value = ::core::option::Option::None; self.name.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for UninterpretedOption { @@ -7564,8 +7601,6 @@ pub mod uninterpreted_option { pub is_extension: bool, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for NamePart { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -7594,18 +7629,22 @@ pub mod uninterpreted_option { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; size += 1u32 + ::buffa::types::string_encoded_len(&self.name_part) as u32; size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; ::buffa::encoding::Tag::new( 1u32, @@ -7656,14 +7695,10 @@ pub mod uninterpreted_option { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.name_part.clear(); self.is_extension = false; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for NamePart { @@ -7707,8 +7742,6 @@ pub struct FeatureSet { >, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FeatureSet { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -7743,8 +7776,9 @@ impl ::buffa::Message for FeatureSet { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.field_presence { @@ -7772,11 +7806,14 @@ impl ::buffa::Message for FeatureSet { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.field_presence { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -8006,9 +8043,6 @@ impl ::buffa::Message for FeatureSet { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.field_presence = ::core::option::Option::None; self.enum_type = ::core::option::Option::None; @@ -8019,7 +8053,6 @@ impl ::buffa::Message for FeatureSet { self.enforce_naming_style = ::core::option::Option::None; self.default_symbol_visibility = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FeatureSet { @@ -8342,8 +8375,6 @@ pub mod feature_set { pub struct VisibilityFeature { #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for VisibilityFeature { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -8369,16 +8400,20 @@ pub mod feature_set { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; self.__buffa_unknown_fields.write_to(buf); } @@ -8400,12 +8435,8 @@ pub mod feature_set { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for VisibilityFeature { @@ -8510,8 +8541,6 @@ pub struct FeatureSetDefaults { pub maximum_edition: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FeatureSetDefaults { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -8541,8 +8570,9 @@ impl ::buffa::Message for FeatureSetDefaults { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.minimum_edition { @@ -8552,17 +8582,22 @@ impl ::buffa::Message for FeatureSetDefaults { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } for v in &self.defaults { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.minimum_edition { ::buffa::encoding::Tag::new(4u32, ::buffa::encoding::WireType::Varint) @@ -8580,8 +8615,8 @@ impl ::buffa::Message for FeatureSetDefaults { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -8657,15 +8692,11 @@ impl ::buffa::Message for FeatureSetDefaults { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.minimum_edition = ::core::option::Option::None; self.maximum_edition = ::core::option::Option::None; self.defaults.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FeatureSetDefaults { @@ -8698,8 +8729,6 @@ pub mod feature_set_defaults { pub fixed_features: ::buffa::MessageField, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FeatureSetEditionDefault { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -8729,31 +8758,39 @@ pub mod feature_set_defaults { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.edition { size += 1u32 + ::buffa::types::int32_encoded_len(v.to_i32()) as u32; } if self.overridable_features.is_set() { - let inner_size = self.overridable_features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.overridable_features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } if self.fixed_features.is_set() { - let inner_size = self.fixed_features.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.fixed_features.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.edition { ::buffa::encoding::Tag::new(3u32, ::buffa::encoding::WireType::Varint) @@ -8766,11 +8803,8 @@ pub mod feature_set_defaults { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.overridable_features.cached_size() as u64, - buf, - ); - self.overridable_features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.overridable_features.write_to(__cache, buf); } if self.fixed_features.is_set() { ::buffa::encoding::Tag::new( @@ -8778,11 +8812,8 @@ pub mod feature_set_defaults { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint( - self.fixed_features.cached_size() as u64, - buf, - ); - self.fixed_features.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.fixed_features.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -8853,15 +8884,11 @@ pub mod feature_set_defaults { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.edition = ::core::option::Option::None; self.overridable_features = ::buffa::MessageField::none(); self.fixed_features = ::buffa::MessageField::none(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FeatureSetEditionDefault { @@ -8931,8 +8958,6 @@ pub struct SourceCodeInfo { pub location: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for SourceCodeInfo { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -8958,22 +8983,28 @@ impl ::buffa::Message for SourceCodeInfo { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.location { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.location { ::buffa::encoding::Tag::new( @@ -8981,8 +9012,8 @@ impl ::buffa::Message for SourceCodeInfo { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -9016,13 +9047,9 @@ impl ::buffa::Message for SourceCodeInfo { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.location.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for SourceCodeInfo { @@ -9137,8 +9164,6 @@ pub mod source_code_info { >, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Location { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -9170,8 +9195,9 @@ pub mod source_code_info { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.leading_comments { @@ -9204,11 +9230,14 @@ pub mod source_code_info { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.leading_comments { ::buffa::encoding::Tag::new( @@ -9385,9 +9414,6 @@ pub mod source_code_info { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.leading_comments = ::core::option::Option::None; self.trailing_comments = ::core::option::Option::None; @@ -9395,7 +9421,6 @@ pub mod source_code_info { self.span.clear(); self.leading_detached_comments.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Location { @@ -9420,8 +9445,6 @@ pub struct GeneratedCodeInfo { pub annotation: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for GeneratedCodeInfo { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -9449,22 +9472,28 @@ impl ::buffa::Message for GeneratedCodeInfo { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.annotation { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.annotation { ::buffa::encoding::Tag::new( @@ -9472,8 +9501,8 @@ impl ::buffa::Message for GeneratedCodeInfo { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -9507,13 +9536,9 @@ impl ::buffa::Message for GeneratedCodeInfo { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.annotation.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for GeneratedCodeInfo { @@ -9554,8 +9579,6 @@ pub mod generated_code_info { pub semantic: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Annotation { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -9587,8 +9610,9 @@ pub mod generated_code_info { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let Some(ref v) = self.source_file { @@ -9614,11 +9638,14 @@ pub mod generated_code_info { + payload; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let Some(ref v) = self.source_file { ::buffa::encoding::Tag::new( @@ -9768,9 +9795,6 @@ pub mod generated_code_info { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.source_file = ::core::option::Option::None; self.begin = ::core::option::Option::None; @@ -9778,7 +9802,6 @@ pub mod generated_code_info { self.semantic = ::core::option::Option::None; self.path.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Annotation { diff --git a/buffa-test/src/tests/edge_cases.rs b/buffa-test/src/tests/edge_cases.rs index 7ea3e7f..6abe22f 100644 --- a/buffa-test/src/tests/edge_cases.rs +++ b/buffa-test/src/tests/edge_cases.rs @@ -384,14 +384,14 @@ fn test_unpacked_fixed_width_wire_format() { assert_eq!(bytes[0], 0x0D); // tag for element 0 assert_eq!(bytes[5], 0x0D); // tag for element 1 // compute_size must match encode_to_vec length. - assert_eq!(msg.compute_size() as usize, bytes.len()); + assert_eq!(msg.encoded_len() as usize, bytes.len()); } #[test] fn test_unpacked_fixed_width_empty() { let msg = UnpackedFixedWidth::default(); assert_eq!(msg.encode_to_vec().len(), 0); - assert_eq!(msg.compute_size(), 0); + assert_eq!(msg.encoded_len(), 0); } // ── Map with fixed-width key/value types ───────────────────────────── @@ -417,7 +417,7 @@ fn test_map_fixed_width_round_trip() { #[test] fn test_map_fixed_width_compute_size_matches_encode() { - // compute_size() must equal encode_to_vec().len() — a mismatch would + // encoded_len() must equal encode_to_vec().len() — a mismatch would // indicate the map_element_size_expr constants are wrong. let mut msg = MapFixedWidth::default(); msg.fx32_to_bool.insert(1, true); @@ -425,7 +425,7 @@ fn test_map_fixed_width_compute_size_matches_encode() { msg.fx64_to_double.insert(100, f64::INFINITY); msg.sfx32_to_float.insert(-1, f32::NEG_INFINITY); - let size = msg.compute_size() as usize; + let size = msg.encoded_len() as usize; let bytes = msg.encode_to_vec(); assert_eq!(size, bytes.len(), "compute_size mismatch"); } diff --git a/buffa-test/src/tests/message_set.rs b/buffa-test/src/tests/message_set.rs index 495181a..4d85572 100644 --- a/buffa-test/src/tests/message_set.rs +++ b/buffa-test/src/tests/message_set.rs @@ -146,7 +146,7 @@ fn compute_size_matches_encoded_length() { }, ); - let size = container.compute_size(); + let size = container.encoded_len(); let bytes = container.encode_to_vec(); assert_eq!(size as usize, bytes.len()); } @@ -169,7 +169,7 @@ fn stray_varint_preserved_through_roundtrip() { // re-emitted as-is. Total length preserved. let reencoded = decoded.encode_to_vec(); assert_eq!(reencoded.len(), wire.len()); - assert_eq!(decoded.compute_size() as usize, reencoded.len()); + assert_eq!(decoded.encoded_len() as usize, reencoded.len()); // Decode again to verify the stray varint survived. let redecoded = Container::decode_from_slice(&reencoded).expect("redecode"); @@ -187,7 +187,7 @@ fn stray_varint_preserved_through_roundtrip() { fn empty_container_encodes_empty() { let container = Container::default(); assert_eq!(container.encode_to_vec(), Vec::::new()); - assert_eq!(container.compute_size(), 0); + assert_eq!(container.encoded_len(), 0); } /// Clearing after setting an extension yields an empty encode. diff --git a/buffa-test/src/tests/view.rs b/buffa-test/src/tests/view.rs index b78cd7e..dda0ea8 100644 --- a/buffa-test/src/tests/view.rs +++ b/buffa-test/src/tests/view.rs @@ -260,7 +260,7 @@ fn test_compute_size_matches_encode_len() { msg.id = 99; msg.name = "Bob".into(); msg.tags = vec!["a".into(), "b".into()]; - let size = msg.compute_size() as usize; + let size = msg.encoded_len() as usize; let bytes = msg.encode_to_vec(); assert_eq!(size, bytes.len()); } diff --git a/buffa-types/src/generated/google.protobuf.any.rs b/buffa-types/src/generated/google.protobuf.any.rs index 5737b40..0008401 100644 --- a/buffa-types/src/generated/google.protobuf.any.rs +++ b/buffa-types/src/generated/google.protobuf.any.rs @@ -138,8 +138,6 @@ pub struct Any { pub value: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Any { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -168,8 +166,9 @@ impl ::buffa::Message for Any { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if !self.type_url.is_empty() { @@ -179,11 +178,14 @@ impl ::buffa::Message for Any { size += 1u32 + ::buffa::types::bytes_encoded_len(&self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if !self.type_url.is_empty() { ::buffa::encoding::Tag::new( @@ -241,14 +243,10 @@ impl ::buffa::Message for Any { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.type_url.clear(); self.value.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Any { @@ -488,7 +486,6 @@ impl<'a> ::buffa::MessageView<'a> for AnyView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.duration.rs b/buffa-types/src/generated/google.protobuf.duration.rs index 88e8c8b..46bfd1a 100644 --- a/buffa-types/src/generated/google.protobuf.duration.rs +++ b/buffa-types/src/generated/google.protobuf.duration.rs @@ -85,8 +85,6 @@ pub struct Duration { pub nanos: i32, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Duration { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -115,8 +113,9 @@ impl ::buffa::Message for Duration { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.seconds != 0i64 { @@ -126,11 +125,14 @@ impl ::buffa::Message for Duration { size += 1u32 + ::buffa::types::int32_encoded_len(self.nanos) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.seconds != 0i64 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -182,14 +184,10 @@ impl ::buffa::Message for Duration { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.seconds = 0i64; self.nanos = 0i32; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Duration { @@ -376,7 +374,6 @@ impl<'a> ::buffa::MessageView<'a> for DurationView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.empty.rs b/buffa-types/src/generated/google.protobuf.empty.rs index 03092a9..d1b0113 100644 --- a/buffa-types/src/generated/google.protobuf.empty.rs +++ b/buffa-types/src/generated/google.protobuf.empty.rs @@ -15,8 +15,6 @@ pub struct Empty { #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Empty { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -42,16 +40,20 @@ impl ::buffa::Message for Empty { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; self.__buffa_unknown_fields.write_to(buf); } @@ -73,12 +75,8 @@ impl ::buffa::Message for Empty { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Empty { @@ -173,7 +171,6 @@ impl<'a> ::buffa::MessageView<'a> for EmptyView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.field_mask.rs b/buffa-types/src/generated/google.protobuf.field_mask.rs index 24a25f9..9fdd8cc 100644 --- a/buffa-types/src/generated/google.protobuf.field_mask.rs +++ b/buffa-types/src/generated/google.protobuf.field_mask.rs @@ -233,8 +233,6 @@ pub struct FieldMask { pub paths: ::buffa::alloc::vec::Vec<::buffa::alloc::string::String>, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FieldMask { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -260,19 +258,23 @@ impl ::buffa::Message for FieldMask { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.paths { size += 1u32 + ::buffa::types::string_encoded_len(v) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.paths { ::buffa::encoding::Tag::new( @@ -312,13 +314,9 @@ impl ::buffa::Message for FieldMask { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.paths.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FieldMask { @@ -642,7 +640,6 @@ impl<'a> ::buffa::MessageView<'a> for FieldMaskView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.struct.rs b/buffa-types/src/generated/google.protobuf.struct.rs index 7dc6f12..ad284db 100644 --- a/buffa-types/src/generated/google.protobuf.struct.rs +++ b/buffa-types/src/generated/google.protobuf.struct.rs @@ -56,8 +56,6 @@ pub struct Struct { pub fields: ::buffa::__private::HashMap<::buffa::alloc::string::String, Value>, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Struct { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -83,15 +81,18 @@ impl ::buffa::Message for Struct { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for (k, v) in &self.fields { let entry_size: u32 = 1u32 + ::buffa::types::string_encoded_len(k) as u32 + 1u32 + { - let inner = v.compute_size(); + let __slot = __cache.reserve(); + let inner = v.compute_size(__cache); + __cache.set(__slot, inner); ::buffa::encoding::varint_len(inner as u64) as u32 + inner }; size @@ -99,19 +100,20 @@ impl ::buffa::Message for Struct { + entry_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for (k, v) in &self.fields { + let __v_len = __cache.next_size(); let entry_size: u32 = 1u32 + ::buffa::types::string_encoded_len(k) as u32 + 1u32 - + { - let inner = v.compute_size(); - ::buffa::encoding::varint_len(inner as u64) as u32 + inner - }; + + (::buffa::encoding::varint_len(__v_len as u64) as u32 + __v_len); ::buffa::encoding::Tag::new( 1u32, ::buffa::encoding::WireType::LengthDelimited, @@ -129,8 +131,8 @@ impl ::buffa::Message for Struct { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__v_len as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -219,13 +221,9 @@ impl ::buffa::Message for Struct { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.fields.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Struct { @@ -382,7 +380,6 @@ impl<'a> ::buffa::MessageView<'a> for StructView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -407,8 +404,6 @@ pub struct Value { pub kind: Option, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Value { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -434,8 +429,9 @@ impl ::buffa::Message for Value { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if let ::core::option::Option::Some(ref v) = self.kind { @@ -453,13 +449,17 @@ impl ::buffa::Message for Value { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } value::Kind::StructValue(x) => { - let inner = x.compute_size(); + let __slot = __cache.reserve(); + let inner = x.compute_size(__cache); + __cache.set(__slot, inner); size += 1u32 + ::buffa::encoding::varint_len(inner as u64) as u32 + inner; } value::Kind::ListValue(x) => { - let inner = x.compute_size(); + let __slot = __cache.reserve(); + let inner = x.compute_size(__cache); + __cache.set(__slot, inner); size += 1u32 + ::buffa::encoding::varint_len(inner as u64) as u32 + inner; @@ -467,11 +467,14 @@ impl ::buffa::Message for Value { } } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if let ::core::option::Option::Some(ref v) = self.kind { match v { @@ -513,8 +516,8 @@ impl ::buffa::Message for Value { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(x.cached_size() as u64, buf); - x.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + x.write_to(__cache, buf); } value::Kind::ListValue(x) => { ::buffa::encoding::Tag::new( @@ -522,8 +525,8 @@ impl ::buffa::Message for Value { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(x.cached_size() as u64, buf); - x.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + x.write_to(__cache, buf); } } } @@ -647,13 +650,9 @@ impl ::buffa::Message for Value { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.kind = ::core::option::Option::None; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Value { @@ -876,7 +875,6 @@ impl<'a> ::buffa::MessageView<'a> for ValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -946,8 +944,6 @@ pub struct ListValue { pub values: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for ListValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -973,22 +969,28 @@ impl ::buffa::Message for ListValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.values { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.values { ::buffa::encoding::Tag::new( @@ -996,8 +998,8 @@ impl ::buffa::Message for ListValue { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -1031,13 +1033,9 @@ impl ::buffa::Message for ListValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.values.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for ListValue { @@ -1145,7 +1143,6 @@ impl<'a> ::buffa::MessageView<'a> for ListValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.timestamp.rs b/buffa-types/src/generated/google.protobuf.timestamp.rs index 0112a72..116d60d 100644 --- a/buffa-types/src/generated/google.protobuf.timestamp.rs +++ b/buffa-types/src/generated/google.protobuf.timestamp.rs @@ -120,8 +120,6 @@ pub struct Timestamp { pub nanos: i32, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Timestamp { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -150,8 +148,9 @@ impl ::buffa::Message for Timestamp { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.seconds != 0i64 { @@ -161,11 +160,14 @@ impl ::buffa::Message for Timestamp { size += 1u32 + ::buffa::types::int32_encoded_len(self.nanos) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.seconds != 0i64 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -217,14 +219,10 @@ impl ::buffa::Message for Timestamp { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.seconds = 0i64; self.nanos = 0i32; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Timestamp { @@ -446,7 +444,6 @@ impl<'a> ::buffa::MessageView<'a> for TimestampView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa-types/src/generated/google.protobuf.wrappers.rs b/buffa-types/src/generated/google.protobuf.wrappers.rs index d99c5f9..9793090 100644 --- a/buffa-types/src/generated/google.protobuf.wrappers.rs +++ b/buffa-types/src/generated/google.protobuf.wrappers.rs @@ -13,8 +13,6 @@ pub struct DoubleValue { pub value: f64, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for DoubleValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -40,19 +38,23 @@ impl ::buffa::Message for DoubleValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0f64 { size += 1u32 + ::buffa::types::FIXED64_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0f64 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Fixed64) @@ -89,13 +91,9 @@ impl ::buffa::Message for DoubleValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0f64; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for DoubleValue { @@ -199,7 +197,6 @@ impl<'a> ::buffa::MessageView<'a> for DoubleValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -224,8 +221,6 @@ pub struct FloatValue { pub value: f32, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for FloatValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -251,19 +246,23 @@ impl ::buffa::Message for FloatValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0f32 { size += 1u32 + ::buffa::types::FIXED32_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0f32 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Fixed32) @@ -300,13 +299,9 @@ impl ::buffa::Message for FloatValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0f32; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for FloatValue { @@ -410,7 +405,6 @@ impl<'a> ::buffa::MessageView<'a> for FloatValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -435,8 +429,6 @@ pub struct Int64Value { pub value: i64, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Int64Value { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -462,19 +454,23 @@ impl ::buffa::Message for Int64Value { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0i64 { size += 1u32 + ::buffa::types::int64_encoded_len(self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0i64 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -511,13 +507,9 @@ impl ::buffa::Message for Int64Value { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0i64; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Int64Value { @@ -621,7 +613,6 @@ impl<'a> ::buffa::MessageView<'a> for Int64ValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -646,8 +637,6 @@ pub struct UInt64Value { pub value: u64, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for UInt64Value { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -673,19 +662,23 @@ impl ::buffa::Message for UInt64Value { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0u64 { size += 1u32 + ::buffa::types::uint64_encoded_len(self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0u64 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -722,13 +715,9 @@ impl ::buffa::Message for UInt64Value { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0u64; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for UInt64Value { @@ -832,7 +821,6 @@ impl<'a> ::buffa::MessageView<'a> for UInt64ValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -857,8 +845,6 @@ pub struct Int32Value { pub value: i32, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for Int32Value { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -884,19 +870,23 @@ impl ::buffa::Message for Int32Value { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0i32 { size += 1u32 + ::buffa::types::int32_encoded_len(self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0i32 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -933,13 +923,9 @@ impl ::buffa::Message for Int32Value { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0i32; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for Int32Value { @@ -1043,7 +1029,6 @@ impl<'a> ::buffa::MessageView<'a> for Int32ValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -1068,8 +1053,6 @@ pub struct UInt32Value { pub value: u32, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for UInt32Value { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1095,19 +1078,23 @@ impl ::buffa::Message for UInt32Value { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value != 0u32 { size += 1u32 + ::buffa::types::uint32_encoded_len(self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value != 0u32 { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -1144,13 +1131,9 @@ impl ::buffa::Message for UInt32Value { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = 0u32; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for UInt32Value { @@ -1254,7 +1237,6 @@ impl<'a> ::buffa::MessageView<'a> for UInt32ValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -1279,8 +1261,6 @@ pub struct BoolValue { pub value: bool, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for BoolValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1306,19 +1286,23 @@ impl ::buffa::Message for BoolValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.value { size += 1u32 + ::buffa::types::BOOL_ENCODED_LEN as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.value { ::buffa::encoding::Tag::new(1u32, ::buffa::encoding::WireType::Varint) @@ -1355,13 +1339,9 @@ impl ::buffa::Message for BoolValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value = false; self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for BoolValue { @@ -1465,7 +1445,6 @@ impl<'a> ::buffa::MessageView<'a> for BoolValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -1490,8 +1469,6 @@ pub struct StringValue { pub value: ::buffa::alloc::string::String, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for StringValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1517,19 +1494,23 @@ impl ::buffa::Message for StringValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if !self.value.is_empty() { size += 1u32 + ::buffa::types::string_encoded_len(&self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if !self.value.is_empty() { ::buffa::encoding::Tag::new( @@ -1569,13 +1550,9 @@ impl ::buffa::Message for StringValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for StringValue { @@ -1679,7 +1656,6 @@ impl<'a> ::buffa::MessageView<'a> for StringValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } @@ -1704,8 +1680,6 @@ pub struct BytesValue { pub value: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for BytesValue { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -1731,19 +1705,23 @@ impl ::buffa::Message for BytesValue { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if !self.value.is_empty() { size += 1u32 + ::buffa::types::bytes_encoded_len(&self.value) as u32; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if !self.value.is_empty() { ::buffa::encoding::Tag::new( @@ -1783,13 +1761,9 @@ impl ::buffa::Message for BytesValue { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.value.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for BytesValue { @@ -1893,7 +1867,6 @@ impl<'a> ::buffa::MessageView<'a> for BytesValueView<'a> { .to_owned() .unwrap_or_default() .into(), - ..::core::default::Default::default() } } } diff --git a/buffa/src/cached_size.rs b/buffa/src/cached_size.rs deleted file mode 100644 index 5154d24..0000000 --- a/buffa/src/cached_size.rs +++ /dev/null @@ -1,189 +0,0 @@ -//! Cached encoded size for efficient serialization. -//! -//! Protobuf's wire format requires knowing the encoded size of sub-messages -//! before writing them (for length-delimited encoding). Without caching, this -//! requires recomputing sizes at every nesting level, leading to O(depth^2) -//! or even exponential time for deeply nested messages. -//! -//! `CachedSize` stores the computed encoded size in the message struct itself. -//! The serialization pipeline becomes: -//! 1. `compute_size()` — walk the message tree, compute and cache all sizes. -//! 2. `write_to()` — walk the tree again, using cached sizes for length prefixes. -//! -//! Both passes are O(n) in the total message size, making serialization linear. -//! -//! # Design note: `AtomicU32` over `Cell` -//! -//! An earlier design used `Cell` to avoid "atomic overhead", which made -//! generated message structs `!Sync`. In practice, `Relaxed`-ordered atomic -//! loads and stores compile to identical instructions as plain memory accesses -//! on every major platform (x86/x86_64, ARM64, ARM32, RISC-V) — the compiler -//! barrier `Relaxed` adds is free at runtime. Switching to `AtomicU32` makes -//! messages `Sync`, which enables `Arc` and parallel read access -//! without any measurable serialization overhead. - -use core::sync::atomic::{AtomicU32, Ordering}; - -/// A cached encoded byte size, stored in each generated message struct. -/// -/// Uses `AtomicU32` with `Relaxed` ordering so that generated message structs -/// are `Sync`. On all major platforms `Relaxed` load/store compiles to a plain -/// memory access — there is no runtime cost compared to `Cell`. -/// -/// The maximum protobuf message size is 2 GiB, so `u32` is sufficient. -/// -/// # Thread safety -/// -/// `CachedSize` is `Send + Sync`. Serialization (`compute_size` followed by -/// `write_to`) must still be performed sequentially on one thread per message; -/// `Sync` simply means a message can be placed in an `Arc` or behind a shared -/// reference when no serialization is in progress. -#[derive(Debug)] -pub struct CachedSize { - size: AtomicU32, -} - -impl CachedSize { - /// Create a new `CachedSize` with no cached value. - #[inline] - pub const fn new() -> Self { - Self { - size: AtomicU32::new(0), - } - } - - /// Get the cached size. Returns 0 if not yet computed. - #[inline] - pub fn get(&self) -> u32 { - self.size.load(Ordering::Relaxed) - } - - /// Set the cached size. - #[inline] - pub fn set(&self, size: u32) { - self.size.store(size, Ordering::Relaxed); - } -} - -impl Default for CachedSize { - #[inline] - fn default() -> Self { - Self::new() - } -} - -impl Clone for CachedSize { - #[inline] - fn clone(&self) -> Self { - // Don't propagate the cached value — the clone may diverge. - Self::new() - } -} - -impl PartialEq for CachedSize { - #[inline] - fn eq(&self, _other: &Self) -> bool { - // Cached size is not part of message equality. - true - } -} - -impl Eq for CachedSize {} - -impl core::hash::Hash for CachedSize { - #[inline] - fn hash(&self, _state: &mut H) { - // Cached size is not part of message identity; consistent with - // `PartialEq` always returning `true`. Lets generated messages - // derive `Hash`. - } -} - -#[cfg(feature = "arbitrary")] -impl<'a> arbitrary::Arbitrary<'a> for CachedSize { - fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - Ok(CachedSize::new()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // Compile-time proof that CachedSize is Send + Sync. - const _: fn() = || { - fn assert_send_sync() {} - assert_send_sync::(); - }; - - #[test] - fn test_new_returns_zero() { - assert_eq!(CachedSize::new().get(), 0); - } - - #[test] - fn test_default_returns_zero() { - assert_eq!(CachedSize::default().get(), 0); - } - - #[test] - fn test_set_and_get_roundtrip() { - let cs = CachedSize::new(); - cs.set(42); - assert_eq!(cs.get(), 42); - cs.set(0); - assert_eq!(cs.get(), 0); - cs.set(u32::MAX); - assert_eq!(cs.get(), u32::MAX); - } - - #[test] - fn test_clone_resets_to_zero() { - let cs = CachedSize::new(); - cs.set(100); - let cloned = cs.clone(); - // Clone resets to zero so a diverged clone recomputes its size. - assert_eq!(cloned.get(), 0); - // Original is unchanged. - assert_eq!(cs.get(), 100); - } - - #[test] - fn test_partial_eq_ignores_value() { - let a = CachedSize::new(); - let b = CachedSize::new(); - a.set(1); - b.set(99); - // Cached size is not part of message equality. - assert_eq!(a, b); - } - - #[test] - fn test_hash_ignores_value() { - use core::hash::{Hash, Hasher}; - use std::collections::hash_map::DefaultHasher; - - fn hash(x: &CachedSize) -> u64 { - let mut h = DefaultHasher::new(); - x.hash(&mut h); - h.finish() - } - - let a = CachedSize::new(); - let b = CachedSize::new(); - a.set(1); - b.set(99); - // Hash is consistent with Eq (both ignore the cached value). - assert_eq!(hash(&a), hash(&b)); - } - - // Compile-time proof that a struct containing CachedSize and - // UnknownFields can derive Hash. - #[allow(dead_code)] - #[derive(Hash)] - struct MessageLike { - value: i32, - __cached: CachedSize, - __unknown: crate::UnknownFields, - } -} diff --git a/buffa/src/extension.rs b/buffa/src/extension.rs index a2eab9a..c3d767c 100644 --- a/buffa/src/extension.rs +++ b/buffa/src/extension.rs @@ -1433,7 +1433,7 @@ mod tests { } impl crate::Message for TestMsg { - fn compute_size(&self) -> u32 { + fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 { let mut n = 0; if self.a != 0 { n += 1 + crate::encoding::varint_len(self.a as i64 as u64); @@ -1444,7 +1444,7 @@ mod tests { n += self.unknown.encoded_len(); n as u32 } - fn write_to(&self, buf: &mut impl bytes::BufMut) { + fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl bytes::BufMut) { use crate::encoding::encode_varint; if self.a != 0 { encode_varint(1 << 3, buf); @@ -1469,9 +1469,6 @@ mod tests { } Ok(()) } - fn cached_size(&self) -> u32 { - self.compute_size() - } fn clear(&mut self) { *self = Self::default(); } diff --git a/buffa/src/lib.rs b/buffa/src/lib.rs index 7012a54..91cf428 100644 --- a/buffa/src/lib.rs +++ b/buffa/src/lib.rs @@ -119,7 +119,6 @@ pub use ::bytes; #[cfg(feature = "json")] pub mod any_registry; -mod cached_size; pub mod editions; pub mod encoding; pub mod enumeration; @@ -137,6 +136,7 @@ pub mod message; pub mod message_field; pub mod message_set; pub mod oneof; +mod size_cache; pub mod types; pub mod unknown_fields; pub mod view; @@ -151,6 +151,7 @@ pub use extension::{Extension, ExtensionCodec, ExtensionSet}; pub use message::{DecodeOptions, Message, RECURSION_LIMIT}; pub use message_field::{DefaultInstance, MessageField}; pub use oneof::Oneof; +pub use size_cache::SizeCache; pub use unknown_fields::{UnknownField, UnknownFieldData, UnknownFields}; pub use view::{ DefaultViewInstance, HasDefaultViewInstance, MapView, MessageFieldView, MessageView, OwnedView, @@ -185,12 +186,9 @@ pub mod __private { #[cfg(feature = "std")] pub use std::collections::HashMap; - /// Cached encoded size for the two-pass serialization model. - /// - /// Emitted as a `#[doc(hidden)]` field on every generated message struct. - /// The size is accessed through [`Message::cached_size`](crate::Message::cached_size), - /// not this type directly. See the `cached_size` module docs for design notes. - pub use crate::cached_size::CachedSize; + /// External size cache threaded through the two-pass serialization model. + /// See the `size_cache` module docs for design notes. + pub use crate::size_cache::SizeCache; } /// Minimal fixture types for compile-checking doc examples. @@ -222,10 +220,10 @@ pub mod __doctest_fixtures { } impl Message for Person { - fn compute_size(&self) -> u32 { + fn compute_size(&self, _cache: &mut SizeCache) -> u32 { 0 } - fn write_to(&self, _buf: &mut impl bytes::BufMut) {} + fn write_to(&self, _cache: &mut SizeCache, _buf: &mut impl bytes::BufMut) {} fn merge_field( &mut self, tag: crate::encoding::Tag, @@ -234,9 +232,6 @@ pub mod __doctest_fixtures { ) -> Result<(), DecodeError> { crate::encoding::skip_field(tag, buf) } - fn cached_size(&self) -> u32 { - 0 - } fn clear(&mut self) { *self = Self::default(); } diff --git a/buffa/src/message.rs b/buffa/src/message.rs index 0a08304..c7ee073 100644 --- a/buffa/src/message.rs +++ b/buffa/src/message.rs @@ -2,7 +2,8 @@ //! //! Every generated message type implements [`Message`], which provides //! encode/decode/merge methods and a two-pass serialization model -//! (`compute_size` → `write_to`) that avoids the exponential-time +//! (`compute_size` populates a [`SizeCache`](crate::SizeCache), `write_to` +//! consumes it) that avoids the exponential-time //! problem affecting naïve length-delimited encoders. use bytes::{Buf, BufMut}; @@ -39,7 +40,8 @@ pub const RECURSION_LIMIT: u32 = 100; /// /// Manual implementation is intentionally high-friction: /// - You must correctly implement the two-pass serialization contract -/// (`compute_size` caches sizes before `write_to` uses them). +/// (`compute_size` populates the [`SizeCache`](crate::SizeCache) in the +/// same traversal order that `write_to` consumes it). /// - You must implement wire-format decoding in `merge_field`. /// - [`DefaultInstance`] is an `unsafe` supertrait; you must uphold its /// safety contract for the default-instance pointer. @@ -54,28 +56,34 @@ pub const RECURSION_LIMIT: u32 = 100; /// Serialization is a two-pass process to avoid the exponential-time problem /// that affects prost with deeply nested messages: /// -/// 1. **`compute_size()`** — walks the message tree and caches the encoded -/// size of every sub-message in its `CachedSize` field. -/// 2. **`write_to()`** — walks the tree again, writing bytes and using the +/// 1. **`compute_size()`** — walks the message tree and records the encoded +/// size of every length-delimited sub-message in a [`SizeCache`]. +/// 2. **`write_to()`** — walks the tree again, writing bytes and consuming /// cached sizes for length-prefixed sub-messages. /// -/// The convenience method `encode()` performs both passes. If you need to -/// serialize the same message multiple times without mutation in between, -/// you can call `compute_size()` once and then `write_to()` repeatedly. +/// The provided [`encode`](Self::encode) method performs both passes with a +/// fresh [`SizeCache`] — most callers use that and never touch the cache +/// directly. `compute_size` / `write_to` take the cache explicitly so that +/// manual `Message` implementations can thread it through nested-message +/// recursion. /// /// # Thread safety /// -/// `Message` requires `Send + Sync`. The `CachedSize` field uses `AtomicU32` -/// with `Relaxed` ordering, so messages can be placed in an `Arc` and shared -/// across threads. Serialization (`compute_size` → `write_to`) must still be -/// sequenced on a single thread per message — `merge` requires `&mut self`, -/// and `compute_size`/`write_to` must be called in order without interleaving -/// from another thread to produce a valid encoding. +/// `Message` requires `Send + Sync`. Generated structs contain no interior +/// mutability — serialization state lives in the external [`SizeCache`], not +/// in the message — so messages can be placed in an `Arc` and shared across +/// threads freely. `merge` requires `&mut self`, so mutation is exclusive. +/// +/// [`SizeCache`]: crate::SizeCache pub trait Message: DefaultInstance + Clone + PartialEq + Send + Sync { - /// Compute and cache the encoded byte size of this message. + /// Compute the encoded byte size of this message, recording nested + /// sub-message sizes in `cache` for `write_to` to consume. /// - /// This recursively computes sizes for all sub-messages and stores them - /// in each message's `CachedSize` field. Must be called before `write_to()`. + /// Most callers should use [`encode`](Self::encode) instead, which runs + /// both passes with a fresh cache. Manual `Message` implementations call + /// this recursively on nested message fields, wrapping each call in + /// [`SizeCache::reserve`] / [`SizeCache::set`] for length-delimited + /// fields — see the user guide's custom-types section for the pattern. /// /// # Size limit /// @@ -83,32 +91,51 @@ pub trait Message: DefaultInstance + Clone + PartialEq + Send + Sync { /// is `u32`, so messages whose encoded size exceeds `u32::MAX` (4 GiB) /// will produce a wrapped (undefined) size and a truncated encoding. /// Stay well within the 2 GiB spec limit. - fn compute_size(&self) -> u32; + /// + /// [`SizeCache::reserve`]: crate::SizeCache::reserve + /// [`SizeCache::set`]: crate::SizeCache::set + fn compute_size(&self, cache: &mut crate::SizeCache) -> u32; - /// Write this message's encoded bytes to a buffer. + /// Write this message's encoded bytes to a buffer, consuming + /// nested-message sizes from `cache` (populated by a prior + /// `compute_size` call on the same cache). /// - /// Assumes `compute_size()` has already been called. Uses cached sizes - /// for length-delimited sub-message headers. - fn write_to(&self, buf: &mut impl BufMut); + /// Most callers should use [`encode`](Self::encode) instead. + fn write_to(&self, cache: &mut crate::SizeCache, buf: &mut impl BufMut); - /// Convenience: compute size, then write. This is the primary encoding API. + /// Compute size, then write. This is the primary encoding API. fn encode(&self, buf: &mut impl BufMut) { - self.compute_size(); - self.write_to(buf); + let mut cache = crate::SizeCache::new(); + self.compute_size(&mut cache); + self.write_to(&mut cache, buf); + } + + /// Compute the encoded byte size of this message. + /// + /// Walks the message tree, discarding the intermediate [`SizeCache`]. + /// If you also intend to encode, prefer [`encode`](Self::encode) or + /// [`encode_to_vec`](Self::encode_to_vec) — they do a single size pass + /// and reuse the cache for the write. + /// + /// [`SizeCache`]: crate::SizeCache + fn encoded_len(&self) -> u32 { + self.compute_size(&mut crate::SizeCache::new()) } /// Encode this message as a length-delimited byte sequence. fn encode_length_delimited(&self, buf: &mut impl BufMut) { - let len = self.compute_size(); + let mut cache = crate::SizeCache::new(); + let len = self.compute_size(&mut cache); crate::encoding::encode_varint(len as u64, buf); - self.write_to(buf); + self.write_to(&mut cache, buf); } /// Encode this message to a new `Vec`. fn encode_to_vec(&self) -> alloc::vec::Vec { - let size = self.compute_size() as usize; + let mut cache = crate::SizeCache::new(); + let size = self.compute_size(&mut cache) as usize; let mut buf = alloc::vec::Vec::with_capacity(size); - self.write_to(&mut buf); + self.write_to(&mut cache, &mut buf); buf } @@ -121,9 +148,10 @@ pub trait Message: DefaultInstance + Clone + PartialEq + Send + Sync { /// are zero-copy with respect to the encoded bytes — but saves readers /// from having to know that `From> for Bytes` is zero-copy. fn encode_to_bytes(&self) -> bytes::Bytes { - let size = self.compute_size() as usize; + let mut cache = crate::SizeCache::new(); + let size = self.compute_size(&mut cache) as usize; let mut buf = bytes::BytesMut::with_capacity(size); - self.write_to(&mut buf); + self.write_to(&mut cache, &mut buf); buf.freeze() } @@ -374,11 +402,6 @@ pub trait Message: DefaultInstance + Clone + PartialEq + Send + Sync { Ok(()) } - /// The cached encoded size from the last `compute_size()` call. - /// - /// Returns 0 if `compute_size()` has never been called. - fn cached_size(&self) -> u32; - /// Clear all fields to their default values. fn clear(&mut self); } @@ -658,17 +681,15 @@ fn read_varint(reader: &mut impl std::io::Read) -> Result { #[cfg(test)] mod tests { use super::*; - use crate::cached_size::CachedSize; use crate::encoding::encode_varint; use crate::error::DecodeError; use crate::message_field::DefaultInstance; + use crate::size_cache::SizeCache; // Minimal hand-written Message for testing merge_length_delimited. - // Includes `CachedSize` to mirror the shape of generated message structs. #[derive(Clone, Debug, Default, PartialEq)] struct FlatMsg { value: i32, - __buffa_cached_size: CachedSize, } unsafe impl DefaultInstance for FlatMsg { @@ -679,17 +700,15 @@ mod tests { } impl Message for FlatMsg { - fn compute_size(&self) -> u32 { - let size = if self.value != 0 { + fn compute_size(&self, _cache: &mut SizeCache) -> u32 { + if self.value != 0 { 1 + crate::types::int32_encoded_len(self.value) as u32 } else { 0 - }; - self.__buffa_cached_size.set(size); - size + } } - fn write_to(&self, buf: &mut impl BufMut) { + fn write_to(&self, _cache: &mut SizeCache, buf: &mut impl BufMut) { if self.value != 0 { crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf); crate::types::encode_int32(self.value, buf); @@ -713,10 +732,6 @@ mod tests { Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } - fn clear(&mut self) { *self = Self::default(); } @@ -730,10 +745,7 @@ mod tests { #[test] fn test_merge_length_delimited_basic() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let mut dst = FlatMsg::default(); dst.merge_length_delimited(&mut wire_bytes(&src).as_slice(), RECURSION_LIMIT) .unwrap(); @@ -745,21 +757,13 @@ mod tests { // Second merge overwrites (proto3 last-wins for scalar fields). let mut dst = FlatMsg::default(); dst.merge_length_delimited( - &mut wire_bytes(&FlatMsg { - value: 1, - __buffa_cached_size: CachedSize::default(), - }) - .as_slice(), + &mut wire_bytes(&FlatMsg { value: 1 }).as_slice(), RECURSION_LIMIT, ) .unwrap(); assert_eq!(dst.value, 1); dst.merge_length_delimited( - &mut wire_bytes(&FlatMsg { - value: 2, - __buffa_cached_size: CachedSize::default(), - }) - .as_slice(), + &mut wire_bytes(&FlatMsg { value: 2 }).as_slice(), RECURSION_LIMIT, ) .unwrap(); @@ -798,10 +802,7 @@ mod tests { // to merge_length_delimited itself is the boundary: it decrements to // 0 and calls merge with depth=0, which for FlatMsg (a leaf) succeeds. // Passing depth=0 directly must return RecursionLimitExceeded. - let src = FlatMsg { - value: 7, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 7 }; let mut dst = FlatMsg::default(); assert_eq!( dst.merge_length_delimited(&mut wire_bytes(&src).as_slice(), 0), @@ -815,10 +816,7 @@ mod tests { #[test] fn test_decode_from_slice_basic() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let bytes = src.encode_to_vec(); let dst = FlatMsg::decode_from_slice(&bytes).unwrap(); assert_eq!(dst.value, 42); @@ -826,10 +824,7 @@ mod tests { #[test] fn test_encode_to_bytes_matches_encode_to_vec() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let vec = src.encode_to_vec(); let bytes = src.encode_to_bytes(); assert_eq!(vec.as_slice(), bytes.as_ref()); @@ -855,10 +850,7 @@ mod tests { #[test] fn test_merge_from_slice_basic() { - let src = FlatMsg { - value: 7, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 7 }; let bytes = src.encode_to_vec(); let mut dst = FlatMsg::default(); dst.merge_from_slice(&bytes).unwrap(); @@ -867,14 +859,8 @@ mod tests { #[test] fn test_merge_from_slice_last_wins() { - let src1 = FlatMsg { - value: 1, - __buffa_cached_size: CachedSize::default(), - }; - let src2 = FlatMsg { - value: 2, - __buffa_cached_size: CachedSize::default(), - }; + let src1 = FlatMsg { value: 1 }; + let src2 = FlatMsg { value: 2 }; let mut dst = FlatMsg::default(); dst.merge_from_slice(&src1.encode_to_vec()).unwrap(); dst.merge_from_slice(&src2.encode_to_vec()).unwrap(); @@ -886,10 +872,7 @@ mod tests { #[test] fn test_decode_options_default_works() { - let src = FlatMsg { - value: 99, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 99 }; let bytes = src.encode_to_vec(); let msg: FlatMsg = DecodeOptions::new().decode_from_slice(&bytes).unwrap(); assert_eq!(msg.value, 99); @@ -897,10 +880,7 @@ mod tests { #[test] fn test_decode_options_max_message_size_rejects() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let bytes = src.encode_to_vec(); // Set max size to 1 byte — smaller than the encoded message. let result: Result = DecodeOptions::new() @@ -911,10 +891,7 @@ mod tests { #[test] fn test_decode_options_max_message_size_exact_boundary() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let bytes = src.encode_to_vec(); // Exact size should succeed. let msg: FlatMsg = DecodeOptions::new() @@ -933,10 +910,7 @@ mod tests { fn test_decode_options_custom_recursion_limit() { // FlatMsg has no nested messages, so any recursion limit >= 0 works. // Just verify the API compiles and runs. - let src = FlatMsg { - value: 7, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 7 }; let bytes = src.encode_to_vec(); let msg: FlatMsg = DecodeOptions::new() .with_recursion_limit(1) @@ -947,10 +921,7 @@ mod tests { #[test] fn test_decode_options_merge() { - let src = FlatMsg { - value: 55, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 55 }; let bytes = src.encode_to_vec(); let mut msg = FlatMsg::default(); DecodeOptions::new() @@ -961,10 +932,7 @@ mod tests { #[test] fn test_decode_options_merge_rejects_oversize() { - let src = FlatMsg { - value: 55, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 55 }; let bytes = src.encode_to_vec(); let mut msg = FlatMsg::default(); let result = DecodeOptions::new() @@ -975,10 +943,7 @@ mod tests { #[test] fn test_decode_options_length_delimited() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let mut ld_bytes = alloc::vec::Vec::new(); src.encode_length_delimited(&mut ld_bytes); let msg: FlatMsg = DecodeOptions::new() @@ -989,10 +954,7 @@ mod tests { #[test] fn test_decode_options_length_delimited_rejects_oversize() { - let src = FlatMsg { - value: 42, - __buffa_cached_size: CachedSize::default(), - }; + let src = FlatMsg { value: 42 }; let mut ld_bytes = alloc::vec::Vec::new(); src.encode_length_delimited(&mut ld_bytes); let result: Result = DecodeOptions::new() diff --git a/buffa/src/size_cache.rs b/buffa/src/size_cache.rs new file mode 100644 index 0000000..6407c95 --- /dev/null +++ b/buffa/src/size_cache.rs @@ -0,0 +1,182 @@ +//! External size cache for linear-time serialization. +//! +//! Protobuf's wire format requires knowing the encoded size of a sub-message +//! before writing it (for the length-delimited prefix). Without caching, each +//! nesting level recomputes all sizes below it — O(depth²) for chains, +//! exponential for branchy trees. prost has this problem. +//! +//! `SizeCache` records sub-message sizes in a `Vec` indexed by +//! pre-order DFS traversal, populated by `compute_size` and consumed in the +//! same order by `write_to`. Both passes are O(n). +//! +//! The cache is external to message structs — generated types hold no +//! serialization state, so `let Msg { a, b, .. } = m;` is not forced by +//! hidden plumbing fields. A fresh `SizeCache` is constructed inside the +//! provided `Message::encode*` methods; manual implementers of `Message` +//! thread it through their `compute_size` / `write_to`. +//! +//! # Traversal-order invariant +//! +//! `reserve`/`set` calls during `compute_size` must occur in the same +//! order as `next` calls during `write_to`. Generated code guarantees this +//! by iterating fields identically in both functions and by guarding both +//! with identical presence checks (both take `&self`, so the message is +//! immutable between passes). Manual `Message` implementations must uphold +//! the same ordering. + +use alloc::vec::Vec; + +/// Transient pre-order cache of nested-message sizes for the two-pass +/// serialization model (`compute_size` populates, `write_to` consumes). +/// +/// `Message::encode` and friends construct and discard a `SizeCache` +/// internally — most callers never name this type. It appears in the +/// `compute_size` / `write_to` signatures so that manual `Message` +/// implementations can thread it through nested-message recursion. +/// +/// Reusable across encodes: call [`clear`](Self::clear) between uses to +/// retain the allocation. +#[derive(Debug, Default)] +pub struct SizeCache { + sizes: Vec, + cursor: usize, +} + +impl SizeCache { + /// Create an empty cache. + #[inline] + pub const fn new() -> Self { + Self { + sizes: Vec::new(), + cursor: 0, + } + } + + /// Clear the cache for reuse. Retains the allocated capacity. + #[inline] + pub fn clear(&mut self) { + self.sizes.clear(); + self.cursor = 0; + } + + /// Reserve a slot for a nested message's size. Call immediately before + /// recursing into `child.compute_size(cache)`, then fill the slot with + /// [`set`](Self::set) after the recursion returns. This reserves the slot + /// in pre-order even though the size is known in post-order. + /// + /// Used by generated `compute_size` implementations. + #[inline] + pub fn reserve(&mut self) -> usize { + let idx = self.sizes.len(); + self.sizes.push(0); + idx + } + + /// Fill a previously-reserved slot. + /// + /// Used by generated `compute_size` implementations. + #[inline] + pub fn set(&mut self, idx: usize, size: u32) { + self.sizes[idx] = size; + } + + /// Consume the next cached size in pre-order. + /// + /// Used by generated `write_to` implementations for length-delimited + /// nested message headers. + /// + /// # Panics + /// + /// Panics if the cursor runs past the end of the cache — i.e. if + /// `write_to` traversal diverges from `compute_size` traversal. For + /// generated code this indicates a codegen bug; for manual `Message` + /// implementations it indicates a traversal-order mismatch. + #[inline] + #[track_caller] + pub fn next_size(&mut self) -> u32 { + let size = *self.sizes.get(self.cursor).unwrap_or_else(|| { + panic!( + "SizeCache cursor overrun: write_to consumed {} slots but \ + compute_size produced {} (traversal-order mismatch)", + self.cursor + 1, + self.sizes.len() + ) + }); + self.cursor += 1; + size + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn empty_cache_is_default() { + let c = SizeCache::new(); + assert_eq!(c.sizes.len(), 0); + assert_eq!(c.cursor, 0); + } + + #[test] + fn reserve_set_next_roundtrip() { + let mut c = SizeCache::new(); + let s0 = c.reserve(); + let s1 = c.reserve(); + c.set(s0, 10); + c.set(s1, 20); + assert_eq!(c.next_size(), 10); + assert_eq!(c.next_size(), 20); + } + + #[test] + fn preorder_reservation_with_nested_recursion() { + // Simulates: root has children [A, B]; A has child X. + // compute_size pre-order entry: A, X, B + // write_to consumes in the same order. + let mut c = SizeCache::new(); + + // compute root: + // reserve slot for A + let slot_a = c.reserve(); + // compute A: + // reserve slot for X + let slot_x = c.reserve(); + // compute X: leaf, no nested messages, returns 5 + c.set(slot_x, 5); + // A returns 7 (includes X's 5 plus framing) + c.set(slot_a, 7); + // reserve slot for B + let slot_b = c.reserve(); + // compute B: leaf, returns 3 + c.set(slot_b, 3); + + // write_to root consumes A, X, B in pre-order: + assert_eq!(c.next_size(), 7); // A's length prefix + assert_eq!(c.next_size(), 5); // X's length prefix (inside A.write_to) + assert_eq!(c.next_size(), 3); // B's length prefix + } + + #[test] + fn clear_resets_and_retains_capacity() { + let mut c = SizeCache::new(); + c.reserve(); + c.set(0, 42); + let cap = c.sizes.capacity(); + c.clear(); + assert_eq!(c.sizes.len(), 0); + assert_eq!(c.cursor, 0); + assert!(c.sizes.capacity() >= cap); + // Reusable after clear: + let s = c.reserve(); + c.set(s, 99); + assert_eq!(c.next_size(), 99); + } + + #[test] + #[should_panic] + fn next_past_end_panics() { + let mut c = SizeCache::new(); + c.next_size(); + } +} diff --git a/buffa/src/view.rs b/buffa/src/view.rs index de795b9..a71f6eb 100644 --- a/buffa/src/view.rs +++ b/buffa/src/view.rs @@ -60,7 +60,6 @@ //! pub tags: Vec, //! pub address: MessageField
, //! #[doc(hidden)] pub __buffa_unknown_fields: UnknownFields, -//! #[doc(hidden)] pub __buffa_cached_size: /* internal */, //! } //! //! // Borrowed view type (zero-copy from input buffer) @@ -1149,7 +1148,7 @@ mod tests { } impl crate::Message for SimpleMessage { - fn compute_size(&self) -> u32 { + fn compute_size(&self, _cache: &mut crate::SizeCache) -> u32 { let mut size = 0u32; if self.id != 0 { size += 1 + crate::types::int32_encoded_len(self.id) as u32; @@ -1160,7 +1159,7 @@ mod tests { size } - fn write_to(&self, buf: &mut impl bytes::BufMut) { + fn write_to(&self, _cache: &mut crate::SizeCache, buf: &mut impl bytes::BufMut) { if self.id != 0 { crate::encoding::Tag::new(1, crate::encoding::WireType::Varint).encode(buf); crate::types::encode_int32(self.id, buf); @@ -1186,10 +1185,6 @@ mod tests { Ok(()) } - fn cached_size(&self) -> u32 { - 0 - } - fn clear(&mut self) { self.id = 0; self.name.clear(); diff --git a/docs/guide.md b/docs/guide.md index 97b6fe7..cefe25c 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -410,8 +410,6 @@ pub struct Person { pub nickname: Option, #[doc(hidden)] pub __buffa_unknown_fields: buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: buffa::__private::CachedSize, } ``` @@ -420,7 +418,6 @@ Key design choices: - **`MessageField`** for sub-message fields (not `Option>`) - **`EnumValue`** for open enum fields (not raw `i32`) - **`__buffa_unknown_fields`** preserves fields from newer schema versions -- **`__buffa_cached_size`** enables linear-time serialization - **Module nesting** for nested message types (`outer::Inner`, not `OuterInner`) ### `MessageField` — ergonomic optional messages @@ -611,10 +608,10 @@ msg.clear(); Buffa uses a two-pass model to avoid the exponential-time size computation that affects prost with deeply nested messages: -1. **`compute_size()`** — walks the message tree bottom-up, caching each sub-message's encoded size in its `CachedSize` field. -2. **`write_to()`** — walks the tree again, writing bytes and using cached sizes for length-delimited sub-message headers. +1. **`compute_size(&self, cache)`** — walks the message tree, recording each nested sub-message's encoded size in a transient `SizeCache` (a pre-order `Vec`). +2. **`write_to(&self, cache, buf)`** — walks the tree again, writing bytes and consuming cached sizes for length-delimited sub-message headers. -`encode()`, `encode_to_vec()`, and `encode_to_bytes()` perform both passes automatically. If you serialize the same message multiple times without mutation, you can call `compute_size()` once and `write_to()` repeatedly. +`encode()`, `encode_to_vec()`, and `encode_to_bytes()` run both passes with a fresh `SizeCache` internally — you never touch the cache directly for the common case. If you just want the size without encoding, use `encoded_len()`. ### Error handling @@ -1236,12 +1233,11 @@ message Int64Range { } ``` -The generated code would produce a struct with `start: i64` and `end: i64` fields. But in Rust, it's more natural to work with `std::ops::Range`. You can implement `Message` on a thin newtype that wraps the standard range type — no `UnknownFields` or `CachedSize` fields needed for a simple leaf message like this: +The generated code would produce a struct with `start: i64` and `end: i64` fields. But in Rust, it's more natural to work with `std::ops::Range`. You can implement `Message` on a thin newtype that wraps the standard range type — no extra fields needed for a simple leaf message like this: ```rust,ignore // my-common-protos/src/lib.rs use std::ops::{Deref, DerefMut}; -use std::sync::atomic::{AtomicU32, Ordering}; use buffa::Message; use buffa::error::DecodeError; @@ -1252,15 +1248,11 @@ use buffa::error::DecodeError; #[derive(Clone, Debug, Default, PartialEq)] pub struct Int64Range { inner: std::ops::Range, - /// Cached encoded size — internal bookkeeping, not a user-visible field. - /// Needed when this type is used as a sub-message field (the parent's - /// write_to reads the cached size for the length prefix). - cached_size: AtomicU32, } impl Int64Range { pub fn new(range: std::ops::Range) -> Self { - Self { inner: range, cached_size: AtomicU32::new(0) } + Self { inner: range } } } @@ -1282,7 +1274,8 @@ impl From for std::ops::Range { } impl Message for Int64Range { - fn compute_size(&self) -> u32 { + fn compute_size(&self, _cache: &mut buffa::SizeCache) -> u32 { + // Leaf message (no nested message fields) — _cache goes unused. let mut size = 0u32; if self.inner.start != 0 { size += 1 + buffa::types::int64_encoded_len(self.inner.start) as u32; @@ -1290,11 +1283,10 @@ impl Message for Int64Range { if self.inner.end != 0 { size += 1 + buffa::types::int64_encoded_len(self.inner.end) as u32; } - self.cached_size.store(size, Ordering::Relaxed); size } - fn write_to(&self, buf: &mut impl bytes::BufMut) { + fn write_to(&self, _cache: &mut buffa::SizeCache, buf: &mut impl bytes::BufMut) { if self.inner.start != 0 { buffa::encoding::Tag::new(1, buffa::encoding::WireType::Varint) .encode(buf); @@ -1321,13 +1313,8 @@ impl Message for Int64Range { Ok(()) } - fn cached_size(&self) -> u32 { - self.cached_size.load(Ordering::Relaxed) - } - fn clear(&mut self) { self.inner = 0..0; - self.cached_size.store(0, Ordering::Relaxed); } } @@ -1343,7 +1330,7 @@ unsafe impl buffa::DefaultInstance for Int64Range { Note what's *not* needed: - **`UnknownFields`** — omitted since this is a simple leaf type where round-trip preservation of unknown fields isn't important. Unknown tags are silently skipped via `skip_field`. -- **`CachedSize` as a public field** — the cached size is an internal `AtomicU32` that satisfies the `Message` trait contract. It doesn't need to be part of the public API. +- **Any size-caching state** — leaf messages (no nested message fields) ignore the `_cache` parameter entirely. For non-leaf manual implementations, wrap each nested-message `compute_size` call in `cache.reserve()` / `cache.set()` and consume with `cache.next_size()` in `write_to` — see the generated code for any WKT message with a sub-message field for the pattern. ### View types for custom implementations diff --git a/docs/migration-from-protobuf.md b/docs/migration-from-protobuf.md index 0daf494..899dcd3 100644 --- a/docs/migration-from-protobuf.md +++ b/docs/migration-from-protobuf.md @@ -107,7 +107,7 @@ The output filename is derived from the proto package name (e.g., `my.package` // Size -msg.compute_size(); -let size = msg.cached_size() as usize; -+let size = msg.compute_size() as usize; // returns the size directly ++let size = msg.encoded_len() as usize; // single call, no cache plumbing ``` ### From v4 diff --git a/examples/logging/src/gen/context.v1.context.rs b/examples/logging/src/gen/context.v1.context.rs index c49f247..17cb18e 100644 --- a/examples/logging/src/gen/context.v1.context.rs +++ b/examples/logging/src/gen/context.v1.context.rs @@ -29,8 +29,6 @@ pub struct RequestContext { >, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for RequestContext { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -62,8 +60,9 @@ impl ::buffa::Message for RequestContext { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if !self.request_id.is_empty() { @@ -86,11 +85,14 @@ impl ::buffa::Message for RequestContext { + entry_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if !self.request_id.is_empty() { ::buffa::encoding::Tag::new( @@ -269,9 +271,6 @@ impl ::buffa::Message for RequestContext { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.request_id.clear(); self.user_id.clear(); @@ -279,7 +278,6 @@ impl ::buffa::Message for RequestContext { self.path.clear(); self.metadata.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for RequestContext { diff --git a/examples/logging/src/gen/log.v1.log.rs b/examples/logging/src/gen/log.v1.log.rs index d544d95..ae02fc2 100644 --- a/examples/logging/src/gen/log.v1.log.rs +++ b/examples/logging/src/gen/log.v1.log.rs @@ -88,8 +88,6 @@ pub struct LogEntry { >, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for LogEntry { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -122,12 +120,15 @@ impl ::buffa::Message for LogEntry { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; if self.timestamp.is_set() { - let inner_size = self.timestamp.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.timestamp.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -145,7 +146,9 @@ impl ::buffa::Message for LogEntry { size += 1u32 + ::buffa::types::string_encoded_len(&self.logger) as u32; } if self.context.is_set() { - let inner_size = self.context.compute_size(); + let __slot = __cache.reserve(); + let inner_size = self.context.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; @@ -158,11 +161,14 @@ impl ::buffa::Message for LogEntry { + entry_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; if self.timestamp.is_set() { ::buffa::encoding::Tag::new( @@ -170,8 +176,8 @@ impl ::buffa::Message for LogEntry { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.timestamp.cached_size() as u64, buf); - self.timestamp.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.timestamp.write_to(__cache, buf); } { let val = self.severity.to_i32(); @@ -203,8 +209,8 @@ impl ::buffa::Message for LogEntry { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(self.context.cached_size() as u64, buf); - self.context.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + self.context.write_to(__cache, buf); } for (k, v) in &self.fields { let entry_size: u32 = 1u32 + ::buffa::types::string_encoded_len(k) as u32 @@ -371,9 +377,6 @@ impl ::buffa::Message for LogEntry { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.timestamp = ::buffa::MessageField::none(); self.severity = ::buffa::EnumValue::from(0); @@ -382,7 +385,6 @@ impl ::buffa::Message for LogEntry { self.context = ::buffa::MessageField::none(); self.fields.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for LogEntry { @@ -401,8 +403,6 @@ pub struct LogBatch { pub entries: ::buffa::alloc::vec::Vec, #[doc(hidden)] pub __buffa_unknown_fields: ::buffa::UnknownFields, - #[doc(hidden)] - pub __buffa_cached_size: ::buffa::__private::CachedSize, } impl ::core::fmt::Debug for LogBatch { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { @@ -428,22 +428,28 @@ impl ::buffa::Message for LogBatch { /// The result is a `u32`; the protobuf specification requires all /// messages to fit within 2 GiB (2,147,483,647 bytes), so a /// compliant message will never overflow this type. - fn compute_size(&self) -> u32 { - #[allow(unused_imports)] + #[allow(clippy::let_and_return)] + fn compute_size(&self, __cache: &mut ::buffa::SizeCache) -> u32 { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; let mut size = 0u32; for v in &self.entries { - let inner_size = v.compute_size(); + let __slot = __cache.reserve(); + let inner_size = v.compute_size(__cache); + __cache.set(__slot, inner_size); size += 1u32 + ::buffa::encoding::varint_len(inner_size as u64) as u32 + inner_size; } size += self.__buffa_unknown_fields.encoded_len() as u32; - self.__buffa_cached_size.set(size); size } - fn write_to(&self, buf: &mut impl ::buffa::bytes::BufMut) { - #[allow(unused_imports)] + fn write_to( + &self, + __cache: &mut ::buffa::SizeCache, + buf: &mut impl ::buffa::bytes::BufMut, + ) { + #[allow(unused_variables, unused_imports)] use ::buffa::Enumeration as _; for v in &self.entries { ::buffa::encoding::Tag::new( @@ -451,8 +457,8 @@ impl ::buffa::Message for LogBatch { ::buffa::encoding::WireType::LengthDelimited, ) .encode(buf); - ::buffa::encoding::encode_varint(v.cached_size() as u64, buf); - v.write_to(buf); + ::buffa::encoding::encode_varint(__cache.next_size() as u64, buf); + v.write_to(__cache, buf); } self.__buffa_unknown_fields.write_to(buf); } @@ -486,13 +492,9 @@ impl ::buffa::Message for LogBatch { } ::core::result::Result::Ok(()) } - fn cached_size(&self) -> u32 { - self.__buffa_cached_size.get() - } fn clear(&mut self) { self.entries.clear(); self.__buffa_unknown_fields.clear(); - self.__buffa_cached_size.set(0); } } impl ::buffa::ExtensionSet for LogBatch {