realm_db_reader/value/
into.rs

1use std::fmt::Debug;
2
3use anyhow::anyhow;
4use chrono::{DateTime, Utc};
5
6use crate::{
7    table::Row,
8    value::{ARRAY_VALUE_KEY, Backlink, Link, Value},
9};
10
11macro_rules! value_try_into {
12    (Option<$target:ty>, $source:ident) => {
13        impl TryFrom<Value> for Option<$target> {
14            type Error = anyhow::Error;
15
16            fn try_from(value: Value) -> Result<Self, Self::Error> {
17                match value {
18                    Value::$source(val) => Ok(Some(val)),
19                    Value::None => Ok(None),
20                    value => Err(anyhow::anyhow!(
21                        "Expected a {} value, found {value:?}",
22                        stringify!($source)
23                    )),
24                }
25            }
26        }
27    };
28
29    ($target:ty, $source:ident) => {
30        impl TryFrom<Value> for $target {
31            type Error = anyhow::Error;
32
33            fn try_from(value: Value) -> Result<Self, Self::Error> {
34                match value {
35                    Value::$source(val) => Ok(val),
36                    table => Err(anyhow::anyhow!(
37                        "Expected a {} value, found {table:?}",
38                        stringify!($source)
39                    )),
40                }
41            }
42        }
43
44        impl<'a> TryFrom<Row<'a>> for $target {
45            type Error = anyhow::Error;
46
47            fn try_from(mut value: Row<'a>) -> Result<Self, Self::Error> {
48                let Some(value) = value.take(ARRAY_VALUE_KEY) else {
49                    return Err(anyhow!(
50                        "Expected a row with field `{ARRAY_VALUE_KEY}`, found {value:?}",
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: Debug,
77{
78    type Error = anyhow::Error;
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| {
86                        anyhow!("Failed to convert value in row to Vec<T>: {e:?}",)
87                    })?);
88                }
89
90                Ok(result)
91            }
92            value => Err(anyhow!("Expected a Table value, found {value:?}")),
93        }
94    }
95}