mysql_common/binlog/
misc.rs1use byteorder::{BigEndian as BE, ReadBytesExt};
10use saturating::Saturating as S;
11
12use std::{
13 cmp::min,
14 io::{self, Write},
15};
16
17use crate::value::Value;
18
19pub const TIMEF_INT_OFS: i64 = 0x800000;
20pub const TIMEF_OFS: i64 = 0x800000000000;
21pub const DATETIMEF_INT_OFS: i64 = 0x8000000000;
22
23pub fn my_packed_time_make_int(i: i64) -> i64 {
24 ((i as u64) << 24) as i64
25}
26
27pub fn my_packed_time_make(i: i64, f: i64) -> i64 {
28 ((i as u64) << 24) as i64 + f
29}
30
31pub fn my_time_packed_from_binary<T: io::Read>(mut input: T, dec: u32) -> io::Result<i64> {
32 match dec {
33 1 | 2 => {
34 let mut intpart = input.read_u24::<BE>()? as i64 - TIMEF_INT_OFS;
35 let mut frac = input.read_u8()? as u32;
36 if intpart < 0 && frac > 0 {
37 intpart += 1;
38 frac -= 0x100;
39 }
40 Ok(my_packed_time_make(intpart, (frac as i64) * 10_000))
41 }
42 3 | 4 => {
43 let mut intpart = input.read_u24::<BE>()? as i64 - TIMEF_INT_OFS;
44 let mut frac = input.read_u16::<BE>()? as i32;
45 if intpart < 0 && frac > 0 {
46 intpart += 1;
47 frac -= 0x10000;
48 }
49 Ok(my_packed_time_make(intpart, (frac * 100) as i64))
50 }
51 5 | 6 => Ok((input.read_u48::<BE>()? as i64) - TIMEF_OFS),
52 _ => {
53 let i = input.read_u24::<BE>()? as i64 - TIMEF_INT_OFS;
54 Ok(my_packed_time_make_int(i))
55 }
56 }
57}
58
59pub fn my_packed_time_get_int_part(i: i64) -> i64 {
60 i >> 24
61}
62
63pub fn my_packed_time_get_frac_part(i: i64) -> i64 {
64 i % (1 << 24)
65}
66
67pub fn time_from_packed(mut tmp: i64) -> Value {
68 let neg = if tmp < 0 {
69 tmp = -tmp;
70 true
71 } else {
72 false
73 };
74 let hms = my_packed_time_get_int_part(tmp);
75 let h = ((hms >> 12) as u32) % (1 << 10);
76 let d = h / 24;
77 let h = h % 24;
78 let m = ((hms >> 6) as u32) % (1 << 6);
79 let s = ((hms) as u32) % (1 << 6);
80 let u = my_packed_time_get_frac_part(tmp);
81 Value::Time(neg, d, h as u8, m as u8, s as u8, u as u32)
82}
83
84pub fn my_datetime_packed_from_binary<T: io::Read>(mut input: T, dec: u32) -> io::Result<i64> {
85 let intpart = (input.read_uint::<BE>(5)? as i64) - DATETIMEF_INT_OFS;
86 let frac = match dec {
87 1 | 2 => (input.read_i8()? as i32) * 10_000,
88 3 | 4 => (input.read_i16::<BE>()? as i32) * 100,
89 5 | 6 => input.read_i24::<BE>()?,
90 _ => return Ok(my_packed_time_make_int(intpart)),
91 };
92 Ok(my_packed_time_make(intpart, frac as i64))
93}
94
95pub fn datetime_from_packed(mut tmp: i64) -> Value {
96 if tmp < 0 {
97 tmp = -tmp;
98 }
99 let usec = my_packed_time_get_frac_part(tmp);
100 let ymdhms = my_packed_time_get_int_part(tmp);
101
102 let ymd = ymdhms >> 17;
103 let ym = ymd >> 5;
104 let hms = ymdhms % (1 << 17);
105
106 let day = ymd % (1 << 5);
107 let mon = ym % 13;
108 let year = (ym / 13) as u32;
109
110 let sec = hms % (1 << 6);
111 let min = (hms >> 6) % (1 << 6);
112 let hour = (hms >> 12) as u32;
113
114 Value::Date(
115 year as u16,
116 mon as u8,
117 day as u8,
118 hour as u8,
119 min as u8,
120 sec as u8,
121 usec as u32,
122 )
123}
124
125pub fn my_timestamp_from_binary<T: io::Read>(mut input: T, dec: u8) -> io::Result<(i32, i32)> {
126 let sec = input.read_u32::<BE>()? as i32;
127 let usec = match dec {
128 1 | 2 => input.read_i8()? as i32 * 10000,
129 3 | 4 => input.read_i16::<BE>()? as i32 * 100,
130 5 | 6 => input.read_i24::<BE>()?,
131 _ => 0,
132 };
133 Ok((sec, usec))
134}
135
136pub(crate) struct LimitedWrite<T> {
137 limit: S<usize>,
138 write: T,
139}
140
141impl<T> LimitedWrite<T> {
142 pub fn new(write: T, limit: S<usize>) -> Self {
143 Self { limit, write }
144 }
145}
146
147impl<T: Write> Write for LimitedWrite<T> {
148 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
149 let limit = min(buf.len(), self.limit.0);
150 let count = self.write.write(&buf[..limit])?;
151 self.limit -= S(count);
152 Ok(count)
153 }
154
155 fn flush(&mut self) -> io::Result<()> {
156 self.write.flush()
157 }
158}
159
160pub(crate) trait LimitWrite: Write + Sized {
161 fn limit(&mut self, limit: S<usize>) -> LimitedWrite<&mut Self> {
162 LimitedWrite::new(self, limit)
163 }
164}
165
166impl<T: Write> LimitWrite for T {}