1use std::str::FromStr;
2
3use crate::{Error, Result};
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum Value {
7 Null,
8 Integer(i64),
9 Real(f64),
10 Text(String),
11 Blob(Vec<u8>),
12}
13
14#[derive(Debug, Copy, Clone)]
16pub enum ValueType {
17 Integer = 1,
18 Real,
19 Text,
20 Blob,
21 Null,
22}
23
24impl FromStr for ValueType {
25 type Err = ();
26
27 fn from_str(s: &str) -> std::result::Result<ValueType, Self::Err> {
28 match s {
29 "TEXT" => Ok(ValueType::Text),
30 "INTEGER" => Ok(ValueType::Integer),
31 "BLOB" => Ok(ValueType::Blob),
32 "NULL" => Ok(ValueType::Null),
33 "REAL" => Ok(ValueType::Real),
34 _ => Err(()),
35 }
36 }
37}
38
39impl Value {
40 #[must_use]
44 pub fn is_null(&self) -> bool {
45 matches!(self, Self::Null)
46 }
47
48 #[must_use]
52 pub fn is_integer(&self) -> bool {
53 matches!(self, Self::Integer(..))
54 }
55
56 #[must_use]
60 pub fn is_real(&self) -> bool {
61 matches!(self, Self::Real(..))
62 }
63
64 pub fn as_real(&self) -> Option<&f64> {
65 if let Self::Real(v) = self {
66 Some(v)
67 } else {
68 None
69 }
70 }
71
72 #[must_use]
76 pub fn is_text(&self) -> bool {
77 matches!(self, Self::Text(..))
78 }
79
80 pub fn as_text(&self) -> Option<&String> {
81 if let Self::Text(v) = self {
82 Some(v)
83 } else {
84 None
85 }
86 }
87
88 pub fn as_integer(&self) -> Option<&i64> {
89 if let Self::Integer(v) = self {
90 Some(v)
91 } else {
92 None
93 }
94 }
95
96 #[must_use]
100 pub fn is_blob(&self) -> bool {
101 matches!(self, Self::Blob(..))
102 }
103
104 pub fn as_blob(&self) -> Option<&Vec<u8>> {
105 if let Self::Blob(v) = self {
106 Some(v)
107 } else {
108 None
109 }
110 }
111}
112
113impl Into<limbo_core::Value> for Value {
114 fn into(self) -> limbo_core::Value {
115 match self {
116 Value::Null => limbo_core::Value::Null,
117 Value::Integer(n) => limbo_core::Value::Integer(n),
118 Value::Real(n) => limbo_core::Value::Float(n),
119 Value::Text(t) => limbo_core::Value::from_text(&t),
120 Value::Blob(items) => limbo_core::Value::from_blob(items),
121 }
122 }
123}
124
125impl From<i8> for Value {
126 fn from(value: i8) -> Value {
127 Value::Integer(value as i64)
128 }
129}
130
131impl From<i16> for Value {
132 fn from(value: i16) -> Value {
133 Value::Integer(value as i64)
134 }
135}
136
137impl From<i32> for Value {
138 fn from(value: i32) -> Value {
139 Value::Integer(value as i64)
140 }
141}
142
143impl From<i64> for Value {
144 fn from(value: i64) -> Value {
145 Value::Integer(value)
146 }
147}
148
149impl From<u8> for Value {
150 fn from(value: u8) -> Value {
151 Value::Integer(value as i64)
152 }
153}
154
155impl From<u16> for Value {
156 fn from(value: u16) -> Value {
157 Value::Integer(value as i64)
158 }
159}
160
161impl From<u32> for Value {
162 fn from(value: u32) -> Value {
163 Value::Integer(value as i64)
164 }
165}
166
167impl TryFrom<u64> for Value {
168 type Error = Error;
169
170 fn try_from(value: u64) -> Result<Value> {
171 if value > i64::MAX as u64 {
172 Err(Error::ToSqlConversionFailure(
173 "u64 is too large to fit in an i64".into(),
174 ))
175 } else {
176 Ok(Value::Integer(value as i64))
177 }
178 }
179}
180
181impl From<f32> for Value {
182 fn from(value: f32) -> Value {
183 Value::Real(value as f64)
184 }
185}
186
187impl From<f64> for Value {
188 fn from(value: f64) -> Value {
189 Value::Real(value)
190 }
191}
192
193impl From<&str> for Value {
194 fn from(value: &str) -> Value {
195 Value::Text(value.to_owned())
196 }
197}
198
199impl From<String> for Value {
200 fn from(value: String) -> Value {
201 Value::Text(value)
202 }
203}
204
205impl From<&[u8]> for Value {
206 fn from(value: &[u8]) -> Value {
207 Value::Blob(value.to_owned())
208 }
209}
210
211impl From<Vec<u8>> for Value {
212 fn from(value: Vec<u8>) -> Value {
213 Value::Blob(value)
214 }
215}
216
217impl From<bool> for Value {
218 fn from(value: bool) -> Value {
219 Value::Integer(value as i64)
220 }
221}
222
223impl<T> From<Option<T>> for Value
224where
225 T: Into<Value>,
226{
227 fn from(value: Option<T>) -> Self {
228 match value {
229 Some(inner) => inner.into(),
230 None => Value::Null,
231 }
232 }
233}
234
235#[derive(Debug)]
237pub enum ValueRef<'a> {
238 Null,
239 Integer(i64),
240 Real(f64),
241 Text(&'a [u8]),
242 Blob(&'a [u8]),
243}
244
245impl ValueRef<'_> {
246 pub fn data_type(&self) -> ValueType {
247 match *self {
248 ValueRef::Null => ValueType::Null,
249 ValueRef::Integer(_) => ValueType::Integer,
250 ValueRef::Real(_) => ValueType::Real,
251 ValueRef::Text(_) => ValueType::Text,
252 ValueRef::Blob(_) => ValueType::Blob,
253 }
254 }
255
256 #[must_use]
260 pub fn is_null(&self) -> bool {
261 matches!(self, Self::Null)
262 }
263
264 #[must_use]
268 pub fn is_integer(&self) -> bool {
269 matches!(self, Self::Integer(..))
270 }
271
272 pub fn as_integer(&self) -> Option<&i64> {
273 if let Self::Integer(v) = self {
274 Some(v)
275 } else {
276 None
277 }
278 }
279
280 #[must_use]
284 pub fn is_real(&self) -> bool {
285 matches!(self, Self::Real(..))
286 }
287
288 pub fn as_real(&self) -> Option<&f64> {
289 if let Self::Real(v) = self {
290 Some(v)
291 } else {
292 None
293 }
294 }
295
296 #[must_use]
300 pub fn is_text(&self) -> bool {
301 matches!(self, Self::Text(..))
302 }
303
304 pub fn as_text(&self) -> Option<&[u8]> {
305 if let Self::Text(v) = self {
306 Some(v)
307 } else {
308 None
309 }
310 }
311
312 #[must_use]
316 pub fn is_blob(&self) -> bool {
317 matches!(self, Self::Blob(..))
318 }
319
320 pub fn as_blob(&self) -> Option<&[u8]> {
321 if let Self::Blob(v) = self {
322 Some(v)
323 } else {
324 None
325 }
326 }
327}
328
329impl From<ValueRef<'_>> for Value {
330 fn from(vr: ValueRef<'_>) -> Value {
331 match vr {
332 ValueRef::Null => Value::Null,
333 ValueRef::Integer(i) => Value::Integer(i),
334 ValueRef::Real(r) => Value::Real(r),
335 ValueRef::Text(s) => Value::Text(String::from_utf8_lossy(s).to_string()),
336 ValueRef::Blob(b) => Value::Blob(b.to_vec()),
337 }
338 }
339}
340
341impl<'a> From<&'a str> for ValueRef<'a> {
342 fn from(s: &str) -> ValueRef<'_> {
343 ValueRef::Text(s.as_bytes())
344 }
345}
346
347impl<'a> From<&'a [u8]> for ValueRef<'a> {
348 fn from(s: &[u8]) -> ValueRef<'_> {
349 ValueRef::Blob(s)
350 }
351}
352
353impl<'a> From<&'a Value> for ValueRef<'a> {
354 fn from(v: &'a Value) -> ValueRef<'a> {
355 match *v {
356 Value::Null => ValueRef::Null,
357 Value::Integer(i) => ValueRef::Integer(i),
358 Value::Real(r) => ValueRef::Real(r),
359 Value::Text(ref s) => ValueRef::Text(s.as_bytes()),
360 Value::Blob(ref b) => ValueRef::Blob(b),
361 }
362 }
363}
364
365impl<'a, T> From<Option<T>> for ValueRef<'a>
366where
367 T: Into<ValueRef<'a>>,
368{
369 #[inline]
370 fn from(s: Option<T>) -> ValueRef<'a> {
371 match s {
372 Some(x) => x.into(),
373 None => ValueRef::Null,
374 }
375 }
376}