use alloc::collections::BTreeMap;
#[cfg(feature = "sets")]
use alloc::collections::BTreeSet;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::any;
#[allow(unused_imports, reason = "not used in all targets")]
use core::convert::{Into, TryFrom};
use core::str::FromStr;
#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(all(feature = "sets", feature = "std"))]
use std::collections::HashSet;
use crate::edn::{Edn, Error};
pub mod parse;
#[cfg(feature = "sets")]
use ordered_float::OrderedFloat;
#[allow(clippy::missing_errors_doc)]
pub trait Deserialize: Sized {
fn deserialize(edn: &Edn) -> Result<Self, Error>;
}
fn build_deserialize_error(edn: &Edn, type_: &str) -> Error {
Error::Deserialize(format!("couldn't convert `{edn}` into `{type_}`"))
}
impl Deserialize for () {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Nil => Ok(()),
_ => Err(build_deserialize_error(edn, "unit")),
}
}
}
#[cfg(feature = "sets")]
impl Deserialize for OrderedFloat<f64> {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
edn.to_float()
.ok_or_else(|| build_deserialize_error(edn, "edn_rs::Double"))
.map(Into::into)
}
}
impl Deserialize for f64 {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
edn.to_float()
.ok_or_else(|| build_deserialize_error(edn, "edn_rs::Double"))
}
}
macro_rules! impl_deserialize_int {
( $( $name:ty ),+ ) => {
$(
impl Deserialize for $name {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
let int = edn
.to_int()
.ok_or_else(|| build_deserialize_error(edn, "int"))?;
Ok(Self::try_from(int)?)
}
}
)+
};
}
impl_deserialize_int!(i8, i16, i32, i64, isize);
macro_rules! impl_deserialize_uint {
( $( $name:ty ),+ ) => {
$(
impl Deserialize for $name {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
let uint = edn
.to_uint()
.ok_or_else(|| build_deserialize_error(edn, "uint"))?;
Ok(Self::try_from(uint)?)
}
}
)+
};
}
impl_deserialize_uint!(u8, u16, u32, u64, usize);
impl Deserialize for bool {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
edn.to_bool()
.ok_or_else(|| build_deserialize_error(edn, "bool"))
}
}
impl Deserialize for String {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Str(s) => {
if s.starts_with('\"') {
Ok(s.replace('\"', ""))
} else {
Ok(s.clone())
}
}
e => Ok(e.to_string()),
}
}
}
impl Deserialize for char {
fn deserialize(edn: &Edn) -> Result<Self, Error> {
edn.to_char()
.ok_or_else(|| build_deserialize_error(edn, "char"))
}
}
impl<T> Deserialize for Vec<T>
where
T: Deserialize,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Vector(_) => Ok(edn
.iter_some()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|e| Deserialize::deserialize(e))
.collect::<Result<Self, Error>>()?),
Edn::List(_) => Ok(edn
.iter_some()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|e| Deserialize::deserialize(e))
.collect::<Result<Self, Error>>()?),
#[cfg(feature = "sets")]
Edn::Set(_) => Ok(edn
.iter_some()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|e| Deserialize::deserialize(e))
.collect::<Result<Self, Error>>()?),
_ => Err(build_deserialize_error(edn, any::type_name::<Self>())),
}
}
}
#[cfg(feature = "std")]
impl<T, H> Deserialize for HashMap<String, T, H>
where
T: Deserialize,
H: std::hash::BuildHasher + std::default::Default,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Map(_) => edn
.map_iter()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|(key, e)| {
Ok((
key.clone(),
Deserialize::deserialize(e).map_err(|_| {
Error::Deserialize(format!(
"Cannot safely deserialize {:?} to {}",
edn, "HashMap"
))
})?,
))
})
.collect::<Result<Self, Error>>(),
_ => Err(build_deserialize_error(edn, any::type_name::<Self>())),
}
}
}
impl<T> Deserialize for BTreeMap<String, T>
where
T: Deserialize,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Map(_) => edn
.map_iter()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|(key, e)| {
Ok((
key.clone(),
Deserialize::deserialize(e).map_err(|_| {
Error::Deserialize(format!(
"Cannot safely deserialize {:?} to {}",
edn, "BTreeMap"
))
})?,
))
})
.collect::<Result<Self, Error>>(),
_ => Err(build_deserialize_error(edn, any::type_name::<Self>())),
}
}
}
#[cfg(all(feature = "sets", feature = "std"))]
impl<T, H> Deserialize for HashSet<T, H>
where
T: std::cmp::Eq + std::hash::Hash + Deserialize,
H: std::hash::BuildHasher + std::default::Default,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Set(_) => edn
.set_iter()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|e| {
Deserialize::deserialize(e).map_err(|_| {
Error::Deserialize(format!(
"Cannot safely deserialize {:?} to {}",
edn, "HashSet"
))
})
})
.collect::<Result<Self, Error>>(),
_ => Err(build_deserialize_error(edn, any::type_name::<Self>())),
}
}
}
#[cfg(feature = "sets")]
impl<T> Deserialize for BTreeSet<T>
where
T: core::cmp::Eq + core::hash::Hash + core::cmp::Ord + Deserialize,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Set(_) => edn
.set_iter()
.ok_or_else(|| Error::Iter(format!("Could not create iter from {edn:?}")))?
.map(|e| {
Deserialize::deserialize(e).map_err(|_| {
Error::Deserialize(format!(
"Cannot safely deserialize {:?} to {}",
edn, "BTreeSet"
))
})
})
.collect::<Result<Self, Error>>(),
_ => Err(build_deserialize_error(edn, any::type_name::<Self>())),
}
}
}
impl<T> Deserialize for Option<T>
where
T: Deserialize,
{
fn deserialize(edn: &Edn) -> Result<Self, Error> {
match edn {
Edn::Nil => Ok(None),
_ => Ok(Some(from_edn(edn)?)),
}
}
}
pub fn from_str<T: Deserialize>(s: &str) -> Result<T, Error> {
let edn = Edn::from_str(s)?;
from_edn(&edn)
}
pub fn from_edn<T: Deserialize>(edn: &Edn) -> Result<T, Error> {
T::deserialize(edn)
}