use serde_json::Value;
pub trait PersistValue: Sized + 'static {
fn to_json(&self) -> Value;
fn from_json(value: &Value) -> Option<Self>;
}
impl PersistValue for bool {
fn to_json(&self) -> Value {
Value::Bool(*self)
}
fn from_json(value: &Value) -> Option<Self> {
value.as_bool()
}
}
impl PersistValue for String {
fn to_json(&self) -> Value {
Value::String(self.clone())
}
fn from_json(value: &Value) -> Option<Self> {
value.as_str().map(str::to_owned)
}
}
macro_rules! persist_int {
($($ty:ty),* $(,)?) => {
$(
impl PersistValue for $ty {
fn to_json(&self) -> Value {
Value::from(*self)
}
fn from_json(value: &Value) -> Option<Self> {
value.as_i64().and_then(|n| Self::try_from(n).ok())
.or_else(|| value.as_u64().and_then(|n| Self::try_from(n).ok()))
}
}
)*
};
}
persist_int!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
impl PersistValue for f32 {
fn to_json(&self) -> Value {
Value::from(*self)
}
fn from_json(value: &Value) -> Option<Self> {
value.as_f64().map(|n| n as f32)
}
}
impl PersistValue for f64 {
fn to_json(&self) -> Value {
Value::from(*self)
}
fn from_json(value: &Value) -> Option<Self> {
value.as_f64()
}
}
impl<T: PersistValue> PersistValue for Vec<T> {
fn to_json(&self) -> Value {
Value::Array(self.iter().map(PersistValue::to_json).collect())
}
fn from_json(value: &Value) -> Option<Self> {
value.as_array()?.iter().map(T::from_json).collect()
}
}