use std::{fmt, marker::PhantomData, str::FromStr};
use itertools::Itertools;
use serde::{Deserializer, Serializer};
pub fn deserialize<'de, V, T, D>(deserializer: D) -> Result<V, D::Error>
where
V: FromIterator<T>,
T: FromStr,
T::Err: fmt::Display,
D: Deserializer<'de>,
{
struct CommaSeparated<V, T>(PhantomData<(T, V)>);
impl<V, T> serde::de::Visitor<'_> for CommaSeparated<V, T>
where
V: FromIterator<T>,
T: FromStr,
T::Err: fmt::Display,
{
type Value = V;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string containing comma-separated elements")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let iter = s.split(',').map(FromStr::from_str);
iter.collect::<Result<_, _>>()
.map_err(serde::de::Error::custom)
}
}
let visitor = CommaSeparated(PhantomData);
deserializer.deserialize_str(visitor)
}
pub fn serialize<S, T>(v: &[T], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: fmt::Display,
{
serializer.serialize_str(&v.iter().map(|v| v.to_string()).join(","))
}