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()