shopify_function_wasm_api/
read.rs1use crate::Value;
6use std::collections::{BTreeMap, HashMap};
7
8#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum Error {
12 #[error("Invalid type")]
14 InvalidType,
15}
16
17pub trait Deserialize: Sized {
44 fn deserialize(value: &Value) -> Result<Self, Error>;
46}
47
48impl Deserialize for Value {
49 fn deserialize(value: &Value) -> Result<Self, Error> {
50 Ok(*value)
51 }
52}
53
54impl Deserialize for () {
55 fn deserialize(value: &Value) -> Result<Self, Error> {
56 if value.is_null() {
57 Ok(())
58 } else {
59 Err(Error::InvalidType)
60 }
61 }
62}
63
64impl Deserialize for bool {
65 fn deserialize(value: &Value) -> Result<Self, Error> {
66 value.as_bool().ok_or(Error::InvalidType)
67 }
68}
69
70macro_rules! impl_deserialize_for_int {
71 ($ty:ty) => {
72 impl Deserialize for $ty {
73 fn deserialize(value: &Value) -> Result<Self, Error> {
74 value
75 .as_number()
76 .and_then(|n| {
77 if n.trunc() == n && n >= <$ty>::MIN as f64 && n <= <$ty>::MAX as f64 {
78 Some(n as $ty)
79 } else {
80 None
81 }
82 })
83 .ok_or(Error::InvalidType)
84 }
85 }
86 };
87}
88
89impl_deserialize_for_int!(i8);
90impl_deserialize_for_int!(i16);
91impl_deserialize_for_int!(i32);
92impl_deserialize_for_int!(i64);
93impl_deserialize_for_int!(u8);
94impl_deserialize_for_int!(u16);
95impl_deserialize_for_int!(u32);
96impl_deserialize_for_int!(u64);
97impl_deserialize_for_int!(usize);
98impl_deserialize_for_int!(isize);
99
100impl Deserialize for f64 {
101 fn deserialize(value: &Value) -> Result<Self, Error> {
102 value.as_number().ok_or(Error::InvalidType)
103 }
104}
105
106impl Deserialize for String {
107 fn deserialize(value: &Value) -> Result<Self, Error> {
108 value.as_string().ok_or(Error::InvalidType)
109 }
110}
111
112impl Deserialize for char {
113 fn deserialize(value: &Value) -> Result<Self, Error> {
114 let s = value.as_string().ok_or(Error::InvalidType)?;
115 let mut chars = s.chars();
116 match (chars.next(), chars.next()) {
117 (Some(c), None) => Ok(c),
118 _ => Err(Error::InvalidType),
119 }
120 }
121}
122
123impl<T: Deserialize> Deserialize for Option<T> {
124 fn deserialize(value: &Value) -> Result<Self, Error> {
125 if value.is_null() {
126 Ok(None)
127 } else {
128 Ok(Some(T::deserialize(value)?))
129 }
130 }
131}
132
133impl<T: Deserialize> Deserialize for Vec<T> {
134 fn deserialize(value: &Value) -> Result<Self, Error> {
135 if let Some(len) = value.array_len() {
136 let mut vec = Vec::with_capacity(len);
137 for i in 0..len {
138 vec.push(T::deserialize(&value.get_at_index(i))?);
139 }
140 Ok(vec)
141 } else {
142 Err(Error::InvalidType)
143 }
144 }
145}
146
147impl<T: Deserialize> Deserialize for HashMap<String, T> {
148 fn deserialize(value: &Value) -> Result<Self, Error> {
149 let Some(obj_len) = value.obj_len() else {
150 return Err(Error::InvalidType);
151 };
152
153 let mut map = HashMap::new();
154
155 for i in 0..obj_len {
156 let key = value.get_obj_key_at_index(i).ok_or(Error::InvalidType)?;
157 let value = value.get_at_index(i);
158 map.insert(key, T::deserialize(&value)?);
159 }
160
161 Ok(map)
162 }
163}
164
165impl<T: Deserialize> Deserialize for BTreeMap<String, T> {
166 fn deserialize(value: &Value) -> Result<Self, Error> {
167 let Some(obj_len) = value.obj_len() else {
168 return Err(Error::InvalidType);
169 };
170
171 let mut map = BTreeMap::new();
172
173 for i in 0..obj_len {
174 let key = value.get_obj_key_at_index(i).ok_or(Error::InvalidType)?;
175 let value = value.get_at_index(i);
176 map.insert(key, T::deserialize(&value)?);
177 }
178
179 Ok(map)
180 }
181}
182
183macro_rules! impl_deserialize_tuple {
184 ($n:literal) => {
185 seq_macro::seq!(N in 0..$n {
186 impl<#(T~N: Deserialize,)*> Deserialize for (#(T~N,)*) {
187 fn deserialize(value: &Value) -> Result<Self, Error> {
188 let Some(len) = value.array_len() else {
189 return Err(Error::InvalidType);
190 };
191
192 if len != $n {
193 return Err(Error::InvalidType);
194 }
195
196 Ok((#(T~N::deserialize(&value.get_at_index(N))?,)*))
197 }
198 }
199 });
200 }
201}
202
203seq_macro::seq!(N in 2..=10 {
204 impl_deserialize_tuple!(N);
205});
206
207macro_rules! impl_deserialize_array {
208 ($n:literal) => {
209 impl<T: Deserialize> Deserialize for [T; $n] {
210 fn deserialize(value: &Value) -> Result<Self, Error> {
211 let Some(len) = value.array_len() else {
212 return Err(Error::InvalidType);
213 };
214
215 if len != $n {
216 return Err(Error::InvalidType);
217 }
218
219 seq_macro::seq!(N in 0..$n {
220 Ok([#(T::deserialize(&value.get_at_index(N))?,)*])
221 })
222 }
223 }
224 };
225}
226
227seq_macro::seq!(N in 0..=32 {
228 impl_deserialize_array!(N);
229});
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::Context;
235
236 fn deserialize_json_value<T: Deserialize>(value: serde_json::Value) -> Result<T, Error> {
237 let context = Context::new_with_input(value);
238 let value = context.input_get().unwrap();
239 T::deserialize(&value)
240 }
241
242 #[test]
243 fn test_deserialize_bool() {
244 [true, false].iter().for_each(|&b| {
245 let value = serde_json::json!(b);
246 let result: bool = deserialize_json_value(value).unwrap();
247 assert_eq!(result, b);
248 });
249 }
250
251 macro_rules! test_deserialize_int {
252 ($ty:ty) => {
253 paste::paste! {
254 #[test]
255 fn [<test_deserialize_ $ty>]() {
256 [$ty::MIN, 0 as $ty, $ty::MAX].iter().for_each(|&n| {
257 let value = serde_json::json!(n);
258 let result: $ty = deserialize_json_value(value).unwrap();
259 assert_eq!(result, n);
260 });
261 }
262 }
263 };
264 }
265
266 test_deserialize_int!(i8);
267 test_deserialize_int!(i16);
268 test_deserialize_int!(i32);
269 test_deserialize_int!(i64);
270 test_deserialize_int!(u8);
271 test_deserialize_int!(u16);
272 test_deserialize_int!(u32);
273 test_deserialize_int!(u64);
274 test_deserialize_int!(usize);
275 test_deserialize_int!(isize);
276
277 #[test]
278 fn test_deserialize_f64() {
279 let value = serde_json::json!(1.0);
280 let result: f64 = deserialize_json_value(value).unwrap();
281 assert_eq!(result, 1.0);
282 }
283
284 #[test]
285 fn test_deserialize_string() {
286 let value = serde_json::json!("test");
287 let result: String = deserialize_json_value(value).unwrap();
288 assert_eq!(result, "test");
289 }
290
291 #[test]
292 fn test_deserialize_char() {
293 let value = serde_json::json!("a");
294 let result: char = deserialize_json_value(value).unwrap();
295 assert_eq!(result, 'a');
296
297 let value = serde_json::json!("ab");
299 assert!(deserialize_json_value::<char>(value).is_err());
300
301 let value = serde_json::json!("");
302 assert!(deserialize_json_value::<char>(value).is_err());
303 }
304
305 #[test]
306 fn test_deserialize_option() {
307 [None, Some(1), Some(2)].iter().for_each(|&opt| {
308 let value = serde_json::json!(opt);
309 let result: Option<i32> = deserialize_json_value(value).unwrap();
310 assert_eq!(result, opt);
311 });
312 }
313
314 #[test]
315 fn test_deserialize_vec() {
316 let value = serde_json::json!([1, 2, 3]);
317 let result: Vec<i32> = deserialize_json_value(value).unwrap();
318 assert_eq!(result, vec![1, 2, 3]);
319 }
320
321 #[test]
322 fn test_deserialize_hash_map() {
323 let value = serde_json::json!({
324 "key1": "value1",
325 "key2": "value2",
326 });
327 let result: HashMap<String, String> = deserialize_json_value(value).unwrap();
328 let expected = HashMap::from([
329 ("key1".to_string(), "value1".to_string()),
330 ("key2".to_string(), "value2".to_string()),
331 ]);
332 assert_eq!(result, expected);
333 }
334
335 #[test]
336 fn test_deserialize_btree_map() {
337 let value = serde_json::json!({
338 "key1": "value1",
339 "key2": "value2",
340 });
341 let result: BTreeMap<String, String> = deserialize_json_value(value).unwrap();
342 let expected = BTreeMap::from([
343 ("key1".to_string(), "value1".to_string()),
344 ("key2".to_string(), "value2".to_string()),
345 ]);
346 assert_eq!(result, expected);
347 }
348
349 #[test]
350 fn test_deserialize_unit() {
351 let value = serde_json::json!(null);
352 deserialize_json_value::<()>(value).unwrap();
353 }
354
355 #[test]
356 fn test_deserialize_tuple() {
357 let value = serde_json::json!([1, 2, 3]);
358 let result: (i32, i32, i32) = deserialize_json_value(value).unwrap();
359 assert_eq!(result, (1, 2, 3));
360 }
361
362 #[test]
363 fn test_deserialize_fixed_array() {
364 let value = serde_json::json!([1, 2, 3]);
365 let result: [i32; 3] = deserialize_json_value(value).unwrap();
366 assert_eq!(result, [1, 2, 3]);
367
368 let value = serde_json::json!([1, 2]);
370 assert!(deserialize_json_value::<[i32; 3]>(value).is_err());
371
372 let value = serde_json::json!([1, 2, 3, 4]);
373 assert!(deserialize_json_value::<[i32; 3]>(value).is_err());
374
375 let value = serde_json::json!([]);
377 let result: [i32; 0] = deserialize_json_value(value).unwrap();
378 assert_eq!(result, [] as [i32; 0]);
379
380 let value = serde_json::json!([42]);
381 let result: [i32; 1] = deserialize_json_value(value).unwrap();
382 assert_eq!(result, [42]);
383
384 let value = serde_json::json!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
386 let result: [i32; 10] = deserialize_json_value(value).unwrap();
387 assert_eq!(result, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
388 }
389}