use corium_core::{EntityId, Keyword, TotalF64};
use corium_query::edn::Edn;
use crate::ClientError;
pub trait IntoEdn {
fn into_edn(self) -> Edn;
}
impl IntoEdn for Edn {
fn into_edn(self) -> Edn {
self
}
}
impl IntoEdn for &Edn {
fn into_edn(self) -> Edn {
self.clone()
}
}
impl IntoEdn for bool {
fn into_edn(self) -> Edn {
Edn::Bool(self)
}
}
impl IntoEdn for i64 {
fn into_edn(self) -> Edn {
Edn::Long(self)
}
}
impl IntoEdn for i32 {
fn into_edn(self) -> Edn {
Edn::Long(i64::from(self))
}
}
impl IntoEdn for u32 {
fn into_edn(self) -> Edn {
Edn::Long(i64::from(self))
}
}
impl IntoEdn for f64 {
fn into_edn(self) -> Edn {
Edn::Double(TotalF64(self))
}
}
impl IntoEdn for &str {
fn into_edn(self) -> Edn {
Edn::Str(self.to_owned())
}
}
impl IntoEdn for String {
fn into_edn(self) -> Edn {
Edn::Str(self)
}
}
impl IntoEdn for &String {
fn into_edn(self) -> Edn {
Edn::Str(self.clone())
}
}
impl IntoEdn for Keyword {
fn into_edn(self) -> Edn {
Edn::Keyword(self)
}
}
impl IntoEdn for &Keyword {
fn into_edn(self) -> Edn {
Edn::Keyword(self.clone())
}
}
impl IntoEdn for EntityId {
fn into_edn(self) -> Edn {
Edn::Long(i64::try_from(self.raw()).unwrap_or(i64::MAX))
}
}
pub trait FromEdn: Sized {
fn from_edn(form: &Edn) -> Result<Self, ClientError>;
}
fn decode_err(what: &str, form: &Edn) -> ClientError {
ClientError::Decode(format!("expected {what}, got {form}"))
}
impl FromEdn for Edn {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
Ok(form.clone())
}
}
impl FromEdn for bool {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Bool(value) => Ok(*value),
other => Err(decode_err("bool", other)),
}
}
}
impl FromEdn for i64 {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Long(value) => Ok(*value),
other => Err(decode_err("long", other)),
}
}
}
impl FromEdn for f64 {
#[allow(clippy::cast_precision_loss)]
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Double(value) => Ok(value.0),
Edn::Long(value) => Ok(*value as Self),
other => Err(decode_err("double", other)),
}
}
}
impl FromEdn for String {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Str(value) => Ok(value.clone()),
other => Err(decode_err("string", other)),
}
}
}
impl FromEdn for Keyword {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Keyword(value) => Ok(value.clone()),
other => Err(decode_err("keyword", other)),
}
}
}
impl FromEdn for EntityId {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Long(value) => u64::try_from(*value)
.map(EntityId::from_raw)
.map_err(|_| decode_err("entity id", form)),
other => Err(decode_err("entity id", other)),
}
}
}
impl<T: FromEdn> FromEdn for Option<T> {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Nil => Ok(None),
other => T::from_edn(other).map(Some),
}
}
}
impl<T: FromEdn> FromEdn for Vec<T> {
fn from_edn(form: &Edn) -> Result<Self, ClientError> {
match form {
Edn::Vector(items) | Edn::List(items) | Edn::Set(items) => {
items.iter().map(T::from_edn).collect()
}
other => Err(decode_err("collection", other)),
}
}
}