From 84e751b80f722a864b9b3714cd0fd1dee4368760 Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Sun, 27 Oct 2024 15:59:27 +0100 Subject: [PATCH] Fix direct lookup newtype schema generation (fixes #25) --- .../field_types_and_instantiations.rs | 11 ++++- .../src/build_schema/mod.rs | 40 ++++++++++++------- .../src/build_schema/type_lookup.rs | 1 + 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/serde_avro_derive_macros/src/build_schema/field_types_and_instantiations.rs b/serde_avro_derive_macros/src/build_schema/field_types_and_instantiations.rs index 9d2ccf0..455a381 100644 --- a/serde_avro_derive_macros/src/build_schema/field_types_and_instantiations.rs +++ b/serde_avro_derive_macros/src/build_schema/field_types_and_instantiations.rs @@ -7,6 +7,11 @@ pub(super) struct FieldTypeAndInstantiationsBuilder<'t, 'm> { pub(super) errors: &'m mut TokenStream, pub(super) namespace: &'m Option, pub(super) expand_namespace_var: bool, + /// Whether at least one of the fields id directly looked up in the schema, + /// without necessarily inserting a new node. This is useful for newtype + /// struct serialization without logical type, whose type (and lookup) + /// should be directly the inner one + pub(super) has_direct_lookup: bool, } pub(super) enum FieldKind<'a> { @@ -203,8 +208,10 @@ impl<'t> FieldTypeAndInstantiationsBuilder<'t, '_> { } } } - override_field_instantiation - .unwrap_or_else(|| quote! { builder.find_or_build::<#ty>() }) + override_field_instantiation.unwrap_or_else(|| { + self.has_direct_lookup = true; + quote! { builder.find_or_build::<#ty>() } + }) } Some(logical_type_litstr) => { let logical_type_str_raw = logical_type_litstr.value(); diff --git a/serde_avro_derive_macros/src/build_schema/mod.rs b/serde_avro_derive_macros/src/build_schema/mod.rs index d2b84bc..f390ee1 100644 --- a/serde_avro_derive_macros/src/build_schema/mod.rs +++ b/serde_avro_derive_macros/src/build_schema/mod.rs @@ -107,6 +107,7 @@ pub(crate) fn schema_impl(input: SchemaDeriveInput) -> Result Result::TypeLookup }; + type_lookup_decl = None; + quote! { + <#field_type as serde_avro_derive::BuildSchema>::append_schema(builder); + } + } else { + let namespace_var = field_types_and_instantiations + .expand_namespace_var + .then(lazy_compute_namespace); + (type_lookup, type_lookup_decl, _) = type_lookup::build_type_lookup( + type_ident, + &generics, + None, + std::slice::from_ref(&field_type), + ); + quote! { + let n_nodes = builder.nodes.len(); + #namespace_var + let new_node_key = #field_instantiation; + assert_eq!(n_nodes, new_node_key.idx()); + } } } else { // named struct diff --git a/serde_avro_derive_macros/src/build_schema/type_lookup.rs b/serde_avro_derive_macros/src/build_schema/type_lookup.rs index ff2d819..93b84d3 100644 --- a/serde_avro_derive_macros/src/build_schema/type_lookup.rs +++ b/serde_avro_derive_macros/src/build_schema/type_lookup.rs @@ -1,5 +1,6 @@ use super::*; +/// Returned boolean is `has_non_lifetime_generics` pub(super) fn build_type_lookup( type_ident: &syn::Ident, generics: &syn::Generics,