use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
use super::Model;
#[derive(Debug, Clone)]
pub struct ReverseSet<C: Model> {
parent_id: Option<serde_json::Value>,
fk_column: Option<&'static str>,
resolved: Option<Vec<C>>,
_phantom: PhantomData<C>,
}
impl<C: Model> Default for ReverseSet<C> {
fn default() -> Self {
Self::empty()
}
}
impl<C: Model> ReverseSet<C> {
pub fn empty() -> Self {
Self {
parent_id: None,
fk_column: None,
resolved: None,
_phantom: PhantomData,
}
}
pub fn resolved(&self) -> Option<&[C]> {
self.resolved.as_deref()
}
pub fn set_parent_id(&mut self, id: serde_json::Value) {
self.parent_id = Some(id);
}
pub fn set_fk_column(&mut self, col: &'static str) {
self.fk_column = Some(col);
}
pub fn parent_link(&self) -> Option<(&serde_json::Value, &'static str)> {
match (&self.parent_id, self.fk_column) {
(Some(id), Some(col)) => Some((id, col)),
_ => None,
}
}
pub fn set_resolved(&mut self, rows: Vec<C>) {
self.resolved = Some(rows);
}
}
impl<C: Model + Serialize> Serialize for ReverseSet<C> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match &self.resolved {
Some(rows) => rows.serialize(s),
None => Vec::<C>::new().serialize(s),
}
}
}
impl<'de, C: Model + Deserialize<'de>> Deserialize<'de> for ReverseSet<C> {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let opt = Option::<Vec<C>>::deserialize(d).unwrap_or(None);
Ok(Self {
parent_id: None,
fk_column: None,
resolved: opt,
_phantom: PhantomData,
})
}
}
impl<C: Model> sqlx::Type<sqlx::Sqlite> for ReverseSet<C> {
fn type_info() -> sqlx::sqlite::SqliteTypeInfo {
<i64 as sqlx::Type<sqlx::Sqlite>>::type_info()
}
fn compatible(ty: &sqlx::sqlite::SqliteTypeInfo) -> bool {
<i64 as sqlx::Type<sqlx::Sqlite>>::compatible(ty)
}
}
impl<C: Model> sqlx::Type<sqlx::Postgres> for ReverseSet<C> {
fn type_info() -> sqlx::postgres::PgTypeInfo {
<i64 as sqlx::Type<sqlx::Postgres>>::type_info()
}
fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool {
<i64 as sqlx::Type<sqlx::Postgres>>::compatible(ty)
}
}
impl<'r, C: Model> sqlx::Decode<'r, sqlx::Sqlite> for ReverseSet<C> {
fn decode(
value: sqlx::sqlite::SqliteValueRef<'r>,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
let _ = <i64 as sqlx::Decode<sqlx::Sqlite>>::decode(value)?;
Ok(Self::empty())
}
}
impl<'r, C: Model> sqlx::Decode<'r, sqlx::Postgres> for ReverseSet<C> {
fn decode(
value: sqlx::postgres::PgValueRef<'r>,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
let _ = <i64 as sqlx::Decode<sqlx::Postgres>>::decode(value)?;
Ok(Self::empty())
}
}