rbdc_mysql/types/
time.rs

1use crate::types::{Decode, Encode};
2use crate::value::{MySqlValue, MySqlValueFormat};
3use bytes::Buf;
4use rbdc::types::time::Time;
5use rbdc::Error;
6use std::str::FromStr;
7
8impl Encode for Time {
9    fn encode(self, buf: &mut Vec<u8>) -> Result<usize, Error> {
10        self.0.encode(buf)
11    }
12}
13
14impl Decode for Time {
15    fn decode(value: MySqlValue) -> Result<Self, Error> {
16        Ok(Time(fastdate::Time::decode(value)?))
17    }
18}
19
20impl Encode for fastdate::Time {
21    fn encode(self, buf: &mut Vec<u8>) -> Result<usize, Error> {
22        let len = time_encoded_len(&self);
23        buf.push(len);
24
25        // sign byte: Time is never negative
26        buf.push(0);
27
28        // Number of days in the interval; always 0 for time-of-day values.
29        // https://mariadb.com/kb/en/resultset-row/#teimstamp-binary-encoding
30        buf.extend_from_slice(&[0_u8; 4]);
31
32        encode_time(&self, len > 8, buf);
33
34        Ok(len as usize)
35    }
36}
37
38impl Decode for fastdate::Time {
39    fn decode(value: MySqlValue) -> Result<Self, Error> {
40        Ok(match value.format() {
41            MySqlValueFormat::Text => {
42                fastdate::Time::from_str(value.as_str()?).map_err(|e| Error::from(e.to_string()))?
43            }
44            MySqlValueFormat::Binary => {
45                let buf = value.as_bytes()?;
46                let len = buf[0];
47                if len > 4 {
48                    decode_time(&buf[5..])
49                } else {
50                    fastdate::Time {
51                        nano: 0,
52                        sec: 0,
53                        minute: 0,
54                        hour: 0,
55                    }
56                }
57            }
58        })
59    }
60}
61
62pub fn decode_time(mut buf: &[u8]) -> fastdate::Time {
63    let hour = buf.get_u8();
64    let minute = buf.get_u8();
65    let seconds = buf.get_u8();
66    let micros = if !buf.is_empty() {
67        // microseconds : int<EOF>
68        buf.get_uint_le(buf.len())
69    } else {
70        0
71    };
72    // NaiveTime::from_hms_micro(hour as u32, minute as u32, seconds as u32, micros as u32)
73    fastdate::Time {
74        nano: micros as u32 * 1000,
75        sec: seconds,
76        minute: minute,
77        hour,
78    }
79}
80
81fn encode_time(time: &fastdate::Time, include_micros: bool, buf: &mut Vec<u8>) {
82    buf.push(time.get_hour());
83    buf.push(time.get_minute());
84    buf.push(time.get_sec());
85
86    if include_micros {
87         let micro=time.get_nano() / 1000;
88         buf.extend(&micro.to_le_bytes());
89    }
90}
91
92#[inline(always)]
93fn time_encoded_len(time: &fastdate::Time) -> u8 {
94    if time.get_nano() == 0 {
95        // if micro_seconds is 0, length is 8 and micro_seconds is not sent
96        8
97    } else {
98        // otherwise length is 12
99        12
100    }
101}