use std::str::FromStr;
use serde::{
de::{SeqAccess, Visitor},
ser::SerializeSeq,
Deserialize, Serialize,
};
use serde_json::Number;
use crate::{gc::*, obj::Obj, Int, Map};
use std::{fmt, marker::PhantomData};
use im::HashMap;
use num_bigint::BigInt;
use serde::de::{self, Unexpected};
impl<T: Serialize + GcCompat> Serialize for GcCow<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
GcCow::call_ref_unchecked(*self, |x| x.serialize(serializer))
}
}
impl<'de, T: Deserialize<'de> + GcCompat> Deserialize<'de> for GcCow<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let x = T::deserialize(deserializer)?;
Ok(GcCow::new(x))
}
}
impl Serialize for Int {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let jv = Number::from_str(&format!("{self}")).unwrap();
jv.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Int {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let jv = Number::deserialize(deserializer)?;
Ok(Int::wrap(jv.as_str().parse::<BigInt>().map_err(|_| {
de::Error::invalid_value(
Unexpected::Other(format!("non-integer number {}", jv.as_str()).leak()),
&"an integer",
)
})?))
}
}
impl<K: Serialize + Obj, V: Serialize + Obj> Serialize for Map<K, V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut eleser = serializer.serialize_seq(Some(self.len_as_usize()))?;
for kv in self.iter() {
eleser.serialize_element(&kv)?;
}
eleser.end()
}
}
impl<'de, K: Obj + Deserialize<'de>, V: Obj + Deserialize<'de>> Deserialize<'de> for Map<K, V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct ElmVisitor<K, V>(PhantomData<K>, PhantomData<V>);
impl<'de, K: Obj + Deserialize<'de>, V: Obj + Deserialize<'de>> Visitor<'de> for ElmVisitor<K, V> {
type Value = Map<K, V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a libspecr::Map<_, _>")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut map = HashMap::new();
while let Some((k, v)) = seq.next_element::<(K, V)>()? {
let None = map.insert(k, v) else {
return Err(de::Error::duplicate_field(format!("{:?}", k).leak()));
};
}
Ok(Map(GcCow::new(map)))
}
}
deserializer.deserialize_seq(ElmVisitor::<K, V>(PhantomData, PhantomData))
}
}