use crate::{QList, QListElement, QSet, QSetElement, QStringList, QVector, QVectorElement};
use cxx::ExternType;
use serde::de::{SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{self, Formatter};
use std::marker::PhantomData;
macro_rules! seq_impl {
($t:ident, $element:ident, $insert:expr) => {
impl<T> Serialize for $t<T>
where
T: $element + Serialize,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_seq(self.iter())
}
}
impl<'de, T> Deserialize<'de> for $t<T>
where
T: $element + Deserialize<'de> + ExternType<Kind = cxx::kind::Trivial>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct SeqVisitor<T: $element> {
marker: PhantomData<$t<T>>,
}
impl<'de, T> Visitor<'de> for SeqVisitor<T>
where
T: $element + Deserialize<'de> + ExternType<Kind = cxx::kind::Trivial>,
{
type Value = $t<T>;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = Self::Value::default();
if let Some(size_hint) = seq.size_hint() {
values.reserve_usize(size_hint);
}
while let Some(value) = seq.next_element()? {
$insert(&mut values, value);
}
Ok(values)
}
}
let visitor = SeqVisitor {
marker: PhantomData,
};
deserializer.deserialize_seq(visitor)
}
}
};
}
seq_impl!(QList, QListElement, QList::append);
seq_impl!(QSet, QSetElement, QSet::insert);
seq_impl!(QVector, QVectorElement, QVector::append);
macro_rules! deref_impl {
($t:ty) => {
impl Serialize for $t {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
(**self).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for $t {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct SeqVisitor;
impl<'de> Visitor<'de> for SeqVisitor {
type Value = $t;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut list = Self::Value::default();
let values = &mut *list;
if let Some(size_hint) = seq.size_hint() {
values.reserve_usize(size_hint);
}
while let Some(value) = seq.next_element()? {
values.append(value);
}
Ok(list)
}
}
let visitor = SeqVisitor;
deserializer.deserialize_seq(visitor)
}
}
};
}
deref_impl!(QStringList);
#[cfg(test)]
pub fn roundtrip<T>(value: &T) -> T
where
T: Serialize + serde::de::DeserializeOwned,
{
let serialized = serde_json::to_value(value).expect("error serializing value");
match serde_json::from_value(serialized) {
Ok(deserialized) => deserialized,
Err(e) => panic!(
"error deserializing {}: {e}",
serde_json::to_value(value).unwrap()
),
}
}