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