qusql-mysql 0.1.0

Async mysql connector
Documentation
//! Contains bindings for various chrono types
use crate::{
    bind::{Bind, BindResult, Writer},
    constants::type_,
    decode::{Column, Decode},
    package_parser::{DecodeError, DecodeResult, PackageParser},
};

impl Bind for chrono::NaiveTime {
    const TYPE: u8 = type_::TIME;
    #[inline]
    fn bind(&self, writer: &mut Writer<'_>) -> BindResult<bool> {
        use chrono::Timelike;
        let ms = self.nanosecond() / 1000;
        writer.put_u8(if ms == 0 { 8 } else { 12 });
        writer.put_u8(self.hour().try_into()?);
        writer.put_u8(self.minute().try_into()?);
        writer.put_u8(self.second().try_into()?);
        if ms != 0 {
            writer.put_u32(ms);
        }
        Ok(true)
    }
}

impl<'a> Decode<'a> for chrono::NaiveTime {
    fn decode_none_null(parser: &mut PackageParser<'a>, c: &Column) -> DecodeResult<Self> {
        if c.r#type != type_::TIME {
            return Err(DecodeError::TypeError {
                expected: type_::TIME,
                got: c.r#type,
            });
        }
        let long = match parser.get_u8()? {
            0 => return Ok(chrono::NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap()),
            8 => false,
            12 => true,
            len => return Err(DecodeError::InvalidSize(len)),
        };
        let positive = parser.get_u8()? == 0;
        let days = parser.get_u32()?;
        let hour = parser.get_u8()?;
        let min = parser.get_u8()?;
        let sec = parser.get_u8()?;
        let micro = if long { parser.get_u32()? } else { 0 };
        if days != 0 || !positive {
            return Err(DecodeError::InvalidValue);
        }
        chrono::NaiveTime::from_hms_micro_opt(hour.into(), min.into(), sec.into(), micro)
            .ok_or(DecodeError::InvalidValue)
    }
}

impl Bind for chrono::NaiveDateTime {
    const TYPE: u8 = type_::DATETIME;

    fn bind(&self, writer: &mut Writer<'_>) -> BindResult<bool> {
        use chrono::{Datelike, Timelike};
        let msec = self.time().nanosecond() / 1000;
        writer.put_u8(if msec == 0 { 7 } else { 11 });
        writer.put_i16(self.date().year().try_into()?);
        writer.put_u8(self.date().month().try_into()?);
        writer.put_u8(self.date().day().try_into()?);
        writer.put_u8(self.time().hour().try_into()?);
        writer.put_u8(self.time().minute().try_into()?);
        writer.put_u8(self.time().second().try_into()?);
        if msec != 0 {
            writer.put_u32(msec);
        }
        Ok(true)
    }
}

impl<'a> Decode<'a> for chrono::NaiveDateTime {
    fn decode_none_null(p: &mut PackageParser<'a>, c: &Column) -> DecodeResult<Self> {
        if c.r#type != type_::TIMESTAMP && c.r#type != type_::DATE && c.r#type != type_::DATETIME {
            return Err(DecodeError::TypeError {
                expected: type_::TIMESTAMP,
                got: c.r#type,
            });
        }

        let len = p.get_u8().unwrap();
        match len {
            0 => Ok(chrono::NaiveDateTime::new(
                chrono::NaiveDate::from_ymd_opt(0, 1, 1).unwrap(),
                chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
            )),
            4 => {
                let year = p.get_i16().unwrap();
                let month = p.get_u8().unwrap();
                let day = p.get_u8().unwrap();
                Ok(chrono::NaiveDateTime::new(
                    chrono::NaiveDate::from_ymd_opt(year.into(), month.into(), day.into())
                        .ok_or(DecodeError::InvalidValue)?,
                    chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
                ))
            }
            7 => {
                let year = p.get_i16().unwrap();
                let month = p.get_u8().unwrap();
                let day = p.get_u8().unwrap();
                let hour = p.get_u8().unwrap();
                let min = p.get_u8().unwrap();
                let sec = p.get_u8().unwrap();
                Ok(chrono::NaiveDateTime::new(
                    chrono::NaiveDate::from_ymd_opt(year.into(), month.into(), day.into())
                        .ok_or(DecodeError::InvalidValue)?,
                    chrono::NaiveTime::from_hms_opt(hour.into(), min.into(), sec.into())
                        .ok_or(DecodeError::InvalidValue)?,
                ))
            }
            11 => {
                let year = p.get_i16().unwrap();
                let month = p.get_u8().unwrap();
                let day = p.get_u8().unwrap();
                let hour = p.get_u8().unwrap();
                let min = p.get_u8().unwrap();
                let sec = p.get_u8().unwrap();
                let micro = p.get_u32().unwrap();
                Ok(chrono::NaiveDateTime::new(
                    chrono::NaiveDate::from_ymd_opt(year.into(), month.into(), day.into())
                        .ok_or(DecodeError::InvalidValue)?,
                    chrono::NaiveTime::from_hms_micro_opt(
                        hour.into(),
                        min.into(),
                        sec.into(),
                        micro,
                    )
                    .ok_or(DecodeError::InvalidValue)?,
                ))
            }
            _ => Err(DecodeError::InvalidSize(len)),
        }
    }
}

impl Bind for chrono::NaiveDate {
    const TYPE: u8 = type_::DATE;
    #[inline]
    fn bind(&self, writer: &mut Writer<'_>) -> BindResult<bool> {
        use chrono::Datelike;
        writer.put_u8(4);
        writer.put_i16(self.year().try_into()?);
        writer.put_u8(self.month().try_into()?);
        writer.put_u8(self.day().try_into()?);
        Ok(true)
    }
}

impl<'a> Decode<'a> for chrono::NaiveDate {
    fn decode_none_null(p: &mut PackageParser<'a>, c: &Column) -> DecodeResult<Self> {
        if c.r#type != type_::DATE {
            return Err(DecodeError::TypeError {
                expected: type_::DATE,
                got: c.r#type,
            });
        }
        let len = p.get_u8().unwrap();
        match len {
            0 => Ok(chrono::NaiveDate::from_ymd_opt(0, 1, 1).unwrap()),
            4 => {
                let year = p.get_i16().unwrap();
                let month = p.get_u8().unwrap();
                let day = p.get_u8().unwrap();
                chrono::NaiveDate::from_ymd_opt(year.into(), month.into(), day.into())
                    .ok_or(DecodeError::InvalidValue)
            }
            _ => Err(DecodeError::InvalidSize(len)),
        }
    }
}

impl Bind for chrono::DateTime<chrono::Utc> {
    const TYPE: u8 = type_::DATETIME;

    fn bind(&self, writer: &mut Writer<'_>) -> BindResult<bool> {
        self.naive_utc().bind(writer)
    }
}

impl<'a> Decode<'a> for chrono::DateTime<chrono::Utc> {
    fn decode_none_null(p: &mut PackageParser<'a>, c: &Column) -> DecodeResult<Self> {
        Ok(chrono::NaiveDateTime::decode_none_null(p, c)?.and_utc())
    }
}