mysql_common/misc/raw/
int.rs

1// Copyright (c) 2021 Anatoly Ikorsky
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use bytes::BufMut;
10
11use std::{
12    fmt,
13    hash::Hash,
14    io,
15    marker::PhantomData,
16    ops::{Deref, DerefMut},
17};
18
19use crate::{
20    io::{BufMutExt, ParseBuf},
21    proto::{MyDeserialize, MySerialize},
22};
23
24/// Wrapper for an integer, that defines serialization and deserialization.
25#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
26#[repr(transparent)]
27pub struct RawInt<T: IntRepr>(pub T::Primitive, PhantomData<T>);
28
29impl<T: IntRepr> fmt::Debug for RawInt<T>
30where
31    T::Primitive: fmt::Debug,
32{
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        self.0.fmt(f)
35    }
36}
37
38impl<T: IntRepr> RawInt<T> {
39    pub fn new(x: T::Primitive) -> Self {
40        Self(x, PhantomData)
41    }
42}
43
44impl<T: IntRepr> Deref for RawInt<T> {
45    type Target = T::Primitive;
46
47    fn deref(&self) -> &Self::Target {
48        &self.0
49    }
50}
51
52impl<T: IntRepr> DerefMut for RawInt<T> {
53    fn deref_mut(&mut self) -> &mut Self::Target {
54        &mut self.0
55    }
56}
57
58impl<'de, T: IntRepr> MyDeserialize<'de> for RawInt<T> {
59    const SIZE: Option<usize> = T::SIZE;
60    type Ctx = ();
61
62    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
63        T::deserialize(buf).map(Self::new)
64    }
65}
66
67impl<T: IntRepr> MySerialize for RawInt<T> {
68    fn serialize(&self, buf: &mut Vec<u8>) {
69        T::serialize(self.0, buf);
70    }
71}
72
73/// Serialized representation of an integer.
74pub trait IntRepr {
75    const SIZE: Option<usize>;
76    type Primitive: fmt::Debug + Default + Copy + Eq + Ord + Hash;
77
78    fn serialize(val: Self::Primitive, buf: &mut Vec<u8>);
79    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive>;
80}
81
82impl IntRepr for u8 {
83    const SIZE: Option<usize> = Some(1);
84    type Primitive = Self;
85
86    fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
87        buf.put_u8(val)
88    }
89
90    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
91        Ok(buf.eat_u8())
92    }
93}
94
95impl IntRepr for i8 {
96    const SIZE: Option<usize> = Some(1);
97    type Primitive = Self;
98
99    fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
100        buf.put_i8(val)
101    }
102
103    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
104        Ok(buf.eat_i8())
105    }
106}
107
108macro_rules! def_end_repr {
109    ($( $(#[$m:meta])* $name:ident, $t:ty, $size:expr, $ser:ident, $de:ident; )+) => {
110        $(
111            $(#[$m])*
112            ///
113            /// # Panic
114            ///
115            /// Note, that `IntPepr::deserialize` won't check buffer length.
116            #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
117            pub struct $name;
118
119            impl IntRepr for $name {
120                const SIZE: Option<usize> = $size;
121                type Primitive = $t;
122
123                fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
124                    buf.$ser(val)
125                }
126
127                fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
128                    Ok(buf.$de())
129                }
130            }
131        )+
132    };
133    ($( $(#[$m:meta])* checked $name:ident, $t:ty, $size:expr, $ser:ident, $de:ident; )+) => {
134        $(
135            $(#[$m])*
136            #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
137            pub struct $name;
138
139            impl IntRepr for $name {
140                const SIZE: Option<usize> = $size;
141                type Primitive = $t;
142
143                fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
144                    buf.$ser(val)
145                }
146
147                fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
148                    buf.$de().ok_or_else(crate::misc::unexpected_buf_eof)
149                }
150            }
151        )+
152    };
153}
154
155def_end_repr! {
156    /// Little-endian u16.
157    LeU16, u16, Some(2), put_u16_le, eat_u16_le;
158    /// Little-endian u24.
159    LeU24, u32, Some(3), put_u24_le, eat_u24_le;
160    /// Little-endian u32.
161    LeU32, u32, Some(4), put_u32_le, eat_u32_le;
162    /// Little-endian u48.
163    LeU48, u64, Some(6), put_u48_le, eat_u48_le;
164    /// Little-endian u56.
165    LeU56, u64, Some(7), put_u56_le, eat_u56_le;
166    /// Little-endian u64.
167    LeU64, u64, Some(8), put_u64_le, eat_u64_le;
168    /// Little-endian i16.
169    LeI16, i16, Some(2), put_i16_le, eat_i16_le;
170    /// Little-endian i24.
171    LeI24, i32, Some(3), put_i24_le, eat_i24_le;
172    /// Little-endian i32.
173    LeI32, i32, Some(4), put_i32_le, eat_i32_le;
174    /// Little-endian i56.
175    LeI56, i64, Some(7), put_i56_le, eat_i56_le;
176    /// Little-endian i64.
177    LeI64, i64, Some(8), put_i64_le, eat_i64_le;
178}
179
180def_end_repr! {
181    /// Length-encoded integer.
182    checked LenEnc, u64, None, put_lenenc_int, checked_eat_lenenc_int;
183}
184
185/// Lower 2 bytes of a little-endian u32.
186#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
187pub struct LeU32LowerHalf;
188
189impl IntRepr for LeU32LowerHalf {
190    const SIZE: Option<usize> = Some(2);
191    type Primitive = u32;
192
193    fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
194        LeU16::serialize((val & 0x0000_FFFF) as u16, buf);
195    }
196
197    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
198        LeU16::deserialize(buf).map(|x| x as u32)
199    }
200}
201
202/// Upper 2 bytes of a little-endian u32.
203#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
204pub struct LeU32UpperHalf;
205
206impl IntRepr for LeU32UpperHalf {
207    const SIZE: Option<usize> = Some(2);
208    type Primitive = u32;
209
210    fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
211        LeU16::serialize((val >> 16) as u16, buf);
212    }
213
214    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
215        LeU16::deserialize(buf).map(|x| (x as u32) << 16)
216    }
217}
218
219/// Constant u8 value.
220///
221/// `T` is an error type if parsed value does not match.
222#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
223pub struct ConstU8<T, const N: u8>(PhantomData<T>);
224
225impl<T, const N: u8> ConstU8<T, N> {
226    pub const fn new() -> Self {
227        Self(PhantomData)
228    }
229
230    pub const fn value(&self) -> u8 {
231        N
232    }
233}
234
235impl<'de, T, const N: u8> MyDeserialize<'de> for ConstU8<T, N>
236where
237    T: std::error::Error + Send + Sync + 'static,
238    T: Default,
239{
240    const SIZE: Option<usize> = Some(1);
241    type Ctx = ();
242
243    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
244        if buf.eat_u8() == N {
245            Ok(Self(PhantomData))
246        } else {
247            Err(io::Error::new(io::ErrorKind::InvalidData, T::default()))
248        }
249    }
250}
251
252impl<T, const N: u8> MySerialize for ConstU8<T, N> {
253    fn serialize(&self, buf: &mut Vec<u8>) {
254        buf.put_u8(N);
255    }
256}
257
258/// Constant u8 value.
259///
260/// `T` is an error type if parsed value does not match.
261#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
262pub struct ConstU32<T, const N: u32>(PhantomData<T>);
263
264impl<T, const N: u32> ConstU32<T, N> {
265    pub fn new() -> Self {
266        Self(PhantomData)
267    }
268}
269
270impl<'de, T, const N: u32> MyDeserialize<'de> for ConstU32<T, N>
271where
272    T: std::error::Error + Send + Sync + 'static,
273    T: Default,
274{
275    const SIZE: Option<usize> = Some(4);
276    type Ctx = ();
277
278    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
279        if buf.eat_u32_le() == N {
280            Ok(Self(PhantomData))
281        } else {
282            Err(io::Error::new(io::ErrorKind::InvalidData, T::default()))
283        }
284    }
285}
286
287impl<T, const N: u32> MySerialize for ConstU32<T, N> {
288    fn serialize(&self, buf: &mut Vec<u8>) {
289        buf.put_u32_le(N);
290    }
291}
292
293/// Varialbe-length integer (used within JSONB).
294#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
295pub struct VarLen;
296
297impl IntRepr for VarLen {
298    const SIZE: Option<usize> = None;
299    type Primitive = u32;
300
301    fn serialize(mut val: Self::Primitive, buf: &mut Vec<u8>) {
302        loop {
303            let mut byte = (val & 0x7F) as u8;
304            val >>= 7;
305            if val != 0 {
306                byte |= 0x80;
307                buf.put_u8(byte);
308                break;
309            } else {
310                buf.put_u8(byte);
311            }
312        }
313    }
314
315    fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
316        // variable-length integer should take up to 5 bytes
317        const MAX_REPR_LEN: usize = 5;
318
319        let mut len = 0_u64;
320        for i in 0..MAX_REPR_LEN {
321            let byte = *buf.parse::<RawInt<u8>>(())? as u64;
322            len |= (byte & 0x7f) << (7 * i);
323            if byte & 0x80 == 0 {
324                if len > (u32::MAX as u64) {
325                    return Err(io::Error::new(
326                        io::ErrorKind::InvalidData,
327                        "invalid variable-length value (> u32::MAX)",
328                    ));
329                }
330                return Ok(len as u32);
331            }
332        }
333
334        Err(io::Error::new(
335            io::ErrorKind::InvalidData,
336            "invalid variable-length value (more than 5 bytes)",
337        ))
338    }
339}