diff --git a/Cargo.lock b/Cargo.lock index e3528dc..bd38a09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -761,16 +761,17 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde_columnar" -version = "0.3.12" +version = "0.3.13" dependencies = [ "bincode", "criterion", @@ -788,7 +789,7 @@ dependencies = [ [[package]] name = "serde_columnar_derive" -version = "0.3.6" +version = "0.3.7" dependencies = [ "darling", "proc-macro2", @@ -796,11 +797,20 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_core" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 2c6eb42..114ab8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,9 @@ resolver = "2" homepage = "https://github.com/loro-dev/columnar" repository = "https://github.com/loro-dev/columnar" +[workspace.dependencies] +serde = { version = "^1" } + # Added profile settings from fuzz/Cargo.toml [profile.release] debug = 1 diff --git a/README.md b/README.md index 2151fe6..7c4ce50 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ For more detailed introduction, please refer to this `Notion` link: [Serde-Colum ![Image](https://github.com/user-attachments/assets/48475c7d-61c8-4903-892d-70d702137dba) -## 🚧 This crate is in progress and not stable, should not be used in production environments - ## Features 🚀 `serde_columnar` comes with several remarkable features: diff --git a/columnar/Cargo.toml b/columnar/Cargo.toml index 20a695e..ed8a889 100644 --- a/columnar/Cargo.toml +++ b/columnar/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_columnar" -version = "0.3.12" +version = "0.3.13" edition = "2021" authors = ["leonzhao ", "zxch3n "] license = "MIT OR Apache-2.0" @@ -10,17 +10,17 @@ repository = "https://github.com/loro-dev/columnar" keywords = ["columnar", "column-oriented", "compression", "serde", "compatible"] [dependencies] -serde = { version = "1.0" } -serde_columnar_derive = { path = "../columnar_derive", version = "0.3.6" } +serde = { workspace = true } +serde_columnar_derive = { path = "../columnar_derive", version = "0.3.7" } postcard = { version = "^1.1.0", features = ["alloc"] } thiserror = "1.0" lazy_static = { version = "1.4", optional = true } bincode = { version = "1.3.3", optional = true } itertools = "^0.11.0" -flate2 = { version = "1.0", optional = true } +flate2 = { version = "^1.1", optional = true } [dev-dependencies] -serde = { version = "1.0.188", features = ["derive"] } +serde = { workspace = true, features = ["derive"] } criterion = "0.5.1" serde_json = "1.0" insta = { version = "1.31.0", features = ["yaml"] } diff --git a/columnar/src/__serde_utils.rs b/columnar/src/__serde_utils.rs new file mode 100644 index 0000000..0af4d32 --- /dev/null +++ b/columnar/src/__serde_utils.rs @@ -0,0 +1,139 @@ +use serde::{ + de::{Error, Unexpected, Visitor}, + Deserializer, +}; +use std::borrow::Cow; + +pub fn borrow_cow_str<'de: 'a, 'a, D, R>(deserializer: D) -> Result +where + D: Deserializer<'de>, + R: From>, +{ + struct CowStrVisitor; + + impl<'a> Visitor<'a> for CowStrVisitor { + type Value = Cow<'a, str>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.to_owned())) + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_string(self, v: String) -> Result + where + E: Error, + { + Ok(Cow::Owned(v)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + match str::from_utf8(v) { + Ok(s) => Ok(Cow::Owned(s.to_owned())), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), + } + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + match str::from_utf8(v) { + Ok(s) => Ok(Cow::Borrowed(s)), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), + } + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + match String::from_utf8(v) { + Ok(s) => Ok(Cow::Owned(s)), + Err(e) => Err(Error::invalid_value( + Unexpected::Bytes(&e.into_bytes()), + &self, + )), + } + } + } + + deserializer.deserialize_str(CowStrVisitor).map(From::from) +} + +pub fn borrow_cow_bytes<'de: 'a, 'a, D, R>(deserializer: D) -> Result +where + D: Deserializer<'de>, + R: From>, +{ + struct CowBytesVisitor; + + impl<'a> Visitor<'a> for CowBytesVisitor { + type Value = Cow<'a, [u8]>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.as_bytes().to_vec())) + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v.as_bytes())) + } + + fn visit_string(self, v: String) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.into_bytes())) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.to_vec())) + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + Ok(Cow::Owned(v)) + } + } + + deserializer + .deserialize_bytes(CowBytesVisitor) + .map(From::from) +} diff --git a/columnar/src/lib.rs b/columnar/src/lib.rs index c808d43..c1d4352 100644 --- a/columnar/src/lib.rs +++ b/columnar/src/lib.rs @@ -100,6 +100,7 @@ pub use wrap::{ColumnarMap, ColumnarVec}; pub use postcard::Error as PostcardError; pub use serde_columnar_derive::*; +pub mod __serde_utils; #[cfg(feature = "bench")] extern crate lazy_static; diff --git a/columnar_derive/Cargo.toml b/columnar_derive/Cargo.toml index 1658c03..1045d31 100644 --- a/columnar_derive/Cargo.toml +++ b/columnar_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_columnar_derive" -version = "0.3.6" +version = "0.3.7" edition = "2021" authors = ["leonzhao ", "zxch3n "] license = "MIT OR Apache-2.0" diff --git a/columnar_derive/src/serde/de.rs b/columnar_derive/src/serde/de.rs index c0a0a26..53a61af 100644 --- a/columnar_derive/src/serde/de.rs +++ b/columnar_derive/src/serde/de.rs @@ -73,7 +73,7 @@ impl DeFieldAttrs { quote::quote!( let #field_name = { #wrapper - ::serde::__private::Option::map( + std::option::Option::map( ::serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut seq)?, |__wrap| __wrap.value).ok_or_else(|| __A::Error::custom("DeserializeUnexpectedEnd"))? }; @@ -118,9 +118,9 @@ impl DeFieldAttrs { segments: Punctuated::new(), }; let span = Span::call_site(); - path.segments.push(Ident::new("serde", span).into()); - path.segments.push(Ident::new("__private", span).into()); - path.segments.push(Ident::new("de", span).into()); + path.segments + .push(Ident::new("serde_columnar", span).into()); + path.segments.push(Ident::new("__serde_utils", span).into()); path.segments .push(Ident::new("borrow_cow_str", span).into()); let ans = syn::ExprPath { @@ -135,9 +135,9 @@ impl DeFieldAttrs { segments: Punctuated::new(), }; let span = Span::call_site(); - path.segments.push(Ident::new("serde", span).into()); - path.segments.push(Ident::new("__private", span).into()); - path.segments.push(Ident::new("de", span).into()); + path.segments + .push(Ident::new("serde_columnar", span).into()); + path.segments.push(Ident::new("__serde_utils", span).into()); path.segments .push(Ident::new("borrow_cow_bytes", span).into()); let ans = syn::ExprPath { @@ -381,19 +381,19 @@ fn wrap_deserialize_with( #[doc(hidden)] struct __DeserializeWith #de_impl_generics #where_clause { value: #value_ty, - phantom: ::serde::__private::PhantomData<#this_type #ty_generics>, - lifetime: ::serde::__private::PhantomData<&#delife ()>, + phantom: std::marker::PhantomData<#this_type #ty_generics>, + lifetime: std::marker::PhantomData<&#delife ()>, } impl #de_impl_generics serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause { - fn deserialize<__D>(__deserializer: __D) -> ::serde::__private::Result + fn deserialize<__D>(__deserializer: __D) -> std::result::Result where __D: serde::Deserializer<#delife>, { - ::serde::__private::Ok(__DeserializeWith { + std::result::Result::Ok(__DeserializeWith { value: #deserialize_with(__deserializer)?, - phantom: ::serde::__private::PhantomData, - lifetime: ::serde::__private::PhantomData, + phantom: std::marker::PhantomData, + lifetime: std::marker::PhantomData, }) } } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index bf032b7..81e331d 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,7 +9,7 @@ cargo-fuzz = true [dependencies] libfuzzer-sys = "0.4" -serde = { version = "1.0", features = ["derive"] } +serde = { workspace = true, features = ["derive"] } arbitrary = { version = "1.1.7", features = ["derive"] } postcard = "^1.0"