tank_core/
as_value.rs

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