Skip to main content

sql_peas/
value.rs

1use std::convert::TryFrom;
2
3use crate::error::{Error, Result};
4
5/// A value.
6#[derive(Clone, Debug, Default, PartialEq)]
7pub enum Value {
8    /// Binary data.
9    Binary(Vec<u8>),
10    /// A floating-point number.
11    Float(f64),
12    /// An integer number.
13    Integer(i64),
14    /// A string.
15    String(String),
16    /// A null value.
17    #[default]
18    Null,
19}
20
21/// The type of a value.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum Type {
24    /// The binary type.
25    Binary,
26    /// The floating-point type.
27    Float,
28    /// The integer type.
29    Integer,
30    /// The string type.
31    String,
32    /// The null type.
33    Null,
34}
35
36impl Value {
37    /// Return the type.
38    pub fn kind(&self) -> Type {
39        match self {
40            Value::Binary(_) => Type::Binary,
41            Value::Float(_) => Type::Float,
42            Value::Integer(_) => Type::Integer,
43            Value::String(_) => Type::String,
44            Value::Null => Type::Null,
45        }
46    }
47
48    /// Try to return the value.
49    #[inline]
50    pub fn try_into<'l, T>(&'l self) -> Result<T>
51    where
52        T: TryFrom<&'l Value, Error = Error>,
53    {
54        T::try_from(self)
55    }
56}
57
58macro_rules! implement(
59    ($type:ty, Null) => {
60        impl From<$type> for Value {
61            #[inline]
62            fn from(_: $type) -> Self {
63                Value::Null
64            }
65        }
66    };
67    ($type:ty, $value:ident) => {
68        impl From<$type> for Value {
69            #[inline]
70            fn from(value: $type) -> Self {
71                Value::$value(value.into())
72            }
73        }
74    };
75);
76
77implement!(Vec<u8>, Binary);
78implement!(&[u8], Binary);
79implement!(f64, Float);
80implement!(i64, Integer);
81implement!(String, String);
82implement!(&str, String);
83implement!((), Null);
84
85macro_rules! implement(
86    (@value $type:ty, $value:ident) => {
87        impl TryFrom<Value> for $type {
88            type Error = Error;
89
90            #[inline]
91            fn try_from(value: Value) -> Result<Self> {
92                if let Value::$value(value) = value {
93                    return Ok(value);
94                }
95                raise!("failed to convert");
96            }
97        }
98
99        impl TryFrom<Value> for Option<$type> {
100            type Error = Error;
101
102            #[inline]
103            fn try_from(value: Value) -> Result<Self> {
104                if let Value::Null = value {
105                    return Ok(None);
106                }
107                <$type>::try_from(value).and_then(|value| Ok(Some(value)))
108            }
109        }
110    };
111    (@reference (), Null) => {
112        impl TryFrom<&Value> for () {
113            type Error = Error;
114
115            #[inline]
116            fn try_from(value: &Value) -> Result<Self> {
117                if let &Value::Null = value {
118                    return Ok(());
119                }
120                raise!("failed to convert");
121            }
122        }
123    };
124    (@reference $type:ty, $value:ident) => {
125        impl TryFrom<&Value> for $type {
126            type Error = Error;
127
128            #[inline]
129            fn try_from(value: &Value) -> Result<Self> {
130                if let &Value::$value(value) = value {
131                    return Ok(value);
132                }
133                raise!("failed to convert");
134            }
135        }
136
137        impl TryFrom<&Value> for Option<$type> {
138            type Error = Error;
139
140            #[inline]
141            fn try_from(value: &Value) -> Result<Self> {
142                if let &Value::Null = value {
143                    return Ok(None);
144                }
145                <$type>::try_from(value).and_then(|value| Ok(Some(value)))
146            }
147        }
148    };
149    (@reference-lifetime $type:ty, $value:ident) => {
150        impl<'l> TryFrom<&'l Value> for $type {
151            type Error = Error;
152
153            #[inline]
154            fn try_from(value: &'l Value) -> Result<Self> {
155                if let &Value::$value(ref value) = value {
156                    return Ok(value);
157                }
158                raise!("failed to convert");
159            }
160        }
161
162        impl<'l> TryFrom<&'l Value> for Option<$type> {
163            type Error = Error;
164
165            #[inline]
166            fn try_from(value: &'l Value) -> Result<Self> {
167                if let Value::Null = value {
168                    return Ok(None);
169                }
170                <$type>::try_from(value).and_then(|value| Ok(Some(value)))
171            }
172        }
173    };
174);
175
176implement!(@value Vec<u8>, Binary);
177implement!(@reference-lifetime &'l [u8], Binary);
178implement!(@reference f64, Float);
179implement!(@reference i64, Integer);
180implement!(@value String, String);
181implement!(@reference-lifetime &'l str, String);
182implement!(@reference (), Null);
183
184impl<T> From<Option<T>> for Value
185where
186    T: Into<Value>,
187    Value: From<T>,
188{
189    #[inline]
190    fn from(value: Option<T>) -> Self {
191        match value {
192            Some(value) => Value::from(value),
193            _ => Self::Null,
194        }
195    }
196}