1use corium_core::{EntityId, Keyword, TotalF64};
6use corium_query::edn::Edn;
7
8use crate::ClientError;
9
10pub trait IntoEdn {
17 fn into_edn(self) -> Edn;
19}
20
21impl IntoEdn for Edn {
22 fn into_edn(self) -> Edn {
23 self
24 }
25}
26
27impl IntoEdn for &Edn {
28 fn into_edn(self) -> Edn {
29 self.clone()
30 }
31}
32
33impl IntoEdn for bool {
34 fn into_edn(self) -> Edn {
35 Edn::Bool(self)
36 }
37}
38
39impl IntoEdn for i64 {
40 fn into_edn(self) -> Edn {
41 Edn::Long(self)
42 }
43}
44
45impl IntoEdn for i32 {
46 fn into_edn(self) -> Edn {
47 Edn::Long(i64::from(self))
48 }
49}
50
51impl IntoEdn for u32 {
52 fn into_edn(self) -> Edn {
53 Edn::Long(i64::from(self))
54 }
55}
56
57impl IntoEdn for f64 {
58 fn into_edn(self) -> Edn {
59 Edn::Double(TotalF64(self))
60 }
61}
62
63impl IntoEdn for &str {
64 fn into_edn(self) -> Edn {
65 Edn::Str(self.to_owned())
66 }
67}
68
69impl IntoEdn for String {
70 fn into_edn(self) -> Edn {
71 Edn::Str(self)
72 }
73}
74
75impl IntoEdn for &String {
76 fn into_edn(self) -> Edn {
77 Edn::Str(self.clone())
78 }
79}
80
81impl IntoEdn for Keyword {
82 fn into_edn(self) -> Edn {
83 Edn::Keyword(self)
84 }
85}
86
87impl IntoEdn for &Keyword {
88 fn into_edn(self) -> Edn {
89 Edn::Keyword(self.clone())
90 }
91}
92
93impl IntoEdn for EntityId {
94 fn into_edn(self) -> Edn {
95 Edn::Long(i64::try_from(self.raw()).unwrap_or(i64::MAX))
96 }
97}
98
99pub trait FromEdn: Sized {
115 fn from_edn(form: &Edn) -> Result<Self, ClientError>;
121}
122
123fn decode_err(what: &str, form: &Edn) -> ClientError {
124 ClientError::Decode(format!("expected {what}, got {form}"))
125}
126
127impl FromEdn for Edn {
128 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
129 Ok(form.clone())
130 }
131}
132
133impl FromEdn for bool {
134 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
135 match form {
136 Edn::Bool(value) => Ok(*value),
137 other => Err(decode_err("bool", other)),
138 }
139 }
140}
141
142impl FromEdn for i64 {
143 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
144 match form {
145 Edn::Long(value) => Ok(*value),
146 other => Err(decode_err("long", other)),
147 }
148 }
149}
150
151impl FromEdn for f64 {
152 #[allow(clippy::cast_precision_loss)]
153 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
154 match form {
155 Edn::Double(value) => Ok(value.0),
156 Edn::Long(value) => Ok(*value as Self),
159 other => Err(decode_err("double", other)),
160 }
161 }
162}
163
164impl FromEdn for String {
165 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
166 match form {
167 Edn::Str(value) => Ok(value.clone()),
168 other => Err(decode_err("string", other)),
169 }
170 }
171}
172
173impl FromEdn for Keyword {
174 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
175 match form {
176 Edn::Keyword(value) => Ok(value.clone()),
177 other => Err(decode_err("keyword", other)),
178 }
179 }
180}
181
182impl FromEdn for EntityId {
183 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
184 match form {
185 Edn::Long(value) => u64::try_from(*value)
187 .map(EntityId::from_raw)
188 .map_err(|_| decode_err("entity id", form)),
189 other => Err(decode_err("entity id", other)),
190 }
191 }
192}
193
194impl<T: FromEdn> FromEdn for Option<T> {
195 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
196 match form {
197 Edn::Nil => Ok(None),
198 other => T::from_edn(other).map(Some),
199 }
200 }
201}
202
203impl<T: FromEdn> FromEdn for Vec<T> {
204 fn from_edn(form: &Edn) -> Result<Self, ClientError> {
205 match form {
206 Edn::Vector(items) | Edn::List(items) | Edn::Set(items) => {
207 items.iter().map(T::from_edn).collect()
208 }
209 other => Err(decode_err("collection", other)),
210 }
211 }
212}