Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions lang/rust/avro/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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(())
}
}
2 changes: 1 addition & 1 deletion lang/rust/avro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 30 additions & 0 deletions lang/rust/avro/src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ impl<'b> ser::Serializer for &'b mut Serializer {
) -> Result<Self::SerializeStructVariant, Self::Error> {
Ok(StructVariantSerializer::new(index, variant, len))
}

fn is_human_readable(&self) -> bool {
crate::util::is_human_readable()
}
}

impl ser::SerializeSeq for SeqSerializer {
Expand Down Expand Up @@ -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());
}
}
29 changes: 29 additions & 0 deletions lang/rust/avro/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>;

Expand Down Expand Up @@ -153,6 +161,27 @@ pub fn safe_len(len: usize) -> AvroResult<usize> {
}
}

/// 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::*;
Expand Down