1use std::convert::TryFrom;
2
3use crate::error::{Error, Result};
4
5#[derive(Clone, Debug, Default, PartialEq)]
7pub enum Value {
8 Binary(Vec<u8>),
10 Float(f64),
12 Integer(i64),
14 String(String),
16 #[default]
18 Null,
19}
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum Type {
24 Binary,
26 Float,
28 Integer,
30 String,
32 Null,
34}
35
36impl Value {
37 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 #[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}