use std::marker::PhantomData;
use chrono::NaiveDateTime;
use tokio_postgres as postgres;
use tokio_postgres::types::{to_sql_checked, FromSql, ToSql};
use ulid::Ulid;
use crate::Table;
use super::untyped_key;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Key<T> {
key: untyped_key::Key,
_phantom: PhantomData<T>,
}
impl<T: Table> Clone for Key<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Table> Copy for Key<T> {}
impl<T: Table> FromSql<'_> for Key<T> {
fn from_sql(
ty: &postgres::types::Type,
raw: &[u8],
) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(Self {
key: untyped_key::Key::from_sql(ty, raw)?,
_phantom: PhantomData,
})
}
fn accepts(ty: &postgres::types::Type) -> bool {
untyped_key::Key::accepts_impl(ty)
}
}
impl<T: std::fmt::Debug + Table> ToSql for Key<T> {
fn to_sql(
&self,
ty: &postgres::types::Type,
out: &mut bytes::BytesMut,
) -> Result<postgres::types::IsNull, Box<dyn std::error::Error + Sync + Send>>
where
Self: Sized,
{
self.key.to_sql(ty, out)
}
fn accepts(ty: &postgres::types::Type) -> bool
where
Self: Sized,
{
untyped_key::Key::accepts_impl(ty)
}
to_sql_checked!();
}
impl<T: Table> Key<T> {
pub fn from_untyped(key: untyped_key::Key) -> Self {
Self {
key,
_phantom: PhantomData,
}
}
pub fn new() -> Self {
Self {
key: untyped_key::Key::new(),
_phantom: PhantomData,
}
}
pub async fn fetch<C: postgres::GenericClient + Sync>(
self,
client: &C,
) -> Result<Option<T>, postgres::Error> {
T::fetch_by_key(self, client).await
}
pub async fn delete<C: postgres::GenericClient + Sync>(
self,
client: &C,
) -> Result<u64, postgres::Error> {
T::delete_by_key(self, client).await
}
pub fn inner(&self) -> Ulid {
self.key.0
}
pub fn timestamp(&self) -> NaiveDateTime {
let ms = self.key.0.timestamp_ms();
let ms = ms as i64;
NaiveDateTime::from_timestamp_millis(ms).unwrap()
}
pub fn untyped(&self) -> untyped_key::Key {
self.key
}
}
impl<T: Table + std::fmt::Debug> std::fmt::Debug for Key<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.key.0)
}
}