From b2a1b794f3f45a9b95a1709f6f85c56261523994 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Fri, 7 Jul 2023 14:25:44 +0200 Subject: [PATCH] Support Deserialization for `VarZeroVec` (#3643) --- utils/zerovec/src/varzerovec/serde.rs | 124 +++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/utils/zerovec/src/varzerovec/serde.rs b/utils/zerovec/src/varzerovec/serde.rs index 649b29cfb25..ece4c37cc91 100644 --- a/utils/zerovec/src/varzerovec/serde.rs +++ b/utils/zerovec/src/varzerovec/serde.rs @@ -25,6 +25,32 @@ impl Default for VarZeroVecVisitor { } } +struct VarZeroSliceBoxVisitor { + #[allow(clippy::type_complexity)] // this is a private marker type, who cares + marker: PhantomData<(fn() -> Box, F)>, +} + +impl Default for VarZeroSliceBoxVisitor { + fn default() -> Self { + Self { + marker: PhantomData, + } + } +} + +struct VarZeroSliceRefVisitor { + #[allow(clippy::type_complexity)] // this is a private marker type, who cares + marker: PhantomData<(fn() -> Box, F)>, +} + +impl Default for VarZeroSliceRefVisitor { + fn default() -> Self { + Self { + marker: PhantomData, + } + } +} + impl<'de, T, F> Visitor<'de> for VarZeroVecVisitor where T: VarULE + ?Sized, @@ -60,6 +86,62 @@ where } } +impl<'de, T, F> Visitor<'de> for VarZeroSliceBoxVisitor +where + T: VarULE + ?Sized, + Box: Deserialize<'de>, + F: VarZeroVecFormat, +{ + type Value = Box>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence or borrowed buffer of bytes") + } + + fn visit_borrowed_bytes(self, bytes: &'de [u8]) -> Result + where + E: de::Error, + { + VarZeroSlice::parse_byte_slice(bytes) + .map(VarULE::to_boxed) + .map_err(de::Error::custom) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut vec: Vec> = if let Some(capacity) = seq.size_hint() { + Vec::with_capacity(capacity) + } else { + Vec::new() + }; + while let Some(value) = seq.next_element::>()? { + vec.push(value); + } + Ok(VarZeroVec::from(&vec).to_boxed()) + } +} + +impl<'de, T, F> Visitor<'de> for VarZeroSliceRefVisitor +where + T: VarULE + ?Sized, + F: VarZeroVecFormat, +{ + type Value = &'de VarZeroSlice; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence or borrowed buffer of bytes") + } + + fn visit_borrowed_bytes(self, bytes: &'de [u8]) -> Result + where + E: de::Error, + { + VarZeroSlice::parse_byte_slice(bytes).map_err(de::Error::custom) + } +} + /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate impl<'de, 'a, T, F> Deserialize<'de> for VarZeroVec<'a, T, F> where @@ -72,7 +154,7 @@ where where D: Deserializer<'de>, { - let visitor = VarZeroVecVisitor::default(); + let visitor: VarZeroVecVisitor = VarZeroVecVisitor::default(); if deserializer.is_human_readable() { deserializer.deserialize_seq(visitor) } else { @@ -85,7 +167,6 @@ where impl<'de, 'a, T, F> Deserialize<'de> for &'a VarZeroSlice where T: VarULE + ?Sized, - Box: Deserialize<'de>, F: VarZeroVecFormat, 'de: 'a, { @@ -98,15 +179,30 @@ where "&VarZeroSlice cannot be deserialized from human-readable formats", )) } else { - let deserialized: VarZeroVec<'a, T, F> = VarZeroVec::deserialize(deserializer)?; - let borrowed = if let VarZeroVec::Borrowed(b) = deserialized { - b - } else { - return Err(de::Error::custom( - "&VarZeroSlice can only deserialize in zero-copy ways", - )); - }; - Ok(borrowed) + let visitor: VarZeroSliceRefVisitor = VarZeroSliceRefVisitor::default(); + let deserialized: &'a VarZeroSlice<_, _> = deserializer.deserialize_bytes(visitor)?; + Ok(deserialized) + } + } +} + +/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate +impl<'de, 'a, T, F> Deserialize<'de> for Box> +where + T: VarULE + ?Sized, + Box: Deserialize<'de>, + F: VarZeroVecFormat, + 'de: 'a, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let visitor: VarZeroSliceBoxVisitor = VarZeroSliceBoxVisitor::default(); + if deserializer.is_human_readable() { + deserializer.deserialize_seq(visitor) + } else { + deserializer.deserialize_bytes(visitor) } } } @@ -160,6 +256,12 @@ mod test { _data: VarZeroVec<'data, str>, } + #[derive(serde::Serialize, serde::Deserialize)] + struct DeriveTest_VarZeroVec_of_VarZeroSlice<'data> { + #[serde(borrow)] + _data: VarZeroVec<'data, VarZeroSlice>, + } + #[derive(serde::Serialize, serde::Deserialize)] struct DeriveTest_VarZeroSlice<'data> { #[serde(borrow)]