rust-postgres/postgres-types/src/special.rs

110 lines
3.0 KiB
Rust
Raw Normal View History

use bytes::BytesMut;
use postgres_protocol::types;
use std::error::Error;
use std::{i32, i64};
use crate::{FromSql, IsNull, ToSql, Type};
/// A wrapper that can be used to represent infinity with `Type::Date` types.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Date<T> {
/// Represents `infinity`, a date that is later than all other dates.
PosInfinity,
/// Represents `-infinity`, a date that is earlier than all other dates.
NegInfinity,
/// The wrapped date.
Value(T),
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Date<T> {
2018-12-09 01:40:37 +00:00
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
2017-02-15 06:46:19 +00:00
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 {
2018-04-22 21:55:20 +00:00
*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 {
2018-04-22 21:55:20 +00:00
*ty == Type::DATE && T::accepts(ty)
}
to_sql_checked!();
}
2016-02-22 03:17:23 +00:00
/// A wrapper that can be used to represent infinity with `Type::Timestamp` and `Type::Timestamptz`
/// types.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Timestamp<T> {
/// Represents `infinity`, a timestamp that is later than all other timestamps.
PosInfinity,
/// Represents `-infinity`, a timestamp that is earlier than all other timestamps.
NegInfinity,
/// The wrapped timestamp.
Value(T),
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Timestamp<T> {
2018-12-09 01:40:37 +00:00
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
2017-02-15 06:46:19 +00:00
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 {
2017-07-09 07:02:45 +00:00
match *ty {
2018-04-22 21:55:20 +00:00
Type::TIMESTAMP | Type::TIMESTAMPTZ if T::accepts(ty) => true,
_ => false,
2017-07-09 07:02:45 +00:00
}
}
}
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 {
2017-07-09 07:02:45 +00:00
match *ty {
2018-04-22 21:55:20 +00:00
Type::TIMESTAMP | Type::TIMESTAMPTZ if T::accepts(ty) => true,
_ => false,
2017-07-09 07:02:45 +00:00
}
}
to_sql_checked!();
}