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