diff --git a/Cargo.lock b/Cargo.lock index ac864b45..72e9b567 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,6 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "serial_test", "sha2", "snap", "strum", @@ -494,83 +493,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -702,16 +624,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.27" @@ -814,47 +726,12 @@ version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pin-project-lite" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.31" @@ -969,15 +846,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "redox_syscall" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.11.1" @@ -1081,27 +949,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scc" -version = "2.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b202022bb57c049555430e11fc22fea12909276a80a4c3d368da36ac1d88ed" -dependencies = [ - "sdd", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sdd" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c1eeaf4b6a87c7479688c6d52b9f1153cedd3c489300564f932b065c6eab95" - [[package]] name = "semver" version = "1.0.23" @@ -1149,31 +996,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serial_test" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" -dependencies = [ - "futures", - "log", - "once_cell", - "parking_lot", - "scc", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sha2" version = "0.10.9" @@ -1191,21 +1013,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - [[package]] name = "snap" version = "1.1.1" diff --git a/avro/Cargo.toml b/avro/Cargo.toml index 48337e91..6986cbfa 100644 --- a/avro/Cargo.toml +++ b/avro/Cargo.toml @@ -88,7 +88,6 @@ criterion = { default-features = false, version = "0.7.0" } hex-literal = { default-features = false, version = "1.0.0" } md-5 = { default-features = false, version = "0.10.6" } pretty_assertions = { default-features = false, version = "1.4.1", features = ["std"] } -serial_test = "3.2.0" sha2 = { default-features = false, version = "0.10.9" } paste = { default-features = false, version = "1.0.15" } rstest = { default-features = false, version = "0.26.1" } diff --git a/avro/src/de.rs b/avro/src/de.rs index 13021260..5b3013f0 100644 --- a/avro/src/de.rs +++ b/avro/src/de.rs @@ -766,15 +766,12 @@ mod tests { use num_bigint::BigInt; use pretty_assertions::assert_eq; use serde::{Deserialize, Serialize}; - use serial_test::serial; - use std::sync::atomic::Ordering; use uuid::Uuid; use apache_avro_test_helper::TestResult; - use crate::Decimal; - use super::*; + use crate::Decimal; #[derive(PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct StringEnum { @@ -1541,26 +1538,10 @@ mod tests { } #[test] - #[serial(serde_is_human_readable)] - fn avro_3747_human_readable_false() -> TestResult { - use serde::de::Deserializer as SerdeDeserializer; - - let is_human_readable = false; - crate::util::SERDE_HUMAN_READABLE.store(is_human_readable, Ordering::Release); - - let deser = &Deserializer::new(&Value::Null); - - assert_eq!(deser.is_human_readable(), is_human_readable); - - Ok(()) - } - - #[test] - #[serial(serde_is_human_readable)] fn avro_3747_human_readable_true() -> TestResult { use serde::de::Deserializer as SerdeDeserializer; - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); + assert!(crate::util::is_human_readable()); let deser = &Deserializer::new(&Value::Null); diff --git a/avro/src/schema.rs b/avro/src/schema.rs index 833ca30f..67526233 100644 --- a/avro/src/schema.rs +++ b/avro/src/schema.rs @@ -2637,14 +2637,12 @@ pub mod derive { #[cfg(test)] mod tests { use super::*; - use crate::{SpecificSingleObjectWriter, error::Details, rabin::Rabin}; + use crate::{error::Details, rabin::Rabin}; use apache_avro_test_helper::{ TestResult, logger::{assert_logged, assert_not_logged}, }; use serde_json::json; - use serial_test::serial; - use std::sync::atomic::Ordering; #[test] fn test_invalid_schema() { @@ -6704,55 +6702,6 @@ mod tests { Ok(()) } - #[test] - #[serial(serde_is_human_readable)] - fn avro_rs_53_uuid_with_fixed() -> TestResult { - #[derive(Debug, Serialize, Deserialize)] - struct Comment { - id: crate::Uuid, - } - - impl AvroSchema for Comment { - fn get_schema() -> Schema { - Schema::parse_str( - r#"{ - "type" : "record", - "name" : "Comment", - "fields" : [ { - "name" : "id", - "type" : { - "type" : "fixed", - "size" : 16, - "logicalType" : "uuid", - "name": "FixedUUID" - } - } ] - }"#, - ) - .expect("Invalid Comment Avro schema") - } - } - - let payload = Comment { - id: "de2df598-9948-4988-b00a-a41c0e287398".parse()?, - }; - let mut buffer = Vec::new(); - - // serialize the Uuid as String - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); - let bytes = SpecificSingleObjectWriter::::with_capacity(64)? - .write_ref(&payload, &mut buffer)?; - assert_eq!(bytes, 47); - - // serialize the Uuid as Bytes - crate::util::SERDE_HUMAN_READABLE.store(false, Ordering::Release); - let bytes = SpecificSingleObjectWriter::::with_capacity(64)? - .write_ref(&payload, &mut buffer)?; - assert_eq!(bytes, 27); - - Ok(()) - } - #[test] fn avro_3926_uuid_schema_for_fixed_with_size_16() -> TestResult { let schema = json!( diff --git a/avro/src/ser.rs b/avro/src/ser.rs index 8e6e595e..881073df 100644 --- a/avro/src/ser.rs +++ b/avro/src/ser.rs @@ -492,8 +492,6 @@ mod tests { use apache_avro_test_helper::TestResult; use pretty_assertions::assert_eq; use serde::{Deserialize, Serialize}; - use serial_test::serial; - use std::sync::atomic::Ordering; #[derive(Debug, Deserialize, Serialize, Clone)] struct Test { @@ -1021,23 +1019,10 @@ mod tests { } #[test] - #[serial(serde_is_human_readable)] - fn avro_3747_human_readable_false() { - use serde::ser::Serializer as SerdeSerializer; - - crate::util::SERDE_HUMAN_READABLE.store(false, Ordering::Release); - - let ser = &mut Serializer {}; - - assert_eq!(ser.is_human_readable(), false); - } - - #[test] - #[serial(serde_is_human_readable)] fn avro_3747_human_readable_true() { use serde::ser::Serializer as SerdeSerializer; - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); + assert!(crate::util::is_human_readable()); let ser = &mut Serializer {}; diff --git a/avro/src/ser_schema.rs b/avro/src/ser_schema.rs index e62d21d1..c68aa682 100644 --- a/avro/src/ser_schema.rs +++ b/avro/src/ser_schema.rs @@ -1773,11 +1773,9 @@ mod tests { use num_bigint::{BigInt, Sign}; use serde::Serialize; use serde_bytes::{ByteArray, Bytes}; - use serial_test::serial; use std::{ collections::{BTreeMap, HashMap}, marker::PhantomData, - sync::atomic::Ordering, }; use uuid::Uuid; @@ -2418,7 +2416,6 @@ mod tests { } #[test] - #[serial(serde_is_human_readable)] fn test_serialize_bigdecimal() -> TestResult { let schema = Schema::parse_str( r#"{ @@ -2427,7 +2424,7 @@ mod tests { }"#, )?; - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); + assert!(crate::util::is_human_readable()); let mut buffer: Vec = Vec::new(); let names = HashMap::new(); let mut serializer = SchemaAwareWriteSerializer::new(&mut buffer, &schema, &names, None); @@ -2441,7 +2438,6 @@ mod tests { } #[test] - #[serial(serde_is_human_readable)] fn test_serialize_uuid() -> TestResult { let schema = Schema::parse_str( r#"{ @@ -2450,7 +2446,7 @@ mod tests { }"#, )?; - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); + assert!(crate::util::is_human_readable()); let mut buffer: Vec = Vec::new(); let names = HashMap::new(); let mut serializer = SchemaAwareWriteSerializer::new(&mut buffer, &schema, &names, None); @@ -2718,7 +2714,6 @@ mod tests { } #[test] - #[serial(serde_is_human_readable)] // for BigDecimal and Uuid fn test_serialize_recursive_record() -> TestResult { let schema = Schema::parse_str( r#"{ @@ -2745,7 +2740,7 @@ mod tests { inner_record: Option>, } - crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release); + assert!(crate::util::is_human_readable()); let mut buffer: Vec = Vec::new(); let rs = ResolvedSchema::try_from(&schema)?; let mut serializer = diff --git a/avro/src/util.rs b/avro/src/util.rs index a751fcd5..d4074749 100644 --- a/avro/src/util.rs +++ b/avro/src/util.rs @@ -19,10 +19,7 @@ use crate::{AvroResult, error::Details, schema::Documentation}; use serde_json::{Map, Value}; use std::{ io::{Read, Write}, - sync::{ - Once, - atomic::{AtomicBool, AtomicUsize, Ordering}, - }, + sync::OnceLock, }; /// Maximum number of bytes that can be allocated when decoding @@ -30,15 +27,15 @@ use std::{ /// data, whose length field might be interpreted as enormous. /// See max_allocation_bytes to change this limit. pub const DEFAULT_MAX_ALLOCATION_BYTES: usize = 512 * 1024 * 1024; -static MAX_ALLOCATION_BYTES: AtomicUsize = AtomicUsize::new(DEFAULT_MAX_ALLOCATION_BYTES); -static MAX_ALLOCATION_BYTES_ONCE: Once = Once::new(); +static MAX_ALLOCATION_BYTES: OnceLock = OnceLock::new(); /// Whether to set serialization & deserialization traits /// as `human_readable` or not. /// See [set_serde_human_readable] to change this value. // crate-visible for testing -pub(crate) static SERDE_HUMAN_READABLE: AtomicBool = AtomicBool::new(true); -static SERDE_HUMAN_READABLE_ONCE: Once = Once::new(); +pub(crate) static SERDE_HUMAN_READABLE: OnceLock = OnceLock::new(); +/// Whether the serializer and deserializer should indicate to types that the format is human-readable. +pub const DEFAULT_SERDE_HUMAN_READABLE: bool = true; pub trait MapHelper { fn string(&self, key: &str) -> Option; @@ -144,18 +141,13 @@ fn decode_variable(reader: &mut R) -> AvroResult { Ok(i) } -/// Set a new maximum number of bytes that can be allocated when decoding data. -/// Once called, the limit cannot be changed. +/// Set the maximum number of bytes that can be allocated when decoding data. /// -/// **NOTE** This function must be called before decoding **any** data. The -/// library leverages [`std::sync::Once`](https://doc.rust-lang.org/std/sync/struct.Once.html) -/// to set the limit either when calling this method, or when decoding for -/// the first time. +/// This function only changes the setting once. On subsequent calls the value will stay the same +/// as the first time it is called. It is automatically called on first allocation and defaults to +/// [`DEFAULT_MAX_ALLOCATION_BYTES`]. pub fn max_allocation_bytes(num_bytes: usize) -> usize { - MAX_ALLOCATION_BYTES_ONCE.call_once(|| { - MAX_ALLOCATION_BYTES.store(num_bytes, Ordering::Release); - }); - MAX_ALLOCATION_BYTES.load(Ordering::Acquire) + *MAX_ALLOCATION_BYTES.get_or_init(|| num_bytes) } pub fn safe_len(len: usize) -> AvroResult { @@ -172,22 +164,20 @@ pub fn safe_len(len: usize) -> AvroResult { } } -/// Set whether serializing/deserializing is marked as human readable in serde traits. -/// This will adjust the return value of `is_human_readable()` for both. -/// Once called, the value cannot be changed. +/// Set whether the serializer and deserializer should indicate to types that the format is human-readable. /// -/// **NOTE** This function must be called before serializing/deserializing **any** data. The -/// library leverages [`std::sync::Once`](https://doc.rust-lang.org/std/sync/struct.Once.html) -/// to set the limit either when calling this method, or when decoding for -/// the first time. -pub fn set_serde_human_readable(human_readable: bool) { - SERDE_HUMAN_READABLE_ONCE.call_once(|| { - SERDE_HUMAN_READABLE.store(human_readable, Ordering::Release); - }); +/// This function only changes the setting once. On subsequent calls the value will stay the same +/// as the first time it is called. It is automatically called on first allocation and defaults to +/// [`DEFAULT_SERDE_HUMAN_READABLE`]. +/// +/// *NOTE*: Changing this setting can change the output of [`from_value`](crate::from_value) and the +/// accepted input of [`to_value`]. +pub fn set_serde_human_readable(human_readable: bool) -> bool { + *SERDE_HUMAN_READABLE.get_or_init(|| human_readable) } pub(crate) fn is_human_readable() -> bool { - SERDE_HUMAN_READABLE.load(Ordering::Acquire) + *SERDE_HUMAN_READABLE.get_or_init(|| DEFAULT_SERDE_HUMAN_READABLE) } #[cfg(test)] diff --git a/avro/tests/serde_human_readable_false.rs b/avro/tests/serde_human_readable_false.rs new file mode 100644 index 00000000..38333bd0 --- /dev/null +++ b/avro/tests/serde_human_readable_false.rs @@ -0,0 +1,45 @@ +use apache_avro::{AvroSchema, Schema, SpecificSingleObjectWriter}; +use apache_avro_test_helper::TestResult; +use serde::{Deserialize, Serialize}; + +#[test] +fn avro_rs_53_uuid_with_fixed() -> TestResult { + #[derive(Debug, Serialize, Deserialize)] + struct Comment { + id: apache_avro::Uuid, + } + + impl AvroSchema for Comment { + fn get_schema() -> Schema { + Schema::parse_str( + r#"{ + "type" : "record", + "name" : "Comment", + "fields" : [ { + "name" : "id", + "type" : { + "type" : "fixed", + "size" : 16, + "logicalType" : "uuid", + "name": "FixedUUID" + } + } ] + }"#, + ) + .expect("Invalid Comment Avro schema") + } + } + + let payload = Comment { + id: "de2df598-9948-4988-b00a-a41c0e287398".parse()?, + }; + let mut buffer = Vec::new(); + + // serialize the Uuid as Bytes + assert!(!apache_avro::set_serde_human_readable(false)); + let bytes = SpecificSingleObjectWriter::::with_capacity(64)? + .write_ref(&payload, &mut buffer)?; + assert_eq!(bytes, 27); + + Ok(()) +} diff --git a/avro/tests/serde_human_readable_true.rs b/avro/tests/serde_human_readable_true.rs new file mode 100644 index 00000000..b89cf910 --- /dev/null +++ b/avro/tests/serde_human_readable_true.rs @@ -0,0 +1,45 @@ +use apache_avro::{AvroSchema, Schema, SpecificSingleObjectWriter}; +use apache_avro_test_helper::TestResult; +use serde::{Deserialize, Serialize}; + +#[test] +fn avro_rs_53_uuid_with_fixed_true() -> TestResult { + #[derive(Debug, Serialize, Deserialize)] + struct Comment { + id: apache_avro::Uuid, + } + + impl AvroSchema for Comment { + fn get_schema() -> Schema { + Schema::parse_str( + r#"{ + "type" : "record", + "name" : "Comment", + "fields" : [ { + "name" : "id", + "type" : { + "type" : "fixed", + "size" : 16, + "logicalType" : "uuid", + "name": "FixedUUID" + } + } ] + }"#, + ) + .expect("Invalid Comment Avro schema") + } + } + + let payload = Comment { + id: "de2df598-9948-4988-b00a-a41c0e287398".parse()?, + }; + let mut buffer = Vec::new(); + + // serialize the Uuid as String + assert!(apache_avro::set_serde_human_readable(true)); + let bytes = SpecificSingleObjectWriter::::with_capacity(64)? + .write_ref(&payload, &mut buffer)?; + assert_eq!(bytes, 47); + + Ok(()) +}