use super::{Expr, IntoExpr, List, Path, Value};
use crate::schema::{Field, Load};
use toasty_core::schema::app::{FieldPrimitive, FieldTy, SerializeFormat};
use toasty_core::{schema::db, stmt};
use std::fmt;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Json<T>(pub T);
impl<T> From<T> for Json<T> {
fn from(value: T) -> Self {
Json(value)
}
}
impl<T> std::ops::Deref for Json<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> std::ops::DerefMut for Json<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T> AsRef<T> for Json<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T> AsMut<T> for Json<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T> Load for Json<T>
where
T: for<'de> serde_core::Deserialize<'de>,
{
type Output = Self;
fn ty() -> stmt::Type {
stmt::Type::String
}
fn load(value: stmt::Value) -> crate::Result<Self> {
let json = <String as Load>::load(value)?;
serde_json::from_str(&json).map(Json).map_err(|e| {
toasty_core::Error::from_args(format_args!("failed to deserialize JSON field: {e}"))
})
}
fn reload(target: &mut Self, value: stmt::Value) -> crate::Result<()> {
*target = Self::load(value)?;
Ok(())
}
}
impl<T> Field for Json<T>
where
T: serde_core::Serialize + for<'de> serde_core::Deserialize<'de>,
{
type ExprTarget = Self;
type Path<Origin> = Path<Origin, Self>;
type ListPath<Origin> = Path<Origin, List<Self::ExprTarget>>;
type Update<'a> = ();
type Inner = Self;
fn new_path<Origin>(path: Path<Origin, Self>) -> Self::Path<Origin> {
path
}
fn new_list_path<Origin>(path: Path<Origin, List<Self::ExprTarget>>) -> Self::ListPath<Origin> {
path
}
fn new_update<'a>(
_assignments: &'a mut toasty_core::stmt::Assignments,
_projection: toasty_core::stmt::Projection,
) -> Self::Update<'a> {
}
fn field_ty(storage_ty: Option<db::Type>) -> FieldTy {
FieldTy::Primitive(FieldPrimitive {
ty: stmt::Type::String,
storage_ty,
serialize: Some(SerializeFormat::Json),
})
}
fn key_constraint<Origin>(&self, _target: Path<Origin, Self::Inner>) -> Expr<bool> {
unreachable!("Json<T> fields cannot be used as foreign-key targets")
}
}
impl<T> IntoExpr<Json<T>> for Json<T>
where
T: serde_core::Serialize,
{
fn into_expr(self) -> Expr<Json<T>> {
let json = serde_json::to_string(&self.0).expect("failed to serialize");
Expr::<String>::from_value(Value::from(json)).cast()
}
fn by_ref(&self) -> Expr<Json<T>> {
let json = serde_json::to_string(&self.0).expect("failed to serialize");
Expr::<String>::from_value(Value::from(json)).cast()
}
}
impl<T> IntoExpr<Json<T>> for T
where
T: serde_core::Serialize,
{
fn into_expr(self) -> Expr<Json<T>> {
let json = serde_json::to_string(&self).expect("failed to serialize");
Expr::<String>::from_value(Value::from(json)).cast()
}
fn by_ref(&self) -> Expr<Json<T>> {
let json = serde_json::to_string(self).expect("failed to serialize");
Expr::<String>::from_value(Value::from(json)).cast()
}
}
impl<T> super::assignment::Assign<Json<T>> for Json<T>
where
T: serde_core::Serialize,
{
fn into_assignment(self) -> super::assignment::Assignment<Json<T>> {
super::set(<Self as IntoExpr<Json<T>>>::into_expr(self))
}
}
impl<T> super::assignment::Assign<Json<T>> for T
where
T: serde_core::Serialize,
{
fn into_assignment(self) -> super::assignment::Assignment<Json<T>> {
super::set(<Self as IntoExpr<Json<T>>>::into_expr(self))
}
}
impl<T: fmt::Display> fmt::Display for Json<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}