toolu_orm_core/
relational_row.rs1use serde::de::DeserializeOwned;
9
10use crate::error::DbCoreError;
11
12pub fn parse_json_array_of_arrays(json: &str) -> Result<Vec<Vec<serde_json::Value>>, DbCoreError> {
18 let parsed: serde_json::Value =
19 serde_json::from_str(json).map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
20
21 let outer = parsed
22 .as_array()
23 .ok_or_else(|| DbCoreError::RowMapping("expected JSON array".to_owned()))?;
24
25 let mut rows = Vec::with_capacity(outer.len());
26 for item in outer {
27 let inner = item
28 .as_array()
29 .ok_or_else(|| DbCoreError::RowMapping("expected inner array in JSON row".to_owned()))?
30 .clone();
31 rows.push(inner);
32 }
33
34 Ok(rows)
35}
36
37pub fn parse_json_single_array(json: &str) -> Result<Vec<serde_json::Value>, DbCoreError> {
46 let parsed: serde_json::Value =
47 serde_json::from_str(json).map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
48
49 if parsed.is_null() {
50 return Ok(Vec::new());
51 }
52
53 parsed
54 .as_array()
55 .cloned()
56 .ok_or_else(|| DbCoreError::RowMapping("expected JSON array or null".to_owned()))
57}
58
59pub fn from_json_object_slice<T: DeserializeOwned>(
66 values: &[serde_json::Value],
67 keys: &[&str],
68) -> Result<T, DbCoreError> {
69 if values.len() != keys.len() {
70 return Err(DbCoreError::RowMapping(format!(
71 "column count mismatch: got {} values for {} keys",
72 values.len(),
73 keys.len()
74 )));
75 }
76 let mut map = serde_json::Map::new();
77 for (k, v) in keys.iter().zip(values.iter()) {
78 map.insert((*k).to_owned(), v.clone());
79 }
80 serde_json::from_value(serde_json::Value::Object(map))
81 .map_err(|e| DbCoreError::RowMapping(e.to_string()))
82}
83
84pub struct RelationDeserializer<'a> {
86 values: &'a [serde_json::Value],
87}
88
89impl<'a> RelationDeserializer<'a> {
90 pub fn new(values: &'a [serde_json::Value]) -> Self {
92 Self { values }
93 }
94
95 pub fn get<T: DeserializeOwned>(&self, index: usize) -> Result<T, DbCoreError> {
102 let val = self.values.get(index).ok_or_else(|| {
103 DbCoreError::RowMapping(format!(
104 "relation column index {index} out of bounds (len {})",
105 self.values.len()
106 ))
107 })?;
108 serde_json::from_value(val.clone())
109 .map_err(|e| DbCoreError::RowMapping(format!("column {index}: {e}")))
110 }
111
112 pub fn len(&self) -> usize {
114 self.values.len()
115 }
116
117 pub fn is_empty(&self) -> bool {
119 self.values.is_empty()
120 }
121}
122
123pub trait FromRelationalRow: Sized {
125 const SCALAR_COLUMNS: &'static [&'static str];
127
128 fn from_relational_values(values: &[serde_json::Value]) -> Result<Self, DbCoreError>;
134}