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