From 8bd7810f3ff85e700594bd6e3a60d2e11d7e8edc Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Tue, 7 Oct 2025 20:08:11 +0100 Subject: [PATCH] Use serde_core where possible --- README.md | 2 +- pbjson-build/src/generator.rs | 8 +++--- pbjson-build/src/generator/enumeration.rs | 14 +++++----- pbjson-build/src/generator/message.rs | 32 ++++++++++++---------- pbjson-build/src/lib.rs | 8 +++--- pbjson-test/Cargo.toml | 1 + pbjson-types/Cargo.toml | 2 +- pbjson-types/descriptors.bin | Bin 134036 -> 107061 bytes pbjson-types/src/duration.rs | 26 ++++++++++-------- pbjson-types/src/lib.rs | 6 ++-- pbjson-types/src/list_value.rs | 12 ++++---- pbjson-types/src/null_value.rs | 12 ++++---- pbjson-types/src/struct.rs | 12 ++++---- pbjson-types/src/timestamp.rs | 20 +++++++------- pbjson-types/src/value.rs | 4 +-- pbjson-types/src/wrappers.rs | 26 +++++++++--------- pbjson/Cargo.toml | 1 + pbjson/src/lib.rs | 26 +++++++++--------- 18 files changed, 110 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 2f8750a..3fb3e7e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Pbjson -Pbjson is a set of crates to automatically generate [serde](https://serde.rs/) [Serialize](https://docs.rs/serde/1.0.130/serde/trait.Serialize.html) and [Deserialize](https://docs.rs/serde/1.0.130/serde/trait.Deserialize.html) implementations for auto-generated prost types. +Pbjson is a set of crates to automatically generate [serde](https://serde.rs/) [Serialize](https://docs.rs/serde_core/1.0.228/serde_core/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_core/1.0.228/serde_core/trait.Deserialize.html) implementations for auto-generated prost types. See [pbjson-build](https://docs.rs/pbjson-build) for usage instructions diff --git a/pbjson-build/src/generator.rs b/pbjson-build/src/generator.rs index 1f450c2..98d1a15 100644 --- a/pbjson-build/src/generator.rs +++ b/pbjson-build/src/generator.rs @@ -37,11 +37,11 @@ fn write_fields_array<'a, W: Write, I: Iterator>( fn write_serialize_start(indent: usize, rust_type: &str, writer: &mut W) -> Result<()> { writeln!( writer, - r#"{indent}impl serde::Serialize for {rust_type} {{ + r#"{indent}impl serde_core::Serialize for {rust_type} {{ {indent} #[allow(deprecated)] {indent} fn serialize(&self, serializer: S) -> std::result::Result {indent} where -{indent} S: serde::Serializer, +{indent} S: serde_core::Serializer, {indent} {{"#, indent = Indent(indent), rust_type = rust_type @@ -60,11 +60,11 @@ fn write_serialize_end(indent: usize, writer: &mut W) -> Result<()> { fn write_deserialize_start(indent: usize, rust_type: &str, writer: &mut W) -> Result<()> { writeln!( writer, - r#"{indent}impl<'de> serde::Deserialize<'de> for {rust_type} {{ + r#"{indent}impl<'de> serde_core::Deserialize<'de> for {rust_type} {{ {indent} #[allow(deprecated)] {indent} fn deserialize(deserializer: D) -> std::result::Result {indent} where -{indent} D: serde::Deserializer<'de>, +{indent} D: serde_core::Deserializer<'de>, {indent} {{"#, indent = Indent(indent), rust_type = rust_type diff --git a/pbjson-build/src/generator/enumeration.rs b/pbjson-build/src/generator/enumeration.rs index c833484..6c3a78e 100644 --- a/pbjson-build/src/generator/enumeration.rs +++ b/pbjson-build/src/generator/enumeration.rs @@ -98,7 +98,7 @@ fn write_visitor( writer, r#"{indent}struct GeneratedVisitor; -{indent}impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {{ +{indent}impl<'de> serde_core::de::Visitor<'de> for GeneratedVisitor {{ {indent} type Value = {rust_type}; {indent} fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{ @@ -107,31 +107,31 @@ fn write_visitor( {indent} fn visit_i64(self, v: i64) -> std::result::Result {indent} where -{indent} E: serde::de::Error, +{indent} E: serde_core::de::Error, {indent} {{ {indent} i32::try_from(v) {indent} .ok() {indent} .and_then(|x| x.try_into().ok()) {indent} .ok_or_else(|| {{ -{indent} serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) +{indent} serde_core::de::Error::invalid_value(serde_core::de::Unexpected::Signed(v), &self) {indent} }}) {indent} }} {indent} fn visit_u64(self, v: u64) -> std::result::Result {indent} where -{indent} E: serde::de::Error, +{indent} E: serde_core::de::Error, {indent} {{ {indent} i32::try_from(v) {indent} .ok() {indent} .and_then(|x| x.try_into().ok()) {indent} .ok_or_else(|| {{ -{indent} serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) +{indent} serde_core::de::Error::invalid_value(serde_core::de::Unexpected::Unsigned(v), &self) {indent} }}) {indent} }} {indent} fn visit_str(self, value: &str) -> std::result::Result {indent} where -{indent} E: serde::de::Error, +{indent} E: serde_core::de::Error, {indent} {{"#, indent = Indent(indent), rust_type = rust_type, @@ -151,7 +151,7 @@ fn write_visitor( writeln!( writer, - "{indent}_ => Err(serde::de::Error::unknown_variant(value, FIELDS)),", + "{indent}_ => Err(serde_core::de::Error::unknown_variant(value, FIELDS)),", indent = Indent(indent + 3) )?; writeln!(writer, "{}}}", Indent(indent + 2))?; diff --git a/pbjson-build/src/generator/message.rs b/pbjson-build/src/generator/message.rs index 2822f56..582fa05 100644 --- a/pbjson-build/src/generator/message.rs +++ b/pbjson-build/src/generator/message.rs @@ -143,7 +143,11 @@ fn write_struct_serialize_start( writer: &mut W, emit_fields: bool, ) -> Result<()> { - writeln!(writer, "{}use serde::ser::SerializeStruct;", Indent(indent))?; + writeln!( + writer, + "{}use serde_core::ser::SerializeStruct;", + Indent(indent) + )?; let required_len = message .fields @@ -211,7 +215,7 @@ fn write_decode_variant( writeln!(writer, "{}::try_from({})", resolver.rust_type(path), value)?; write!( writer, - "{}.map_err(|_| serde::ser::Error::custom(format!(\"Invalid variant {{}}\", {})))", + "{}.map_err(|_| serde_core::ser::Error::custom(format!(\"Invalid variant {{}}\", {})))", Indent(indent), value ) @@ -521,7 +525,7 @@ fn write_deserialize_message( writeln!( writer, - r#"{indent}impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {{ + r#"{indent}impl<'de> serde_core::de::Visitor<'de> for GeneratedVisitor {{ {indent} type Value = {rust_type}; {indent} fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{ @@ -530,7 +534,7 @@ fn write_deserialize_message( {indent} fn visit_map(self, mut map_: V) -> std::result::Result<{rust_type}, V::Error> {indent} where -{indent} V: serde::de::MapAccess<'de>, +{indent} V: serde_core::de::MapAccess<'de>, {indent} {{"#, indent = Indent(indent), name = message.path, @@ -593,7 +597,7 @@ fn write_deserialize_message( )?; writeln!( writer, - "{}let _ = map_.next_value::()?;", + "{}let _ = map_.next_value::()?;", Indent(indent + 5), )?; writeln!(writer, "{}}}", Indent(indent + 4))?; @@ -609,7 +613,7 @@ fn write_deserialize_message( )?; writeln!( writer, - "{}let _ = map_.next_value::()?;", + "{}let _ = map_.next_value::()?;", Indent(indent + 3) )?; writeln!(writer, "{}}}", Indent(indent + 2))?; @@ -621,7 +625,7 @@ fn write_deserialize_message( FieldModifier::Required => { writeln!( writer, - "{indent}{field}: {field}__.ok_or_else(|| serde::de::Error::missing_field(\"{json_name}\"))?,", + "{indent}{field}: {field}__.ok_or_else(|| serde_core::de::Error::missing_field(\"{json_name}\"))?,", indent = Indent(indent + 3), field = field.rust_field_name(), json_name = field.json_name() @@ -699,14 +703,14 @@ fn write_deserialize_field_name( writeln!( writer, - r#"{indent}impl<'de> serde::Deserialize<'de> for GeneratedField {{ + r#"{indent}impl<'de> serde_core::Deserialize<'de> for GeneratedField {{ {indent} fn deserialize(deserializer: D) -> std::result::Result {indent} where -{indent} D: serde::Deserializer<'de>, +{indent} D: serde_core::Deserializer<'de>, {indent} {{ {indent} struct GeneratedVisitor; -{indent} impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {{ +{indent} impl<'de> serde_core::de::Visitor<'de> for GeneratedVisitor {{ {indent} type Value = GeneratedField; {indent} fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{ @@ -716,7 +720,7 @@ fn write_deserialize_field_name( {indent} #[allow(unused_variables)] {indent} fn visit_str(self, value: &str) -> std::result::Result {indent} where -{indent} E: serde::de::Error, +{indent} E: serde_core::de::Error, {indent} {{"#, indent = Indent(indent) )?; @@ -752,7 +756,7 @@ fn write_deserialize_field_name( } else { writeln!( writer, - "{}_ => Err(serde::de::Error::unknown_field(value, FIELDS)),", + "{}_ => Err(serde_core::de::Error::unknown_field(value, FIELDS)),", Indent(indent + 5) )?; } @@ -766,7 +770,7 @@ fn write_deserialize_field_name( } else { writeln!( writer, - "{}Err(serde::de::Error::unknown_field(value, FIELDS))", + "{}Err(serde_core::de::Error::unknown_field(value, FIELDS))", Indent(indent + 5) )?; } @@ -840,7 +844,7 @@ fn write_deserialize_field( // Note: this will report duplicate field if multiple value are specified for a one of writeln!( writer, - "{}return Err(serde::de::Error::duplicate_field(\"{}\"));", + "{}return Err(serde_core::de::Error::duplicate_field(\"{}\"));", Indent(indent + 2), json_name )?; diff --git a/pbjson-build/src/lib.rs b/pbjson-build/src/lib.rs index 912bbee..56ba503 100644 --- a/pbjson-build/src/lib.rs +++ b/pbjson-build/src/lib.rs @@ -1,5 +1,5 @@ //! `pbjson-build` consumes the descriptor output of [`prost-build`][1] and generates -//! [`serde::Serialize`][2] and [`serde::Deserialize`][3] implementations +//! [`serde_core::Serialize`][2] and [`serde_core::Deserialize`][3] implementations //! that are compliant with the [protobuf JSON mapping][4] //! //! # Usage @@ -63,11 +63,11 @@ //! ``` //! //! The module will now contain the generated prost structs for your protobuf definition -//! along with compliant implementations of [serde::Serialize][2] and [serde::Deserialize][3] +//! along with compliant implementations of [serde_core::Serialize][2] and [serde_core::Deserialize][3] //! //! [1]: https://docs.rs/prost-build -//! [2]: https://docs.rs/serde/1.0.130/serde/trait.Serialize.html -//! [3]: https://docs.rs/serde/1.0.130/serde/trait.Deserialize.html +//! [2]: https://docs.rs/serde_core/1.0.228/serde_core/trait.Serialize.html +//! [3]: https://docs.rs/serde_core/1.0.228/serde_core/trait.Deserialize.html //! [4]: https://developers.google.com/protocol-buffers/docs/proto3#json #![deny(rustdoc::broken_intra_doc_links, rustdoc::bare_urls, rust_2018_idioms)] diff --git a/pbjson-test/Cargo.toml b/pbjson-test/Cargo.toml index a806e8d..1d970da 100644 --- a/pbjson-test/Cargo.toml +++ b/pbjson-test/Cargo.toml @@ -11,6 +11,7 @@ prost = "0.14" pbjson = { path = "../pbjson" } pbjson-types = { path = "../pbjson-types" } serde = { version = "1.0", features = ["derive"] } +serde_core = { version = "1.0.200" } [features] ignore-unknown-fields = [] diff --git a/pbjson-types/Cargo.toml b/pbjson-types/Cargo.toml index 8499095..e4210fa 100644 --- a/pbjson-types/Cargo.toml +++ b/pbjson-types/Cargo.toml @@ -15,7 +15,7 @@ bytes = "1.0" chrono = { version = "0.4", default-features = false, features = ["alloc"] } pbjson = { path = "../pbjson", version = "0.8" } prost = "0.14" -serde = { version = "1.0", features = ["derive"] } +serde_core = { version = "1.0.200" } [dev-dependencies] serde_json = "1.0" diff --git a/pbjson-types/descriptors.bin b/pbjson-types/descriptors.bin index c3b3ed27313f28474d61c081cbc454839f4b171f..ad65b4f33b96c9d25d546635f705e2d4c67f922f 100644 GIT binary patch delta 21055 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

l`*FmN z<*-rg_x*Ue+#;iw+|98Q-BU=a^g|#Y#f{J6W?3~|F5m;3Ht)a}V`VC)vcf(e%V0%p zLq;ccJUnw*f`y_(XSRbj`1&ZGkSTcp$s_nUZsDo}k`x(60U%_)Dl#~KGzA1v1JpB+ zE|9IU)s;?s1+6u{-Cs`$+IOt6M~rgs=Q)50V_#$&m)mC9Pbh^D>s7Xc0m}ymgin}g zggf~pX}P-7A{C66etts*-lkHfG+YhZ0^%_iK8Et)B;WuH=7)B%7%?6ld3!3Ng7I0} zkq&BTm(8sxy?Vgj;i?Qj$TON1T;AW&nyjZx4w0Ds4}hN?#7&xrsrC_-?F@*#d$1=8OT z@r68gGy+7#mWe7Gvf0AuUSfwDX!14_2(3;)pvEP3sDUPJB{yc*hzrD8fr+Z%0Tv*# zsz7HpW%r$|5)e_}DJOeVcHc24FU{^M&1fL>Ofe0-j{*cNC8XtJ?wF*umu2^zR1=7( z@062$S$5wMx7lo4{X=1s$O6lGT{mkL{3d)zicJue zK|?4MHAD_xx2^82F%>3Lq6`YE_~hkv+X#nA1A=3pZMGppg1I>LV^A9qyfcBXDt!fC zL2R3?UWWh(O55zQ<7C_-mri$f*q@7A91ym^&QRUh`HJEe2ZSwr>_y-_OE>0AKl$)w z1Mv_FBnqi$iRK&$k?ycn+yb8=(jB&nTL6Seci4zq%p~g$i(v1vji16IPxh+2f1f8x zeZ7fa0qcj|74P0uXh5&HCYh^Uq@aJK+;ET~8+em#jVZfd=7#H6f7G2sm}31XR`gOB zQW=_%I^K+E1ih_PEuTcAXSERZOV@WGm4KqL6i(wLgI3&jB;P;<3{>U<7FetW`UySx z$fnGU(6`EDE`ro=dD_n_v`PtJ20%eQ#F+N6bfBMd0-#@zE;^(BuL<0h{ zxXCUZ5mkYRZ?X~9ryDL*0tJ3RvRTG^^hh*WQdyEl=nFd2nD&v>PWL%!D-EeEU}uR1 zAn%3HpAe6FnS=MF*n(m^fH&Cq^?mY-H1{-p(R9Q;WuE;Yn|m6`A7pdS)At9&{yB<$ zn7vzx{iV#lj-t@(XR1ZSG*@D|rAI=tx_^;_ zQ;wD+?rF8TH8MUjga1~$B$7St4sRvqaULm!4@8e`jVk-mfr{CiRb-4%hIG0EQSgK6 zCBNdveW9%|DkF_r>SHtBu=~7HYA=vvaBvND)dON)FBSCZ-LPINNU3V*LL>%CR_n{8_%K;vld(_kfpaQ-B;RP`AER(^;FUS@d5II z;dWfE>HSpEmtD6Y6lf2mBGnKewC6#+YypG_AJoehKxof{HnIyT+@8m7$-`0&H4qXa z6Zf!ILwp6HhqW341fhqu8d9dkZ%GYLtNyLlz&zGKfKmeiVw`_V8c5@upR#{v$KF)q zOeqz=vynEr7+mGkFh6bwcf4PJ?Blv$K%$MuZFO)15LF(x3*}W9fMDlw8&_feN;{-{ zS}LBhgZUr4bm~(P3G%s~ibzn8p0ZVx098QZDe`@3KMN3^?^Cvl5&(qn{FIF-0Ub5w zWB%;5gDoF={$4$Q@_GJbgXk}Vzo8VZe2Q7^vyIxapBw*wIct<>eDe2Zq^&>jobP~B zy{tn$_rO!VtV2D>5;_lIs>|$vF|zxjk)`3^XRA{^e8tG_vyYUys{k>w`|PPTyelA( zKOa3uTA6$*{p!DJWqkaanO=`^Xrl8}4m30WXI2KQEP{Oh=iV`d0*ON^(#imYad;J0 zrb5jYS~*|UW(J>GhRV$3(`fxoS{eM!Ku8D|fbdN%cK8Z9f74b5An5!}TN%p3dV?3c z+I(8<-q5B75UK%`rUoG9+8f%`6r}98?bybIJlCVVtG8{ZpZgveiUP7V@7Y1|$M5^^ z>D~c}mfq9q1Q2!J(}n^dn0ike3V=|j_q3q^2t)B6846yr3P=?{`B${b=eL6Y-)WQo z)$O$)6et0tBDD!1l)(Q)FIs?EXlkzo5CZ>%7A-s@MPr81y&z#sD%){j1eMoy3Sq$k zVb`AzrP#})hh)@Kh6fF+B5UJdfz>Y?S4GP6=K`x>7~KWOy1QhpE=Z`Q3}4aP3lh^* zU==XBdqDyL23m*!LccCZ43;M|0HI$OB*si|PheS~?7D<8wd^Rh?L6xrY&*lKgd|K; z8g(^SG^N)ia%B2-0SCF(B}T~12!PxWY$!Pn1=OMS33gxcHv=IZn$hbMYDVKLdbd8I z+*g30vp%8RSIUXJBth=0UqCbZl7wrBw=F(aJ8ZQUKA)F0E3OAA2LKRBa)t z)QwuD0HGQ{sZs#Z;Eh_Pic)W9w0j3qdN}}o$sN}zezT&h|(PHOc=jNbWgIx>of06sIWLb zQ0qTWsIWN0Xa@)xf@K7H^790u;zO}lCj<)ImFP~##jqiFCDa2Cj7Pz{68QD`BUC}a zdlKD0ii;`!o`ia>f(p`L>`Cx*B-DRIx9(0D_avlk0F2=QLTVF04A0#O6{7`+=I>4% zDlhr~gdFZpsEa-TA%}YswoDNR2szx7C>rX^>03lCKk%ie@Be)E`s&&3ui!P>gU;SF z{=sXs5DEkisc3=o$-bVx_zHnPpl2^Y2>bz>y)>_i2zp4)EBp;Q4@GpyzcS4WOJ?05O7((7d|D#6~ZbvL8>xUQX=3I3d0x zN*+((g7?4ChA2hR`lk}c(}~?flL9#yPbFOW&n2ID};*bO7V&z}=2 ze$EJR@#h4;a7S-S%Q*d?6S%iX!GA)az}^HdS5Q!oVbBCZ(e$YVi0-AHghjXxa{WUD zWU@B_SA+sWDPr@PgduNA0s=vRa+Cl%z5qe#nFR7L_zj5^ z=fypr=x)yu*ZR*#M2My56Do-##dGWVgu2845Ja9&;F&JT4kZ6VLLH@~SZM%icF5~^ zA)-X$cp;IJM~o;8N-rd2q{|0;0QV)-g<(MG89+^n5(f4qRDKt}g4Di5k-VP)kn7^Y zuw)8VUreYw^C@-~0BTB<8SrAn6gdkoCVX|d0;NIf#Yo&J{MQ7o#YhR#eJX&O6y*T? zHDZc#0REaN(qlt;hJPh(kW67{UP`FDz$s2O1gI(bblm?^#1$Q^;m301NjFM^)Jq9m z2Hr~wUX1NUBKEzcDEkO+5K&Sq{R~)!k~Wazg?Cfv=L36MXrF1WUla$sp}zUxLy5f1cIbU#?|lmr|WTLk+RGvT|oXsl6=V%Sw)n_Mb8%D z-eG1rg2R-PCCgK5oU07aXE|O4^(c8bLBt z9XrrPNeXB~A_pWsa>{l3NTxQ%TMpv<3MHx`zX9oJh<&3~Z#hn-k%*>~us!q*34ar7 z#z+8JLAx}yzLZHCA34YcH2ZxN17-?P@fhzAN3JTdE5d!dk$tto2(EuW< zAxmV{fablIu;km8M1f`=5b^~%Mu4XO9xd^7B3g`o*dHW}3muE+3}DO|Af%=P#60*Q zp{{EK1i23q>fu^|Xzqgq4gm^au>j)o{|AXN7docw0T8%f^kG7sr&57p$n7KaU!JBj z1|&aDSOeWcSYbl+N!gzytj`j0wyA_EL8bE@t13dE&YE5b^y&h~nxRGy?#MdF_zw6W zLr`py!?Dgu6ez*^e2R9F6ONWVTLMBJrlSHU5?th{!*oJ`#Kn$ETVq%vWY!@gz{ACk z$~q(j;PsArjEZ5@00J>7S}YjDMUZDI#{z6`aEu@v3-Y3X&|^Vf)CNZ_7sYJpH#k_& zxQ}edKg}rd*ff_SR*9?LZAc?a@pk) zkjhmKmIqx01-c_a!kdu@d45GT=!Br#VL8f10B?2F6Jk_=xBx;;9G@^;gl7&-1F(Iy zW84smp8P2wwCKs7y4q3iNT4*xUF{5>qC`(?;nmL6qm}5f9|y5xZU{wh&@|Z2qG!qb z28;e0C!7XAfaJB2=nWG6b&j<&6urTszdq7>AW&ylr1ePpxzRCx5Q?7W{*6weRLPOk zXKr#VPwSsdp8-auVic?NnVTF$$))Hyedgv!^fG-02rYVXB5p7nLY!A zo+m&UNL=|IO%ypf$#wWXwV~RC?FEd%l(PiSZK5B&5om)Ea@wHZKXi`WTFA3N6V;na13J|}EW*%Tv0YWB0Q59JNNl;SB!S*AL@yAforkM8%k2rm# zLkbXre#C)8Dh2H$!4=eo|1p$woFx5kk)-1+>EHH3fWb#e($esw1iJ88B>Fgs{&$Y` z@1f{%IR>KqgJac(b;x2p?)cVpH5ho@>ramH=Wr~@k^YmDka?HI@{zA69E%vI6;nRs z1%wwNz{L{|-g}W+&yRUM8L6;*uL}sR!a$JydD3AWCavd3yPk^He)%vL5b}Be7eFIV zIsA4hX+5~!>lpjPv7n1cKA}Li&S8h63*hmJ{OG^5E${lL=y!F@c6t!_}pwU_AoE> zq6)tEIV$s!7%N8T<;7l95t{icaVGr(n}+-)$9g3kava5j*H;~@I%JK8{58j-cUvGk z+SC81?-=JNm2bu=c>n3(K{KXl#>n-4-LXE^GzkL|uRBR<7Uqi(G)LcX>@jYUo75N- z0%}Ay3Q~E)fqPmL)l&0_hAu|hE{#z*hOVO6N3=jk+)MsEUN>#Scn)jLmJ zUd4WxHowU4YHPujCi+z~q$l&EHbl#(3$vW2Mk!p;Skn50-sEPZ(C1GaxQXnm@Qd-E zk(Fj^0}y)nnUkls4FrP(5XyNW1PFZQ;Adi`8ONJ&Ym&aPA?YaJky7f{BtzRlzp}C> znKM~`1-UiJ!)i2$k-Q*jCzR>HcGbQh>1;?QBtJ%iOvi;uN9HFL118h4HtCeB8H-a8 zY>oV+b8%8FPAEfDc74+Mx|*^;pw;grom#$4UW`u#5@E!J`zxo0CRy`B-QZLb=O3JKHlyjT^TN zI@g6em~AcNaIcK7F3X<_1vECD(G7vr%}G3?$XdYbeKx4S-eMr!QIHlHMO_M>P^1TQjI#q_Su$x#;a{4TKPpZWDEz@qG?N9(xR6Y~TXH7- zD4I^21dAMz0j>Iu21Jl_KN^}5Awqf{9>#9KPpIHIW|@OH1|`%x#X57!^IOu$45PV6 z??jNc-I{dD+}kMXTS6;DPtv$2X_oCE0k+h)%ZnWp*uhnS?4R_NeAd(Trn9>cx02Ee zMT#yrbs~pTBVdJKbnyBW?sZA-C^eEVZK?|}5GjX>!P9IQKlqGe(g*D_yxj)bd?jbucxRPJ>?}S zl37*kLxQA{kQrpylSINf*(HFqKK?YR;w}us%m5)bz&>MOX?~jIMD~QN0vbO}syucs z0c-QqBsLT^iYN-~PFfSnj@4@?YpqsR2nRh?DyNcsaf68BobrHOiX1$1{DWGc00$^a zt{4HPb|>?stIY^*v)>rDO^g6jyOZO_yK@y&n0$97t>|6SQ^(YkwAvfuEKEeZkLmBfR3YCK>xe}S6{dOXN%{vxTCg%X@3u;q*} zYN23+8bV5n{6!L8s^W^%B6}mybw;Q*k^g^p68k+xfL?{Vo0z76b_r?3y-8yNG3XPB zJ_1$>#BsiRlj@aQd`08;CWp#jvjT|T-Ah8hfX*UIsQ33LjS*#?WS(%}v9+lM$rCEE z02;6Jk4NGcpXE=ojnX&Hpyw;-N-riH)Vr$zRt!sjm7b1jmaxKv$>aQnLpX^w%cMNu zA_Or;_b1hl2ZBZBu~;4j07MV&PvRWpBJ_az57|9LU05l*K!I&^p|^GU0`?E!K4c!Z zqxc5}4#GTAIGZ^6n0ry%%s*7j!^X-6PINa&)gFqvL85*r8Fquz>>=vLp9PkhQf#=A zu_xT_d-B8|OG{DocS)o%tC#_wF|vI9oxkCQlz+mOH{1Wavhagn+HLHDM<;)yt}z^ChX zFYhOAFns=u#_?TFC`MrKvBg#I5;FoMx46Y};xhs)Y;m#2CiQ0o_8wc@Lr3!_Kq4@P zTigK^?jPvK9tZ^@+lh_)uyDv=U>9>qEsW zC4ErzY1cW#T?smUND-fNyN@3xGHC$l!E<>3kc~1x==^i8ije?B&F9=cGK&fzcz@32 zKmrJn&i}x+U&qbl(9mHMP&}9yDC6_ZdWE`?R3dU-PQ@dM=!XO!x2+;>bBvo>Uy4<(M%7 zOuVGWj1f$rM4rDe0!+N*mJi`eG=xBluesf~j1cWL41(lq*(6C{U(4FaB*dQ+UM zfaGf~POkTASpo5e+kNIp(a>EuQrO*(j}&K}K}AV(-^iv;n)^mJb<*57T=md6S7Bn< z;GQW(!e@1^^&#}^WUnr*ew#Sc{n-f7CzpQf0?$Rji)w4_t{g57#kKm%=!O#Xk8~Gg zjM|5s>AWZo_vjicF)|CsKJgjPG)fe+p7T@W>n3|YJha*0~Zg1 zkqx1-!DxQus-ql+B_h&C%cq6MRXb)b0!BOFlTx3u@iR~1&c=p*AC`lsxvupINI7N36c5JfJh*TaZZ_dyJPhhYQ4URVR3%;# zSr`SC@DL6Cb|QY3I%EKYjqA~^-eUDDLh9E!DLoZ`a$p0mvOpV&F=km_=8i5?VLY+v z!;2KqS-jCgTRwW2MdlMA9~~XQz+&qaC!JZF6E7tr9OpyPbvXwA>IFgg2#`0u1Y)e$ z<;b6G0f>(mMP-Q)KwXv;@1m$Ipo?=1&TEPHmv_kkbJ`0ikrG{;gF}cXy8Th&-Q-jF zU89sWFxIjAv8AHH9z4iR;(6CWDYHB_$aP$-z~+$H35?9)Kf8C#5Cd~78H10*VwK$w z&k&RPPi4%olsPgs)xEY5O9v)&I@Te|Ht$|FL6kV9e70n!okI6%a%{<_n@!y}94Ve1 z-DD&nl{n$>o9s;v#XlIrZ?ZQb26iDO{*lLFp1u2)qr^Hf;Owvlq+y=zcU@T5~-#HoE({*XA^&zow3OO`Z&Pe>`JpCyJHY_%nkwZy5gB5Z(#6qHlgz)F?h4F^iHGBdoY~e`KbD?}tK=VDq>Pef>B`o0XZJ0a zh+~YAqq^U?M9k?&F$KN7f<#^HNb*w8UonHOYN?d9$S&7;i7&1f<_+wvw~im!V_1GNWapY z(j(`JnUGce91lb=4NEdMu#I?Rge1hVYPx3&GW3H!L`d}yZbA2(SBd^`JIGA)E9r`z zY*BOQWK~<2s*b<#c2|8fVp>F6A`g#+HkbaC$Ri^2 zLw`!-l*s%{84=o_BP07mfBv4Fdsv5Qv6%w5+q+NLCQj#vn*NzmO5Ks~H7VW8(sEK; z3Wm~sG4|i|yOF#`@~^%^t6e#%&1tw}=;@_khS9xen;1N9hT&-I4*|?b(v!A&Etr8E z=*Nh2Ox)SAT2XeN=uTcOPW?(brv+y=a@Pidb6UpD8l!vl)xsNBqt+x|&CMFMCIP~l zRD;+ObB^`*q}Zv<`9ohd=d^&Hq&TN{dCXIc?kV`m_;IHw&N)BGJVkL12%Mh+&RJVv z9hbz?tS#%df5qB@eTlh5X$z&+n2kpF``e){jY?ZMy~b=*+5!liH)?HxU)&OFXPM8s z<}20~sH)kbWKMY{W}DHy`x?l+P05^-OUyPUb3ov{P0Jknvz4)PS?1QYU$M-w8!%TY znNyyIx!UMnajh6UVYQMuCu^9imCONw^VN_!hs$tmf1!w7M2o-Zp0h*r?SA@NG3P6r zsN^?LF2IH4H_%K)HUnI0A-cbIo#=BcE%?Adyz7Kv^ZGB-9o7lFWvRYG;nxYAM*e{; z4$cxU6|u|FA6Uzc*L{U!L0#defsiuj4n|k-%T#!>2VME}I?<220t~vcSzus@cYx^n zW`U7WAiA=desY#4G7d7g3G!mdd}3(6I`c_gp(l&BVPC for std::time::Duration { type Error = std::num::TryFromIntError; @@ -25,10 +25,12 @@ impl From for Duration { impl Serialize for Duration { fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { if self.seconds != 0 && self.nanos != 0 && (self.nanos < 0) != (self.seconds < 0) { - return Err(serde::ser::Error::custom("Duration has inconsistent signs")); + return Err(serde_core::ser::Error::custom( + "Duration has inconsistent signs", + )); } let mut s = if self.seconds == 0 { @@ -67,11 +69,11 @@ impl<'de> Visitor<'de> for DurationVisitor { fn visit_str(self, s: &str) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { let s = s .strip_suffix('s') - .ok_or_else(|| serde::de::Error::custom("missing 's' suffix"))?; + .ok_or_else(|| serde_core::de::Error::custom("missing 's' suffix"))?; let (negative, s) = match s.strip_prefix('-') { Some(s) => (true, s), @@ -82,11 +84,11 @@ impl<'de> Visitor<'de> for DurationVisitor { Some((seconds_str, decimal_str)) => { let exp = 9_u32 .checked_sub(decimal_str.len() as u32) - .ok_or_else(|| serde::de::Error::custom("too many decimal places"))?; + .ok_or_else(|| serde_core::de::Error::custom("too many decimal places"))?; let pow = 10_u32.pow(exp); - let seconds = seconds_str.parse().map_err(serde::de::Error::custom)?; - let decimal: u32 = decimal_str.parse().map_err(serde::de::Error::custom)?; + let seconds = seconds_str.parse().map_err(serde_core::de::Error::custom)?; + let decimal: u32 = decimal_str.parse().map_err(serde_core::de::Error::custom)?; Duration { seconds, @@ -94,7 +96,7 @@ impl<'de> Visitor<'de> for DurationVisitor { } } None => Duration { - seconds: s.parse().map_err(serde::de::Error::custom)?, + seconds: s.parse().map_err(serde_core::de::Error::custom)?, nanos: 0, }, }; @@ -109,10 +111,10 @@ impl<'de> Visitor<'de> for DurationVisitor { } } -impl<'de> serde::Deserialize<'de> for Duration { +impl<'de> serde_core::Deserialize<'de> for Duration { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { deserializer.deserialize_str(DurationVisitor) } diff --git a/pbjson-types/src/lib.rs b/pbjson-types/src/lib.rs index caf506a..c372ae7 100644 --- a/pbjson-types/src/lib.rs +++ b/pbjson-types/src/lib.rs @@ -1,12 +1,12 @@ //! `pbjson-types` provides the `google.protobuf` types, commonly known as well-known-types, -//! with [`serde::Serialize`][1] and [`serde::Deserialize`][2] implementations +//! with [`serde_core::Serialize`][1] and [`serde_core::Deserialize`][2] implementations //! that are compliant with the [protobuf JSON mapping][3] //! //! __Note: Coverage of all types is currently incomplete, //! some may have non-compliant implementations__ //! -//! [1]: https://docs.rs/serde/1.0.130/serde/trait.Serialize.html -//! [2]: https://docs.rs/serde/1.0.130/serde/trait.Deserialize.html +//! [1]: https://docs.rs/serde_core/1.0.228/serde_core/trait.Serialize.html +//! [2]: https://docs.rs/serde_core/1.0.228/serde_core/trait.Deserialize.html //! [3]: https://developers.google.com/protocol-buffers/docs/proto3#json #![deny(rustdoc::broken_intra_doc_links, rustdoc::bare_urls, rust_2018_idioms)] diff --git a/pbjson-types/src/list_value.rs b/pbjson-types/src/list_value.rs index 35062f8..077b28e 100644 --- a/pbjson-types/src/list_value.rs +++ b/pbjson-types/src/list_value.rs @@ -36,19 +36,19 @@ impl FromIterator for ListValue { } } -impl serde::Serialize for ListValue { +impl serde_core::Serialize for ListValue { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { self.values.serialize(ser) } } -impl<'de> serde::Deserialize<'de> for ListValue { +impl<'de> serde_core::Deserialize<'de> for ListValue { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { deserializer.deserialize_seq(ListValueVisitor) } @@ -56,7 +56,7 @@ impl<'de> serde::Deserialize<'de> for ListValue { struct ListValueVisitor; -impl<'de> serde::de::Visitor<'de> for ListValueVisitor { +impl<'de> serde_core::de::Visitor<'de> for ListValueVisitor { type Value = ListValue; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -65,7 +65,7 @@ impl<'de> serde::de::Visitor<'de> for ListValueVisitor { fn visit_seq(self, mut seq: A) -> Result where - A: serde::de::SeqAccess<'de>, + A: serde_core::de::SeqAccess<'de>, { let mut list = Vec::new(); diff --git a/pbjson-types/src/null_value.rs b/pbjson-types/src/null_value.rs index bd0f9af..dab7ec6 100644 --- a/pbjson-types/src/null_value.rs +++ b/pbjson-types/src/null_value.rs @@ -6,19 +6,19 @@ impl From<()> for NullValue { } } -impl serde::Serialize for NullValue { +impl serde_core::Serialize for NullValue { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { ().serialize(ser) } } -impl<'de> serde::Deserialize<'de> for NullValue { +impl<'de> serde_core::Deserialize<'de> for NullValue { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { deserializer.deserialize_unit(NullValueVisitor) } @@ -26,7 +26,7 @@ impl<'de> serde::Deserialize<'de> for NullValue { struct NullValueVisitor; -impl<'de> serde::de::Visitor<'de> for NullValueVisitor { +impl<'de> serde_core::de::Visitor<'de> for NullValueVisitor { type Value = NullValue; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -35,7 +35,7 @@ impl<'de> serde::de::Visitor<'de> for NullValueVisitor { fn visit_unit(self) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { Ok(NullValue::NullValue) } diff --git a/pbjson-types/src/struct.rs b/pbjson-types/src/struct.rs index 428dcaa..0bb939d 100644 --- a/pbjson-types/src/struct.rs +++ b/pbjson-types/src/struct.rs @@ -17,19 +17,19 @@ impl FromIterator<(String, crate::Value)> for Struct { } } -impl serde::Serialize for Struct { +impl serde_core::Serialize for Struct { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { self.fields.serialize(ser) } } -impl<'de> serde::Deserialize<'de> for Struct { +impl<'de> serde_core::Deserialize<'de> for Struct { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { deserializer.deserialize_map(StructVisitor) } @@ -37,7 +37,7 @@ impl<'de> serde::Deserialize<'de> for Struct { struct StructVisitor; -impl<'de> serde::de::Visitor<'de> for StructVisitor { +impl<'de> serde_core::de::Visitor<'de> for StructVisitor { type Value = Struct; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -46,7 +46,7 @@ impl<'de> serde::de::Visitor<'de> for StructVisitor { fn visit_map(self, mut map_access: A) -> Result where - A: serde::de::MapAccess<'de>, + A: serde_core::de::MapAccess<'de>, { let mut map = std::collections::HashMap::new(); diff --git a/pbjson-types/src/timestamp.rs b/pbjson-types/src/timestamp.rs index a842e13..80e33ad 100644 --- a/pbjson-types/src/timestamp.rs +++ b/pbjson-types/src/timestamp.rs @@ -1,7 +1,7 @@ use crate::Timestamp; use chrono::{DateTime, Utc}; -use serde::de::Visitor; -use serde::Serialize; +use serde_core::de::Visitor; +use serde_core::Serialize; impl TryFrom for DateTime { type Error = &'static str; @@ -30,9 +30,9 @@ impl From> for Timestamp { impl Serialize for Timestamp { fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { - let t: DateTime = (*self).try_into().map_err(serde::ser::Error::custom)?; + let t: DateTime = (*self).try_into().map_err(serde_core::ser::Error::custom)?; serializer.serialize_str(t.to_rfc3339().as_str()) } } @@ -48,18 +48,18 @@ impl<'de> Visitor<'de> for TimestampVisitor { fn visit_str(self, s: &str) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { - let d = DateTime::parse_from_rfc3339(s).map_err(serde::de::Error::custom)?; + let d = DateTime::parse_from_rfc3339(s).map_err(serde_core::de::Error::custom)?; let d: DateTime = d.into(); Ok(d.into()) } } -impl<'de> serde::Deserialize<'de> for Timestamp { +impl<'de> serde_core::Deserialize<'de> for Timestamp { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { deserializer.deserialize_str(TimestampVisitor) } @@ -69,8 +69,8 @@ impl<'de> serde::Deserialize<'de> for Timestamp { mod tests { use super::*; use chrono::{FixedOffset, TimeZone}; - use serde::de::value::{BorrowedStrDeserializer, Error}; - use serde::Deserialize; + use serde_core::de::value::{BorrowedStrDeserializer, Error}; + use serde_core::Deserialize; #[test] fn test_date() { diff --git a/pbjson-types/src/value.rs b/pbjson-types/src/value.rs index c3fc87b..6044242 100644 --- a/pbjson-types/src/value.rs +++ b/pbjson-types/src/value.rs @@ -1,6 +1,6 @@ pub use crate::pb::google::protobuf::value::Kind; -use serde::{ +use serde_core::{ de::{self, MapAccess, SeqAccess}, ser, Deserialize, Deserializer, Serialize, Serializer, }; @@ -113,7 +113,7 @@ impl<'de> Deserialize<'de> for Kind { struct KindVisitor; -impl<'de> serde::de::Visitor<'de> for KindVisitor { +impl<'de> serde_core::de::Visitor<'de> for KindVisitor { type Value = Kind; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/pbjson-types/src/wrappers.rs b/pbjson-types/src/wrappers.rs index 0c5fae0..63d9518 100644 --- a/pbjson-types/src/wrappers.rs +++ b/pbjson-types/src/wrappers.rs @@ -2,10 +2,10 @@ use prost::bytes::Bytes; macro_rules! ser_scalar_value { ($typ: ty) => { - impl serde::Serialize for $typ { + impl serde_core::Serialize for $typ { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { self.value.serialize(ser) } @@ -14,12 +14,12 @@ macro_rules! ser_scalar_value { } macro_rules! deser_scalar_value { ($typ: ty) => { - impl<'de> serde::Deserialize<'de> for $typ { + impl<'de> serde_core::Deserialize<'de> for $typ { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { - let value = serde::Deserialize::deserialize(deserializer)?; + let value = serde_core::Deserialize::deserialize(deserializer)?; Ok(Self { value }) } } @@ -27,10 +27,10 @@ macro_rules! deser_scalar_value { } macro_rules! ser_bytes_value { ($typ: ty) => { - impl serde::Serialize for $typ { + impl serde_core::Serialize for $typ { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { use pbjson::private::base64::engine::Engine; let value = @@ -42,10 +42,10 @@ macro_rules! ser_bytes_value { } macro_rules! deser_bytes_value { ($typ: ty) => { - impl<'de> serde::Deserialize<'de> for $typ { + impl<'de> serde_core::Deserialize<'de> for $typ { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { let value = pbjson::private::BytesDeserialize::deserialize(deserializer)?.0; Ok(Self { value }) @@ -55,10 +55,10 @@ macro_rules! deser_bytes_value { } macro_rules! ser_long_value { ($typ: ty) => { - impl serde::Serialize for $typ { + impl serde_core::Serialize for $typ { fn serialize(&self, ser: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { let value = self.value.to_string(); value.serialize(ser) @@ -68,10 +68,10 @@ macro_rules! ser_long_value { } macro_rules! deser_number_value { ($typ: ty) => { - impl<'de> serde::Deserialize<'de> for $typ { + impl<'de> serde_core::Deserialize<'de> for $typ { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { let value = pbjson::private::NumberDeserialize::deserialize(deserializer)?.0; Ok(Self { value }) diff --git a/pbjson/Cargo.toml b/pbjson/Cargo.toml index def9cef..f1082ba 100644 --- a/pbjson/Cargo.toml +++ b/pbjson/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/influxdata/pbjson" [dependencies] serde = { version = "1.0", features = ["derive"] } +serde_core = { version = "1.0.200" } base64 = "0.22" [dev-dependencies] diff --git a/pbjson/src/lib.rs b/pbjson/src/lib.rs index ea7828b..ddce160 100644 --- a/pbjson/src/lib.rs +++ b/pbjson/src/lib.rs @@ -1,5 +1,5 @@ -//! `pbjson` is a set of crates to automatically generate [`serde::Serialize`] and -//! [`serde::Deserialize`] implementations for [prost][1] generated structs that +//! `pbjson` is a set of crates to automatically generate [`serde_core::Serialize`] and +//! [`serde_core::Deserialize`] implementations for [prost][1] generated structs that //! are compliant with the [protobuf JSON mapping][2] //! //! See [pbjson-build][3] for usage instructions @@ -25,8 +25,8 @@ pub mod private { use base64::engine::DecodePaddingMode; use base64::engine::{GeneralPurpose, GeneralPurposeConfig}; use base64::Engine; - use serde::de::Visitor; - use serde::Deserialize; + use serde_core::de::Visitor; + use serde_core::Deserialize; use std::borrow::Cow; use std::str::FromStr; @@ -34,7 +34,7 @@ pub mod private { #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Hash, Ord, Eq)] pub struct NumberDeserialize(pub T); - #[derive(Deserialize)] + #[derive(serde::Deserialize)] #[serde(untagged)] enum Content<'a, T> { #[serde(borrow)] @@ -42,18 +42,18 @@ pub mod private { Number(T), } - impl<'de, T> serde::Deserialize<'de> for NumberDeserialize + impl<'de, T> Deserialize<'de> for NumberDeserialize where - T: FromStr + serde::Deserialize<'de>, + T: FromStr + Deserialize<'de>, ::Err: std::error::Error, { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { let content = Content::deserialize(deserializer)?; Ok(Self(match content { - Content::Str(v) => v.parse().map_err(serde::de::Error::custom)?, + Content::Str(v) => v.parse().map_err(serde_core::de::Error::custom)?, Content::Number(v) => v, })) } @@ -70,7 +70,7 @@ pub mod private { fn visit_str(self, s: &str) -> Result where - E: serde::de::Error, + E: serde_core::de::Error, { const INDIFFERENT_PAD: GeneralPurposeConfig = GeneralPurposeConfig::new() .with_decode_padding_mode(DecodePaddingMode::Indifferent); @@ -93,7 +93,7 @@ pub mod private { } _ => Err(e), }) - .map_err(serde::de::Error::custom)?; + .map_err(serde_core::de::Error::custom)?; Ok(decoded) } } @@ -107,7 +107,7 @@ pub mod private { { fn deserialize(deserializer: D) -> Result where - D: serde::Deserializer<'de>, + D: serde_core::Deserializer<'de>, { Ok(Self(deserializer.deserialize_str(Base64Visitor)?.into())) } @@ -119,7 +119,7 @@ pub mod private { use base64::Engine; use bytes::Bytes; use rand::prelude::*; - use serde::de::value::{BorrowedStrDeserializer, Error}; + use serde_core::de::value::{BorrowedStrDeserializer, Error}; #[test] fn test_bytes() {