1use crate::types::error::CruxError;
2use chrono::prelude::*;
3use edn_rs::{Deserialize, Edn, EdnError};
4use std::collections::BTreeSet;
5use std::str::FromStr;
6
7#[derive(Debug, PartialEq, Clone)]
8#[allow(non_snake_case)]
9pub struct TxLogResponse {
11 pub tx___tx_id: usize,
12 #[cfg(feature = "time_as_str")]
13 pub tx___tx_time: String,
14 #[cfg(not(feature = "time_as_str"))]
15 pub tx___tx_time: DateTime<FixedOffset>,
16 pub tx__event___tx_events: Option<Vec<Vec<String>>>,
17}
18
19impl Deserialize for TxLogResponse {
20 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
21 #[cfg(not(feature = "time_as_str"))]
22 let tx_time: String = edn_rs::from_edn(&edn[":crux.tx/tx-time"])?;
23
24 Ok(Self {
25 tx___tx_id: edn_rs::from_edn(&edn[":crux.tx/tx-id"]).unwrap_or(0usize),
26 #[cfg(feature = "time_as_str")]
27 tx___tx_time: edn_rs::from_edn(&edn[":crux.tx/tx-time"])?,
28 #[cfg(not(feature = "time_as_str"))]
29 tx___tx_time: tx_time
30 .parse::<DateTime<FixedOffset>>()
31 .map_err(|_| EdnError::Deserialize("Unable to deserialize `:crux.tx/tx-time`, verify if the transaction time you're sending is correct".to_string()))?,
32 tx__event___tx_events: edn_rs::from_edn(&edn[":crux.tx.event/tx-events"])?,
33 })
34 }
35}
36
37impl TxLogResponse {
38 #[cfg(test)]
39 pub fn default() -> Self {
40 Self {
41 tx___tx_id: 8usize,
42 tx___tx_time: "2020-07-16T21:53:14.628-00:00"
43 .parse::<DateTime<FixedOffset>>()
44 .unwrap(),
45 tx__event___tx_events: None,
46 }
47 }
48}
49
50#[derive(Debug, PartialEq, Clone)]
51#[allow(non_snake_case)]
52pub struct TxLogsResponse {
54 pub tx_events: Vec<TxLogResponse>,
55}
56
57impl FromStr for TxLogsResponse {
58 type Err = CruxError;
59 fn from_str(resp: &str) -> Result<Self, CruxError> {
60 let clean_edn = resp.replace("#crux/id", "").replace("#inst", "");
61 edn_rs::from_str(&clean_edn).map_err(|e| e.into())
62 }
63}
64
65impl Deserialize for TxLogsResponse {
66 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
67 Ok(Self {
68 tx_events: edn
69 .iter()
70 .ok_or(EdnError::Deserialize(format!(
71 "The following Edn cannot be deserialized to TxLogs: {:?}",
72 edn
73 )))?
74 .map(edn_rs::from_edn)
75 .collect::<Result<Vec<TxLogResponse>, EdnError>>()?,
76 })
77 }
78}
79
80#[derive(Debug, PartialEq, Clone)]
81#[allow(non_snake_case)]
82pub struct EntityTxResponse {
84 pub db___id: String,
85 pub db___content_hash: String,
86 #[cfg(feature = "time_as_str")]
87 pub db___valid_time: String,
88 #[cfg(not(feature = "time_as_str"))]
89 pub db___valid_time: DateTime<FixedOffset>,
90 pub tx___tx_id: usize,
91 #[cfg(feature = "time_as_str")]
92 pub tx___tx_time: String,
93 #[cfg(not(feature = "time_as_str"))]
94 pub tx___tx_time: DateTime<FixedOffset>,
95}
96
97impl FromStr for EntityTxResponse {
98 type Err = CruxError;
99 fn from_str(resp: &str) -> Result<Self, CruxError> {
100 let clean_edn = resp.replace("#crux/id", "");
101 edn_rs::from_str(&clean_edn).map_err(|e| e.into())
102 }
103}
104
105impl EntityTxResponse {
106 #[cfg(test)]
107 pub fn default() -> Self {
108 Self {
109 db___id: "d72ccae848ce3a371bd313865cedc3d20b1478ca".to_string(),
110 db___content_hash: "1828ebf4466f98ea3f5252a58734208cd0414376".to_string(),
111 db___valid_time: "2020-07-19T04:12:13.788-00:00"
112 .parse::<DateTime<FixedOffset>>()
113 .unwrap(),
114 tx___tx_id: 28usize,
115 tx___tx_time: "2020-07-19T04:12:13.788-00:00"
116 .parse::<DateTime<FixedOffset>>()
117 .unwrap(),
118 }
119 }
120}
121
122impl Deserialize for EntityTxResponse {
123 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
124 #[cfg(not(feature = "time_as_str"))]
125 let valid_time: String = edn_rs::from_edn(&edn[":crux.db/valid-time"])?;
126 #[cfg(not(feature = "time_as_str"))]
127 let tx_time: String = edn_rs::from_edn(&edn[":crux.tx/tx-time"])?;
128
129 Ok(Self {
130 db___id: edn_rs::from_edn(&edn[":crux.db/id"])?,
131 db___content_hash: edn_rs::from_edn(&edn[":crux.db/content-hash"])?,
132 #[cfg(feature = "time_as_str")]
133 db___valid_time: edn_rs::from_edn(&edn[":crux.db/valid-time"]),
134 #[cfg(not(feature = "time_as_str"))]
135 db___valid_time: valid_time.parse::<DateTime<FixedOffset>>().unwrap(),
136 tx___tx_id: edn_rs::from_edn(&edn[":crux.tx/tx-id"]).unwrap_or(0usize),
137 #[cfg(feature = "time_as_str")]
138 tx___tx_time: edn_rs::from_edn(&edn[":crux.tx/tx-time"]),
139 #[cfg(not(feature = "time_as_str"))]
140 tx___tx_time: tx_time.parse::<DateTime<FixedOffset>>().unwrap(),
141 })
142 }
143}
144
145#[doc(hidden)]
146#[cfg(not(feature = "async"))]
147pub(crate) struct QueryResponse(pub(crate) BTreeSet<Vec<String>>);
148
149#[cfg(not(feature = "async"))]
150impl Deserialize for QueryResponse {
151 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
152 if edn.set_iter().is_some() {
153 Ok(Self(
154 edn.set_iter()
155 .ok_or(EdnError::Deserialize(format!(
156 "The following Edn cannot be deserialized to BTreeSet: {:?}",
157 edn
158 )))?
159 .map(|e| {
160 e.to_vec().ok_or(EdnError::Deserialize(format!(
161 "The following Edn cannot be deserialized to Vec: {:?}",
162 edn
163 )))
164 })
165 .collect::<Result<BTreeSet<Vec<String>>, EdnError>>()?,
166 ))
167 } else {
168 Ok(Self(
169 edn.iter()
170 .ok_or(EdnError::Deserialize(format!(
171 "The following Edn cannot be deserialized to BTreeSet: {:?}",
172 edn
173 )))?
174 .map(|e| {
175 e.to_vec().ok_or(EdnError::Deserialize(format!(
176 "The following Edn cannot be deserialized to Vec: {:?}",
177 edn
178 )))
179 })
180 .collect::<Result<BTreeSet<Vec<String>>, EdnError>>()?,
181 ))
182 }
183 }
184}
185
186#[cfg(feature = "async")]
187#[derive(Clone, Debug, PartialEq)]
188pub struct QueryAsyncResponse(pub(crate) BTreeSet<Vec<String>>);
190
191#[cfg(feature = "async")]
192impl Deserialize for QueryAsyncResponse {
193 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
194 if edn.set_iter().is_some() {
195 Ok(Self {
196 0: edn
197 .set_iter()
198 .ok_or(EdnError::Deserialize(format!(
199 "The following Edn cannot be deserialize to BTreeSet: {:?}",
200 edn
201 )))?
202 .map(|e| {
203 e.to_vec().ok_or(EdnError::Deserialize(format!(
204 "The following Edn cannot be deserialized to Vec: {:?}",
205 edn
206 )))
207 })
208 .collect::<Result<BTreeSet<Vec<String>>, EdnError>>()?,
209 })
210 } else {
211 Ok(Self {
212 0: edn
213 .iter()
214 .ok_or(EdnError::Deserialize(format!(
215 "The following Edn cannot be deserialize to BTreeSet: {:?}",
216 edn
217 )))?
218 .map(|e| {
219 e.to_vec().ok_or(EdnError::Deserialize(format!(
220 "The following Edn cannot be deserialized to Vec: {:?}",
221 edn
222 )))
223 })
224 .collect::<Result<BTreeSet<Vec<String>>, EdnError>>()?,
225 })
226 }
227 }
228}
229
230#[derive(Debug, PartialEq, Clone)]
231#[allow(non_snake_case)]
232pub struct EntityHistoryElement {
233 #[cfg(feature = "time_as_str")]
234 pub db___valid_time: String,
235 #[cfg(not(feature = "time_as_str"))]
236 pub db___valid_time: DateTime<FixedOffset>,
237 pub tx___tx_id: usize,
238 #[cfg(feature = "time_as_str")]
239 pub tx___tx_time: String,
240 #[cfg(not(feature = "time_as_str"))]
241 pub tx___tx_time: DateTime<FixedOffset>,
242 pub db___content_hash: String,
243 pub db__doc: Option<Edn>,
244}
245
246impl Deserialize for EntityHistoryElement {
247 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
248 #[cfg(not(feature = "time_as_str"))]
249 let valid_time: String = edn_rs::from_edn(&edn[":crux.db/valid-time"])?;
250 #[cfg(not(feature = "time_as_str"))]
251 let tx_time: String = edn_rs::from_edn(&edn[":crux.tx/tx-time"])?;
252
253 Ok(Self {
254 db___content_hash: edn_rs::from_edn(&edn[":crux.db/content-hash"])?,
255 #[cfg(feature = "time_as_str")]
256 db___valid_time: edn_rs::from_edn(&edn[":crux.db/valid-time"])?,
257 #[cfg(not(feature = "time_as_str"))]
258 db___valid_time: valid_time.parse::<DateTime<FixedOffset>>().unwrap(),
259 tx___tx_id: edn_rs::from_edn(&edn[":crux.tx/tx-id"]).unwrap_or(0usize),
260 #[cfg(feature = "time_as_str")]
261 tx___tx_time: edn_rs::from_edn(&edn[":crux.tx/tx-time"])?,
262 #[cfg(not(feature = "time_as_str"))]
263 tx___tx_time: tx_time.parse::<DateTime<FixedOffset>>().unwrap(),
264 db__doc: edn.get(":crux.db/doc").map(|d| d.to_owned()),
265 })
266 }
267}
268
269#[cfg(test)]
270impl EntityHistoryElement {
271 pub fn default() -> Self {
272 Self {
273 db___content_hash: "1828ebf4466f98ea3f5252a58734208cd0414376".to_string(),
274 db___valid_time: "2020-07-19T04:12:13.788-00:00"
275 .parse::<DateTime<FixedOffset>>()
276 .unwrap(),
277 tx___tx_id: 28usize,
278 tx___tx_time: "2020-07-19T04:12:13.788-00:00"
279 .parse::<DateTime<FixedOffset>>()
280 .unwrap(),
281 db__doc: None,
282 }
283 }
284
285 pub fn default_docs() -> Self {
286 Self {
287 db___content_hash: "1828ebf4466f98ea3f5252a58734208cd0414376".to_string(),
288 db___valid_time: "2020-07-19T04:12:13.788-00:00"
289 .parse::<DateTime<FixedOffset>>()
290 .unwrap(),
291 tx___tx_id: 28usize,
292 tx___tx_time: "2020-07-19T04:12:13.788-00:00"
293 .parse::<DateTime<FixedOffset>>()
294 .unwrap(),
295 db__doc: Some(Edn::Key(":docs".to_string())),
296 }
297 }
298}
299
300#[derive(Debug, PartialEq, Clone)]
302pub struct EntityHistoryResponse {
303 pub history: Vec<EntityHistoryElement>,
304}
305
306impl FromStr for EntityHistoryResponse {
307 type Err = CruxError;
308 fn from_str(resp: &str) -> Result<Self, CruxError> {
309 let clean_edn = resp.replace("#crux/id", "").replace("#inst", "");
310 edn_rs::from_str(&clean_edn).map_err(|e| e.into())
311 }
312}
313
314impl Deserialize for EntityHistoryResponse {
315 fn deserialize(edn: &Edn) -> Result<Self, EdnError> {
316 Ok(Self {
317 history: edn
318 .iter()
319 .ok_or(EdnError::Deserialize(format!(
320 "The following Edn cannot be deserialize to entity-history: {:?}",
321 edn
322 )))?
323 .map(edn_rs::from_edn)
324 .collect::<Result<Vec<EntityHistoryElement>, EdnError>>()?,
325 })
326 }
327}