use bytes::BytesMut;
use postgres_protocol::types;
use std::error::Error;
use std::{i32, i64};
use crate::{FromSql, IsNull, ToSql, Type};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Date<T> {
PosInfinity,
NegInfinity,
Value(T),
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Date<T> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
match types::date_from_sql(raw)? {
i32::MAX => Ok(Date::PosInfinity),
i32::MIN => Ok(Date::NegInfinity),
_ => T::from_sql(ty, raw).map(Date::Value),
}
}
fn accepts(ty: &Type) -> bool {
*ty == Type::DATE && T::accepts(ty)
}
}
impl<T: ToSql> ToSql for Date<T> {
fn to_sql(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
let value = match *self {
Date::PosInfinity => i32::MAX,
Date::NegInfinity => i32::MIN,
Date::Value(ref v) => return v.to_sql(ty, out),
};
types::date_to_sql(value, out);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
*ty == Type::DATE && T::accepts(ty)
}
to_sql_checked!();
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Timestamp<T> {
PosInfinity,
NegInfinity,
Value(T),
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Timestamp<T> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
match types::timestamp_from_sql(raw)? {
i64::MAX => Ok(Timestamp::PosInfinity),
i64::MIN => Ok(Timestamp::NegInfinity),
_ => T::from_sql(ty, raw).map(Timestamp::Value),
}
}
fn accepts(ty: &Type) -> bool {
matches!(*ty, Type::TIMESTAMP | Type::TIMESTAMPTZ if T::accepts(ty))
}
}
impl<T: ToSql> ToSql for Timestamp<T> {
fn to_sql(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
let value = match *self {
Timestamp::PosInfinity => i64::MAX,
Timestamp::NegInfinity => i64::MIN,
Timestamp::Value(ref v) => return v.to_sql(ty, out),
};
types::timestamp_to_sql(value, out);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
matches!(*ty, Type::TIMESTAMP | Type::TIMESTAMPTZ if T::accepts(ty))
}
to_sql_checked!();
}