tank_core/
as_value.rs

1use crate::{Error, FixedDecimal, Interval, Passive, Result, Value, consume_while, truncate_long};
2use anyhow::Context;
3use atoi::{FromRadix10, FromRadix10Signed};
4use fast_float::parse_partial;
5use rust_decimal::{Decimal, prelude::FromPrimitive, prelude::ToPrimitive};
6use std::{
7    any, array,
8    borrow::Cow,
9    cell::{Cell, RefCell},
10    collections::{BTreeMap, HashMap, LinkedList, VecDeque},
11    hash::Hash,
12    mem,
13    rc::Rc,
14    sync::{Arc, RwLock},
15};
16use time::{PrimitiveDateTime, format_description::parse_borrowed};
17use uuid::Uuid;
18
19/// Value conversion and simple parsing utilities. It is the central conversion and
20/// parsing abstraction used throughout `tank` to move between native Rust types and
21/// the dynamically typed [`Value`] representation that backs query parameters and
22/// row decoding.
23///
24/// # Implementing `AsValue` for custom types
25/// Implementations must decide how to represent themselves as a [`Value`]. For
26/// example wrapping a struct inside `Value::Map` or serialising into
27/// `Value::Varchar`. A minimal implementation:
28///
29/// # Parsing contract
30/// * `parse` delegates to `extract` then verifies the slice is exhausted.
31/// * `extract` MUST update the input slice only on success.
32/// * Implementations should return descriptive errors including the original
33///   fragment; prefer `any::type_name::<Self>()` for uniform messages.
34///
35/// # Error semantics
36/// * Range checks always occur before returning numeric conversions. The error
37///   message includes both the offending literal and target type.
38/// * Temporal parsing attempts multiple format strings, if none match an error
39///   with the remaining slice is returned.
40/// * `parse` errors when residual unconsumed input remains, helping surface
41///   accidental trailing characters like `123abc`.
42///
43/// # Examples
44/// ```rust
45/// use tank_core::{AsValue, Value};
46/// let v = 42i32.as_value();
47/// assert!(matches!(v, Value::Int32(Some(42), ..)));
48/// let n: i32 = AsValue::try_from_value(v).unwrap();
49/// assert_eq!(n, 42);
50/// ```
51pub trait AsValue {
52    /// Return an "empty" (NULL-like) value variant for this type. Used when
53    /// constructing composite `Value` containers (arrays, maps) or representing
54    /// absent optional data. This should never allocate and should not rely on
55    /// default trait implementations of `Self`.
56    fn as_empty_value() -> Value;
57    /// Convert this value into its owned [`Value`] representation. This should
58    /// perform any necessary wrapping (e.g. collections into `List`, decimals
59    /// into `Decimal`) but avoid lossy transformations unless explicitly
60    /// documented.
61    fn as_value(self) -> Value;
62    /// Attempt to convert a dynamic [`Value`] into `Self`.
63    ///
64    /// Implementations should:
65    /// * Accept the canonical `Value` variant for the type (e.g. `Value::Int32`
66    ///   for `i32`).
67    /// * Optionally accept alternate numeric widths performing range checks.
68    /// * Optionally fall back to parsing `Value::Unknown` via [`AsValue::parse`].
69    /// * Return an `Error` describing the mismatch on failure.
70    fn try_from_value(value: Value) -> Result<Self>
71    where
72        Self: Sized;
73    /// Parse a full string into `Self` delegating to [`AsValue::extract`].
74    ///
75    /// Fails if the parsing routine does not consume the entire input (guards
76    /// against accidentally accepting things like `123abc`). Prefer `extract`
77    /// when embedding within a higher level parser, and `parse` for top-level
78    /// user input / literals.
79    fn parse(input: impl AsRef<str>) -> Result<Self>
80    where
81        Self: Sized,
82    {
83        let mut value = input.as_ref();
84        let result = Self::extract(&mut value)?;
85        if !value.is_empty() {
86            return Err(Error::msg(format!(
87                "Value `{}` parsed correctly as {} but it did not consume all the input (remaining: `{}`)",
88                truncate_long!(input.as_ref()),
89                any::type_name::<Self>(),
90                truncate_long!(value),
91            )));
92        }
93        Ok(result)
94    }
95    /// Attempt to parse a prefix from the provided string slice, updating the
96    /// slice to point to the remaining (unconsumed) portion on success.
97    ///
98    /// Returning an error MUST leave the slice untouched. This enables parser
99    /// combinators / backtracking without a separate buffering strategy.
100    fn extract(value: &mut &str) -> Result<Self>
101    where
102        Self: Sized,
103    {
104        Err(Error::msg(format!(
105            "Cannot parse '{value}' as {}",
106            any::type_name::<Self>()
107        )))
108    }
109}
110
111impl<T: AsValue> From<T> for Value {
112    fn from(value: T) -> Self {
113        value.as_value()
114    }
115}
116
117impl From<&'static str> for Value {
118    fn from(value: &'static str) -> Self {
119        Value::Varchar(Some(value.into()))
120    }
121}
122
123macro_rules! impl_as_value {
124    ($source:ty, $destination:path $(, $pat_rest:pat => $expr_rest:expr)* $(,)?) => {
125        impl AsValue for $source {
126            fn as_empty_value() -> Value {
127                $destination(None)
128            }
129            fn as_value(self) -> Value {
130                $destination(Some(self as _))
131            }
132            fn try_from_value(value: Value) -> Result<Self> {
133                match value {
134                    $destination(Some(v), ..) => Ok(v as _),
135                    $($pat_rest => $expr_rest,)*
136                    #[allow(unreachable_patterns)]
137                    Value::Int32(Some(v), ..) => {
138                        if (v as i128).clamp(<$source>::MIN as _, <$source>::MAX as _) != v as i128 {
139                            return Err(Error::msg(format!(
140                                "Value {v}: i32 is out of range for {}",
141                                any::type_name::<Self>(),
142                            )));
143                        }
144                        Ok(v as $source)
145                    },
146                    #[allow(unreachable_patterns)]
147                    Value::Int64(Some(v), ..) => {
148                        if (v as i128).clamp(<$source>::MIN as _, <$source>::MAX as _) != v as i128 {
149                            return Err(Error::msg(format!(
150                                "Value {v}: i64 is out of range for {}",
151                                any::type_name::<Self>(),
152                            )));
153                        }
154                        Ok(v as $source)
155                    }
156                    Value::Unknown(Some(ref v), ..) => Self::parse(v),
157                    _ => Err(Error::msg(format!(
158                        "Cannot convert {value:?} to {}",
159                        any::type_name::<Self>(),
160                    ))),
161                }
162            }
163            fn extract(input: &mut &str) -> Result<Self> {
164                if input.is_empty() {
165                    return Err(Error::msg(format!(
166                        "Cannot extract {} from empty string",
167                        any::type_name::<Self>(),
168                    )));
169                }
170                let mut value = *input;
171                macro_rules! do_extract {
172                    ($parse:expr) => {{
173                        let (num, tail) = $parse();
174                        if tail > 0 {
175                            let min = <$source>::MIN;
176                            let max = <$source>::MAX;
177                            if num < min as _ || num > max as _ {
178                                return Err(Error::msg(format!(
179                                    "Parsed integer {} is out of range for {}",
180                                    value,
181                                    any::type_name::<Self>(),
182                                )))
183                            }
184                            value = &value[tail..];
185                            *input = value;
186                            return Ok(num as _);
187                        }
188                    }
189                }}
190                let mut v = value;
191                let is_negative = value.starts_with('-');
192                let first = if is_negative {
193                    v = &v[1..];
194                    1
195                } else {
196                    0
197                };
198                let v = &value[first..v.chars().take_while(char::is_ascii_digit).count()];
199                #[allow(unused_comparisons)]
200                let is_signed = <$source>::MIN < 0;
201                let lim = if is_negative {
202                    "170141183460469231731687303715884105728"
203                } else if is_signed {
204                    "170141183460469231731687303715884105727"
205                } else {
206                    "340282366920938463463374607431768211455"
207                };
208                // It's important to avoid overhead otherwise atoi panics
209                if v.len() > lim.len() || v.len() == lim.len() && v > lim {
210                    return Err(Error::msg(format!(
211                        "Value {value} is out of range for {}",
212                        any::type_name::<Self>(),
213                    )));
214                }
215                if is_signed {
216                    do_extract!(|| i128::from_radix_10_signed(value.as_bytes()));
217                } else {
218                    do_extract!(|| u128::from_radix_10(value.as_bytes()));
219                }
220                Err(Error::msg(format!(
221                    "Cannot extract {} from `{value}`",
222                    any::type_name::<Self>(),
223                )))
224            }
225        }
226    };
227}
228impl_as_value!(
229    i8,
230    Value::Int8,
231    Value::UInt8(Some(v), ..) => Ok(v as _),
232    Value::Int16(Some(v), ..) => {
233        let result = v as i8;
234        if result as i16 != v {
235            return Err(Error::msg(format!("Value {v}: i16 is out of range for i8")));
236        }
237        Ok(result)
238    },
239);
240impl_as_value!(
241    i16,
242    Value::Int16,
243    Value::Int8(Some(v), ..) => Ok(v as _),
244    Value::UInt16(Some(v), ..) => Ok(v as _),
245    Value::UInt8(Some(v), ..) => Ok(v as _),
246);
247impl_as_value!(
248    i32,
249    Value::Int32,
250    Value::Int16(Some(v), ..) => Ok(v as _),
251    Value::Int8(Some(v), ..) => Ok(v as _),
252    Value::UInt32(Some(v), ..) => Ok(v as _),
253    Value::UInt16(Some(v), ..) => Ok(v as _),
254    Value::UInt8(Some(v), ..) => Ok(v as _),
255    Value::Decimal(Some(v), ..) => {
256        let error = Error::msg(format!("Value {v}: Decimal does not fit into i32"));
257        if !v.is_integer() {
258            return Err(error.context("The value is not a integer"));
259        }
260        v.to_i32().ok_or(error)
261    }
262);
263impl_as_value!(
264    i64,
265    Value::Int64,
266    Value::Int32(Some(v), ..) => Ok(v as _),
267    Value::Int16(Some(v), ..) => Ok(v as _),
268    Value::Int8(Some(v), ..) => Ok(v as _),
269    Value::UInt64(Some(v), ..) => Ok(v as _),
270    Value::UInt32(Some(v), ..) => Ok(v as _),
271    Value::UInt16(Some(v), ..) => Ok(v as _),
272    Value::UInt8(Some(v), ..) => Ok(v as _),
273    Value::Decimal(Some(v), ..) => {
274        let error = Error::msg(format!("Value {v}: Decimal does not fit into i64"));
275        if !v.is_integer() {
276            return Err(error.context("The value is not a integer"));
277        }
278        v.to_i64().ok_or(error)
279    }
280);
281impl_as_value!(
282    i128,
283    Value::Int128,
284    Value::Int64(Some(v), ..) => Ok(v as _),
285    Value::Int32(Some(v), ..) => Ok(v as _),
286    Value::Int16(Some(v), ..) => Ok(v as _),
287    Value::Int8(Some(v), ..) => Ok(v as _),
288    Value::UInt128(Some(v), ..) => Ok(v as _),
289    Value::UInt64(Some(v), ..) => Ok(v as _),
290    Value::UInt32(Some(v), ..) => Ok(v as _),
291    Value::UInt16(Some(v), ..) => Ok(v as _),
292    Value::UInt8(Some(v), ..) => Ok(v as _),
293    Value::Decimal(Some(v), ..) => {
294        let error = Error::msg(format!("Value {v}: Decimal does not fit into i128"));
295        if !v.is_integer() {
296            return Err(error.context("The value is not a integer"));
297        }
298        v.to_i128().ok_or(error)
299    }
300);
301impl_as_value!(
302    isize,
303    Value::Int64,
304    Value::Int32(Some(v), ..) => Ok(v as _),
305    Value::Int16(Some(v), ..) => Ok(v as _),
306    Value::Int8(Some(v), ..) => Ok(v as _),
307    Value::UInt64(Some(v), ..) => Ok(v as _),
308    Value::UInt32(Some(v), ..) => Ok(v as _),
309    Value::UInt16(Some(v), ..) => Ok(v as _),
310    Value::UInt8(Some(v), ..) => Ok(v as _),
311    Value::Decimal(Some(v), ..) => {
312        let error = Error::msg(format!("Value {v}: Decimal does not fit into i64"));
313        if !v.is_integer() {
314            return Err(error.context("The value is not a integer"));
315        }
316        v.to_isize().ok_or(error)
317    }
318);
319impl_as_value!(
320    u8,
321    Value::UInt8,
322    Value::Int16(Some(v), ..) => {
323        v.to_u8().ok_or(Error::msg(format!("Value {v}: i16 is out of range for u8")))
324    }
325);
326impl_as_value!(
327    u16,
328    Value::UInt16,
329    Value::UInt8(Some(v), ..) => Ok(v as _),
330    Value::Int32(Some(v), ..) => {
331        let result = v as u16;
332        if result as i32 != v {
333            return Err(Error::msg(format!("Value {v}: i32 is out of range for u16")));
334        }
335        Ok(result)
336    }
337);
338impl_as_value!(
339    u32,
340    Value::UInt32,
341    Value::UInt16(Some(v), ..) => Ok(v as _),
342    Value::UInt8(Some(v), ..) => Ok(v as _),
343);
344impl_as_value!(
345    u64,
346    Value::UInt64,
347    Value::UInt32(Some(v), ..) => Ok(v as _),
348    Value::UInt16(Some(v), ..) => Ok(v as _),
349    Value::UInt8(Some(v), ..) => Ok(v as _),
350    Value::Decimal(Some(v), ..) => {
351        let error = Error::msg(format!("Value {v}: Decimal does not fit into u64"));
352        if !v.is_integer() {
353            return Err(error.context("The value is not a integer"));
354        }
355        v.to_u64().ok_or(error)
356    }
357);
358impl_as_value!(
359    u128,
360    Value::UInt128,
361    Value::UInt64(Some(v), ..) => Ok(v as _),
362    Value::UInt32(Some(v), ..) => Ok(v as _),
363    Value::UInt16(Some(v), ..) => Ok(v as _),
364    Value::UInt8(Some(v), ..) => Ok(v as _),
365    Value::Decimal(Some(v), ..) => {
366        let error = Error::msg(format!("Value {v}: Decimal does not fit into u128"));
367        if !v.is_integer() {
368            return Err(error.context("The value is not a integer"));
369        }
370        v.to_u128().ok_or(error)
371    }
372);
373impl_as_value!(
374    usize,
375    Value::UInt64,
376    Value::UInt32(Some(v), ..) => Ok(v as _),
377    Value::UInt16(Some(v), ..) => Ok(v as _),
378    Value::UInt8(Some(v), ..) => Ok(v as _),
379    Value::Decimal(Some(v), ..) => {
380        let error = Error::msg(format!("Value {v}: Decimal does not fit into u64"));
381        if !v.is_integer() {
382            return Err(error.context("The value is not a integer"));
383        }
384        v.to_usize().ok_or(error)
385    }
386);
387
388macro_rules! impl_as_value {
389    ($source:ty, $destination:path, $extract:expr $(, $pat_rest:pat => $expr_rest:expr)* $(,)?) => {
390        impl AsValue for $source {
391            fn as_empty_value() -> Value {
392                $destination(None)
393            }
394            fn as_value(self) -> Value {
395                $destination(Some(self.into()))
396            }
397            fn try_from_value(value: Value) -> Result<Self> {
398                match value {
399                    $destination(Some(v), ..) => Ok(v.into()),
400                    $($pat_rest => $expr_rest,)*
401                    #[allow(unreachable_patterns)]
402                    Value::Unknown(Some(ref v)) => <Self as AsValue>::parse(v),
403                    _ => Err(Error::msg(format!(
404                        "Cannot convert {value:?} to {}",
405                        any::type_name::<Self>(),
406                    ))),
407                }
408            }
409            fn extract(value: &mut &str) -> Result<Self> {
410                $extract(value)
411            }
412        }
413    };
414}
415impl_as_value!(
416    bool,
417    Value::Boolean,
418    |input: &mut &str| {
419        let mut value = *input;
420        let result = consume_while(&mut value, |v| v.is_alphabetic() || *v == '_');
421        let result = match result {
422            x if x.eq_ignore_ascii_case("true") || x.eq_ignore_ascii_case("t") => Ok(true),
423            x if x.eq_ignore_ascii_case("false") || x.eq_ignore_ascii_case("f") => Ok(false),
424            _  => return Err(Error::msg(format!("Cannot parse boolean from '{input}'")))
425        };
426        *input = value;
427        result
428    },
429    Value::Int8(Some(v), ..) => Ok(v != 0),
430    Value::Int16(Some(v), ..) => Ok(v != 0),
431    Value::Int32(Some(v), ..) => Ok(v != 0),
432    Value::Int64(Some(v), ..) => Ok(v != 0),
433    Value::Int128(Some(v), ..) => Ok(v != 0),
434    Value::UInt8(Some(v), ..) => Ok(v != 0),
435    Value::UInt16(Some(v), ..) => Ok(v != 0),
436    Value::UInt32(Some(v), ..) => Ok(v != 0),
437    Value::UInt64(Some(v), ..) => Ok(v != 0),
438    Value::UInt128(Some(v), ..) => Ok(v != 0),
439);
440impl_as_value!(
441    f32,
442    Value::Float32,
443    |v: &mut &str| {
444        let (num, tail) = parse_partial(*v)?;
445        *v = &v[tail..];
446        Ok(num)
447    },
448    Value::Float64(Some(v), ..) => Ok(v as _),
449    Value::Decimal(Some(v), ..) => Ok(v.try_into()?),
450);
451impl_as_value!(
452    f64,
453    Value::Float64,
454    |v: &mut &str| {
455        let (num, tail) = parse_partial(*v)?;
456        *v = &v[tail..];
457        Ok(num)
458    },
459    Value::Float32(Some(v), ..) => Ok(v as _),
460    Value::Decimal(Some(v), ..) => Ok(v.try_into()?),
461);
462impl_as_value!(
463    char,
464    Value::Char,
465    |v: &mut &str| {
466        let result = v.chars().next().ok_or(Error::msg("Empty input"))?;
467        *v = &v[1..];
468        Ok(result)
469    },
470    Value::Varchar(Some(v), ..) => {
471        if v.len() != 1 {
472            return Err(Error::msg("Cannot convert Value::Varchar containing more then one character into a char"))
473        }
474        Ok(v.chars().next().unwrap())
475    }
476);
477impl_as_value!(
478    String,
479    Value::Varchar,
480    |input: &mut &str| {
481        let mut value = *input;
482        let delimiter = value.chars().next();
483        let delimiter = match delimiter {
484            Some('\'') | Some('"') => {
485                value = &value[1..];
486                delimiter
487            },
488            _ => None,
489        };
490        let mut result = String::new();
491        let mut chars = value.chars().peekable();
492        let mut pos = 0;
493        while let Some(c) = chars.next() {
494            if Some(c) == delimiter {
495                if let Some(next_c) = chars.peek()
496                    && Some(*next_c) == delimiter {
497                    result.push_str(&value[..=pos]);
498                    value = &value[(pos + 2)..];
499                    pos = 0;
500                    chars.next();
501                    continue;
502                }
503                result.push_str(&value[..pos]);
504                value = &value[(pos + 1)..];
505                *input = &value;
506                return Ok(result);
507            }
508            pos += 1;
509        }
510        if delimiter.is_some() {
511            result = format!("{}{}", delimiter.unwrap(), result);
512        }
513        result.push_str(&value[..pos]);
514        value = &value[pos..];
515        *input = value;
516        Ok(result)
517    },
518    Value::Char(Some(v), ..) => Ok(v.into()),
519);
520impl_as_value!(Box<[u8]>, Value::Blob, |input: &mut &str| {
521    let mut value = *input;
522    if value[0..2].eq_ignore_ascii_case("\\x") {
523        value = &value[2..];
524    }
525    let hex = consume_while(
526        &mut value,
527        |v| matches!(*v, '0'..='9' | 'a'..='f' | 'A'..='F'),
528    );
529    let result = hex::decode(hex).map(Into::into).context(format!(
530        "While decoding `{}` as {}",
531        truncate_long!(input),
532        any::type_name::<Self>()
533    ))?;
534    *input = value;
535    Ok(result)
536});
537impl_as_value!(Interval, Value::Interval, |input: &mut &str| {
538    let error = || {
539        Err(Error::msg(format!(
540            "Cannot extract interval from '{input}'"
541        )))
542    };
543    let mut value = *input;
544    let boundary = match value.chars().next() {
545        Some(v) if v == '"' || v == '\'' => {
546            value = &value[1..];
547            Some(v)
548        }
549        _ => None,
550    };
551    let mut interval = Interval::ZERO;
552    loop {
553        let mut cur = value;
554        let Ok(count) = i128::extract(&mut cur) else {
555            break;
556        };
557        cur = cur.trim_start();
558        let unit = consume_while(&mut cur, char::is_ascii_alphabetic);
559        if unit.is_empty() {
560            break;
561        }
562        match unit {
563            x if x.eq_ignore_ascii_case("y")
564                || x.eq_ignore_ascii_case("year")
565                || x.eq_ignore_ascii_case("years") =>
566            {
567                interval += Interval::from_years(count as _)
568            }
569            x if x.eq_ignore_ascii_case("mon")
570                || x.eq_ignore_ascii_case("mons")
571                || x.eq_ignore_ascii_case("month")
572                || x.eq_ignore_ascii_case("months") =>
573            {
574                interval += Interval::from_months(count as _)
575            }
576            x if x.eq_ignore_ascii_case("d")
577                || x.eq_ignore_ascii_case("day")
578                || x.eq_ignore_ascii_case("days") =>
579            {
580                interval += Interval::from_days(count as _)
581            }
582            x if x.eq_ignore_ascii_case("h")
583                || x.eq_ignore_ascii_case("hour")
584                || x.eq_ignore_ascii_case("hours") =>
585            {
586                interval += Interval::from_hours(count as _)
587            }
588            x if x.eq_ignore_ascii_case("min")
589                || x.eq_ignore_ascii_case("mins")
590                || x.eq_ignore_ascii_case("minute")
591                || x.eq_ignore_ascii_case("minutes") =>
592            {
593                interval += Interval::from_mins(count as _)
594            }
595            x if x.eq_ignore_ascii_case("s")
596                || x.eq_ignore_ascii_case("sec")
597                || x.eq_ignore_ascii_case("secs")
598                || x.eq_ignore_ascii_case("second")
599                || x.eq_ignore_ascii_case("seconds") =>
600            {
601                interval += Interval::from_secs(count as _)
602            }
603            x if x.eq_ignore_ascii_case("micro")
604                || x.eq_ignore_ascii_case("micros")
605                || x.eq_ignore_ascii_case("microsecond")
606                || x.eq_ignore_ascii_case("microseconds") =>
607            {
608                interval += Interval::from_micros(count as _)
609            }
610            x if x.eq_ignore_ascii_case("ns")
611                || x.eq_ignore_ascii_case("nano")
612                || x.eq_ignore_ascii_case("nanos")
613                || x.eq_ignore_ascii_case("nanosecond")
614                || x.eq_ignore_ascii_case("nanoseconds") =>
615            {
616                interval += Interval::from_nanos(count as _)
617            }
618            _ => return error(),
619        }
620        value = cur.trim_start();
621    }
622    let neg = if Some('-') == value.chars().next() {
623        value = value[1..].trim_ascii_start();
624        true
625    } else {
626        false
627    };
628    let mut time_interval = Interval::ZERO;
629    let (num, tail) = u64::from_radix_10(value.as_bytes());
630    if tail > 0 {
631        time_interval += Interval::from_hours(num as _);
632        value = &value[tail..];
633        if Some(':') == value.chars().next() {
634            value = &value[1..];
635            let (num, tail) = u64::from_radix_10(value.as_bytes());
636            if tail == 0 {
637                return error();
638            }
639            value = &value[tail..];
640            time_interval += Interval::from_mins(num as _);
641            if Some(':') == value.chars().next() {
642                value = &value[1..];
643                let (num, tail) = u64::from_radix_10(value.as_bytes());
644                if tail == 0 {
645                    return error();
646                }
647                value = &value[tail..];
648                time_interval += Interval::from_secs(num as _);
649                if Some('.') == value.chars().next() {
650                    value = &value[1..];
651                    let (mut num, mut tail) = i128::from_radix_10(value.as_bytes());
652                    if tail == 0 {
653                        return error();
654                    }
655                    value = &value[tail..];
656                    tail -= 1;
657                    let magnitude = tail / 3;
658                    num *= 10_i128.pow(2 - tail as u32 % 3);
659                    match magnitude {
660                        0 => time_interval += Interval::from_millis(num),
661                        1 => time_interval += Interval::from_micros(num),
662                        2 => time_interval += Interval::from_nanos(num),
663                        _ => return error(),
664                    }
665                }
666            }
667        }
668        if neg {
669            interval -= time_interval;
670        } else {
671            interval += time_interval;
672        }
673    }
674    if let Some(b) = boundary {
675        if value.chars().next() != Some(b) {
676            return error();
677        }
678        value = value[1..].trim_ascii_start();
679    }
680    *input = value;
681    Ok(interval)
682});
683impl_as_value!(std::time::Duration, Value::Interval, |v| {
684    <Interval as AsValue>::extract(v).map(Into::into)
685});
686impl_as_value!(time::Duration, Value::Interval, |v| {
687    <Interval as AsValue>::extract(v).map(Into::into)
688});
689impl_as_value!(
690    Uuid,
691    Value::Uuid,
692    |v: &mut &str| {
693        let result = Ok(Uuid::parse_str(&v[0..36])?);
694        *v = &v[36..];
695        result
696    },
697    Value::Varchar(Some(v), ..) => Self::parse(v),
698);
699
700macro_rules! parse_time {
701    ($value: ident, $($formats:literal),+ $(,)?) => {
702        'value: {
703            for format in [$($formats,)+] {
704                let format = parse_borrowed::<2>(format)?;
705                let mut parsed = time::parsing::Parsed::new();
706                let remaining = parsed.parse_items($value.as_bytes(), &format);
707                if let Ok(remaining) = remaining {
708                    let result = parsed.try_into()?;
709                    *$value = &$value[($value.len() - remaining.len())..];
710                    break 'value Ok(result);
711                }
712            }
713            Err(Error::msg(format!(
714                "Cannot extract from `{}` as {}",
715                $value,
716                any::type_name::<Self>()
717            )))
718        }
719    }
720}
721
722impl_as_value!(
723    time::Date,
724    Value::Date,
725    |v: &mut &str| {
726        let mut result: time::Date = parse_time!(v, "[year]-[month]-[day]")?;
727        {
728            let mut attempt = v.trim_start();
729            let suffix = consume_while(&mut attempt, char::is_ascii_alphabetic);
730            if suffix.eq_ignore_ascii_case("bc") {
731                *v = attempt;
732                result =
733                    time::Date::from_calendar_date(-(result.year() - 1), result.month(), result.day())?;
734                *v = attempt
735            }
736            if suffix.eq_ignore_ascii_case("ad") {
737                *v = attempt
738            }
739        }
740        Ok(result)
741    },
742    Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
743);
744
745impl_as_value!(
746    time::Time,
747    Value::Time,
748    |v: &mut &str| {
749        let result: time::Time = parse_time!(
750            v,
751            "[hour]:[minute]:[second].[subsecond]",
752            "[hour]:[minute]:[second]",
753            "[hour]:[minute]",
754        )?;
755        Ok(result)
756    },
757    Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
758);
759
760impl_as_value!(
761    time::PrimitiveDateTime,
762    Value::Timestamp,
763    |v: &mut &str| {
764        let result: time::PrimitiveDateTime = parse_time!(
765            v,
766            "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]",
767            "[year]-[month]-[day]T[hour]:[minute]:[second]",
768            "[year]-[month]-[day]T[hour]:[minute]",
769            "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]",
770            "[year]-[month]-[day] [hour]:[minute]:[second]",
771            "[year]-[month]-[day] [hour]:[minute]",
772        )?;
773        Ok(result)
774    },
775    Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
776);
777
778impl_as_value!(
779    time::OffsetDateTime,
780    Value::TimestampWithTimezone,
781    |v: &mut &str| {
782        let result: time::OffsetDateTime = parse_time!(
783            v,
784            "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]",
785            "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]",
786            "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]",
787            "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]",
788            "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]",
789            "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]",
790            "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]",
791            "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]",
792            "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]",
793            "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]",
794            "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]:[offset_minute]",
795            "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]",
796        ).or(<PrimitiveDateTime as AsValue>::extract(v).map(|v| v.assume_utc()))?;
797        Ok(result)
798    },
799    Value::Timestamp(Some(timestamp), ..) => Ok(timestamp.assume_utc()),
800    Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
801);
802
803impl AsValue for Decimal {
804    fn as_empty_value() -> Value {
805        Value::Decimal(None, 0, 0)
806    }
807    fn as_value(self) -> Value {
808        Value::Decimal(Some(self), 0, self.scale() as _)
809    }
810    fn try_from_value(value: Value) -> Result<Self> {
811        match value {
812            Value::Decimal(Some(v), ..) => Ok(v),
813            Value::Int8(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
814            Value::Int16(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
815            Value::Int32(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
816            Value::Int64(Some(v), ..) => Ok(Decimal::new(v, 0)),
817            Value::UInt8(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
818            Value::UInt16(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
819            Value::UInt32(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
820            Value::UInt64(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
821            Value::Float32(Some(v), ..) => Ok(Decimal::from_f32(v)
822                .ok_or(Error::msg(format!("Cannot convert {value:?} to Decimal")))?),
823            Value::Float64(Some(v), ..) => Ok(Decimal::from_f64(v)
824                .ok_or(Error::msg(format!("Cannot convert {value:?} to Decimal")))?),
825            Value::Unknown(Some(v), ..) => Self::parse(&v),
826            _ => Err(Error::msg(format!("Cannot convert {value:?} to Decimal"))),
827        }
828    }
829    fn extract(input: &mut &str) -> Result<Self> {
830        let mut value = *input;
831        let (mut n, len) = i128::from_radix_10_signed(value.as_bytes());
832        value = &value[len..];
833        let n = if value.chars().next() == Some('.') {
834            value = &value[1..];
835            let (dec, len) = i128::from_radix_10(value.as_bytes());
836            n = n * 10u64.pow(len as _) as i128 + dec;
837            value = &value[len..];
838            Decimal::try_from_i128_with_scale(n, len as _)
839                .map_err(|_| Error::msg(format!("Could not create a Decimal from {n}")))
840        } else {
841            Decimal::from_i128(n)
842                .ok_or_else(|| Error::msg(format!("Could not create a Decimal from {n}")))
843        }?;
844        *input = value.trim_ascii_start();
845        Ok(n)
846    }
847}
848
849impl<const W: u8, const S: u8> AsValue for FixedDecimal<W, S> {
850    fn as_empty_value() -> Value {
851        Decimal::as_empty_value()
852    }
853    fn as_value(self) -> Value {
854        Value::Decimal(Some(self.0), W, S)
855    }
856    fn try_from_value(value: Value) -> Result<Self>
857    where
858        Self: Sized,
859    {
860        Ok(Self(Decimal::try_from_value(value)?))
861    }
862}
863
864impl<T: AsValue, const N: usize> AsValue for [T; N] {
865    fn as_empty_value() -> Value {
866        Value::Array(None, Box::new(T::as_empty_value()), N as u32)
867    }
868    fn as_value(self) -> Value {
869        Value::Array(
870            Some(self.into_iter().map(AsValue::as_value).collect()),
871            Box::new(T::as_empty_value()),
872            N as u32,
873        )
874    }
875    fn try_from_value(value: Value) -> Result<Self> {
876        let convert_iter = |iter: Vec<Value>| -> Result<[T; N]> {
877            iter.into_iter()
878                .map(T::try_from_value)
879                .collect::<Result<Vec<_>>>()?
880                .try_into()
881                .map_err(|v: Vec<T>| {
882                    Error::msg(format!(
883                        "Expected array of length {}, got {} elements ({})",
884                        N,
885                        v.len(),
886                        any::type_name::<[T; N]>()
887                    ))
888                })
889        };
890        match value {
891            Value::List(Some(v), ..) if v.len() == N => convert_iter(v),
892            Value::Array(Some(v), ..) if v.len() == N => convert_iter(v.into()),
893            Value::Unknown(Some(v)) => Self::parse(v),
894            _ => Err(Error::msg(format!(
895                "Cannot convert {value:?} to array {}",
896                any::type_name::<Self>()
897            ))),
898        }
899    }
900    fn extract(input: &mut &str) -> Result<Self> {
901        let mut value = *input;
902        let error = Arc::new(format!(
903            "Cannot extract `{}` as array {}",
904            truncate_long!(value),
905            any::type_name::<Self>(),
906        ));
907        let closing = match value.chars().next() {
908            Some('{') => '}',
909            Some('[') => ']',
910            _ => {
911                return Err(Error::msg(error));
912            }
913        };
914        value = &value[1..].trim_ascii_start();
915        // TODO Replace with array::from_fn once stable
916        let mut result = array::from_fn(|i| {
917            let result = T::extract(&mut value)?;
918            value = value.trim_ascii_start();
919            match value.chars().next() {
920                Some(',') => value = &value[1..].trim_ascii_start(),
921                _ if i != N - 1 => {
922                    return Err(Error::msg(error.clone()));
923                }
924                _ => {}
925            }
926            Ok(result)
927        });
928        if let Some(error) = result.iter_mut().find_map(|v| {
929            if let Err(e) = v {
930                let mut r = Error::msg("");
931                mem::swap(e, &mut r);
932                Some(r)
933            } else {
934                None
935            }
936        }) {
937            return Err(error);
938        }
939        if Some(closing) != value.chars().next() {
940            return Err(Error::msg(format!(
941                "Incorrect array `{}`, expected a `{}`",
942                truncate_long!(value),
943                closing
944            )));
945        };
946        value = &value[1..].trim_ascii_start();
947        *input = &value;
948        Ok(result.map(Result::unwrap))
949    }
950}
951
952macro_rules! impl_as_value {
953    ($source:ident) => {
954        impl<T: AsValue> AsValue for $source<T> {
955            fn as_empty_value() -> Value {
956                Value::List(None, Box::new(T::as_empty_value()))
957            }
958            fn as_value(self) -> Value {
959                Value::List(
960                    Some(self.into_iter().map(AsValue::as_value).collect()),
961                    Box::new(T::as_empty_value()),
962                )
963            }
964            fn try_from_value(value: Value) -> Result<Self> {
965                match value {
966                    Value::List(Some(v), ..) => Ok(v
967                        .into_iter()
968                        .map(|v| Ok::<_, Error>(<T as AsValue>::try_from_value(v)?))
969                        .collect::<Result<_>>()?),
970                    Value::List(None, ..) => Ok($source::<T>::new()),
971                    Value::Array(Some(v), ..) => Ok(v
972                        .into_iter()
973                        .map(|v| Ok::<_, Error>(<T as AsValue>::try_from_value(v)?))
974                        .collect::<Result<_>>()?),
975                    _ => Err(Error::msg(format!(
976                        "Cannot convert {value:?} to {}",
977                        any::type_name::<Self>(),
978                    ))),
979                }
980            }
981        }
982    };
983}
984impl_as_value!(Vec);
985impl_as_value!(VecDeque);
986impl_as_value!(LinkedList);
987
988macro_rules! impl_as_value {
989    ($source:ident, $($key_trait:ident),+) => {
990        impl<K: AsValue $(+ $key_trait)+, V: AsValue> AsValue for $source<K, V> {
991            fn as_empty_value() -> Value {
992                Value::Map(None, K::as_empty_value().into(), V::as_empty_value().into())
993            }
994            fn as_value(self) -> Value {
995                Value::Map(
996                    Some(
997                        self.into_iter()
998                            .map(|(k, v)| (k.as_value(), v.as_value()))
999                            .collect(),
1000                    ),
1001                    K::as_empty_value().into(),
1002                    V::as_empty_value().into(),
1003                )
1004            }
1005            fn try_from_value(value: Value) -> Result<Self> {
1006                if let Value::Map(Some(v), ..) = value {
1007                    Ok(v.into_iter()
1008                        .map(|(k, v)| {
1009                            Ok((
1010                                <K as AsValue>::try_from_value(k)?,
1011                                <V as AsValue>::try_from_value(v)?,
1012                            ))
1013                        })
1014                        .collect::<Result<_>>()?)
1015                } else {
1016                    Err(Error::msg(format!(
1017                        "Cannot convert {value:?} to {}",
1018                        any::type_name::<Self>(),
1019                    )))
1020                }
1021            }
1022        }
1023    }
1024}
1025impl_as_value!(BTreeMap, Ord);
1026impl_as_value!(HashMap, Eq, Hash);
1027
1028impl<'a> AsValue for Cow<'a, str> {
1029    fn as_empty_value() -> Value {
1030        Value::Varchar(None)
1031    }
1032    fn as_value(self) -> Value {
1033        Value::Varchar(Some(self.into()))
1034    }
1035    fn try_from_value(value: Value) -> Result<Self>
1036    where
1037        Self: Sized,
1038    {
1039        String::try_from_value(value).map(Into::into)
1040    }
1041}
1042
1043impl<T: AsValue> AsValue for Passive<T> {
1044    fn as_empty_value() -> Value {
1045        T::as_empty_value()
1046    }
1047    fn as_value(self) -> Value {
1048        match self {
1049            Passive::Set(v) => v.as_value(),
1050            Passive::NotSet => T::as_empty_value(),
1051        }
1052    }
1053    fn try_from_value(value: Value) -> Result<Self> {
1054        Ok(Passive::Set(<T as AsValue>::try_from_value(value)?))
1055    }
1056}
1057
1058impl<T: AsValue> AsValue for Option<T> {
1059    fn as_empty_value() -> Value {
1060        T::as_empty_value()
1061    }
1062    fn as_value(self) -> Value {
1063        match self {
1064            Some(v) => v.as_value(),
1065            None => T::as_empty_value(),
1066        }
1067    }
1068    fn try_from_value(value: Value) -> Result<Self> {
1069        Ok(if value.is_null() {
1070            None
1071        } else {
1072            Some(<T as AsValue>::try_from_value(value)?)
1073        })
1074    }
1075    fn extract(value: &mut &str) -> Result<Self>
1076    where
1077        Self: Sized,
1078    {
1079        T::extract(value).map(Some)
1080    }
1081}
1082
1083// TODO: USe the macro below once box_into_inner is stabilized
1084impl<T: AsValue> AsValue for Box<T> {
1085    fn as_empty_value() -> Value {
1086        T::as_empty_value()
1087    }
1088    fn as_value(self) -> Value {
1089        (*self).as_value()
1090    }
1091    fn try_from_value(value: Value) -> Result<Self> {
1092        Ok(Box::new(<T as AsValue>::try_from_value(value)?))
1093    }
1094    fn extract(value: &mut &str) -> Result<Self>
1095    where
1096        Self: Sized,
1097    {
1098        T::extract(value).map(Box::new)
1099    }
1100}
1101
1102macro_rules! impl_as_value {
1103    ($source:ident) => {
1104        impl<T: AsValue + ToOwned<Owned = impl AsValue>> AsValue for $source<T> {
1105            fn as_empty_value() -> Value {
1106                T::as_empty_value()
1107            }
1108            fn as_value(self) -> Value {
1109                $source::<T>::into_inner(self).as_value()
1110            }
1111            fn try_from_value(value: Value) -> Result<Self> {
1112                Ok($source::new(<T as AsValue>::try_from_value(value)?))
1113            }
1114        }
1115    };
1116}
1117// impl_as_value!(Box);
1118impl_as_value!(Cell);
1119impl_as_value!(RefCell);
1120
1121impl<T: AsValue> AsValue for RwLock<T> {
1122    fn as_empty_value() -> Value {
1123        T::as_empty_value()
1124    }
1125    fn as_value(self) -> Value {
1126        self.into_inner()
1127            .expect("Error occurred while trying to take the content of the RwLock")
1128            .as_value()
1129    }
1130    fn try_from_value(value: Value) -> Result<Self> {
1131        Ok(RwLock::new(<T as AsValue>::try_from_value(value)?))
1132    }
1133}
1134
1135macro_rules! impl_as_value {
1136    ($source:ident) => {
1137        impl<T: AsValue + ToOwned<Owned = impl AsValue>> AsValue for $source<T> {
1138            fn as_empty_value() -> Value {
1139                T::as_empty_value()
1140            }
1141            fn as_value(self) -> Value {
1142                $source::try_unwrap(self)
1143                    .map(|v| v.as_value())
1144                    .unwrap_or_else(|v| v.as_ref().to_owned().as_value())
1145            }
1146            fn try_from_value(value: Value) -> Result<Self> {
1147                Ok($source::new(<T as AsValue>::try_from_value(value)?))
1148            }
1149        }
1150    };
1151}
1152impl_as_value!(Arc);
1153impl_as_value!(Rc);