mysql_common/misc/raw/
bytes.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
9pub use super::int::LenEnc;
10
11use std::{borrow::Cow, cmp::min, fmt, io, marker::PhantomData};
12
13use bytes::BufMut;
14
15use crate::{
16    io::{BufMutExt, ParseBuf},
17    misc::unexpected_buf_eof,
18    proto::{MyDeserialize, MySerialize},
19};
20
21use super::{int::VarLen, RawInt};
22
23/// Wrapper for a raw byte sequence, that came from a server.
24///
25/// `T` encodes the serialized representation.
26#[derive(Clone, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
27#[repr(transparent)]
28pub struct RawBytes<'a, T: BytesRepr>(pub Cow<'a, [u8]>, PhantomData<T>);
29
30impl<'a, T: BytesRepr> RawBytes<'a, T> {
31    /// Wraps the given value.
32    pub fn new(text: impl Into<Cow<'a, [u8]>>) -> Self {
33        Self(text.into(), PhantomData)
34    }
35
36    /// Converts self to a 'static version.
37    pub fn into_owned(self) -> RawBytes<'static, T> {
38        RawBytes(Cow::Owned(self.0.into_owned()), PhantomData)
39    }
40
41    /// Returns `true` if bytes is empty.
42    pub fn is_empty(&self) -> bool {
43        self.len() == 0
44    }
45
46    /// Returns the _effective_ length of a string, which is no more than `T::MAX_LEN`.
47    pub fn len(&self) -> usize {
48        min(self.0.as_ref().len(), T::MAX_LEN)
49    }
50
51    /// Returns the _effective_ bytes (see `RawBytes::len`).
52    pub fn as_bytes(&self) -> &[u8] {
53        &self.0.as_ref()[..self.len()]
54    }
55
56    /// Returns the value as a UTF-8 string (lossy contverted).
57    pub fn as_str(&'a self) -> Cow<'a, str> {
58        String::from_utf8_lossy(self.as_bytes())
59    }
60}
61
62impl<'a, T: Into<Cow<'a, [u8]>>, U: BytesRepr> From<T> for RawBytes<'a, U> {
63    fn from(bytes: T) -> RawBytes<'a, U> {
64        RawBytes::new(bytes)
65    }
66}
67
68impl<T: BytesRepr> PartialEq<[u8]> for RawBytes<'_, T> {
69    fn eq(&self, other: &[u8]) -> bool {
70        self.0.as_ref().eq(other)
71    }
72}
73
74impl<T: BytesRepr> MySerialize for RawBytes<'_, T> {
75    fn serialize(&self, buf: &mut Vec<u8>) {
76        T::serialize(self.0.as_ref(), buf)
77    }
78}
79
80impl<'de, T: BytesRepr> MyDeserialize<'de> for RawBytes<'de, T> {
81    const SIZE: Option<usize> = T::SIZE;
82    type Ctx = T::Ctx;
83
84    #[inline(always)]
85    fn deserialize(ctx: Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
86        Ok(Self(T::deserialize(ctx, buf)?, PhantomData))
87    }
88}
89
90impl<T: BytesRepr> fmt::Debug for RawBytes<'_, T> {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.debug_struct("RawBytes")
93            .field("value", &self.as_str())
94            .field(
95                "max_len",
96                &(if self.0.len() <= T::MAX_LEN {
97                    format!("{}", T::MAX_LEN)
98                } else {
99                    format!("{} EXCEEDED!", T::MAX_LEN)
100                }),
101            )
102            .finish()
103    }
104}
105
106/// Representation of a serialized bytes.
107pub trait BytesRepr {
108    /// Maximum length of bytes for this repr (depends on how lenght is stored).
109    const MAX_LEN: usize;
110    const SIZE: Option<usize>;
111    type Ctx;
112
113    fn serialize(text: &[u8], buf: &mut Vec<u8>);
114
115    /// Implementation must check the length of the buffer if `Self::SIZE.is_none()`.
116    fn deserialize<'de>(ctx: Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>>;
117}
118
119impl BytesRepr for LenEnc {
120    const MAX_LEN: usize = usize::MAX;
121    const SIZE: Option<usize> = None;
122    type Ctx = ();
123
124    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
125        buf.put_lenenc_int(text.len() as u64);
126        buf.put_slice(text);
127    }
128
129    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
130        let len = buf.parse::<RawInt<LenEnc>>(())?;
131        buf.checked_eat(len.0 as usize)
132            .map(Cow::Borrowed)
133            .ok_or_else(unexpected_buf_eof)
134    }
135}
136
137/// A byte sequence prepended by it's u8 length.
138///
139/// `serialize` will truncate byte sequence if its too long.
140#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct U8Bytes;
142
143impl BytesRepr for U8Bytes {
144    const MAX_LEN: usize = u8::MAX as usize;
145    const SIZE: Option<usize> = None;
146    type Ctx = ();
147
148    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
149        buf.put_u8_str(text);
150    }
151
152    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
153        let len: RawInt<u8> = buf.parse(())?;
154        buf.checked_eat(len.0 as usize)
155            .map(Cow::Borrowed)
156            .ok_or_else(unexpected_buf_eof)
157    }
158}
159
160/// A byte sequence prepended by it's u32 length.
161///
162/// `serialize` will truncate byte sequence if its too long.
163#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
164pub struct U32Bytes;
165
166impl BytesRepr for U32Bytes {
167    const MAX_LEN: usize = u32::MAX as usize;
168    const SIZE: Option<usize> = None;
169    type Ctx = ();
170
171    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
172        buf.put_u32_str(text);
173    }
174
175    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
176        buf.checked_eat_u32_str()
177            .map(Cow::Borrowed)
178            .ok_or_else(unexpected_buf_eof)
179    }
180}
181
182/// Null-terminated byte sequence.
183///
184/// `deserialize()` will error with `InvalidData` if there is no `0`.
185#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
186pub struct NullBytes;
187
188impl BytesRepr for NullBytes {
189    const MAX_LEN: usize = usize::MAX;
190    const SIZE: Option<usize> = None;
191    type Ctx = ();
192
193    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
194        let last = text.iter().position(|x| *x == 0).unwrap_or(text.len());
195        buf.put_slice(&text[..last]);
196        buf.put_u8(0);
197    }
198
199    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
200        match buf.0.iter().position(|x| *x == 0) {
201            Some(i) => {
202                let out = buf.eat(i);
203                buf.skip(1);
204                Ok(Cow::Borrowed(out))
205            }
206            None => Err(io::Error::new(
207                io::ErrorKind::InvalidData,
208                "no null terminator for null-terminated string",
209            )),
210        }
211    }
212}
213
214/// A byte sequence that lasts from the current position to the end of the buffer.
215#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
216pub struct EofBytes;
217
218impl BytesRepr for EofBytes {
219    const MAX_LEN: usize = usize::MAX;
220    const SIZE: Option<usize> = None;
221    type Ctx = ();
222
223    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
224        buf.put_slice(text);
225    }
226
227    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
228        Ok(Cow::Borrowed(buf.eat_all()))
229    }
230}
231
232/// A byte sequence without length.
233///
234/// Its length is stored somewhere else.
235#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
236pub struct BareBytes<const MAX_LEN: usize>;
237
238impl<const MAX_LEN: usize> BytesRepr for BareBytes<MAX_LEN> {
239    const MAX_LEN: usize = MAX_LEN;
240    const SIZE: Option<usize> = None;
241    type Ctx = usize;
242
243    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
244        let len = min(text.len(), MAX_LEN);
245        buf.put_slice(&text[..len]);
246    }
247
248    fn deserialize<'de>(len: usize, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
249        buf.checked_eat(len)
250            .ok_or_else(unexpected_buf_eof)
251            .map(Cow::Borrowed)
252    }
253}
254
255/// `BareBytes` with `u8` len.
256pub type BareU8Bytes = BareBytes<{ u8::MAX as usize }>;
257
258/// `BareBytes` with `u16` len.
259pub type BareU16Bytes = BareBytes<{ u16::MAX as usize }>;
260
261/// A fixed length byte sequence (right-padded with `0x00`).
262///
263/// `serialize()` truncates the value if it's loo long.
264#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
265pub struct FixedLengthText<const LEN: usize>;
266
267impl<const LEN: usize> BytesRepr for FixedLengthText<LEN> {
268    const MAX_LEN: usize = LEN;
269    const SIZE: Option<usize> = Some(LEN);
270    type Ctx = ();
271
272    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
273        let len = min(LEN, text.len());
274        buf.put_slice(&text[..len]);
275        for _ in 0..(LEN - len) {
276            buf.put_u8(0);
277        }
278    }
279
280    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
281        match Self::SIZE {
282            Some(len) => Ok(Cow::Borrowed(buf.eat(len))),
283            None => buf
284                .checked_eat(LEN)
285                .map(Cow::Borrowed)
286                .ok_or_else(unexpected_buf_eof),
287        }
288    }
289}
290
291impl BytesRepr for VarLen {
292    const MAX_LEN: usize = u32::MAX as usize;
293    const SIZE: Option<usize> = None;
294    type Ctx = ();
295
296    fn serialize(text: &[u8], buf: &mut Vec<u8>) {
297        buf.put_lenenc_int(text.len() as u64);
298        buf.put_slice(text);
299    }
300
301    fn deserialize<'de>((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Cow<'de, [u8]>> {
302        let len = buf.parse::<RawInt<VarLen>>(())?;
303        buf.checked_eat(len.0 as usize)
304            .map(Cow::Borrowed)
305            .ok_or_else(unexpected_buf_eof)
306    }
307}
308
309/// Constantly known byte string.
310#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
311pub struct ConstBytes<T, const LEN: usize>(PhantomData<T>);
312
313pub trait ConstBytesValue<const LEN: usize> {
314    const VALUE: [u8; LEN];
315    type Error: Default + std::error::Error + Send + Sync + 'static;
316}
317
318impl<'de, T, const LEN: usize> MyDeserialize<'de> for ConstBytes<T, LEN>
319where
320    T: Default,
321    T: ConstBytesValue<LEN>,
322{
323    const SIZE: Option<usize> = Some(LEN);
324    type Ctx = ();
325
326    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
327        let bytes: [u8; LEN] = buf.parse_unchecked(())?;
328        if bytes == T::VALUE {
329            Ok(Default::default())
330        } else {
331            Err(io::Error::new(
332                io::ErrorKind::InvalidData,
333                T::Error::default(),
334            ))
335        }
336    }
337}
338
339impl<T, const LEN: usize> MySerialize for ConstBytes<T, LEN>
340where
341    T: ConstBytesValue<LEN>,
342{
343    fn serialize(&self, buf: &mut Vec<u8>) {
344        T::VALUE.serialize(buf)
345    }
346}