realm_db_reader/value/
into.rs1use std::any::type_name;
2use std::error::Error;
3
4use chrono::{DateTime, Utc};
5
6use crate::error::ValueError;
7use crate::table::Row;
8use crate::value::{ARRAY_VALUE_KEY, Backlink, Link, Value};
9
10macro_rules! value_try_into {
11 (Option<$target:ty>, $source:ident) => {
12 impl TryFrom<Value> for Option<$target> {
13 type Error = ValueError;
14
15 fn try_from(value: Value) -> Result<Self, Self::Error> {
16 match value {
17 Value::$source(val) => Ok(Some(val)),
18 Value::None => Ok(None),
19 value => Err(ValueError::UnexpectedType {
20 expected: stringify!($target),
21 found: value,
22 }),
23 }
24 }
25 }
26 };
27
28 ($target:ty, $source:ident) => {
29 impl TryFrom<Value> for $target {
30 type Error = ValueError;
31
32 fn try_from(value: Value) -> Result<Self, Self::Error> {
33 match value {
34 Value::$source(val) => Ok(val),
35 value => Err(ValueError::UnexpectedType {
36 expected: stringify!($target),
37 found: value,
38 }),
39 }
40 }
41 }
42
43 impl<'a> TryFrom<Row<'a>> for $target {
44 type Error = ValueError;
45
46 fn try_from(mut value: Row<'a>) -> Result<Self, Self::Error> {
47 let Some(value) = value.take(ARRAY_VALUE_KEY) else {
48 return Err(ValueError::ExpectedArrayRow {
49 field: ARRAY_VALUE_KEY,
50 found: value.into_owned(),
51 });
52 };
53
54 value.try_into()
55 }
56 }
57 };
58}
59
60value_try_into!(String, String);
61value_try_into!(Option<String>, String);
62value_try_into!(i64, Int);
63value_try_into!(Option<i64>, Int);
64value_try_into!(bool, Bool);
65value_try_into!(f32, Float);
66value_try_into!(f64, Double);
67value_try_into!(DateTime<Utc>, Timestamp);
68value_try_into!(Option<DateTime<Utc>>, Timestamp);
69value_try_into!(Backlink, BackLink);
70value_try_into!(Link, Link);
71value_try_into!(Option<Link>, Link);
72
73impl<'a, T> TryFrom<Value> for Vec<T>
74where
75 T: TryFrom<Row<'a>>,
76 T::Error: Error + 'static,
77{
78 type Error = ValueError;
79
80 fn try_from(value: Value) -> Result<Self, Self::Error> {
81 match value {
82 Value::Table(rows) => {
83 let mut result = Vec::with_capacity(rows.len());
84 for row in rows {
85 result.push(row.try_into().map_err(|e| ValueError::VecConversionError {
86 element_type: type_name::<T>(),
87 source: Box::new(e),
88 })?);
89 }
90
91 Ok(result)
92 }
93 value => Err(ValueError::ExpectedTable { found: value }),
94 }
95 }
96}