tank-postgres 0.36.0

Postgres driver implementation for Tank: the Rust data layer
Documentation
use byteorder::{NetworkEndian, ReadBytesExt};
use bytes::{BufMut, BytesMut};
use postgres_types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
use std::{error::Error, io::Cursor};
use tank_core::Interval;

#[derive(Debug)]
pub(crate) struct IntervalWrap(pub(crate) Interval);

impl ToSql for IntervalWrap {
    fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
    where
        Self: Sized,
    {
        if !matches!(*ty, Type::INTERVAL) {
            return Err(
                tank_core::Error::msg(format!("Cannot write Interval into type: {}", ty)).into(),
            );
        }
        let micros_all = self.0.nanos / 1000;
        let micros = micros_all.clamp(i64::MIN as i128, i64::MAX as i128) as i64;
        let days = (self.0.days as i128 + (micros_all - micros as i128) / Interval::MICROS_IN_DAY)
            .clamp(i32::MIN as i128, i32::MAX as i128) as i32;
        let months = self.0.months.clamp(i32::MIN as i64, i32::MAX as i64) as i32;
        out.put_i64(micros);
        out.put_i32(days);
        out.put_i32(months);
        Ok(IsNull::No)
    }

    fn accepts(ty: &Type) -> bool
    where
        Self: Sized,
    {
        matches!(*ty, Type::INTERVAL)
    }

    to_sql_checked!();
}

impl<'a> FromSql<'a> for IntervalWrap {
    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        if !matches!(*ty, Type::INTERVAL) {
            return Err(tank_core::Error::msg(format!(
                "Cannot read Interval sql from type: {}",
                ty
            ))
            .into());
        }
        let mut result = IntervalWrap(Default::default());
        let mut raw = Cursor::new(raw);
        result.0.nanos = raw.read_i64::<NetworkEndian>()? as i128 * 1000;
        result.0.days = raw.read_i32::<NetworkEndian>()? as i64;
        result.0.months = raw.read_i32::<NetworkEndian>()? as i64;
        Ok(result)
    }

    fn accepts(ty: &Type) -> bool {
        matches!(*ty, Type::INTERVAL)
    }
}

impl From<IntervalWrap> for Interval {
    fn from(value: IntervalWrap) -> Self {
        value.0
    }
}