use crate::types::{Decode, Encode};
use crate::value::{MySqlValueFormat, MySqlValueRef};
use bytes::Buf;
use rbdc::types::time::Time;
use rbdc::Error;
use std::str::FromStr;
impl Encode for Time {
fn encode(self, buf: &mut Vec<u8>) -> Result<usize, Error> {
self.0.encode(buf)
}
}
impl Decode for Time {
fn decode(value: MySqlValueRef<'_>) -> Result<Self, Error> {
Ok(Time(fastdate::Time::decode(value)?))
}
}
impl Encode for fastdate::Time {
fn encode(self, buf: &mut Vec<u8>) -> Result<usize, Error> {
let len = time_encoded_len(&self);
buf.push(len);
buf.push(0);
buf.extend_from_slice(&[0_u8; 4]);
encode_time(&self, len > 8, buf);
Ok(len as usize)
}
}
impl Decode for fastdate::Time {
fn decode(value: MySqlValueRef<'_>) -> Result<Self, Error> {
Ok(match value.format() {
MySqlValueFormat::Text => {
fastdate::Time::from_str(value.as_str()?).map_err(|e| Error::from(e.to_string()))?
}
MySqlValueFormat::Binary => {
let buf = value.as_bytes()?;
let len = buf[0];
if len > 4 {
decode_time(&buf[5..])
} else {
fastdate::Time {
nano: 0,
sec: 0,
minute: 0,
hour: 0,
}
}
}
})
}
}
pub fn decode_time(mut buf: &[u8]) -> fastdate::Time {
let hour = buf.get_u8();
let minute = buf.get_u8();
let seconds = buf.get_u8();
let micros = if !buf.is_empty() {
buf.get_uint_le(buf.len())
} else {
0
};
fastdate::Time {
nano: micros as u32 * 1000,
sec: seconds,
minute: minute,
hour,
}
}
fn encode_time(time: &fastdate::Time, include_micros: bool, buf: &mut Vec<u8>) {
buf.push(time.get_hour());
buf.push(time.get_minute());
buf.push(time.get_sec());
if include_micros {
let micro = time.get_nano() / 1000;
buf.extend(µ.to_le_bytes());
}
}
#[inline(always)]
fn time_encoded_len(time: &fastdate::Time) -> u8 {
if time.get_nano() == 0 {
8
} else {
12
}
}