rbdc_mysql/types/
decode.rs1use crate::protocol::text::ColumnType;
2use crate::value::{MySqlValue, MySqlValueFormat};
3use byteorder::{ByteOrder, LittleEndian};
4use bytes::Buf;
5use fastdate::Date;
6use rbdc::Error;
7
8pub(crate) fn uint_decode(value: MySqlValue) -> Result<u64, Error> {
9 if value.type_info.r#type == ColumnType::Bit {
10 let buf = value.as_bytes()?;
12 let mut value: u64 = 0;
13 for b in buf {
14 value = (*b as u64) | (value << 8);
15 }
16 return Ok(value);
17 }
18
19 Ok(match value.format() {
20 MySqlValueFormat::Text => value.as_str()?.parse().unwrap_or_default(),
21
22 MySqlValueFormat::Binary => {
23 let buf = value.as_bytes()?;
24 LittleEndian::read_uint(buf, buf.len())
25 }
26 })
27}
28
29pub(crate) fn int_decode(value: MySqlValue) -> Result<i64, Error> {
30 Ok(match value.format() {
31 MySqlValueFormat::Text => value.as_str()?.parse().unwrap_or_default(),
32 MySqlValueFormat::Binary => {
33 let buf = value.as_bytes()?;
34 LittleEndian::read_int(buf, buf.len())
35 }
36 })
37}
38
39pub(crate) fn f32_decode(value: MySqlValue) -> Result<f32, Error> {
40 Ok(match value.format() {
41 MySqlValueFormat::Binary => {
42 let buf = value.as_bytes()?;
43
44 if buf.len() == 8 {
45 LittleEndian::read_f64(buf) as f32
48 } else {
49 LittleEndian::read_f32(buf)
50 }
51 }
52
53 MySqlValueFormat::Text => value.as_str()?.parse().unwrap_or_default(),
54 })
55}
56
57pub(crate) fn f64_decode(value: MySqlValue) -> Result<f64, Error> {
58 Ok(match value.format() {
59 MySqlValueFormat::Binary => LittleEndian::read_f64(value.as_bytes()?),
60 MySqlValueFormat::Text => value.as_str()?.parse().unwrap_or_default(),
61 })
62}
63
64pub(crate) fn decode_timestamp(value: MySqlValue) -> Result<String, Error> {
65 Ok(match value.format() {
66 MySqlValueFormat::Text => {
67 let mut v = value.as_str()?.to_string();
68 if !v.ends_with("Z") {
69 v.push_str("Z");
70 }
71 v
72 }
73 MySqlValueFormat::Binary => {
74 let buf = value.as_bytes()?;
75 let len = buf[0];
76 let date = decode_date_buf(&buf[1..])?.to_string();
77 let dt = if len > 4 {
78 decode_time_buf(len - 4, &buf[5..])?
79 } else {
80 "00:00:00".to_string()
81 };
82 date + " " + &dt + "Z"
83 }
84 })
85}
86
87pub(crate) fn decode_year(value: MySqlValue) -> Result<String, Error> {
88 Ok(match value.format() {
89 MySqlValueFormat::Text => value.as_str()?.to_string(),
90 MySqlValueFormat::Binary => {
91 let buf = value.as_bytes()?;
92 let date = decode_year_buf(&buf[1..])?;
93 date
94 }
95 })
96}
97
98pub(crate) fn decode_date(value: MySqlValue) -> Result<String, Error> {
99 Ok(match value.format() {
100 MySqlValueFormat::Text => value.as_str()?.to_string(),
101 MySqlValueFormat::Binary => {
102 let buf = value.as_bytes()?;
103 let date = decode_date_buf(&buf[1..])?.to_string();
104 date
105 }
106 })
107}
108
109pub(crate) fn decode_time(value: MySqlValue) -> Result<String, Error> {
110 Ok(match value.format() {
111 MySqlValueFormat::Text => value.as_str()?.to_string(),
112 MySqlValueFormat::Binary => {
113 let buf = value.as_bytes()?;
114 let len = buf[0];
115 let dt = if len > 4 {
116 decode_time_buf(len - 4, &buf[5..])?
117 } else {
118 "00:00:00".to_string()
119 };
120 dt
121 }
122 })
123}
124
125pub(crate) fn decode_date_buf(buf: &[u8]) -> Result<Date, Error> {
126 if buf.is_empty() {
127 return Ok(Date {
129 year: 0000,
130 mon: 00,
131 day: 00,
132 });
133 }
134 Ok(Date {
135 year: LittleEndian::read_u16(buf) as i32,
136 mon: buf[2] as u8,
137 day: buf[3] as u8,
138 })
139}
140
141pub(crate) fn decode_year_buf(buf: &[u8]) -> Result<String, Error> {
142 if buf.is_empty() {
143 return Ok("".to_string());
145 }
146 Ok(format!("{:0>4}", LittleEndian::read_u16(buf) as i32,))
147}
148
149pub(crate) fn decode_time_buf(_: u8, mut buf: &[u8]) -> Result<String, Error> {
150 let hour = buf.get_u8();
151 let minute = buf.get_u8();
152 let seconds = buf.get_u8();
153 let milliseconds = if buf.len() >= 4 {
154 buf.get_u32_le()
155 } else {
156 0 };
158 Ok(format!(
159 "{:0>2}:{:0>2}:{:0>2}.{:0>6}",
160 hour, minute, seconds, milliseconds
161 ))
162}
163
164pub(crate) fn decode_bool(value: MySqlValue) -> Result<bool, Error> {
165 Ok(int_decode(value)? != 0)
166}