rs_zephyr_sdk/
database.rs1use crate::{env::EnvClient, external::{env_push_stack, read_raw, update_raw, write_raw}, symbol, to_fixed, SdkError};
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Deserialize, Serialize)]
5pub struct TypeWrap(pub Vec<u8>);
6
7impl TypeWrap {
8 pub fn to_i128(&self) -> i128 {
9 let bytes = to_fixed::<u8, 16>(self.0.clone());
10 i128::from_be_bytes(bytes)
11 }
12
13 pub fn to_u64(&self) -> u64 {
14 let bytes = to_fixed::<u8, 8>(self.0.clone());
15 u64::from_be_bytes(bytes)
16 }
17}
18
19#[derive(Clone, Deserialize, Serialize)]
22pub struct TableRows {
23 pub rows: Vec<TableRow>,
25}
26
27pub enum Condition {
30 ColumnEqualTo(String, Vec<u8>)
32}
33
34#[derive(Clone, Deserialize, Serialize)]
36pub struct TableRow {
37 pub row: Vec<TypeWrap>,
39}
40
41mod unsafe_helpers {
42 use crate::external::env_push_stack;
43
44 pub(crate) unsafe fn push_head(table_name: i64, columns: Vec<i64>) {
45 env_push_stack(table_name as i64);
46 env_push_stack(columns.len() as i64);
47
48 for col in columns {
49 env_push_stack(col)
50 }
51 }
52
53 pub(crate) unsafe fn push_data_segments(segments: Vec<(i64, i64)>) {
54 env_push_stack(segments.len() as i64);
55
56 for segment in segments {
57 env_push_stack(segment.0);
58 env_push_stack(segment.1);
59 }
60 }
61}
62
63#[derive(Clone, Default)]
64pub struct Database {}
65
66impl Database {
67 pub fn read_table(table_name: &str, columns: &[&str]) -> Result<TableRows, SdkError> {
68 let table_name = symbol::Symbol::try_from_bytes(table_name.as_bytes()).unwrap();
69 let cols = columns
70 .into_iter()
71 .map(|col| symbol::Symbol::try_from_bytes(col.as_bytes()).unwrap().0 as i64)
72 .collect::<Vec<i64>>();
73
74 unsafe {
75 unsafe_helpers::push_head(table_name.0 as i64, cols)
76 }
77
78 let (status, offset, size) = unsafe { read_raw() };
79 SdkError::express_from_status(status)?;
80
81 let table = {
82 let memory: *const u8 = offset as *const u8;
83
84 let slice = unsafe {
85 core::slice::from_raw_parts(memory, size as usize)
86 };
87
88 if let Ok(table) = bincode::deserialize::<TableRows>(slice) {
89 table
90 } else {
91 return Err(SdkError::Conversion)
92 }
93 };
94
95 Ok(table)
96
97 }
98
99 pub fn write_table(table_name: &str, columns: &[&str], segments: &[&[u8]]) -> Result<(), SdkError> {
100 let table_name = symbol::Symbol::try_from_bytes(table_name.as_bytes()).unwrap();
101 let cols = columns
102 .into_iter()
103 .map(|col| symbol::Symbol::try_from_bytes(col.as_bytes()).unwrap().0 as i64)
104 .collect::<Vec<i64>>();
105
106 let segments = segments
107 .into_iter()
108 .map(|segment| (segment.as_ptr() as i64, segment.len() as i64))
109 .collect::<Vec<(i64, i64)>>();
110
111 unsafe {
112 unsafe_helpers::push_head(table_name.0 as i64, cols);
113 unsafe_helpers::push_data_segments(segments);
114 }
115
116 let status = unsafe { write_raw() };
117 SdkError::express_from_status(status)
118 }
119
120 pub fn update_table(table_name: &str, columns: &[&str], segments: &[&[u8]], conditions: &[Condition]) -> Result<(), SdkError> {
121 let table_name = symbol::Symbol::try_from_bytes(table_name.as_bytes()).unwrap();
122 let cols = columns
123 .into_iter()
124 .map(|col| symbol::Symbol::try_from_bytes(col.as_bytes()).unwrap().0 as i64)
125 .collect::<Vec<i64>>();
126
127 let segments = segments
128 .into_iter()
129 .map(|segment| (segment.as_ptr() as i64, segment.len() as i64))
130 .collect::<Vec<(i64, i64)>>();
131
132 unsafe {
133 unsafe_helpers::push_head(table_name.0 as i64, cols);
134 unsafe_helpers::push_data_segments(segments);
135
136 env_push_stack(conditions.len() as i64);
137
138 let mut args = Vec::new();
139 for cond in conditions {
140 let (colname, operator, value) = match cond {
141 Condition::ColumnEqualTo(colname, value) => (colname, 0, value)
142 };
143
144 env_push_stack(symbol::Symbol::try_from_bytes(colname.as_bytes()).unwrap().0 as i64);
145 env_push_stack(operator as i64);
146
147 args.push((value.as_ptr() as i64, value.len() as i64))
148 }
149
150 env_push_stack(args.len() as i64);
151
152 for segment in args {
153 env_push_stack(segment.0);
154 env_push_stack(segment.1);
155 }
156 }
157
158 let status = unsafe { update_raw() };
159 SdkError::express_from_status(status)
160 }
161}
162
163pub trait DatabaseInteract {
164 fn read_to_rows(env: &EnvClient) -> Vec<Self> where Self: Sized;
165
166 fn put(&self, env: &EnvClient);
167
168 fn update(&self, env: &EnvClient, conditions: &[Condition]);
169}