diff --git a/Cargo.lock b/Cargo.lock index 7bef0b56..3c2c74eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "alloca" version = "0.4.0" @@ -65,6 +71,7 @@ dependencies = [ "md-5", "miniz_oxide 0.9.0", "num-bigint", + "ouroboros", "paste", "pretty_assertions", "quad-rand", @@ -594,6 +601,12 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -816,6 +829,30 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "ouroboros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" +dependencies = [ + "aliasable", + "ouroboros_macro", + "static_assertions", +] + +[[package]] +name = "ouroboros_macro" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + [[package]] name = "page_size" version = "0.6.0" @@ -888,6 +925,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + [[package]] name = "proptest" version = "1.9.0" @@ -1156,6 +1206,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -1174,7 +1230,7 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "syn", diff --git a/avro/Cargo.toml b/avro/Cargo.toml index 49c3c88d..08fcb6a5 100644 --- a/avro/Cargo.toml +++ b/avro/Cargo.toml @@ -62,6 +62,7 @@ digest = { default-features = false, version = "0.10.7", features = ["core-api"] miniz_oxide = { default-features = false, version = "0.9.0", features = ["with-alloc"] } log = { workspace = true } num-bigint = { default-features = false, version = "0.4.6", features = ["std", "serde"] } +ouroboros = { default-features = false, version = "0.18.5", features = ["std"] } regex-lite = { default-features = false, version = "0.1.8", features = ["std", "string"] } serde = { workspace = true } serde_bytes = { workspace = true } diff --git a/avro/examples/specific_single_object.rs b/avro/examples/specific_single_object.rs index fa756cf7..347721a6 100644 --- a/avro/examples/specific_single_object.rs +++ b/avro/examples/specific_single_object.rs @@ -32,7 +32,7 @@ fn main() -> Result<(), Box> { b: "foo".to_string(), }; - let mut writer = SpecificSingleObjectWriter::::with_capacity(1024)?; + let writer = SpecificSingleObjectWriter::::new()?; let reader = SpecificSingleObjectReader::::new()?; for test in repeat_n(test, 2) { diff --git a/avro/examples/test_interop_single_object_encoding.rs b/avro/examples/test_interop_single_object_encoding.rs index e65b35ea..e16c2218 100644 --- a/avro/examples/test_interop_single_object_encoding.rs +++ b/avro/examples/test_interop_single_object_encoding.rs @@ -65,7 +65,7 @@ fn main() -> Result<(), Box> { fn test_write(expected: &[u8]) { let mut encoded: Vec = Vec::new(); - apache_avro::SpecificSingleObjectWriter::::with_capacity(1024) + apache_avro::SpecificSingleObjectWriter::::new() .expect("Resolving failed") .write_value(InteropMessage, &mut encoded) .expect("Encoding failed"); diff --git a/avro/src/reader.rs b/avro/src/reader.rs index 967edb5e..fed35fea 100644 --- a/avro/src/reader.rs +++ b/avro/src/reader.rs @@ -226,21 +226,20 @@ impl<'r, R: Read> Block<'r, R> { }) .ok_or(Details::GetAvroSchemaFromMap)?; if !self.schemata.is_empty() { - let rs = ResolvedSchema::try_from(self.schemata.clone())?; - let names: Names = rs - .get_names() - .iter() - .map(|(name, schema)| (name.clone(), (*schema).clone())) - .collect(); - self.writer_schema = Schema::parse_with_names(&json, names)?; + let mut names = HashMap::new(); resolve_names_with_schemata( self.schemata.iter().copied(), - &mut self.names_refs, + &mut names, &None, + &HashMap::new(), )?; + self.names_refs = names.into_iter().map(|(n, s)| (n, s.clone())).collect(); + self.writer_schema = Schema::parse_with_names(&json, self.names_refs.clone())?; } else { self.writer_schema = Schema::parse(&json)?; - resolve_names(&self.writer_schema, &mut self.names_refs, &None)?; + let mut names = HashMap::new(); + resolve_names(&self.writer_schema, &mut names, &None, &HashMap::new())?; + self.names_refs = names.into_iter().map(|(n, s)| (n, s.clone())).collect(); } Ok(()) } diff --git a/avro/src/schema/resolve.rs b/avro/src/schema/resolve.rs index e82b87d4..61b2e984 100644 --- a/avro/src/schema/resolve.rs +++ b/avro/src/schema/resolve.rs @@ -17,11 +17,10 @@ use crate::error::Details; use crate::schema::{ - DecimalSchema, EnumSchema, FixedSchema, InnerDecimalSchema, Names, NamesRef, Namespace, - RecordSchema, UnionSchema, UuidSchema, + DecimalSchema, EnumSchema, FixedSchema, InnerDecimalSchema, NamesRef, Namespace, RecordSchema, + UnionSchema, UuidSchema, }; use crate::{AvroResult, Error, Schema}; -use std::borrow::Borrow; use std::collections::HashMap; #[derive(Debug)] @@ -31,8 +30,8 @@ pub struct ResolvedSchema<'s> { } impl<'s> ResolvedSchema<'s> { - pub fn get_schemata(&self) -> Vec<&'s Schema> { - self.schemata.clone() + pub fn get_schemata(&self) -> &[&'s Schema] { + &self.schemata } pub fn get_names(&self) -> &NamesRef<'s> { @@ -52,12 +51,7 @@ impl<'s> ResolvedSchema<'s> { /// These schemas will be resolved in order, so references to schemas later in the /// list is not supported. pub fn new_with_schemata(schemata: Vec<&'s Schema>) -> AvroResult { - let mut rs = ResolvedSchema { - names_ref: HashMap::new(), - schemata, - }; - rs.resolve(rs.get_schemata(), &None, None)?; - Ok(rs) + Self::new_with_known_schemata(schemata, &None, &HashMap::new()) } /// Creates `ResolvedSchema` with some already known schemas. @@ -68,83 +62,17 @@ impl<'s> ResolvedSchema<'s> { enclosing_namespace: &Namespace, known_schemata: &'n NamesRef<'n>, ) -> AvroResult { - let names = HashMap::new(); - let mut rs = ResolvedSchema { + let mut names = HashMap::new(); + resolve_names_with_schemata( + schemata_to_resolve.iter().copied(), + &mut names, + enclosing_namespace, + known_schemata, + )?; + Ok(ResolvedSchema { names_ref: names, schemata: schemata_to_resolve, - }; - rs.resolve(rs.get_schemata(), enclosing_namespace, Some(known_schemata))?; - Ok(rs) - } - - fn resolve<'n>( - &mut self, - schemata: Vec<&'s Schema>, - enclosing_namespace: &Namespace, - known_schemata: Option<&'n NamesRef<'n>>, - ) -> AvroResult<()> { - for schema in schemata { - match schema { - Schema::Array(schema) => { - self.resolve(vec![&schema.items], enclosing_namespace, known_schemata)? - } - Schema::Map(schema) => { - self.resolve(vec![&schema.types], enclosing_namespace, known_schemata)? - } - Schema::Union(UnionSchema { schemas, .. }) => { - for schema in schemas { - self.resolve(vec![schema], enclosing_namespace, known_schemata)? - } - } - Schema::Enum(EnumSchema { name, .. }) - | Schema::Fixed(FixedSchema { name, .. }) - | Schema::Uuid(UuidSchema::Fixed(FixedSchema { name, .. })) - | Schema::Decimal(DecimalSchema { - inner: InnerDecimalSchema::Fixed(FixedSchema { name, .. }), - .. - }) - | Schema::Duration(FixedSchema { name, .. }) => { - let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - if self - .names_ref - .insert(fully_qualified_name.clone(), schema) - .is_some() - { - return Err(Details::AmbiguousSchemaDefinition(fully_qualified_name).into()); - } - } - Schema::Record(RecordSchema { name, fields, .. }) => { - let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - if self - .names_ref - .insert(fully_qualified_name.clone(), schema) - .is_some() - { - return Err(Details::AmbiguousSchemaDefinition(fully_qualified_name).into()); - } else { - let record_namespace = fully_qualified_name.namespace; - for field in fields { - self.resolve(vec![&field.schema], &record_namespace, known_schemata)? - } - } - } - Schema::Ref { name } => { - let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - // first search for reference in current schemata, then look into external references. - if !self.names_ref.contains_key(&fully_qualified_name) { - let is_resolved_with_known_schemas = known_schemata - .as_ref() - .map(|names| names.contains_key(&fully_qualified_name)) - .unwrap_or(false); - if !is_resolved_with_known_schemas { - return Err(Details::SchemaResolutionError(fully_qualified_name).into()); - } - } - } - _ => (), - } - } - Ok(()) + }) } } @@ -164,26 +92,43 @@ impl<'s> TryFrom> for ResolvedSchema<'s> { } } -pub struct ResolvedOwnedSchema { - names: Names, +/// Implementation detail of [`ResolvedOwnedSchema`] +/// +/// This struct is self-referencing. The references in `names` point to `root_schema`. +/// This allows resolving an owned schema without having to clone all the named schemas. +#[ouroboros::self_referencing] +struct InnerResolvedOwnedSchema { root_schema: Schema, + #[borrows(root_schema)] + #[covariant] + names: NamesRef<'this>, +} + +/// A variant of [`ResolvedSchema`] that owns the schema +pub struct ResolvedOwnedSchema { + inner: InnerResolvedOwnedSchema, } impl ResolvedOwnedSchema { pub fn new(root_schema: Schema) -> AvroResult { - let mut rs = ResolvedOwnedSchema { - names: HashMap::new(), - root_schema, - }; - resolve_names(&rs.root_schema, &mut rs.names, &None)?; - Ok(rs) + Ok(Self { + inner: InnerResolvedOwnedSchemaTryBuilder { + root_schema, + names_builder: |schema: &Schema| { + let mut names = HashMap::new(); + resolve_names(schema, &mut names, &None, &HashMap::new())?; + Ok::<_, Error>(names) + }, + } + .try_build()?, + }) } pub fn get_root_schema(&self) -> &Schema { - &self.root_schema + self.inner.borrow_root_schema() } - pub fn get_names(&self) -> &Names { - &self.names + pub fn get_names(&self) -> &NamesRef<'_> { + self.inner.borrow_names() } } @@ -195,17 +140,25 @@ impl TryFrom for ResolvedOwnedSchema { } } -pub fn resolve_names( - schema: &Schema, - names: &mut Names, +/// Resolve all references in the schema, saving any named type found in `names` +/// +/// `known_schemata` will be used to resolve references but they won't be added to `names`. +pub fn resolve_names<'s, 'n>( + schema: &'s Schema, + names: &mut NamesRef<'s>, enclosing_namespace: &Namespace, + known_schemata: &NamesRef<'n>, ) -> AvroResult<()> { match schema { - Schema::Array(schema) => resolve_names(&schema.items, names, enclosing_namespace), - Schema::Map(schema) => resolve_names(&schema.types, names, enclosing_namespace), + Schema::Array(schema) => { + resolve_names(&schema.items, names, enclosing_namespace, known_schemata) + } + Schema::Map(schema) => { + resolve_names(&schema.types, names, enclosing_namespace, known_schemata) + } Schema::Union(UnionSchema { schemas, .. }) => { for schema in schemas { - resolve_names(schema, names, enclosing_namespace)? + resolve_names(schema, names, enclosing_namespace, known_schemata)? } Ok(()) } @@ -218,10 +171,7 @@ pub fn resolve_names( }) | Schema::Duration(FixedSchema { name, .. }) => { let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - if names - .insert(fully_qualified_name.clone(), schema.clone()) - .is_some() - { + if names.insert(fully_qualified_name.clone(), schema).is_some() { Err(Details::AmbiguousSchemaDefinition(fully_qualified_name).into()) } else { Ok(()) @@ -229,37 +179,38 @@ pub fn resolve_names( } Schema::Record(RecordSchema { name, fields, .. }) => { let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - if names - .insert(fully_qualified_name.clone(), schema.clone()) - .is_some() - { + if names.insert(fully_qualified_name.clone(), schema).is_some() { Err(Details::AmbiguousSchemaDefinition(fully_qualified_name).into()) } else { let record_namespace = fully_qualified_name.namespace; for field in fields { - resolve_names(&field.schema, names, &record_namespace)? + resolve_names(&field.schema, names, &record_namespace, known_schemata)? } Ok(()) } } Schema::Ref { name } => { let fully_qualified_name = name.fully_qualified_name(enclosing_namespace); - names - .get(&fully_qualified_name) - .map(|_| ()) - .ok_or_else(|| Details::SchemaResolutionError(fully_qualified_name).into()) + if names.contains_key(&fully_qualified_name) + || known_schemata.contains_key(&fully_qualified_name) + { + Ok(()) + } else { + Err(Details::SchemaResolutionError(fully_qualified_name).into()) + } } _ => Ok(()), } } -pub fn resolve_names_with_schemata( - schemata: impl IntoIterator>, - names: &mut Names, +pub fn resolve_names_with_schemata<'s, 'n>( + schemata: impl IntoIterator, + names: &mut NamesRef<'s>, enclosing_namespace: &Namespace, + known_schemata: &NamesRef<'n>, ) -> AvroResult<()> { for schema in schemata { - resolve_names(schema.borrow(), names, enclosing_namespace)?; + resolve_names(schema, names, enclosing_namespace, known_schemata)?; } Ok(()) } diff --git a/avro/src/writer.rs b/avro/src/writer.rs index 72f87d03..6bac42e3 100644 --- a/avro/src/writer.rs +++ b/avro/src/writer.rs @@ -21,7 +21,7 @@ use crate::{ encode::{encode, encode_internal, encode_to_vec}, error::Details, headers::{HeaderBuilder, RabinFingerprintHeader}, - schema::{Name, ResolvedOwnedSchema, ResolvedSchema, Schema}, + schema::{NamesRef, ResolvedOwnedSchema, ResolvedSchema, Schema}, serde::{AvroSchema, ser_schema::SchemaAwareWriteSerializer}, types::Value, }; @@ -594,8 +594,8 @@ pub struct SpecificSingleObjectWriter where T: AvroSchema, { - inner: GenericSingleObjectWriter, - schema: Schema, + resolved: ResolvedOwnedSchema, + header: Vec, _model: PhantomData, } @@ -603,11 +603,24 @@ impl SpecificSingleObjectWriter where T: AvroSchema, { - pub fn with_capacity(buffer_cap: usize) -> AvroResult> { + pub fn new() -> AvroResult { let schema = T::get_schema(); - Ok(SpecificSingleObjectWriter { - inner: GenericSingleObjectWriter::new_with_capacity(&schema, buffer_cap)?, - schema, + let header = RabinFingerprintHeader::from_schema(&schema).build_header(); + let resolved = ResolvedOwnedSchema::new(schema)?; + // We don't use Self::new_with_header_builder as that would mean calling T::get_schema() twice + Ok(Self { + resolved, + header, + _model: PhantomData, + }) + } + + pub fn new_with_header_builder(header_builder: impl HeaderBuilder) -> AvroResult { + let header = header_builder.build_header(); + let resolved = ResolvedOwnedSchema::new(T::get_schema())?; + Ok(Self { + resolved, + header, _model: PhantomData, }) } @@ -617,11 +630,19 @@ impl SpecificSingleObjectWriter where T: AvroSchema + Into, { - /// Write the `Into` to the provided Write object. Returns a result with the number - /// of bytes written including the header - pub fn write_value(&mut self, data: T, writer: &mut W) -> AvroResult { - let v: Value = data.into(); - self.inner.write_value_ref(&v, writer) + /// Write the value to the writer + /// + /// Returns the number of bytes written. + /// + /// Each call writes a complete single-object encoded message (header + data), + /// making each message independently decodable. + pub fn write_value(&self, data: T, writer: &mut W) -> AvroResult { + writer + .write_all(&self.header) + .map_err(Details::WriteBytes)?; + let value: Value = data.into(); + let bytes = write_value_ref_owned_resolved(&self.resolved, &value, writer)?; + Ok(bytes + self.header.len()) } } @@ -629,32 +650,34 @@ impl SpecificSingleObjectWriter where T: AvroSchema + Serialize, { - /// Write the referenced `Serialize` object to the provided `Write` object. + /// Write the object to the writer. /// /// Returns the number of bytes written. /// /// Each call writes a complete single-object encoded message (header + data), /// making each message independently decodable. - pub fn write_ref(&mut self, data: &T, writer: &mut W) -> AvroResult { - // Always write the header for each message (single object encoding requires - // each message to be independently decodable) + pub fn write_ref(&self, data: &T, writer: &mut W) -> AvroResult { writer - .write_all(self.inner.buffer.as_slice()) + .write_all(&self.header) .map_err(Details::WriteBytes)?; - let bytes_written = - self.inner.buffer.len() + write_avro_datum_ref(&self.schema, data, writer)?; + let bytes = write_avro_datum_ref( + self.resolved.get_root_schema(), + self.resolved.get_names(), + data, + writer, + )?; - Ok(bytes_written) + Ok(bytes + self.header.len()) } - /// Write the Serialize object to the provided Write object. + /// Write the object to the writer. /// /// Returns the number of bytes written. /// /// Each call writes a complete single-object encoded message (header + data), /// making each message independently decodable. - pub fn write(&mut self, data: T, writer: &mut W) -> AvroResult { + pub fn write(&self, data: T, writer: &mut W) -> AvroResult { self.write_ref(&data, writer) } } @@ -682,11 +705,11 @@ fn write_value_ref_resolved( } } -fn write_value_ref_owned_resolved( +fn write_value_ref_owned_resolved( resolved_schema: &ResolvedOwnedSchema, value: &Value, - buffer: &mut Vec, -) -> AvroResult<()> { + writer: &mut W, +) -> AvroResult { let root_schema = resolved_schema.get_root_schema(); if let Some(reason) = value.validate_internal( root_schema, @@ -705,9 +728,8 @@ fn write_value_ref_owned_resolved( root_schema, resolved_schema.get_names(), &root_schema.namespace(), - buffer, - )?; - Ok(()) + writer, + ) } /// Encode a compatible value (implementing the `ToAvro` trait) into Avro format, also @@ -730,13 +752,12 @@ pub fn to_avro_datum>(schema: &Schema, value: T) -> AvroResult( schema: &Schema, + names: &NamesRef, data: &T, writer: &mut W, ) -> AvroResult { - let names: HashMap = HashMap::new(); - let mut serializer = SchemaAwareWriteSerializer::new(writer, schema, &names, None); - let bytes_written = data.serialize(&mut serializer)?; - Ok(bytes_written) + let mut serializer = SchemaAwareWriteSerializer::new(writer, schema, names, None); + data.serialize(&mut serializer) } /// Encode a compatible value (implementing the `ToAvro` trait) into Avro format, also @@ -856,7 +877,7 @@ mod tests { zig_i64(3, &mut expected)?; expected.extend([b'f', b'o', b'o']); - let bytes = write_avro_datum_ref(&schema, &data, &mut writer)?; + let bytes = write_avro_datum_ref(&schema, &HashMap::new(), &data, &mut writer)?; assert_eq!(bytes, expected.len()); assert_eq!(writer, expected); @@ -1586,9 +1607,8 @@ mod tests { 1024, ) .expect("Should resolve schema"); - let mut specific_writer = - SpecificSingleObjectWriter::::with_capacity(1024) - .expect("Resolved should pass"); + let specific_writer = SpecificSingleObjectWriter::::new() + .expect("Resolved should pass"); specific_writer .write_ref(&obj1, &mut buf1) .expect("Serialization expected"); @@ -1734,4 +1754,49 @@ mod tests { Ok(()) } + + #[test] + fn avro_rs_439_specific_single_object_writer_ref() -> TestResult { + #[derive(Serialize)] + struct Recursive { + field: bool, + recurse: Option>, + } + + impl AvroSchema for Recursive { + fn get_schema() -> Schema { + Schema::parse_str( + r#"{ + "name": "Recursive", + "type": "record", + "fields": [ + { "name": "field", "type": "boolean" }, + { "name": "recurse", "type": ["null", "Recursive"] } + ] + }"#, + ) + .unwrap() + } + } + + let mut buffer = Vec::new(); + let writer = SpecificSingleObjectWriter::new()?; + + writer.write( + Recursive { + field: true, + recurse: Some(Box::new(Recursive { + field: false, + recurse: None, + })), + }, + &mut buffer, + )?; + assert_eq!( + buffer, + &[195, 1, 83, 223, 43, 26, 181, 179, 227, 224, 1, 2, 0, 0][..] + ); + + Ok(()) + } } diff --git a/avro/tests/serde_human_readable_false.rs b/avro/tests/serde_human_readable_false.rs index 9e87f52e..2f8be3fe 100644 --- a/avro/tests/serde_human_readable_false.rs +++ b/avro/tests/serde_human_readable_false.rs @@ -56,8 +56,7 @@ fn avro_rs_53_uuid_with_fixed() -> TestResult { // serialize the Uuid as Fixed assert!(!apache_avro::util::set_serde_human_readable(false)); - let bytes = SpecificSingleObjectWriter::::with_capacity(64)? - .write_ref(&payload, &mut buffer)?; + let bytes = SpecificSingleObjectWriter::::new()?.write_ref(&payload, &mut buffer)?; assert_eq!(bytes, 26); Ok(()) @@ -77,7 +76,7 @@ fn avro_rs_440_uuid_string() -> TestResult { let mut buffer = Vec::new(); assert!(!apache_avro::util::set_serde_human_readable(false)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; assert_eq!( writer.write(uuid, &mut buffer).unwrap_err().to_string(), "Failed to serialize value of type bytes using schema Uuid(String): 55e840e29b41d4a7164466554400. Cause: Expected a string, but got 16 bytes. Did you mean to use `Schema::Uuid(UuidSchema::Fixed)` or `utils::serde_set_human_readable(true)`?" @@ -100,7 +99,7 @@ fn avro_rs_440_uuid_bytes() -> TestResult { let mut buffer = Vec::new(); assert!(!apache_avro::util::set_serde_human_readable(false)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; writer.write(uuid, &mut buffer)?; assert_eq!( @@ -131,7 +130,7 @@ fn avro_rs_440_uuid_fixed() -> TestResult { let mut buffer = Vec::new(); assert!(!apache_avro::util::set_serde_human_readable(false)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; writer.write(uuid, &mut buffer)?; assert_eq!( diff --git a/avro/tests/serde_human_readable_true.rs b/avro/tests/serde_human_readable_true.rs index 960f72f7..182839e7 100644 --- a/avro/tests/serde_human_readable_true.rs +++ b/avro/tests/serde_human_readable_true.rs @@ -55,8 +55,7 @@ fn avro_rs_53_uuid_with_string_true() -> TestResult { // serialize the Uuid as String assert!(apache_avro::util::set_serde_human_readable(true)); - let bytes = SpecificSingleObjectWriter::::with_capacity(64)? - .write_ref(&payload, &mut buffer)?; + let bytes = SpecificSingleObjectWriter::::new()?.write_ref(&payload, &mut buffer)?; assert_eq!(bytes, 47); Ok(()) @@ -76,7 +75,7 @@ fn avro_rs_440_uuid_string() -> TestResult { let mut buffer = Vec::new(); assert!(apache_avro::util::set_serde_human_readable(true)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; writer.write(uuid, &mut buffer)?; assert_eq!( @@ -101,7 +100,7 @@ fn avro_rs_440_uuid_bytes() -> TestResult { let mut buffer = Vec::new(); assert!(apache_avro::util::set_serde_human_readable(true)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; assert_eq!( writer.write(uuid, &mut buffer).unwrap_err().to_string(), "Failed to serialize value of type string using schema Uuid(Bytes): 550e8400-e29b-41d4-a716-446655440000. Cause: Expected bytes but got a string. Did you mean to use `Schema::Uuid(UuidSchema::String)` or `utils::serde_set_human_readable(false)`?" @@ -127,7 +126,7 @@ fn avro_rs_440_uuid_fixed() -> TestResult { let mut buffer = Vec::new(); assert!(apache_avro::util::set_serde_human_readable(true)); - let mut writer = SpecificSingleObjectWriter::with_capacity(64)?; + let writer = SpecificSingleObjectWriter::new()?; assert_eq!( writer.write(uuid, &mut buffer).unwrap_err().to_string(), r#"Failed to serialize value of type string using schema Uuid(Fixed(FixedSchema { name: Name { name: "uuid", namespace: None }, aliases: None, doc: None, size: 16, default: None, attributes: {} })): 550e8400-e29b-41d4-a716-446655440000. Cause: Expected bytes but got a string. Did you mean to use `Schema::Uuid(UuidSchema::String)` or `utils::serde_set_human_readable(false)`?"#