From 09e583b587e82978033ce4f4c49af0b17bbd4e61 Mon Sep 17 00:00:00 2001 From: Christopher Prohm Date: Tue, 1 Oct 2024 17:17:43 +0200 Subject: [PATCH 01/28] Simplify usage for transmute --- serde_arrow/src/internal/utils/value.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/serde_arrow/src/internal/utils/value.rs b/serde_arrow/src/internal/utils/value.rs index 68037dfe..7cdd9fb8 100644 --- a/serde_arrow/src/internal/utils/value.rs +++ b/serde_arrow/src/internal/utils/value.rs @@ -82,7 +82,7 @@ impl std::hash::Hash for HashF64 { } } -pub fn transmute(value: S) -> Result { +pub fn transmute(value: impl Serialize) -> Result { let value = value.serialize(ValueSerializer)?; T::deserialize(ValueDeserializer::new(&value)) } @@ -577,6 +577,7 @@ impl<'de, 'a> serde::de::Deserializer<'de> for ValueDeserializer<'a> { fn deserialize_byte_buf>(self, visitor: V) -> Result { match self.0 { Value::Bytes(v) => visitor.visit_byte_buf(v.to_owned()), + Value::String(v) => visitor.visit_byte_buf(v.as_bytes().to_owned()), v => fail!("Cannot deserialize bytes from non-bytes value {v:?}"), } } @@ -584,6 +585,7 @@ impl<'de, 'a> serde::de::Deserializer<'de> for ValueDeserializer<'a> { fn deserialize_bytes>(self, visitor: V) -> Result { match self.0 { Value::Bytes(v) => visitor.visit_bytes(v), + Value::String(v) => visitor.visit_bytes(v.as_bytes()), v => fail!("Cannot deserialize bytes from non-bytes value {v:?}"), } } From 6d097467f6e1ec12bfa838c5c057476c5ebbb634 Mon Sep 17 00:00:00 2001 From: Christopher Prohm Date: Tue, 1 Oct 2024 17:17:49 +0200 Subject: [PATCH 02/28] Add jiff as a dev-dep --- Cargo.lock | 27 +++++++++++++++++++++++++++ serde_arrow/Cargo.toml | 1 + 2 files changed, 28 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 213ccbc3..7135d487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1688,6 +1688,32 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jiff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" +dependencies = [ + "jiff-tzdb-platform", + "serde", + "windows-sys 0.59.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "js-sys" version = "0.3.70" @@ -2359,6 +2385,7 @@ dependencies = [ "chrono", "criterion", "half", + "jiff", "rand", "rust_decimal", "serde", diff --git a/serde_arrow/Cargo.toml b/serde_arrow/Cargo.toml index e546c5e0..fa1c2157 100644 --- a/serde_arrow/Cargo.toml +++ b/serde_arrow/Cargo.toml @@ -138,6 +138,7 @@ serde_bytes = "0.11" rand = "0.8" bigdecimal = {version = "0.4", features = ["serde"] } uuid = { version = "1.10.0", features = ["serde", "v4"] } +jiff = { version = "0.1", features = ["serde"] } # for benchmarks # arrow-version:replace: arrow-json-{version} = {{ package = "arrow-json", version = "{version}" }} From 8c8bf3fe6974a44be9d414522e7497049523f7e8 Mon Sep 17 00:00:00 2001 From: Christopher Prohm Date: Tue, 1 Oct 2024 17:17:59 +0200 Subject: [PATCH 03/28] Test various reprs between Chrono and Jiff --- serde_arrow/src/test_with_arrow/impls/jiff.rs | 87 +++++++++++++++++++ serde_arrow/src/test_with_arrow/impls/mod.rs | 1 + 2 files changed, 88 insertions(+) create mode 100644 serde_arrow/src/test_with_arrow/impls/jiff.rs diff --git a/serde_arrow/src/test_with_arrow/impls/jiff.rs b/serde_arrow/src/test_with_arrow/impls/jiff.rs new file mode 100644 index 00000000..bdcf44a8 --- /dev/null +++ b/serde_arrow/src/test_with_arrow/impls/jiff.rs @@ -0,0 +1,87 @@ +use jiff::{ + civil::{date, time, Date, DateTime, Time}, + Span, +}; + +use crate::internal::utils::value; + +#[test] +fn string_repr_examples() { + // date + let obj = date(2023, 12, 31); + assert_eq!(value::transmute::(&obj).unwrap(), "2023-12-31"); + + // date time without time zone + let obj = obj.at(18, 30, 0, 0); + assert_eq!( + value::transmute::(&obj).unwrap(), + "2023-12-31T18:30:00" + ); + + // date time wiht timezone + let obj = obj.intz("UTC").unwrap(); + assert_eq!( + value::transmute::(&obj).unwrap(), + "2023-12-31T18:30:00+00:00[UTC]" + ); + + // time without fractional part + let obj = time(16, 56, 42, 0); + assert_eq!(value::transmute::(&obj).unwrap(), "16:56:42"); + + // time with fractional part + let obj = time(16, 56, 42, 123_000_000); + assert_eq!(value::transmute::(&obj).unwrap(), "16:56:42.123"); + + // day span + let obj = Span::new().days(32); + assert_eq!(value::transmute::(&obj).unwrap(), "P32d"); + + // year month span + let obj = Span::new().years(4).months(7); + assert_eq!(value::transmute::(&obj).unwrap(), "P4y7m"); +} + +/// Test that the different reprs between chrono and jiff are compatible +#[test] +fn transmute_jiff_chrono() { + // date + let chrono = chrono::NaiveDate::from_ymd_opt(2023, 12, 31).unwrap(); + let jiff = date(2023, 12, 31); + + assert_eq!(value::transmute::(&chrono).unwrap(), jiff); + assert_eq!( + value::transmute::(&jiff).unwrap(), + chrono + ); + + // time without fractional part + let chrono = chrono::NaiveTime::from_hms_opt(19, 31, 22).unwrap(); + let jiff = time(19, 31, 22, 0); + + assert_eq!(value::transmute::