This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new c1c595a  Issue #139 - Remove schema_stack field from 
SchemaAwareWriteSerializer (#163)
c1c595a is described below

commit c1c595a053d46f354102a3b4628d3c8600140307
Author: jdarais <[email protected]>
AuthorDate: Sun Mar 16 23:29:10 2025 -0700

    Issue #139 - Remove schema_stack field from SchemaAwareWriteSerializer 
(#163)
    
    * add nullable values to big schema in bench tests
    
    * remove schema_stack in SchemaAwareWriteSerializer
    
    * Rename support structs to match SchemaAwareWriteSerializer
---
 avro/benches/serde.rs  |  39 +--
 avro/src/ser_schema.rs | 661 +++++++++++++++++++++++++++++--------------------
 2 files changed, 421 insertions(+), 279 deletions(-)

diff --git a/avro/benches/serde.rs b/avro/benches/serde.rs
index 46de490..d224b55 100644
--- a/avro/benches/serde.rs
+++ b/avro/benches/serde.rs
@@ -52,8 +52,8 @@ const RAW_BIG_SCHEMA: &str = r#"
   "name": "userInfo",
   "fields": [
     {
-      "default": "NONE",
-      "type": "string",
+      "default": null,
+      "type": ["null", "string"],
       "name": "username"
     },
     {
@@ -62,13 +62,13 @@ const RAW_BIG_SCHEMA: &str = r#"
       "name": "age"
     },
     {
-      "default": "NONE",
-      "type": "string",
+      "default": null,
+      "type": ["null", "string"],
       "name": "phone"
     },
     {
-      "default": "NONE",
-      "type": "string",
+      "default": null,
+      "type": ["null", "string"],
       "name": "housenum"
     },
     {
@@ -121,10 +121,10 @@ struct MailingAddress {
 
 #[derive(Serialize, Clone)]
 struct BigRecord {
-    username: String,
+    username: Option<String>,
     age: i32,
-    phone: String,
-    housenum: String,
+    phone: Option<String>,
+    housenum: Option<String>,
     address: MailingAddress,
 }
 
@@ -192,10 +192,19 @@ fn make_big_record() -> anyhow::Result<(Schema, Value)> {
 
     let big_record = {
         let mut big_record = Record::new(&big_schema).unwrap();
-        big_record.put("username", "username");
+        big_record.put(
+            "username",
+            Value::Union(1, Box::new(Value::String("username".to_owned()))),
+        );
         big_record.put("age", 10i32);
-        big_record.put("phone", "000000000");
-        big_record.put("housenum", "0000");
+        big_record.put(
+            "phone",
+            Value::Union(1, Box::new(Value::String("000000000".to_owned()))),
+        );
+        big_record.put(
+            "housenum",
+            Value::Union(1, Box::new(Value::String("0000".to_owned()))),
+        );
         big_record.put("address", address);
         big_record.into()
     };
@@ -206,10 +215,10 @@ fn make_big_record() -> anyhow::Result<(Schema, Value)> {
 fn make_big_record_ser() -> anyhow::Result<(Schema, BigRecord)> {
     let big_schema = Schema::parse_str(RAW_BIG_SCHEMA)?;
     let big_record = BigRecord {
-        username: String::from("username"),
+        username: Some(String::from("username")),
         age: 10,
-        phone: String::from("000000000"),
-        housenum: String::from("0000"),
+        phone: Some(String::from("000000000")),
+        housenum: Some(String::from("0000")),
         address: MailingAddress {
             street: String::from("street"),
             city: String::from("city"),
diff --git a/avro/src/ser_schema.rs b/avro/src/ser_schema.rs
index 4081629..77bf0ab 100644
--- a/avro/src/ser_schema.rs
+++ b/avro/src/ser_schema.rs
@@ -26,7 +26,7 @@ use crate::{
 };
 use bigdecimal::BigDecimal;
 use serde::ser;
-use std::{borrow::Cow, collections::LinkedList, io::Write, str::FromStr};
+use std::{borrow::Cow, io::Write, str::FromStr};
 
 const RECORD_FIELD_INIT_BUFFER_SIZE: usize = 64;
 const COLLECTION_SERIALIZER_ITEM_LIMIT: usize = 1024;
@@ -38,7 +38,7 @@ const SINGLE_VALUE_INIT_BUFFER_SIZE: usize = 128;
 /// to write any data to the underlying [`std::fmt::Write`] stream.  (See the 
[Data Seralization and
 /// 
Deserialization](https://avro.apache.org/docs/1.12.0/specification/#data-serialization-and-deserialization)
 /// section of the Avro spec for more info.)
-pub struct DirectSerializeSeq<'a, 's, W: Write> {
+pub struct SchemaAwareWriteSerializeSeq<'a, 's, W: Write> {
     ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
     item_schema: &'s Schema,
     item_buffer_size: usize,
@@ -46,13 +46,13 @@ pub struct DirectSerializeSeq<'a, 's, W: Write> {
     bytes_written: usize,
 }
 
-impl<'a, 's, W: Write> DirectSerializeSeq<'a, 's, W> {
+impl<'a, 's, W: Write> SchemaAwareWriteSerializeSeq<'a, 's, W> {
     fn new(
         ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
         item_schema: &'s Schema,
         len: Option<usize>,
-    ) -> DirectSerializeSeq<'a, 's, W> {
-        DirectSerializeSeq {
+    ) -> SchemaAwareWriteSerializeSeq<'a, 's, W> {
+        SchemaAwareWriteSerializeSeq {
             ser,
             item_schema,
             item_buffer_size: SINGLE_VALUE_INIT_BUFFER_SIZE,
@@ -108,7 +108,7 @@ impl<'a, 's, W: Write> DirectSerializeSeq<'a, 's, W> {
     }
 }
 
-impl<W: Write> ser::SerializeSeq for DirectSerializeSeq<'_, '_, W> {
+impl<W: Write> ser::SerializeSeq for SchemaAwareWriteSerializeSeq<'_, '_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -124,7 +124,7 @@ impl<W: Write> ser::SerializeSeq for DirectSerializeSeq<'_, 
'_, W> {
     }
 }
 
-impl<W: Write> ser::SerializeTuple for DirectSerializeSeq<'_, '_, W> {
+impl<W: Write> ser::SerializeTuple for SchemaAwareWriteSerializeSeq<'_, '_, W> 
{
     type Ok = usize;
     type Error = Error;
 
@@ -145,7 +145,7 @@ impl<W: Write> ser::SerializeTuple for 
DirectSerializeSeq<'_, '_, W> {
 /// to write any data to the underlying [`std::fmt::Write`] stream.  (See the 
[Data Seralization and
 /// 
Deserialization](https://avro.apache.org/docs/1.12.0/specification/#data-serialization-and-deserialization)
 /// section of the Avro spec for more info.)
-pub struct DirectSerializeMap<'a, 's, W: Write> {
+pub struct SchemaAwareWriteSerializeMap<'a, 's, W: Write> {
     ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
     item_schema: &'s Schema,
     item_buffer_size: usize,
@@ -153,13 +153,13 @@ pub struct DirectSerializeMap<'a, 's, W: Write> {
     bytes_written: usize,
 }
 
-impl<'a, 's, W: Write> DirectSerializeMap<'a, 's, W> {
+impl<'a, 's, W: Write> SchemaAwareWriteSerializeMap<'a, 's, W> {
     fn new(
         ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
         item_schema: &'s Schema,
         len: Option<usize>,
-    ) -> DirectSerializeMap<'a, 's, W> {
-        DirectSerializeMap {
+    ) -> SchemaAwareWriteSerializeMap<'a, 's, W> {
+        SchemaAwareWriteSerializeMap {
             ser,
             item_schema,
             item_buffer_size: SINGLE_VALUE_INIT_BUFFER_SIZE,
@@ -187,7 +187,7 @@ impl<'a, 's, W: Write> DirectSerializeMap<'a, 's, W> {
     }
 }
 
-impl<W: Write> ser::SerializeMap for DirectSerializeMap<'_, '_, W> {
+impl<W: Write> ser::SerializeMap for SchemaAwareWriteSerializeMap<'_, '_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -244,7 +244,7 @@ impl<W: Write> ser::SerializeMap for DirectSerializeMap<'_, 
'_, W> {
 /// The struct serializer for `SchemaAwareWriteSerializer`, which can 
serialize Avro records.  `DirectSerializeStruct`
 /// can accept fields out of order, but doing so incurs a performance penalty, 
since it requires
 /// `DirectSerializeStruct` to buffer serialized values in order to write them 
to the stream in order.
-pub struct DirectSerializeStruct<'a, 's, W: Write> {
+pub struct SchemaAwareWriteSerializeStruct<'a, 's, W: Write> {
     ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
     record_schema: &'s RecordSchema,
     item_count: usize,
@@ -252,13 +252,13 @@ pub struct DirectSerializeStruct<'a, 's, W: Write> {
     bytes_written: usize,
 }
 
-impl<'a, 's, W: Write> DirectSerializeStruct<'a, 's, W> {
+impl<'a, 's, W: Write> SchemaAwareWriteSerializeStruct<'a, 's, W> {
     fn new(
         ser: &'a mut SchemaAwareWriteSerializer<'s, W>,
         record_schema: &'s RecordSchema,
         len: usize,
-    ) -> DirectSerializeStruct<'a, 's, W> {
-        DirectSerializeStruct {
+    ) -> SchemaAwareWriteSerializeStruct<'a, 's, W> {
+        SchemaAwareWriteSerializeStruct {
             ser,
             record_schema,
             item_count: 0,
@@ -314,7 +314,7 @@ impl<'a, 's, W: Write> DirectSerializeStruct<'a, 's, W> {
     }
 }
 
-impl<W: Write> ser::SerializeStruct for DirectSerializeStruct<'_, '_, W> {
+impl<W: Write> ser::SerializeStruct for SchemaAwareWriteSerializeStruct<'_, 
'_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -386,7 +386,7 @@ impl<W: Write> ser::SerializeStruct for 
DirectSerializeStruct<'_, '_, W> {
     }
 }
 
-impl<W: Write> ser::SerializeStructVariant for DirectSerializeStruct<'_, '_, 
W> {
+impl<W: Write> ser::SerializeStructVariant for 
SchemaAwareWriteSerializeStruct<'_, '_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -405,17 +405,17 @@ impl<W: Write> ser::SerializeStructVariant for 
DirectSerializeStruct<'_, '_, W>
 /// The tuple struct serializer for `SchemaAwareWriteSerializer`.  
`DirectSerializeTupleStruct` can serialize to an Avro
 /// array, record, or big-decimal.  When serializing to a record, fields must 
be provided in the correct order,
 /// since no names are provided.
-pub enum DirectSerializeTupleStruct<'a, 's, W: Write> {
-    Record(DirectSerializeStruct<'a, 's, W>),
-    Array(DirectSerializeSeq<'a, 's, W>),
+pub enum SchemaAwareWriteSerializeTupleStruct<'a, 's, W: Write> {
+    Record(SchemaAwareWriteSerializeStruct<'a, 's, W>),
+    Array(SchemaAwareWriteSerializeSeq<'a, 's, W>),
 }
 
-impl<W: Write> DirectSerializeTupleStruct<'_, '_, W> {
+impl<W: Write> SchemaAwareWriteSerializeTupleStruct<'_, '_, W> {
     fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
     where
         T: ?Sized + ser::Serialize,
     {
-        use DirectSerializeTupleStruct::*;
+        use SchemaAwareWriteSerializeTupleStruct::*;
         match self {
             Record(record_ser) => record_ser.serialize_next_field(&value),
             Array(array_ser) => array_ser.serialize_element(&value),
@@ -423,7 +423,7 @@ impl<W: Write> DirectSerializeTupleStruct<'_, '_, W> {
     }
 
     fn end(self) -> Result<usize, Error> {
-        use DirectSerializeTupleStruct::*;
+        use SchemaAwareWriteSerializeTupleStruct::*;
         match self {
             Record(record_ser) => record_ser.end(),
             Array(array_ser) => array_ser.end(),
@@ -431,7 +431,7 @@ impl<W: Write> DirectSerializeTupleStruct<'_, '_, W> {
     }
 }
 
-impl<W: Write> ser::SerializeTupleStruct for DirectSerializeTupleStruct<'_, 
'_, W> {
+impl<W: Write> ser::SerializeTupleStruct for 
SchemaAwareWriteSerializeTupleStruct<'_, '_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -447,7 +447,7 @@ impl<W: Write> ser::SerializeTupleStruct for 
DirectSerializeTupleStruct<'_, '_,
     }
 }
 
-impl<W: Write> ser::SerializeTupleVariant for DirectSerializeTupleStruct<'_, 
'_, W> {
+impl<W: Write> ser::SerializeTupleVariant for 
SchemaAwareWriteSerializeTupleStruct<'_, '_, W> {
     type Ok = usize;
     type Error = Error;
 
@@ -473,7 +473,6 @@ pub struct SchemaAwareWriteSerializer<'s, W: Write> {
     root_schema: &'s Schema,
     names: &'s NamesRef<'s>,
     enclosing_namespace: Namespace,
-    schema_stack: LinkedList<&'s Schema>,
 }
 
 impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
@@ -497,7 +496,6 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
             root_schema: schema,
             names,
             enclosing_namespace,
-            schema_stack: Default::default(),
         }
     }
 
@@ -523,37 +521,25 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
 
         Ok(bytes_written)
     }
-}
-
-impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s, W> {
-    type Ok = usize;
-    type Error = Error;
-    type SerializeSeq = DirectSerializeSeq<'a, 's, W>;
-    type SerializeTuple = DirectSerializeSeq<'a, 's, W>;
-    type SerializeTupleStruct = DirectSerializeTupleStruct<'a, 's, W>;
-    type SerializeTupleVariant = DirectSerializeTupleStruct<'a, 's, W>;
-    type SerializeMap = DirectSerializeMap<'a, 's, W>;
-    type SerializeStruct = DirectSerializeStruct<'a, 's, W>;
-    type SerializeStructVariant = DirectSerializeStruct<'a, 's, W>;
-
-    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
 
+    fn serialize_bool_with_schema(&mut self, value: bool, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "bool",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
-            Schema::Boolean => 
self.writer.write(&[u8::from(v)]).map_err(Error::WriteBytes),
+            Schema::Boolean => self
+                .writer
+                .write(&[u8::from(value)])
+                .map_err(Error::WriteBytes),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
                         Schema::Boolean => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_bool(v);
+                            return self.serialize_bool_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -567,25 +553,15 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
-        self.serialize_i32(v as i32)
-    }
-
-    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
-        self.serialize_i32(v as i32)
-    }
-
-    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_i32_with_schema(&mut self, value: i32, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "int (i8 | i16 | i32)",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
-            Schema::Int | Schema::TimeMillis | Schema::Date => encode_int(v, 
&mut self.writer),
+            Schema::Int | Schema::TimeMillis | Schema::Date => 
encode_int(value, &mut self.writer),
             Schema::Long
             | Schema::TimeMicros
             | Schema::TimestampMillis
@@ -593,7 +569,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             | Schema::TimestampNanos
             | Schema::LocalTimestampMillis
             | Schema::LocalTimestampMicros
-            | Schema::LocalTimestampNanos => encode_long(v as i64, &mut 
self.writer),
+            | Schema::LocalTimestampNanos => encode_long(value as i64, &mut 
self.writer),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
@@ -609,8 +585,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::LocalTimestampMicros
                         | Schema::LocalTimestampNanos => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_i32(v);
+                            return self.serialize_i32_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -623,19 +598,17 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_i64_with_schema(&mut self, value: i64, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "i64",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Int | Schema::TimeMillis | Schema::Date => {
                 let int_value =
-                    i32::try_from(v).map_err(|cause| 
create_error(cause.to_string()))?;
+                    i32::try_from(value).map_err(|cause| 
create_error(cause.to_string()))?;
                 encode_int(int_value, &mut self.writer)
             }
             Schema::Long
@@ -645,7 +618,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             | Schema::TimestampNanos
             | Schema::LocalTimestampMillis
             | Schema::LocalTimestampMicros
-            | Schema::LocalTimestampNanos => encode_long(v, &mut self.writer),
+            | Schema::LocalTimestampNanos => encode_long(value, &mut 
self.writer),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
@@ -661,8 +634,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::LocalTimestampMicros
                         | Schema::LocalTimestampNanos => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_i64(v);
+                            return self.serialize_i64_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -676,18 +648,16 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_u8_with_schema(&mut self, value: u8, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "u8",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Int | Schema::TimeMillis | Schema::Date => {
-                encode_int(v as i32, &mut self.writer)
+                encode_int(value as i32, &mut self.writer)
             }
             Schema::Long
             | Schema::TimeMicros
@@ -696,8 +666,8 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             | Schema::TimestampNanos
             | Schema::LocalTimestampMillis
             | Schema::LocalTimestampMicros
-            | Schema::LocalTimestampNanos => encode_long(v as i64, &mut 
self.writer),
-            Schema::Bytes => self.write_bytes(&[v]),
+            | Schema::LocalTimestampNanos => encode_long(value as i64, &mut 
self.writer),
+            Schema::Bytes => self.write_bytes(&[value]),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
@@ -714,8 +684,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::LocalTimestampNanos
                         | Schema::Bytes => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_u8(v);
+                            return self.serialize_u8_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -726,23 +695,17 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
-        self.serialize_u32(v as u32)
-    }
-
-    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_u32_with_schema(&mut self, value: u32, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "unsigned int (u16 | u32)",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Int | Schema::TimeMillis | Schema::Date => {
                 let int_value =
-                    i32::try_from(v).map_err(|cause| 
create_error(cause.to_string()))?;
+                    i32::try_from(value).map_err(|cause| 
create_error(cause.to_string()))?;
                 encode_int(int_value, &mut self.writer)
             }
             Schema::Long
@@ -752,7 +715,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             | Schema::TimestampNanos
             | Schema::LocalTimestampMillis
             | Schema::LocalTimestampMicros
-            | Schema::LocalTimestampNanos => encode_long(v as i64, &mut 
self.writer),
+            | Schema::LocalTimestampNanos => encode_long(value as i64, &mut 
self.writer),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
@@ -768,8 +731,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::LocalTimestampMicros
                         | Schema::LocalTimestampNanos => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_u32(v);
+                            return self.serialize_u32_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -782,19 +744,17 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_u64_with_schema(&mut self, value: u64, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "u64",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Int | Schema::TimeMillis | Schema::Date => {
                 let int_value =
-                    i32::try_from(v).map_err(|cause| 
create_error(cause.to_string()))?;
+                    i32::try_from(value).map_err(|cause| 
create_error(cause.to_string()))?;
                 encode_int(int_value, &mut self.writer)
             }
             Schema::Long
@@ -806,7 +766,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             | Schema::LocalTimestampMicros
             | Schema::LocalTimestampNanos => {
                 let long_value =
-                    i64::try_from(v).map_err(|cause| 
create_error(cause.to_string()))?;
+                    i64::try_from(value).map_err(|cause| 
create_error(cause.to_string()))?;
                 encode_long(long_value, &mut self.writer)
             }
             Schema::Union(union_schema) => {
@@ -824,8 +784,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::LocalTimestampMicros
                         | Schema::LocalTimestampNanos => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_u64(v);
+                            return self.serialize_u64_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -839,31 +798,28 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_f32_with_schema(&mut self, value: f32, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "f32",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Float => self
                 .writer
-                .write(&v.to_le_bytes())
+                .write(&value.to_le_bytes())
                 .map_err(Error::WriteBytes),
             Schema::Double => self
                 .writer
-                .write(&(v as f64).to_le_bytes())
+                .write(&(value as f64).to_le_bytes())
                 .map_err(Error::WriteBytes),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
                         Schema::Float | Schema::Double => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_f32(v);
+                            return self.serialize_f32_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -877,31 +833,28 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_f64_with_schema(&mut self, value: f64, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "f64",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
             Schema::Float => self
                 .writer
-                .write(&(v as f32).to_le_bytes())
+                .write(&(value as f32).to_le_bytes())
                 .map_err(Error::WriteBytes),
             Schema::Double => self
                 .writer
-                .write(&v.to_le_bytes())
+                .write(&value.to_le_bytes())
                 .map_err(Error::WriteBytes),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
                         Schema::Float | Schema::Double => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_f64(v);
+                            return self.serialize_f64_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -915,24 +868,21 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_char_with_schema(&mut self, value: char, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "char",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
-            Schema::String | Schema::Bytes => 
self.write_bytes(String::from(v).as_bytes()),
+            Schema::String | Schema::Bytes => 
self.write_bytes(String::from(value).as_bytes()),
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
                         Schema::String | Schema::Bytes => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_char(v);
+                            return self.serialize_char_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -945,39 +895,38 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_str_with_schema(&mut self, value: &str, schema: &Schema) -> 
Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "string",
-            value: format!("{v}. Cause: {cause}"),
+            value: format!("{value}. Cause: {cause}"),
             schema: schema.clone(),
         };
 
         match schema {
-            Schema::String | Schema::Bytes | Schema::Uuid => 
self.write_bytes(v.as_bytes()),
+            Schema::String | Schema::Bytes | Schema::Uuid => 
self.write_bytes(value.as_bytes()),
             Schema::BigDecimal => {
                 // If we get a string for a `BigDecimal` type, expect a 
display string representation, such as "12.75"
                 let decimal_val =
-                    BigDecimal::from_str(v).map_err(|e| 
create_error(e.to_string()))?;
+                    BigDecimal::from_str(value).map_err(|e| 
create_error(e.to_string()))?;
                 let decimal_bytes = big_decimal_as_bytes(&decimal_val)?;
                 self.write_bytes(decimal_bytes.as_slice())
             }
             Schema::Fixed(fixed_schema) => {
-                if v.len() == fixed_schema.size {
-                    self.writer.write(v.as_bytes()).map_err(Error::WriteBytes)
+                if value.len() == fixed_schema.size {
+                    self.writer
+                        .write(value.as_bytes())
+                        .map_err(Error::WriteBytes)
                 } else {
                     Err(create_error(format!(
                         "Fixed schema size ({}) does not match the value 
length ({})",
                         fixed_schema.size,
-                        v.len()
+                        value.len()
                     )))
                 }
             }
             Schema::Ref { name } => {
                 let ref_schema = self.get_ref_schema(name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_str(v)
+                self.serialize_str_with_schema(value, ref_schema)
             }
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
@@ -988,8 +937,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::Fixed(_)
                         | Schema::Ref { name: _ } => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_str(v);
+                            return self.serialize_str_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1003,13 +951,15 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_bytes_with_schema(
+        &mut self,
+        value: &[u8],
+        schema: &Schema,
+    ) -> Result<usize, Error> {
         let create_error = |cause: String| {
             use std::fmt::Write;
-            let mut v_str = String::with_capacity(v.len());
-            for b in v {
+            let mut v_str = String::with_capacity(value.len());
+            for b in value {
                 if write!(&mut v_str, "{:x}", b).is_err() {
                     v_str.push_str("??");
                 }
@@ -1023,47 +973,46 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
 
         match schema {
             Schema::String | Schema::Bytes | Schema::Uuid | Schema::BigDecimal 
=> {
-                self.write_bytes(v)
+                self.write_bytes(value)
             }
             Schema::Fixed(fixed_schema) => {
-                if v.len() == fixed_schema.size {
-                    self.writer.write(v).map_err(Error::WriteBytes)
+                if value.len() == fixed_schema.size {
+                    self.writer.write(value).map_err(Error::WriteBytes)
                 } else {
-                    Err(create_error(format!("Fixed schema size ({}) does not 
match the value length ({})", fixed_schema.size, v.len())))
+                    Err(create_error(format!("Fixed schema size ({}) does not 
match the value length ({})", fixed_schema.size, value.len())))
                 }
             }
             Schema::Duration => {
-                if v.len() == 12 {
-                    self.writer.write(v).map_err(Error::WriteBytes)
+                if value.len() == 12 {
+                    self.writer.write(value).map_err(Error::WriteBytes)
                 } else {
-                    Err(create_error(format!("Duration length must be 12! Got 
({})", v.len())))
+                    Err(create_error(format!("Duration length must be 12! Got 
({})", value.len())))
                 }
             }
             Schema::Decimal(decimal_schema) => match 
decimal_schema.inner.as_ref() {
-                Schema::Bytes => self.write_bytes(v),
-                Schema::Fixed(fixed_schema) => match 
fixed_schema.size.checked_sub(v.len()) {
+                Schema::Bytes => self.write_bytes(value),
+                Schema::Fixed(fixed_schema) => match 
fixed_schema.size.checked_sub(value.len()) {
                     Some(pad) => {
-                        let pad_val = match v.len() {
+                        let pad_val = match value.len() {
                             0 => 0,
-                            _ => v[0],
+                            _ => value[0],
                         };
                         let padding = vec![pad_val; pad];
                         self.writer
                             .write(padding.as_slice())
                             .map_err(Error::WriteBytes)?;
-                        self.writer.write(v).map_err(Error::WriteBytes)
+                        self.writer.write(value).map_err(Error::WriteBytes)
                     }
                     None => Err(Error::CompareFixedSizes {
                         size: fixed_schema.size,
-                        n: v.len(),
+                        n: value.len(),
                     }),
                 },
                 unsupported => Err(create_error(format!("Decimal schema's 
inner should be Bytes or Fixed schema. Got: {unsupported}"))),
             },
             Schema::Ref { name } => {
                 let ref_schema = self.get_ref_schema(name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_bytes(v)
+                self.serialize_bytes_with_schema(value, ref_schema)
             }
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
@@ -1077,8 +1026,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         | Schema::Decimal(_)
                         | Schema::Ref { name: _ } => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_bytes(v);
+                            return self.serialize_bytes_with_schema(value, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1089,9 +1037,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_none_with_schema(&mut self, schema: &Schema) -> Result<usize, 
Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "none",
             value: format!("None. Cause: {cause}"),
@@ -1118,12 +1064,10 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
+    fn serialize_some_with_schema<T>(&mut self, value: &T, schema: &Schema) -> 
Result<usize, Error>
     where
         T: ?Sized + ser::Serialize,
     {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "some",
             value: format!("Some(?). Cause: {cause}"),
@@ -1137,8 +1081,13 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         Schema::Null => { /* skip */ }
                         _ => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return value.serialize(self);
+                            let mut variant_ser = 
SchemaAwareWriteSerializer::new(
+                                &mut *self.writer,
+                                variant_schema,
+                                self.names,
+                                self.enclosing_namespace.clone(),
+                            );
+                            return value.serialize(&mut variant_ser);
                         }
                     }
                 }
@@ -1151,13 +1100,11 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
-        self.serialize_none()
-    }
-
-    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, 
Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_unit_struct_with_schema(
+        &mut self,
+        name: &'static str,
+        schema: &Schema,
+    ) -> Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "unit struct",
             value: format!("{name}. Cause: {cause}"),
@@ -1175,21 +1122,18 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
             Schema::Null => Ok(0),
             Schema::Ref { name: ref_name } => {
                 let ref_schema = self.get_ref_schema(ref_name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_unit_struct(name)
+                self.serialize_unit_struct_with_schema(name, ref_schema)
             }
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
                     match variant_schema {
                         Schema::Record(record_schema) if 
record_schema.fields.is_empty() => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_unit_struct(name);
+                            return 
self.serialize_unit_struct_with_schema(name, variant_schema);
                         }
                         Schema::Null | Schema::Ref { name: _ } => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_unit_struct(name);
+                            return 
self.serialize_unit_struct_with_schema(name, variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1204,14 +1148,13 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_unit_variant(
-        self,
+    fn serialize_unit_variant_with_schema(
+        &mut self,
         name: &'static str,
         variant_index: u32,
         variant: &'static str,
-    ) -> Result<Self::Ok, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+        schema: &Schema,
+    ) -> Result<usize, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "unit variant",
             value: format!("{name}::{variant} (index={variant_index}). Cause: 
{cause}"),
@@ -1240,14 +1183,14 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                 }
 
                 encode_int(variant_index as i32, &mut self.writer)?;
-                self.schema_stack
-                    .push_back(&union_schema.schemas[variant_index as usize]);
-                self.serialize_unit_struct(name)
+                self.serialize_unit_struct_with_schema(
+                    name,
+                    &union_schema.schemas[variant_index as usize],
+                )
             }
             Schema::Ref { name: ref_name } => {
                 let ref_schema = self.get_ref_schema(ref_name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_unit_variant(name, variant_index, variant)
+                self.serialize_unit_variant_with_schema(name, variant_index, 
variant, ref_schema)
             }
             unsupported => Err(create_error(format!(
                 "Unsupported schema: {:?}. Expected: Enum, Union or Ref",
@@ -1256,30 +1199,36 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_newtype_struct<T>(
-        self,
+    fn serialize_newtype_struct_with_schema<T>(
+        &mut self,
         _name: &'static str,
         value: &T,
-    ) -> Result<Self::Ok, Self::Error>
+        schema: &Schema,
+    ) -> Result<usize, Error>
     where
         T: ?Sized + ser::Serialize,
     {
+        let mut inner_ser = SchemaAwareWriteSerializer::new(
+            &mut *self.writer,
+            schema,
+            self.names,
+            self.enclosing_namespace.clone(),
+        );
         // Treat any newtype struct as a transparent wrapper around the 
contained type
-        value.serialize(self)
+        value.serialize(&mut inner_ser)
     }
 
-    fn serialize_newtype_variant<T>(
-        self,
+    fn serialize_newtype_variant_with_schema<T>(
+        &mut self,
         name: &'static str,
         variant_index: u32,
         variant: &'static str,
         value: &T,
-    ) -> Result<Self::Ok, Self::Error>
+        schema: &Schema,
+    ) -> Result<usize, Error>
     where
         T: ?Sized + ser::Serialize,
     {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "newtype variant",
             value: format!("{name}::{variant}(?) (index={variant_index}). 
Cause: {cause}"),
@@ -1298,8 +1247,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     })?;
 
                 encode_int(variant_index as i32, &mut self.writer)?;
-                self.schema_stack.push_back(variant_schema);
-                self.serialize_newtype_struct(variant, value)
+                self.serialize_newtype_struct_with_schema(variant, value, 
variant_schema)
             }
             _ => Err(create_error(format!(
                 "Expected Union schema. Got: {schema}"
@@ -1307,9 +1255,11 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, 
Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_seq_with_schema<'a>(
+        &'a mut self,
+        len: Option<usize>,
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeSeq<'a, 's, W>, Error> {
         let create_error = |cause: String| {
             let len_str = len
                 .map(|l| format!("{l}"))
@@ -1323,7 +1273,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         };
 
         match schema {
-            Schema::Array(array_schema) => Ok(DirectSerializeSeq::new(
+            Schema::Array(array_schema) => 
Ok(SchemaAwareWriteSerializeSeq::new(
                 self,
                 array_schema.items.as_ref(),
                 len,
@@ -1333,8 +1283,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     match variant_schema {
                         Schema::Array(_) => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_seq(len);
+                            return self.serialize_seq_with_schema(len, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1347,9 +1296,11 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, 
Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_tuple_with_schema<'a>(
+        &'a mut self,
+        len: usize,
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeSeq<'a, 's, W>, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "tuple",
             value: format!("tuple (len={len}). Cause: {cause}"),
@@ -1357,7 +1308,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         };
 
         match schema {
-            Schema::Array(array_schema) => Ok(DirectSerializeSeq::new(
+            Schema::Array(array_schema) => 
Ok(SchemaAwareWriteSerializeSeq::new(
                 self,
                 array_schema.items.as_ref(),
                 Some(len),
@@ -1367,8 +1318,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     match variant_schema {
                         Schema::Array(_) => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_tuple(len);
+                            return self.serialize_tuple_with_schema(len, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1381,13 +1331,12 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_tuple_struct(
-        self,
+    fn serialize_tuple_struct_with_schema<'a>(
+        &'a mut self,
         name: &'static str,
         len: usize,
-    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeTupleStruct<'a, 's, W>, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "tuple struct",
             value: format!(
@@ -1398,18 +1347,15 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         };
 
         match schema {
-            Schema::Array(sch) => 
Ok(DirectSerializeTupleStruct::Array(DirectSerializeSeq::new(
-                self,
-                &sch.items,
-                Some(len),
-            ))),
-            Schema::Record(sch) => Ok(DirectSerializeTupleStruct::Record(
-                DirectSerializeStruct::new(self, sch, len),
+            Schema::Array(sch) => 
Ok(SchemaAwareWriteSerializeTupleStruct::Array(
+                SchemaAwareWriteSerializeSeq::new(self, &sch.items, Some(len)),
+            )),
+            Schema::Record(sch) => 
Ok(SchemaAwareWriteSerializeTupleStruct::Record(
+                SchemaAwareWriteSerializeStruct::new(self, sch, len),
             )),
             Schema::Ref { name: ref_name } => {
                 let ref_schema = self.get_ref_schema(ref_name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_tuple_struct(name, len)
+                self.serialize_tuple_struct_with_schema(name, len, ref_schema)
             }
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
@@ -1417,14 +1363,20 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                         Schema::Record(inner) => {
                             if inner.fields.len() == len {
                                 encode_int(i as i32, &mut *self.writer)?;
-                                self.schema_stack.push_back(variant_schema);
-                                return self.serialize_tuple_struct(name, len);
+                                return self.serialize_tuple_struct_with_schema(
+                                    name,
+                                    len,
+                                    variant_schema,
+                                );
                             }
                         }
                         Schema::Array(_) | Schema::Ref { name: _ } => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_tuple_struct(name, len);
+                            return self.serialize_tuple_struct_with_schema(
+                                name,
+                                len,
+                                variant_schema,
+                            );
                         }
                         _ => { /* skip */ }
                     }
@@ -1439,15 +1391,14 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_tuple_variant(
-        self,
+    fn serialize_tuple_variant_with_schema<'a>(
+        &'a mut self,
         name: &'static str,
         variant_index: u32,
         variant: &'static str,
         len: usize,
-    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeTupleStruct<'a, 's, W>, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "tuple variant",
             value: format!(
@@ -1469,8 +1420,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     })?;
 
                 encode_int(variant_index as i32, &mut self.writer)?;
-                self.schema_stack.push_back(variant_schema);
-                self.serialize_tuple_struct(variant, len)
+                self.serialize_tuple_struct_with_schema(variant, len, 
variant_schema)
             }
             _ => Err(create_error(format!(
                 "Expected Union schema. Got: {schema}"
@@ -1478,9 +1428,11 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, 
Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+    fn serialize_map_with_schema<'a>(
+        &'a mut self,
+        len: Option<usize>,
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeMap<'a, 's, W>, Error> {
         let create_error = |cause: String| {
             let len_str = len
                 .map(|l| format!("{}", l))
@@ -1494,7 +1446,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         };
 
         match schema {
-            Schema::Map(map_schema) => Ok(DirectSerializeMap::new(
+            Schema::Map(map_schema) => Ok(SchemaAwareWriteSerializeMap::new(
                 self,
                 map_schema.types.as_ref(),
                 len,
@@ -1504,8 +1456,7 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     match variant_schema {
                         Schema::Map(_) => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_map(len);
+                            return self.serialize_map_with_schema(len, 
variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1520,13 +1471,12 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_struct(
-        self,
+    fn serialize_struct_with_schema<'a>(
+        &'a mut self,
         name: &'static str,
         len: usize,
-    ) -> Result<Self::SerializeStruct, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeStruct<'a, 's, W>, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "struct",
             value: format!("{name}{{ ... }}. Cause: {cause}"),
@@ -1534,13 +1484,14 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         };
 
         match schema {
-            Schema::Record(record_schema) => {
-                Ok(DirectSerializeStruct::new(self, record_schema, len))
-            }
+            Schema::Record(record_schema) => 
Ok(SchemaAwareWriteSerializeStruct::new(
+                self,
+                record_schema,
+                len,
+            )),
             Schema::Ref { name: ref_name } => {
                 let ref_schema = self.get_ref_schema(ref_name)?;
-                self.schema_stack.push_back(ref_schema);
-                self.serialize_struct(name, len)
+                self.serialize_struct_with_schema(name, len, ref_schema)
             }
             Schema::Union(union_schema) => {
                 for (i, variant_schema) in 
union_schema.schemas.iter().enumerate() {
@@ -1549,13 +1500,11 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                             if inner.fields.len() == len && inner.name.name == 
name =>
                         {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_struct(name, len);
+                            return self.serialize_struct_with_schema(name, 
len, variant_schema);
                         }
                         Schema::Ref { name: _ } => {
                             encode_int(i as i32, &mut *self.writer)?;
-                            self.schema_stack.push_back(variant_schema);
-                            return self.serialize_struct(name, len);
+                            return self.serialize_struct_with_schema(name, 
len, variant_schema);
                         }
                         _ => { /* skip */ }
                     }
@@ -1570,15 +1519,14 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
         }
     }
 
-    fn serialize_struct_variant(
-        self,
+    fn serialize_struct_variant_with_schema<'a>(
+        &'a mut self,
         name: &'static str,
         variant_index: u32,
         variant: &'static str,
         len: usize,
-    ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        let schema = self.schema_stack.pop_back().unwrap_or(self.root_schema);
-
+        schema: &'s Schema,
+    ) -> Result<SchemaAwareWriteSerializeStruct<'a, 's, W>, Error> {
         let create_error = |cause: String| Error::SerializeValueWithSchema {
             value_type: "struct variant",
             value: format!("{name}::{variant}{{ ... }} (size={len}. Cause: 
{cause})"),
@@ -1597,14 +1545,199 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s
                     })?;
 
                 encode_int(variant_index as i32, &mut self.writer)?;
-                self.schema_stack.push_back(variant_schema);
-                self.serialize_struct(variant, len)
+                self.serialize_struct_with_schema(variant, len, variant_schema)
             }
             _ => Err(create_error(format!(
                 "Expected Union schema. Got: {schema}"
             ))),
         }
     }
+}
+
+impl<'a, 's, W: Write> ser::Serializer for &'a mut 
SchemaAwareWriteSerializer<'s, W> {
+    type Ok = usize;
+    type Error = Error;
+    type SerializeSeq = SchemaAwareWriteSerializeSeq<'a, 's, W>;
+    type SerializeTuple = SchemaAwareWriteSerializeSeq<'a, 's, W>;
+    type SerializeTupleStruct = SchemaAwareWriteSerializeTupleStruct<'a, 's, 
W>;
+    type SerializeTupleVariant = SchemaAwareWriteSerializeTupleStruct<'a, 's, 
W>;
+    type SerializeMap = SchemaAwareWriteSerializeMap<'a, 's, W>;
+    type SerializeStruct = SchemaAwareWriteSerializeStruct<'a, 's, W>;
+    type SerializeStructVariant = SchemaAwareWriteSerializeStruct<'a, 's, W>;
+
+    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
+        self.serialize_bool_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
+        self.serialize_i32(v as i32)
+    }
+
+    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
+        self.serialize_i32(v as i32)
+    }
+
+    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
+        self.serialize_i32_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
+        self.serialize_i64_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
+        self.serialize_u8_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
+        self.serialize_u32(v as u32)
+    }
+
+    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
+        self.serialize_u32_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
+        self.serialize_u64_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
+        self.serialize_f32_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
+        self.serialize_f64_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
+        self.serialize_char_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
+        self.serialize_str_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
+        self.serialize_bytes_with_schema(v, self.root_schema)
+    }
+
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        self.serialize_none_with_schema(self.root_schema)
+    }
+
+    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        self.serialize_some_with_schema(value, self.root_schema)
+    }
+
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        self.serialize_none()
+    }
+
+    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, 
Self::Error> {
+        self.serialize_unit_struct_with_schema(name, self.root_schema)
+    }
+
+    fn serialize_unit_variant(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+    ) -> Result<Self::Ok, Self::Error> {
+        self.serialize_unit_variant_with_schema(name, variant_index, variant, 
self.root_schema)
+    }
+
+    fn serialize_newtype_struct<T>(
+        self,
+        name: &'static str,
+        value: &T,
+    ) -> Result<Self::Ok, Self::Error>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        self.serialize_newtype_struct_with_schema(name, value, 
self.root_schema)
+    }
+
+    fn serialize_newtype_variant<T>(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        value: &T,
+    ) -> Result<Self::Ok, Self::Error>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        self.serialize_newtype_variant_with_schema(
+            name,
+            variant_index,
+            variant,
+            value,
+            self.root_schema,
+        )
+    }
+
+    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, 
Self::Error> {
+        self.serialize_seq_with_schema(len, self.root_schema)
+    }
+
+    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, 
Self::Error> {
+        self.serialize_tuple_with_schema(len, self.root_schema)
+    }
+
+    fn serialize_tuple_struct(
+        self,
+        name: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+        self.serialize_tuple_struct_with_schema(name, len, self.root_schema)
+    }
+
+    fn serialize_tuple_variant(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+        self.serialize_tuple_variant_with_schema(
+            name,
+            variant_index,
+            variant,
+            len,
+            self.root_schema,
+        )
+    }
+
+    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, 
Self::Error> {
+        self.serialize_map_with_schema(len, self.root_schema)
+    }
+
+    fn serialize_struct(
+        self,
+        name: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeStruct, Self::Error> {
+        self.serialize_struct_with_schema(name, len, self.root_schema)
+    }
+
+    fn serialize_struct_variant(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeStructVariant, Self::Error> {
+        self.serialize_struct_variant_with_schema(
+            name,
+            variant_index,
+            variant,
+            len,
+            self.root_schema,
+        )
+    }
 
     fn is_human_readable(&self) -> bool {
         crate::util::is_human_readable()

Reply via email to