mysql_common/misc/raw/
_const.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 std::{
10    convert::TryFrom,
11    fmt, io,
12    marker::PhantomData,
13    ops::{Deref, DerefMut},
14};
15
16use crate::{
17    io::ParseBuf,
18    proto::{MyDeserialize, MySerialize},
19};
20
21use super::{int::IntRepr, RawInt};
22
23/// Same as `RawConst<T, U>` but holds `U` instead of `T`, i.e. holds the parsed value.
24///
25/// `MyDeserialize::deserialize` will error with `io::ErrorKind::InvalidData`
26/// if `T::try_from(_: U::Primitive)` fails.
27#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
28#[repr(transparent)]
29pub struct Const<T, U>(pub T, PhantomData<U>);
30
31impl<T, U> Const<T, U> {
32    /// Creates a new `Const`.
33    pub fn new(t: T) -> Self {
34        Self(t, PhantomData)
35    }
36}
37
38impl<T, U> Deref for Const<T, U> {
39    type Target = T;
40
41    fn deref(&self) -> &Self::Target {
42        &self.0
43    }
44}
45
46impl<T, U> DerefMut for Const<T, U> {
47    fn deref_mut(&mut self) -> &mut Self::Target {
48        &mut self.0
49    }
50}
51
52impl<'de, T, U> MyDeserialize<'de> for Const<T, U>
53where
54    U: IntRepr,
55    T: TryFrom<U::Primitive>,
56    <T as TryFrom<U::Primitive>>::Error: std::error::Error + Send + Sync + 'static,
57{
58    const SIZE: Option<usize> = U::SIZE;
59    type Ctx = ();
60
61    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
62        let raw_val = buf.parse_unchecked::<RawInt<U>>(())?;
63        T::try_from(*raw_val)
64            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
65            .map(Const::new)
66    }
67}
68
69impl<T, U> MySerialize for Const<T, U>
70where
71    T: Copy,
72    T: Into<U::Primitive>,
73    U: IntRepr,
74{
75    fn serialize(&self, buf: &mut Vec<u8>) {
76        RawInt::<U>::new(self.0.into()).serialize(buf);
77    }
78}
79
80/// Wrapper for a raw value of a MySql constant, enum variant or flags value.
81///
82/// * `T` – specifies the raw value,
83/// * `U` – specifies the parsed value.
84#[derive(Clone, Default, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
85#[repr(transparent)]
86pub struct RawConst<T: IntRepr, U>(pub T::Primitive, PhantomData<U>);
87
88impl<T: IntRepr, U> RawConst<T, U> {
89    /// Creates a new wrapper.
90    pub fn new(t: T::Primitive) -> Self {
91        Self(t, PhantomData)
92    }
93}
94
95impl<T: IntRepr, U> Deref for RawConst<T, U> {
96    type Target = T::Primitive;
97
98    fn deref(&self) -> &Self::Target {
99        &self.0
100    }
101}
102
103impl<T: IntRepr, U> DerefMut for RawConst<T, U> {
104    fn deref_mut(&mut self) -> &mut Self::Target {
105        &mut self.0
106    }
107}
108
109impl<T: IntRepr, U> RawConst<T, U>
110where
111    T::Primitive: Copy,
112    U: TryFrom<T::Primitive>,
113{
114    /// Tries to parse the raw value as `U`.
115    pub fn get(&self) -> Result<U, U::Error> {
116        U::try_from(self.0)
117    }
118}
119
120impl<T: IntRepr, U> fmt::Debug for RawConst<T, U>
121where
122    T: fmt::Debug,
123    T::Primitive: Copy,
124    U: fmt::Debug + TryFrom<T::Primitive>,
125    U::Error: fmt::Debug,
126{
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        match U::try_from(self.0) {
129            Ok(u) => u.fmt(f),
130            Err(t) => write!(
131                f,
132                "Unknown value for type {}: {:?}",
133                std::any::type_name::<U>(),
134                t
135            ),
136        }
137    }
138}
139
140impl<'de, T: IntRepr, U> MyDeserialize<'de> for RawConst<T, U> {
141    const SIZE: Option<usize> = T::SIZE;
142    type Ctx = ();
143
144    fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
145        let value = buf.parse_unchecked::<RawInt<T>>(())?.0;
146        Ok(Self::new(value))
147    }
148}
149
150impl<T: IntRepr, U> MySerialize for RawConst<T, U> {
151    fn serialize(&self, buf: &mut Vec<u8>) {
152        RawInt::<T>::new(self.0).serialize(buf);
153    }
154}