realm_db_reader/value/
into.rs1use 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}