mysqlbinlog_network/mysql_binlog/
packet_helpers.rs1use std::io::{self, Cursor, Read};
2
3use crate::mysql_binlog::errors::DecimalParseError;
4
5use bigdecimal::BigDecimal;
6use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};
7
8pub(crate) fn read_variable_length_integer<R: Read>(r: &mut R) -> io::Result<i64> {
14 let first = r.read_u8()?;
15 if first < 0xfb {
16 Ok(i64::from(first as i8))
17 } else if first == 0xfc {
18 Ok(i64::from(r.read_i16::<LittleEndian>()?))
19 } else if first == 0xfd {
20 let mut buf = [0u8; 4];
22 r.read_exact(&mut buf[0..3])?;
23 Ok(i64::from(LittleEndian::read_i32(&buf)))
25 } else if first == 0xfe {
26 r.read_i64::<LittleEndian>()
27 } else {
28 unreachable!();
29 }
30}
31
32pub(crate) fn read_known_length_integer_be<R: Read>(r: &mut R, bytes: usize) -> io::Result<i64> {
33 Ok(match bytes {
34 1 => i64::from(r.read_i8()?),
35 2 => i64::from(r.read_i16::<BigEndian>()?),
36 3 => {
37 let mut buf = [0u8; 3];
38 r.read_exact(&mut buf)?;
39 let is_neg = buf[0] & 0x80 != 0;
40 buf[0] &= 0x7f;
41 let num: i64 = (i64::from(buf[0]) << 16) | (i64::from(buf[1]) << 8) | i64::from(buf[2]);
42 if is_neg {
43 -1 * num
44 } else {
45 num
46 }
47 }
48 4 => i64::from(r.read_i32::<BigEndian>()?),
49 _ => unimplemented!(),
50 })
51}
52
53pub(crate) fn read_uint24<R: Read>(r: &mut R) -> io::Result<u32> {
54 let mut buf = [0u8; 4];
55 r.read_exact(&mut buf[0..3])?;
56 Ok(LittleEndian::read_u32(&buf))
57}
58
59pub(crate) fn read_int24<R: Read>(r: &mut R) -> io::Result<i32> {
60 let mut buf = [0u8; 4];
61 r.read_exact(&mut buf[0..3])?;
62 Ok(LittleEndian::read_i32(&buf))
63}
64
65pub(crate) fn read_one_byte_length_prefixed_bytes<R: Read>(r: &mut R) -> io::Result<Vec<u8>> {
66 let length = r.read_u8()?;
67 read_nbytes(r, length)
68}
69
70pub(crate) fn read_two_byte_length_prefixed_bytes<R: Read>(r: &mut R) -> io::Result<Vec<u8>> {
71 let length = r.read_u16::<LittleEndian>()? as usize;
72 read_nbytes(r, length)
73}
74
75pub(crate) fn read_var_byte_length_prefixed_bytes<R: Read>(
76 r: &mut R,
77 pl: u8,
78) -> io::Result<Vec<u8>> {
79 let len = match pl {
80 1 => r.read_u8()? as usize,
81 2 => r.read_u16::<LittleEndian>()? as usize,
82 3 => {
83 let mut buf = [0u8; 4];
84 r.read_exact(&mut buf[0..3])?;
85 byteorder::LittleEndian::read_u32(&buf) as usize
86 }
87 4 => r.read_u32::<LittleEndian>()? as usize,
88 8 => r.read_u64::<LittleEndian>()? as usize,
89 l => unreachable!(format!("got unexpected length {0:?}", l)),
90 };
91 read_nbytes(r, len)
92}
93
94pub(crate) fn read_one_byte_length_prefixed_string<R: Read>(r: &mut R) -> io::Result<String> {
95 let buf = read_one_byte_length_prefixed_bytes(r)?;
96 Ok(String::from_utf8_lossy(&buf).into_owned())
97}
98
99pub(crate) fn read_two_byte_length_prefixed_string<R: Read>(r: &mut R) -> io::Result<String> {
100 let buf = read_two_byte_length_prefixed_bytes(r)?;
101 Ok(String::from_utf8_lossy(&buf).into_owned())
102}
103
104pub(crate) fn read_nbytes<R: Read, S: Into<usize>>(
105 r: &mut R,
106 desired_bytes: S,
107) -> io::Result<Vec<u8>> {
108 let mut into = vec![0u8; desired_bytes.into()];
109 r.read_exact(&mut into)?;
110 Ok(into)
111}
112
113pub(crate) fn read_variable_length_bytes<R: Read>(r: &mut R) -> io::Result<Vec<u8>> {
114 let mut byte = 0x80;
115 let mut length = 0usize;
116 let mut shbits = 0u32;
117 while byte & 0x80 != 0 {
118 byte = r.read_u8()?;
119 length |= ((byte & 0x7f) as usize) << shbits;
120 shbits += 7;
121 if shbits >= 57 {
122 panic!("illegal shift, shbits={}", shbits);
123 }
124 }
125 read_nbytes(r, length)
126}
127
128pub(crate) fn read_variable_length_string<R: Read>(r: &mut R) -> io::Result<String> {
129 let buf = read_variable_length_bytes(r)?;
130 Ok(String::from_utf8_lossy(&buf).into_owned())
131}
132
133const DECIMAL_DIGITS_PER_INTEGER: u8 = 9;
134
135pub(crate) fn read_new_decimal<R: Read>(
136 r: &mut R,
137 precision: u8,
138 decimal: u8,
139) -> Result<BigDecimal, DecimalParseError> {
140 let compressed_byte_map = [0usize, 1, 1, 2, 2, 3, 3, 4, 4, 4];
144 let integral = precision - decimal;
145 let uncompressed_integers: usize = (integral / DECIMAL_DIGITS_PER_INTEGER).into();
146 let uncompressed_decimals: usize = (decimal / DECIMAL_DIGITS_PER_INTEGER).into();
147 let compressed_integers: usize =
148 integral as usize - (uncompressed_integers * DECIMAL_DIGITS_PER_INTEGER as usize);
149 let compressed_decimals: usize =
150 decimal as usize - (uncompressed_decimals * DECIMAL_DIGITS_PER_INTEGER as usize);
151
152 let bytes_to_read: usize = uncompressed_integers * 4
153 + compressed_byte_map[compressed_integers]
154 + uncompressed_decimals * 4
155 + compressed_byte_map[compressed_decimals];
156
157 let mut buf = read_nbytes(r, bytes_to_read)?;
158
159 let mut components = Vec::new();
160
161 let is_negative = (buf[0] & 0x80) == 0;
162 buf[0] ^= 0x80;
163 if is_negative {
164 components.push("-".to_owned());
165 }
166 let mut r = Cursor::new(buf);
167 if compressed_integers != 0 {
169 let to_read = compressed_byte_map[compressed_integers];
170 components.push(read_known_length_integer_be(&mut r, to_read)?.to_string())
171 }
172 for _ in 0..uncompressed_integers {
173 components.push(format!("{:09}", r.read_u32::<BigEndian>()?));
174 }
175 components.push(".".to_owned());
176 for _ in 0..uncompressed_decimals {
177 components.push(format!("{:09}", r.read_u32::<LittleEndian>()?));
178 }
179 if compressed_decimals != 0 {
180 components.push(
181 read_known_length_integer_be(&mut r, compressed_byte_map[compressed_decimals])?
182 .to_string(),
183 )
184 }
185 let decimal = components.join("").parse::<BigDecimal>()?;
186 Ok(decimal)
187}
188
189pub(crate) fn read_datetime_subsecond_part<R: Read>(r: &mut R, pack_length: u8) -> io::Result<u32> {
190 Ok(match pack_length {
191 0 => 0u32,
192 1 | 2 => read_known_length_integer_be(r, 1)? as u32,
193 3 | 4 => read_known_length_integer_be(r, 2)? as u32,
194 5 | 6 => read_known_length_integer_be(r, 3)? as u32,
195 _ => 0u32,
196 })
197}
198pub(crate) fn decode_bit<R: Read>(r: &mut R, nbits: u16, length: u8) -> io::Result<i64> {
199 if nbits > 1 {
200 match length {
201 1..=8 => {
202 let mut data = vec![0u8; length as usize];
203 r.read_exact(&mut data)?;
204 return Ok(bf_fixed_length_int(&data) as i64);
205 }
206 _ => return Err(io::Error::from(io::ErrorKind::Other)),
207 }
208 } else {
209 if length != 1 {
210 return Err(io::Error::from(io::ErrorKind::Other));
211 }
212 }
213 Ok(r.read_u8()? as i64)
214}
215pub(crate) fn little_decode_bit<R: Read>(r: &mut R, nbits: u16, length: u16) -> io::Result<i64> {
216 if nbits > 1 {
217 match length {
218 1..=8 => {
219 let mut data = vec![0u8; length as usize];
220 r.read_exact(&mut data)?;
221 return Ok(fixed_length_int(&data) as i64);
222 }
223 _ => return Err(io::Error::from(io::ErrorKind::Other)),
224 }
225 } else {
226 if length != 1 {
227 return Err(io::Error::from(io::ErrorKind::Other));
228 }
229 }
230 Ok(r.read_u8()? as i64)
231}
232
233fn fixed_length_int(buf: &[u8]) -> u64 {
234 let mut num = 0u64;
235 for i in 0..buf.len() {
236 num |= (buf[i] as u64) << (i as u32) * 8;
237 }
238 num
239}
240
241fn bf_fixed_length_int(buf: &[u8]) -> u64 {
242 let mut num = 0u64;
243 for i in 0..buf.len() {
244 num |= (buf[i] as u64) << ((buf.len() - i - 1) as u32) * 8;
245 }
246 num
247}
248
249#[cfg(test)]
250mod tests {
251 use std::io::Cursor;
252
253 use bigdecimal::BigDecimal;
254
255 use super::read_new_decimal;
256 use super::read_var_byte_length_prefixed_bytes;
257
258 #[test]
259 fn test_read_new_decimal() {
260 let mut uut = Cursor::new(vec![0x80, 0x00, 0x00, 0x00, 0x01]);
261 let one = "1.00".parse::<BigDecimal>().unwrap();
262 assert_eq!(
263 read_new_decimal(&mut uut, 10, 0).expect("should parse"),
264 one
265 );
266 let mut uut = Cursor::new(vec![0x80, 0x00, 0x01, 0x00, 0x00]);
267 let zero_point_one = "0.100".parse::<BigDecimal>().unwrap();
268 assert_eq!(
269 read_new_decimal(&mut uut, 5, 5).expect("should parse"),
270 zero_point_one
271 );
272 let mut uut = Cursor::new(vec![128, 0, 5, 0, 212, 49]);
273 let expected = "5.54321".parse::<BigDecimal>().unwrap();
274 assert_eq!(
275 read_new_decimal(&mut uut, 10, 5).expect("should parse"),
276 expected
277 );
278 }
279
280 #[test]
281 fn test_read_var_byte_length_prefixed_bytes() {
282 for (byte_length, input, expected_output) in &[
283 (1, vec![0x01, 0x09], vec![0x09]),
284 (2, vec![0x01, 0x00, 0x0a], vec![0x0a]),
285 (3, vec![0x01, 0x00, 0x00, 0x0b], vec![0x0b]),
286 (
287 4,
288 vec![0x02, 0x00, 0x00, 0x00, 0x0c, 0x0d],
289 vec![0x0c, 0x0d],
290 ),
291 (
292 8,
293 vec![
294 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xe, 0xa,
295 ],
296 vec![0xd, 0xe, 0xa],
297 ),
298 ] {
299 let mut uut = Cursor::new(input);
300 assert_eq!(
301 &read_var_byte_length_prefixed_bytes(&mut uut, *byte_length).expect("should be ok"),
302 expected_output
303 );
304 }
305 }
306}