Implement Serde traits for `ffi_safe::Vec`

This commit is contained in:
Hanno Braun 2022-11-07 16:08:38 +01:00
parent c14e343913
commit 20181e4d4d
2 changed files with 30 additions and 65 deletions

View File

@ -127,6 +127,35 @@ impl<T> Drop for Vec<T> {
unsafe impl<T: Send> Send for Vec<T> {}
unsafe impl<T: Sync> Sync for Vec<T> {}
#[cfg(feature = "serde")]
impl<T> serde::ser::Serialize for Vec<T>
where
T: serde::ser::Serialize,
{
fn serialize<S>(
&self,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
self.deref().serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T> serde::de::Deserialize<'de> for Vec<T>
where
T: serde::de::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
Ok(std::vec::Vec::deserialize(deserializer)?.into())
}
}
/// A FFI-safe version of `Box<str>`.
#[repr(transparent)]
#[derive(Debug, PartialEq, Clone)]

View File

@ -169,6 +169,7 @@ impl Circle {
/// A polygonal chain that is part of a [`Sketch`]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct PolyChain {
points: ffi_safe::Vec<[f64; 2]>,
@ -187,48 +188,6 @@ impl PolyChain {
}
}
#[cfg(feature = "serde")]
impl serde::ser::Serialize for PolyChain {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
let serde_sketch = PolyChainSerde {
points: self.to_points(),
};
serde_sketch.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::de::Deserialize<'de> for PolyChain {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
PolyChainSerde::deserialize(deserializer)
.map(|serde_sketch| PolyChain::from_points(serde_sketch.points))
}
}
/// An owned, non-repr-C [`PolyChain`]
///
/// De/serializing a non-trivial structure with raw pointers is a hassle.
/// This structure is a simple, owned intermediate form that can use the derive
/// macros provided by serde. The implementation of the `Serialize` and
/// `Deserialize` traits for [`PolyChain`] use this type as a stepping stone.
///
/// Note that constructing this requires cloning the points behind
/// [`PolyChain`]. If de/serialization turns out to be a bottleneck, a more
/// complete implementation will be required.
#[cfg(feature = "serde")]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename = "Polyline")]
struct PolyChainSerde {
points: Vec<[f64; 2]>,
}
impl From<Sketch> for Shape {
fn from(shape: Sketch) -> Self {
Self::Shape2d(shape.into())
@ -240,26 +199,3 @@ impl From<Sketch> for Shape2d {
Shape2d::Sketch(shape)
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "serde")]
#[test]
fn test_poly_chain_serialize_loopback() {
use serde_json::{from_str, to_string};
let poly_chain = super::PolyChain::from_points(vec![
[1.0, 1.0],
[2.0, 1.0],
[2.0, 2.0],
[1.0, 2.0],
]);
let json = to_string(&poly_chain).expect("failed to serialize sketch");
let poly_chain_de: super::PolyChain =
from_str(&json).expect("failed to deserialize sketch");
// ensure same content
assert_eq!(poly_chain.to_points(), poly_chain_de.to_points());
}
}