quaint_forked/ast/
values.rs

1use crate::ast::*;
2use crate::error::{Error, ErrorKind};
3
4#[cfg(feature = "bigdecimal")]
5use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
6#[cfg(feature = "chrono")]
7use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
8#[cfg(feature = "json")]
9use serde_json::{Number, Value as JsonValue};
10use std::{
11    borrow::{Borrow, Cow},
12    convert::TryFrom,
13    fmt,
14    str::FromStr,
15};
16#[cfg(feature = "uuid")]
17use uuid::Uuid;
18
19/// A value written to the query as-is without parameterization.
20#[derive(Debug, Clone, PartialEq)]
21pub struct Raw<'a>(pub(crate) Value<'a>);
22
23/// Converts the value into a state to skip parameterization.
24///
25/// Must be used carefully to avoid SQL injections.
26pub trait IntoRaw<'a> {
27    fn raw(self) -> Raw<'a>;
28}
29
30impl<'a, T> IntoRaw<'a> for T
31where
32    T: Into<Value<'a>>,
33{
34    fn raw(self) -> Raw<'a> {
35        Raw(self.into())
36    }
37}
38
39/// A value we must parameterize for the prepared statement. Null values should be
40/// defined by their corresponding type variants with a `None` value for best
41/// compatibility.
42#[derive(Debug, Clone, PartialEq)]
43pub enum Value<'a> {
44    /// 32-bit signed integer.
45    Int32(Option<i32>),
46    /// 64-bit signed integer.
47    Int64(Option<i64>),
48    /// 32-bit floating point.
49    Float(Option<f32>),
50    /// 64-bit floating point.
51    Double(Option<f64>),
52    /// String value.
53    Text(Option<Cow<'a, str>>),
54    /// Database enum value.
55    Enum(Option<Cow<'a, str>>),
56    /// Bytes value.
57    Bytes(Option<Cow<'a, [u8]>>),
58    /// Boolean value.
59    Boolean(Option<bool>),
60    /// A single character.
61    Char(Option<char>),
62    /// An array value (PostgreSQL).
63    Array(Option<Vec<Value<'a>>>),
64    /// A numeric value.
65    #[cfg(feature = "bigdecimal")]
66        Numeric(Option<BigDecimal>),
67    #[cfg(feature = "json")]
68        /// A JSON value.
69    Json(Option<serde_json::Value>),
70    /// A XML value.
71    Xml(Option<Cow<'a, str>>),
72    #[cfg(feature = "uuid")]
73        /// An UUID value.
74    Uuid(Option<Uuid>),
75    #[cfg(feature = "chrono")]
76        /// A datetime value.
77    DateTime(Option<DateTime<Utc>>),
78    #[cfg(feature = "chrono")]
79        /// A date value.
80    Date(Option<NaiveDate>),
81    #[cfg(feature = "chrono")]
82        /// A time value.
83    Time(Option<NaiveTime>),
84}
85
86pub(crate) struct Params<'a>(pub(crate) &'a [Value<'a>]);
87
88impl<'a> fmt::Display for Params<'a> {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        let len = self.0.len();
91
92        write!(f, "[")?;
93        for (i, val) in self.0.iter().enumerate() {
94            write!(f, "{val}")?;
95
96            if i < (len - 1) {
97                write!(f, ",")?;
98            }
99        }
100        write!(f, "]")
101    }
102}
103
104impl<'a> fmt::Display for Value<'a> {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        let res = match self {
107            Value::Int32(val) => val.map(|v| write!(f, "{v}")),
108            Value::Int64(val) => val.map(|v| write!(f, "{v}")),
109            Value::Float(val) => val.map(|v| write!(f, "{v}")),
110            Value::Double(val) => val.map(|v| write!(f, "{v}")),
111            Value::Text(val) => val.as_ref().map(|v| write!(f, "\"{v}\"")),
112            Value::Bytes(val) => val.as_ref().map(|v| write!(f, "<{} bytes blob>", v.len())),
113            Value::Enum(val) => val.as_ref().map(|v| write!(f, "\"{v}\"")),
114            Value::Boolean(val) => val.map(|v| write!(f, "{v}")),
115            Value::Char(val) => val.map(|v| write!(f, "'{v}'")),
116            Value::Array(vals) => vals.as_ref().map(|vals| {
117                let len = vals.len();
118
119                write!(f, "[")?;
120                for (i, val) in vals.iter().enumerate() {
121                    write!(f, "{val}")?;
122
123                    if i < (len - 1) {
124                        write!(f, ",")?;
125                    }
126                }
127                write!(f, "]")
128            }),
129            Value::Xml(val) => val.as_ref().map(|v| write!(f, "{v}")),
130            #[cfg(feature = "bigdecimal")]
131            Value::Numeric(val) => val.as_ref().map(|v| write!(f, "{v}")),
132            #[cfg(feature = "json")]
133            Value::Json(val) => val.as_ref().map(|v| write!(f, "{v}")),
134            #[cfg(feature = "uuid")]
135            Value::Uuid(val) => val.map(|v| write!(f, "\"{v}\"")),
136            #[cfg(feature = "chrono")]
137            Value::DateTime(val) => val.map(|v| write!(f, "\"{v}\"")),
138            #[cfg(feature = "chrono")]
139            Value::Date(val) => val.map(|v| write!(f, "\"{v}\"")),
140            #[cfg(feature = "chrono")]
141            Value::Time(val) => val.map(|v| write!(f, "\"{v}\"")),
142        };
143
144        match res {
145            Some(r) => r,
146            None => write!(f, "null"),
147        }
148    }
149}
150
151#[cfg(feature = "json")]
152impl<'a> From<Value<'a>> for serde_json::Value {
153    fn from(pv: Value<'a>) -> Self {
154        let res = match pv {
155            Value::Int32(i) => i.map(|i| serde_json::Value::Number(Number::from(i))),
156            Value::Int64(i) => i.map(|i| serde_json::Value::Number(Number::from(i))),
157            Value::Float(f) => f.map(|f| match Number::from_f64(f as f64) {
158                Some(number) => serde_json::Value::Number(number),
159                None => serde_json::Value::Null,
160            }),
161            Value::Double(f) => f.map(|f| match Number::from_f64(f) {
162                Some(number) => serde_json::Value::Number(number),
163                None => serde_json::Value::Null,
164            }),
165            Value::Text(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
166            Value::Bytes(bytes) => bytes.map(|bytes| serde_json::Value::String(base64::encode(bytes))),
167            Value::Enum(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
168            Value::Boolean(b) => b.map(serde_json::Value::Bool),
169            Value::Char(c) => c.map(|c| {
170                let bytes = [c as u8];
171                let s = std::str::from_utf8(&bytes)
172                    .expect("interpret byte as UTF-8")
173                    .to_string();
174                serde_json::Value::String(s)
175            }),
176            Value::Xml(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
177            Value::Array(v) => {
178                v.map(|v| serde_json::Value::Array(v.into_iter().map(serde_json::Value::from).collect()))
179            }
180            #[cfg(feature = "bigdecimal")]
181            Value::Numeric(d) => d.map(|d| serde_json::to_value(d.to_f64().unwrap()).unwrap()),
182            #[cfg(feature = "json")]
183            Value::Json(v) => v,
184            #[cfg(feature = "uuid")]
185            Value::Uuid(u) => u.map(|u| serde_json::Value::String(u.hyphenated().to_string())),
186            #[cfg(feature = "chrono")]
187            Value::DateTime(dt) => dt.map(|dt| serde_json::Value::String(dt.to_rfc3339())),
188            #[cfg(feature = "chrono")]
189            Value::Date(date) => date.map(|date| serde_json::Value::String(format!("{date}"))),
190            #[cfg(feature = "chrono")]
191            Value::Time(time) => time.map(|time| serde_json::Value::String(format!("{time}"))),
192        };
193
194        match res {
195            Some(val) => val,
196            None => serde_json::Value::Null,
197        }
198    }
199}
200
201impl<'a> Value<'a> {
202    /// Creates a new 32-bit signed integer.
203    pub fn int32<I>(value: I) -> Self
204    where
205        I: Into<i32>,
206    {
207        Value::Int32(Some(value.into()))
208    }
209
210    /// Creates a new 64-bit signed integer.
211    pub fn int64<I>(value: I) -> Self
212    where
213        I: Into<i64>,
214    {
215        Value::Int64(Some(value.into()))
216    }
217
218    /// Creates a new 32-bit signed integer.
219    pub fn integer<I>(value: I) -> Self
220    where
221        I: Into<i32>,
222    {
223        Value::Int32(Some(value.into()))
224    }
225
226    /// Creates a new decimal value.
227    #[cfg(feature = "bigdecimal")]
228        pub const fn numeric(value: BigDecimal) -> Self {
229        Value::Numeric(Some(value))
230    }
231
232    /// Creates a new float value.
233    pub const fn float(value: f32) -> Self {
234        Self::Float(Some(value))
235    }
236
237    /// Creates a new double value.
238    pub const fn double(value: f64) -> Self {
239        Self::Double(Some(value))
240    }
241
242    /// Creates a new string value.
243    pub fn text<T>(value: T) -> Self
244    where
245        T: Into<Cow<'a, str>>,
246    {
247        Value::Text(Some(value.into()))
248    }
249
250    /// Creates a new enum value.
251    pub fn enum_variant<T>(value: T) -> Self
252    where
253        T: Into<Cow<'a, str>>,
254    {
255        Value::Enum(Some(value.into()))
256    }
257
258    /// Creates a new bytes value.
259    pub fn bytes<B>(value: B) -> Self
260    where
261        B: Into<Cow<'a, [u8]>>,
262    {
263        Value::Bytes(Some(value.into()))
264    }
265
266    /// Creates a new boolean value.
267    pub fn boolean<B>(value: B) -> Self
268    where
269        B: Into<bool>,
270    {
271        Value::Boolean(Some(value.into()))
272    }
273
274    /// Creates a new character value.
275    pub fn character<C>(value: C) -> Self
276    where
277        C: Into<char>,
278    {
279        Value::Char(Some(value.into()))
280    }
281
282    /// Creates a new array value.
283    pub fn array<I, V>(value: I) -> Self
284    where
285        I: IntoIterator<Item = V>,
286        V: Into<Value<'a>>,
287    {
288        Value::Array(Some(value.into_iter().map(|v| v.into()).collect()))
289    }
290
291    /// Creates a new uuid value.
292    #[cfg(feature = "uuid")]
293        pub const fn uuid(value: Uuid) -> Self {
294        Value::Uuid(Some(value))
295    }
296
297    /// Creates a new datetime value.
298    #[cfg(feature = "chrono")]
299        pub const fn datetime(value: DateTime<Utc>) -> Self {
300        Value::DateTime(Some(value))
301    }
302
303    /// Creates a new date value.
304    #[cfg(feature = "chrono")]
305        pub const fn date(value: NaiveDate) -> Self {
306        Value::Date(Some(value))
307    }
308
309    /// Creates a new time value.
310    #[cfg(feature = "chrono")]
311        pub const fn time(value: NaiveTime) -> Self {
312        Value::Time(Some(value))
313    }
314
315    /// Creates a new JSON value.
316    #[cfg(feature = "json")]
317        pub const fn json(value: serde_json::Value) -> Self {
318        Value::Json(Some(value))
319    }
320
321    /// Creates a new XML value.
322    pub fn xml<T>(value: T) -> Self
323    where
324        T: Into<Cow<'a, str>>,
325    {
326        Value::Xml(Some(value.into()))
327    }
328
329    /// `true` if the `Value` is null.
330    pub const fn is_null(&self) -> bool {
331        match self {
332            Value::Int32(i) => i.is_none(),
333            Value::Int64(i) => i.is_none(),
334            Value::Float(i) => i.is_none(),
335            Value::Double(i) => i.is_none(),
336            Value::Text(t) => t.is_none(),
337            Value::Enum(e) => e.is_none(),
338            Value::Bytes(b) => b.is_none(),
339            Value::Boolean(b) => b.is_none(),
340            Value::Char(c) => c.is_none(),
341            Value::Array(v) => v.is_none(),
342            Value::Xml(s) => s.is_none(),
343            #[cfg(feature = "bigdecimal")]
344            Value::Numeric(r) => r.is_none(),
345            #[cfg(feature = "uuid")]
346            Value::Uuid(u) => u.is_none(),
347            #[cfg(feature = "chrono")]
348            Value::DateTime(dt) => dt.is_none(),
349            #[cfg(feature = "chrono")]
350            Value::Date(d) => d.is_none(),
351            #[cfg(feature = "chrono")]
352            Value::Time(t) => t.is_none(),
353            #[cfg(feature = "json")]
354            Value::Json(json) => json.is_none(),
355        }
356    }
357
358    /// `true` if the `Value` is text.
359    pub const fn is_text(&self) -> bool {
360        matches!(self, Value::Text(_))
361    }
362
363    /// Returns a &str if the value is text, otherwise `None`.
364    pub fn as_str(&self) -> Option<&str> {
365        match self {
366            Value::Text(Some(cow)) => Some(cow.borrow()),
367            Value::Bytes(Some(cow)) => std::str::from_utf8(cow.as_ref()).ok(),
368            _ => None,
369        }
370    }
371
372    /// Returns a char if the value is a char, otherwise `None`.
373    pub const fn as_char(&self) -> Option<char> {
374        match self {
375            Value::Char(c) => *c,
376            _ => None,
377        }
378    }
379
380    /// Returns a cloned String if the value is text, otherwise `None`.
381    pub fn to_string(&self) -> Option<String> {
382        match self {
383            Value::Text(Some(cow)) => Some(cow.to_string()),
384            Value::Bytes(Some(cow)) => std::str::from_utf8(cow.as_ref()).map(|s| s.to_owned()).ok(),
385            _ => None,
386        }
387    }
388
389    /// Transforms the `Value` to a `String` if it's text,
390    /// otherwise `None`.
391    pub fn into_string(self) -> Option<String> {
392        match self {
393            Value::Text(Some(cow)) => Some(cow.into_owned()),
394            Value::Bytes(Some(cow)) => String::from_utf8(cow.into_owned()).ok(),
395            _ => None,
396        }
397    }
398
399    /// Returns whether this value is the `Bytes` variant.
400    pub const fn is_bytes(&self) -> bool {
401        matches!(self, Value::Bytes(_))
402    }
403
404    /// Returns a bytes slice if the value is text or a byte slice, otherwise `None`.
405    pub fn as_bytes(&self) -> Option<&[u8]> {
406        match self {
407            Value::Text(Some(cow)) => Some(cow.as_ref().as_bytes()),
408            Value::Bytes(Some(cow)) => Some(cow.as_ref()),
409            _ => None,
410        }
411    }
412
413    /// Returns a cloned `Vec<u8>` if the value is text or a byte slice, otherwise `None`.
414    pub fn to_bytes(&self) -> Option<Vec<u8>> {
415        match self {
416            Value::Text(Some(cow)) => Some(cow.to_string().into_bytes()),
417            Value::Bytes(Some(cow)) => Some(cow.to_vec()),
418            _ => None,
419        }
420    }
421
422    /// `true` if the `Value` is a 32-bit signed integer.
423    pub const fn is_i32(&self) -> bool {
424        matches!(self, Value::Int32(_))
425    }
426
427    /// `true` if the `Value` is a 64-bit signed integer.
428    pub const fn is_i64(&self) -> bool {
429        matches!(self, Value::Int64(_))
430    }
431
432    /// `true` if the `Value` is a signed integer.
433    pub const fn is_integer(&self) -> bool {
434        matches!(self, Value::Int32(_) | Value::Int64(_))
435    }
436
437    /// Returns an `i64` if the value is a 64-bit signed integer, otherwise `None`.
438    pub const fn as_i64(&self) -> Option<i64> {
439        match self {
440            Value::Int64(i) => *i,
441            _ => None,
442        }
443    }
444
445    /// Returns an `i32` if the value is a 32-bit signed integer, otherwise `None`.
446    pub const fn as_i32(&self) -> Option<i32> {
447        match self {
448            Value::Int32(i) => *i,
449            _ => None,
450        }
451    }
452
453    /// Returns an `i64` if the value is a signed integer, otherwise `None`.
454    pub fn as_integer(&self) -> Option<i64> {
455        match self {
456            Value::Int32(i) => i.map(|i| i as i64),
457            Value::Int64(i) => *i,
458            _ => None,
459        }
460    }
461
462    /// Returns a `f64` if the value is a double, otherwise `None`.
463    pub const fn as_f64(&self) -> Option<f64> {
464        match self {
465            Value::Double(Some(f)) => Some(*f),
466            _ => None,
467        }
468    }
469
470    /// Returns a `f32` if the value is a double, otherwise `None`.
471    pub const fn as_f32(&self) -> Option<f32> {
472        match self {
473            Value::Float(Some(f)) => Some(*f),
474            _ => None,
475        }
476    }
477
478    /// `true` if the `Value` is a numeric value or can be converted to one.
479    #[cfg(feature = "bigdecimal")]
480        pub const fn is_numeric(&self) -> bool {
481        matches!(self, Value::Numeric(_) | Value::Float(_) | Value::Double(_))
482    }
483
484    /// Returns a bigdecimal, if the value is a numeric, float or double value,
485    /// otherwise `None`.
486    #[cfg(feature = "bigdecimal")]
487        pub fn into_numeric(self) -> Option<BigDecimal> {
488        match self {
489            Value::Numeric(d) => d,
490            Value::Float(f) => f.and_then(BigDecimal::from_f32),
491            Value::Double(f) => f.and_then(BigDecimal::from_f64),
492            _ => None,
493        }
494    }
495
496    /// Returns a reference to a bigdecimal, if the value is a numeric.
497    /// Otherwise `None`.
498    #[cfg(feature = "bigdecimal")]
499        pub const fn as_numeric(&self) -> Option<&BigDecimal> {
500        match self {
501            Value::Numeric(d) => d.as_ref(),
502            _ => None,
503        }
504    }
505
506    /// `true` if the `Value` is a boolean value.
507    pub const fn is_bool(&self) -> bool {
508        match self {
509            Value::Boolean(_) => true,
510            // For schemas which don't tag booleans
511            Value::Int32(Some(i)) if *i == 0 || *i == 1 => true,
512            Value::Int64(Some(i)) if *i == 0 || *i == 1 => true,
513            _ => false,
514        }
515    }
516
517    /// Returns a bool if the value is a boolean, otherwise `None`.
518    pub const fn as_bool(&self) -> Option<bool> {
519        match self {
520            Value::Boolean(b) => *b,
521            // For schemas which don't tag booleans
522            Value::Int32(Some(i)) if *i == 0 || *i == 1 => Some(*i == 1),
523            Value::Int64(Some(i)) if *i == 0 || *i == 1 => Some(*i == 1),
524            _ => None,
525        }
526    }
527
528    /// `true` if the `Value` is an Array.
529    pub const fn is_array(&self) -> bool {
530        matches!(self, Value::Array(_))
531    }
532
533    pub const fn as_array(&self) -> Option<&Vec<Value>> {
534        match self {
535            Value::Array(a) => a.as_ref(),
536            _ => None,
537        }
538    }
539
540    /// `true` if the `Value` is of UUID type.
541    #[cfg(feature = "uuid")]
542    pub const fn is_uuid(&self) -> bool {
543        matches!(self, Value::Uuid(_))
544    }
545
546    /// Returns an UUID if the value is of UUID type, otherwise `None`.
547    #[cfg(feature = "uuid")]
548    pub const fn as_uuid(&self) -> Option<Uuid> {
549        match self {
550            Value::Uuid(u) => *u,
551            _ => None,
552        }
553    }
554
555    /// `true` if the `Value` is a DateTime.
556    #[cfg(feature = "chrono")]
557    pub const fn is_datetime(&self) -> bool {
558        matches!(self, Value::DateTime(_))
559    }
560
561    /// Returns a `DateTime` if the value is a `DateTime`, otherwise `None`.
562    #[cfg(feature = "chrono")]
563        pub const fn as_datetime(&self) -> Option<DateTime<Utc>> {
564        match self {
565            Value::DateTime(dt) => *dt,
566            _ => None,
567        }
568    }
569
570    /// `true` if the `Value` is a Date.
571    #[cfg(feature = "chrono")]
572        pub const fn is_date(&self) -> bool {
573        matches!(self, Value::Date(_))
574    }
575
576    /// Returns a `NaiveDate` if the value is a `Date`, otherwise `None`.
577    #[cfg(feature = "chrono")]
578        pub const fn as_date(&self) -> Option<NaiveDate> {
579        match self {
580            Value::Date(dt) => *dt,
581            _ => None,
582        }
583    }
584
585    /// `true` if the `Value` is a `Time`.
586    #[cfg(feature = "chrono")]
587        pub const fn is_time(&self) -> bool {
588        matches!(self, Value::Time(_))
589    }
590
591    /// Returns a `NaiveTime` if the value is a `Time`, otherwise `None`.
592    #[cfg(feature = "chrono")]
593        pub const fn as_time(&self) -> Option<NaiveTime> {
594        match self {
595            Value::Time(time) => *time,
596            _ => None,
597        }
598    }
599
600    /// `true` if the `Value` is a JSON value.
601    #[cfg(feature = "json")]
602        pub const fn is_json(&self) -> bool {
603        matches!(self, Value::Json(_))
604    }
605
606    /// Returns a reference to a JSON Value if of Json type, otherwise `None`.
607    #[cfg(feature = "json")]
608        pub const fn as_json(&self) -> Option<&serde_json::Value> {
609        match self {
610            Value::Json(Some(j)) => Some(j),
611            _ => None,
612        }
613    }
614
615    /// Transforms to a JSON Value if of Json type, otherwise `None`.
616    #[cfg(feature = "json")]
617        pub fn into_json(self) -> Option<serde_json::Value> {
618        match self {
619            Value::Json(Some(j)) => Some(j),
620            _ => None,
621        }
622    }
623
624    /// Returns a Vec<T> if the value is an array of T, otherwise `None`.
625    pub fn into_vec<T>(self) -> Option<Vec<T>>
626    where
627        // Implement From<Value>
628        T: TryFrom<Value<'a>>,
629    {
630        match self {
631            Value::Array(Some(vec)) => {
632                let rslt: Result<Vec<_>, _> = vec.into_iter().map(T::try_from).collect();
633                match rslt {
634                    Err(_) => None,
635                    Ok(values) => Some(values),
636                }
637            }
638            _ => None,
639        }
640    }
641}
642
643value!(val: i64, Int64, val);
644value!(val: i32, Int32, val);
645value!(val: bool, Boolean, val);
646value!(val: &'a str, Text, val.into());
647value!(val: String, Text, val.into());
648value!(val: usize, Int64, i64::try_from(val).unwrap());
649value!(val: &'a [u8], Bytes, val.into());
650value!(val: f64, Double, val);
651value!(val: f32, Float, val);
652
653#[cfg(feature = "chrono")]
654value!(val: DateTime<Utc>, DateTime, val);
655#[cfg(feature = "chrono")]
656value!(val: chrono::NaiveTime, Time, val);
657#[cfg(feature = "chrono")]
658value!(val: chrono::NaiveDate, Date, val);
659#[cfg(feature = "bigdecimal")]
660value!(val: BigDecimal, Numeric, val);
661#[cfg(feature = "json")]
662value!(val: JsonValue, Json, val);
663#[cfg(feature = "uuid")]
664value!(val: Uuid, Uuid, val);
665
666impl<'a> TryFrom<Value<'a>> for i64 {
667    type Error = Error;
668
669    fn try_from(value: Value<'a>) -> Result<i64, Self::Error> {
670        value
671            .as_i64()
672            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not an i64")).build())
673    }
674}
675
676impl<'a> TryFrom<Value<'a>> for i32 {
677    type Error = Error;
678
679    fn try_from(value: Value<'a>) -> Result<i32, Self::Error> {
680        value
681            .as_i32()
682            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not an i32")).build())
683    }
684}
685
686#[cfg(feature = "bigdecimal")]
687impl<'a> TryFrom<Value<'a>> for BigDecimal {
688    type Error = Error;
689
690    fn try_from(value: Value<'a>) -> Result<BigDecimal, Self::Error> {
691        value
692            .into_numeric()
693            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not a decimal")).build())
694    }
695}
696
697impl<'a> TryFrom<Value<'a>> for f64 {
698    type Error = Error;
699
700    fn try_from(value: Value<'a>) -> Result<f64, Self::Error> {
701        value
702            .as_f64()
703            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not a f64")).build())
704    }
705}
706
707impl<'a> TryFrom<Value<'a>> for String {
708    type Error = Error;
709
710    fn try_from(value: Value<'a>) -> Result<String, Self::Error> {
711        value
712            .into_string()
713            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not a string")).build())
714    }
715}
716
717impl<'a> TryFrom<Value<'a>> for bool {
718    type Error = Error;
719
720    fn try_from(value: Value<'a>) -> Result<bool, Self::Error> {
721        value
722            .as_bool()
723            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not a bool")).build())
724    }
725}
726
727#[cfg(feature = "chrono")]
728impl<'a> TryFrom<Value<'a>> for DateTime<Utc> {
729    type Error = Error;
730
731    fn try_from(value: Value<'a>) -> Result<DateTime<Utc>, Self::Error> {
732        value
733            .as_datetime()
734            .ok_or_else(|| Error::builder(ErrorKind::conversion("Not a datetime")).build())
735    }
736}
737
738impl<'a> TryFrom<&Value<'a>> for Option<std::net::IpAddr> {
739    type Error = Error;
740
741    fn try_from(value: &Value<'a>) -> Result<Option<std::net::IpAddr>, Self::Error> {
742        match value {
743            val @ Value::Text(Some(_)) => {
744                let text = val.as_str().unwrap();
745
746                match std::net::IpAddr::from_str(text) {
747                    Ok(ip) => Ok(Some(ip)),
748                    Err(e) => Err(e.into()),
749                }
750            }
751            val @ Value::Bytes(Some(_)) => {
752                let text = val.as_str().unwrap();
753
754                match std::net::IpAddr::from_str(text) {
755                    Ok(ip) => Ok(Some(ip)),
756                    Err(e) => Err(e.into()),
757                }
758            }
759            v if v.is_null() => Ok(None),
760            v => {
761                let kind =
762                    ErrorKind::conversion(format!("Couldn't convert value of type `{v:?}` to std::net::IpAddr."));
763
764                Err(Error::builder(kind).build())
765            }
766        }
767    }
768}
769
770#[cfg(feature = "uuid")]
771impl<'a> TryFrom<&Value<'a>> for Option<uuid::Uuid> {
772    type Error = Error;
773
774    fn try_from(value: &Value<'a>) -> Result<Option<uuid::Uuid>, Self::Error> {
775        match value {
776            Value::Uuid(uuid) => Ok(*uuid),
777            val @ Value::Text(Some(_)) => {
778                let text = val.as_str().unwrap();
779
780                match uuid::Uuid::from_str(text) {
781                    Ok(ip) => Ok(Some(ip)),
782                    Err(e) => Err(e.into()),
783                }
784            }
785            val @ Value::Bytes(Some(_)) => {
786                let text = val.as_str().unwrap();
787
788                match uuid::Uuid::from_str(text) {
789                    Ok(ip) => Ok(Some(ip)),
790                    Err(e) => Err(e.into()),
791                }
792            }
793            v if v.is_null() => Ok(None),
794            v => {
795                let kind = ErrorKind::conversion(format!("Couldn't convert value of type `{v:?}` to uuid::Uuid."));
796
797                Err(Error::builder(kind).build())
798            }
799        }
800    }
801}
802
803/// An in-memory temporary table. Can be used in some of the databases in a
804/// place of an actual table. Doesn't work in MySQL 5.7.
805#[derive(Debug, Clone, Default, PartialEq)]
806pub struct Values<'a> {
807    pub(crate) rows: Vec<Row<'a>>,
808}
809
810impl<'a> Values<'a> {
811    /// Create a new empty in-memory set of values.
812    pub fn empty() -> Self {
813        Self { rows: Vec::new() }
814    }
815
816    /// Create a new in-memory set of values.
817    pub fn new(rows: Vec<Row<'a>>) -> Self {
818        Self { rows }
819    }
820
821    /// Create a new in-memory set of values with an allocated capacity.
822    pub fn with_capacity(capacity: usize) -> Self {
823        Self {
824            rows: Vec::with_capacity(capacity),
825        }
826    }
827
828    /// Add value to the temporary table.
829    pub fn push<T>(&mut self, row: T)
830    where
831        T: Into<Row<'a>>,
832    {
833        self.rows.push(row.into());
834    }
835
836    /// The number of rows in the in-memory table.
837    pub fn len(&self) -> usize {
838        self.rows.len()
839    }
840
841    /// True if has no rows.
842    pub fn is_empty(&self) -> bool {
843        self.len() == 0
844    }
845
846    pub fn row_len(&self) -> usize {
847        match self.rows.split_first() {
848            Some((row, _)) => row.len(),
849            None => 0,
850        }
851    }
852
853    pub fn flatten_row(self) -> Option<Row<'a>> {
854        let mut result = Row::with_capacity(self.len());
855
856        for mut row in self.rows.into_iter() {
857            match row.pop() {
858                Some(value) => result.push(value),
859                None => return None,
860            }
861        }
862
863        Some(result)
864    }
865}
866
867impl<'a, I, R> From<I> for Values<'a>
868where
869    I: Iterator<Item = R>,
870    R: Into<Row<'a>>,
871{
872    fn from(rows: I) -> Self {
873        Self {
874            rows: rows.map(|r| r.into()).collect(),
875        }
876    }
877}
878
879impl<'a> IntoIterator for Values<'a> {
880    type Item = Row<'a>;
881    type IntoIter = std::vec::IntoIter<Self::Item>;
882
883    fn into_iter(self) -> Self::IntoIter {
884        self.rows.into_iter()
885    }
886}
887
888#[cfg(test)]
889mod tests {
890    use super::*;
891    #[cfg(feature = "chrono")]
892    use std::str::FromStr;
893
894    #[test]
895    fn a_parameterized_value_of_ints32_can_be_converted_into_a_vec() {
896        let pv = Value::array(vec![1]);
897        let values: Vec<i32> = pv.into_vec().expect("convert into Vec<i32>");
898        assert_eq!(values, vec![1]);
899    }
900
901    #[test]
902    fn a_parameterized_value_of_ints64_can_be_converted_into_a_vec() {
903        let pv = Value::array(vec![1_i64]);
904        let values: Vec<i64> = pv.into_vec().expect("convert into Vec<i64>");
905        assert_eq!(values, vec![1]);
906    }
907
908    #[test]
909    fn a_parameterized_value_of_reals_can_be_converted_into_a_vec() {
910        let pv = Value::array(vec![1.0]);
911        let values: Vec<f64> = pv.into_vec().expect("convert into Vec<f64>");
912        assert_eq!(values, vec![1.0]);
913    }
914
915    #[test]
916    fn a_parameterized_value_of_texts_can_be_converted_into_a_vec() {
917        let pv = Value::array(vec!["test"]);
918        let values: Vec<String> = pv.into_vec().expect("convert into Vec<String>");
919        assert_eq!(values, vec!["test"]);
920    }
921
922    #[test]
923    fn a_parameterized_value_of_booleans_can_be_converted_into_a_vec() {
924        let pv = Value::array(vec![true]);
925        let values: Vec<bool> = pv.into_vec().expect("convert into Vec<bool>");
926        assert_eq!(values, vec![true]);
927    }
928
929    #[test]
930    #[cfg(feature = "chrono")]
931    fn a_parameterized_value_of_datetimes_can_be_converted_into_a_vec() {
932        let datetime = DateTime::from_str("2019-07-27T05:30:30Z").expect("parsing date/time");
933        let pv = Value::array(vec![datetime]);
934        let values: Vec<DateTime<Utc>> = pv.into_vec().expect("convert into Vec<DateTime>");
935        assert_eq!(values, vec![datetime]);
936    }
937
938    #[test]
939    fn a_parameterized_value_of_an_array_cant_be_converted_into_a_vec_of_the_wrong_type() {
940        let pv = Value::array(vec![1]);
941        let rslt: Option<Vec<f64>> = pv.into_vec();
942        assert!(rslt.is_none());
943    }
944
945    #[test]
946    #[cfg(feature = "chrono")]
947    fn display_format_for_datetime() {
948        let dt: DateTime<Utc> = DateTime::from_str("2019-07-27T05:30:30Z").expect("failed while parsing date");
949        let pv = Value::datetime(dt);
950
951        assert_eq!(format!("{pv}"), "\"2019-07-27 05:30:30 UTC\"");
952    }
953
954    #[test]
955    #[cfg(feature = "chrono")]
956    fn display_format_for_date() {
957        let date = NaiveDate::from_ymd_opt(2022, 8, 11).unwrap();
958        let pv = Value::date(date);
959
960        assert_eq!(format!("{pv}"), "\"2022-08-11\"");
961    }
962
963    #[test]
964    #[cfg(feature = "chrono")]
965    fn display_format_for_time() {
966        let time = NaiveTime::from_hms_opt(16, 17, 00).unwrap();
967        let pv = Value::time(time);
968
969        assert_eq!(format!("{pv}"), "\"16:17:00\"");
970    }
971
972    #[test]
973    #[cfg(feature = "uuid")]
974    fn display_format_for_uuid() {
975        let id = Uuid::from_str("67e5504410b1426f9247bb680e5fe0c8").unwrap();
976        let pv = Value::uuid(id);
977
978        assert_eq!(format!("{pv}"), "\"67e55044-10b1-426f-9247-bb680e5fe0c8\"");
979    }
980}