diff --git a/doc/content/en/project/Contributors onboarding guide /_index.md b/doc/content/en/project/Contributors onboarding guide/_index.md similarity index 100% rename from doc/content/en/project/Contributors onboarding guide /_index.md rename to doc/content/en/project/Contributors onboarding guide/_index.md diff --git a/lang/rust/avro/src/de.rs b/lang/rust/avro/src/de.rs index a5bc14b4f00..cfac4d1563f 100644 --- a/lang/rust/avro/src/de.rs +++ b/lang/rust/avro/src/de.rs @@ -537,6 +537,10 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> { { self.deserialize_any(visitor) } + + fn is_human_readable(&self) -> bool { + crate::util::is_human_readable() + } } impl<'de> de::SeqAccess<'de> for SeqDeserializer<'de> { @@ -1220,4 +1224,36 @@ mod tests { assert_eq!(deserialized, reference); Ok(()) } + + #[test] + fn avro_3747_human_readable_false() -> TestResult<()> { + // AVRO-3747: set serde's is_human_readable to false + use serde::de::Deserializer as SerdeDeserializer; + + unsafe { + crate::util::SERDE_HUMAN_READABLE = false; + } + + let deser = Deserializer::new(&Value::Null); + + assert_eq!((&deser).is_human_readable(), false); + + Ok(()) + } + + #[test] + fn avro_3747_human_readable_true() -> TestResult<()> { + // AVRO-3747: set serde's is_human_readable to true + use serde::de::Deserializer as SerdeDeserializer; + + unsafe { + crate::util::SERDE_HUMAN_READABLE = true; + } + + let deser = Deserializer::new(&Value::Null); + + assert!((&deser).is_human_readable()); + + Ok(()) + } } diff --git a/lang/rust/avro/src/lib.rs b/lang/rust/avro/src/lib.rs index 2c6f46c07a3..af856e906f5 100644 --- a/lang/rust/avro/src/lib.rs +++ b/lang/rust/avro/src/lib.rs @@ -748,7 +748,7 @@ pub use reader::{ }; pub use schema::{AvroSchema, Schema}; pub use ser::to_value; -pub use util::max_allocation_bytes; +pub use util::{max_allocation_bytes, set_serde_human_readable}; pub use writer::{ to_avro_datum, to_avro_datum_schemata, GenericSingleObjectWriter, SpecificSingleObjectWriter, Writer, diff --git a/lang/rust/avro/src/ser.rs b/lang/rust/avro/src/ser.rs index c85c8c4d3ee..1c7718ba724 100644 --- a/lang/rust/avro/src/ser.rs +++ b/lang/rust/avro/src/ser.rs @@ -283,6 +283,10 @@ impl<'b> ser::Serializer for &'b mut Serializer { ) -> Result { Ok(StructVariantSerializer::new(index, variant, len)) } + + fn is_human_readable(&self) -> bool { + crate::util::is_human_readable() + } } impl ser::SerializeSeq for SeqSerializer { @@ -998,4 +1002,30 @@ mod tests { "error serializing tuple untagged enum" ); } + + #[test] + fn avro_3747_human_readable_false() { + use serde::ser::Serializer as SerdeSerializer; + + unsafe { + crate::util::SERDE_HUMAN_READABLE = false; + } + + let ser = &mut Serializer {}; + + assert_eq!(ser.is_human_readable(), false); + } + + #[test] + fn avro_3747_human_readable_true() { + use serde::ser::Serializer as SerdeSerializer; + + unsafe { + crate::util::SERDE_HUMAN_READABLE = true; + } + + let ser = &mut Serializer {}; + + assert!(ser.is_human_readable()); + } } diff --git a/lang/rust/avro/src/util.rs b/lang/rust/avro/src/util.rs index e18b5641fce..695a1a6c7f0 100644 --- a/lang/rust/avro/src/util.rs +++ b/lang/rust/avro/src/util.rs @@ -27,6 +27,14 @@ pub const DEFAULT_MAX_ALLOCATION_BYTES: usize = 512 * 1024 * 1024; static mut MAX_ALLOCATION_BYTES: usize = DEFAULT_MAX_ALLOCATION_BYTES; static MAX_ALLOCATION_BYTES_ONCE: Once = Once::new(); +/// Whether to set serialization & deserialization traits +/// as `human_readable` or not. +/// See [set_serde_human_readable] to change this value. +pub const DEFAULT_SERDE_HUMAN_READABLE: bool = true; +// crate visible for testing +pub(crate) static mut SERDE_HUMAN_READABLE: bool = DEFAULT_SERDE_HUMAN_READABLE; +static SERDE_HUMAN_READABLE_ONCE: Once = Once::new(); + pub trait MapHelper { fn string(&self, key: &str) -> Option; @@ -153,6 +161,27 @@ 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. +/// +/// **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) -> bool { + unsafe { + SERDE_HUMAN_READABLE_ONCE.call_once(|| { + SERDE_HUMAN_READABLE = human_readable; + }); + SERDE_HUMAN_READABLE + } +} + +pub(crate) fn is_human_readable() -> bool { + unsafe { SERDE_HUMAN_READABLE } +} + #[cfg(test)] mod tests { use super::*;