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 buf.push(0);
27
28 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 buf.get_uint_le(buf.len())
69 } else {
70 0
71 };
72 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(µ.to_le_bytes());
89 }
90}
91
92#[inline(always)]
93fn time_encoded_len(time: &fastdate::Time) -> u8 {
94 if time.get_nano() == 0 {
95 8
97 } else {
98 12
100 }
101}