Skip to main content

rullst_orm/
resource.rs

1use serde_json::Value;
2
3pub trait ApiResource {
4    fn to_array(&self) -> Value;
5}
6
7pub struct JsonResource<'a, T: ApiResource> {
8    pub data: &'a T,
9}
10
11impl<'a, T: ApiResource> JsonResource<'a, T> {
12    pub fn new(data: &'a T) -> Self {
13        Self { data }
14    }
15
16    pub fn resolve(&self) -> Value {
17        self.data.to_array()
18    }
19}
20
21pub struct ResourceCollection<'a, T: ApiResource> {
22    pub data: &'a [T],
23}
24
25impl<'a, T: ApiResource> ResourceCollection<'a, T> {
26    pub fn new(data: &'a [T]) -> Self {
27        Self { data }
28    }
29
30    pub fn resolve(&self) -> Value {
31        let array: Vec<Value> = self.data.iter().map(|item| item.to_array()).collect();
32        serde_json::json!(array)
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use serde_json::json;
40
41    struct DummyResource {
42        value: i32,
43    }
44
45    impl ApiResource for DummyResource {
46        fn to_array(&self) -> Value {
47            json!({ "value": self.value })
48        }
49    }
50
51    #[test]
52    fn test_json_resource_new_stores_data() {
53        let r = DummyResource { value: 42 };
54        let jr = JsonResource::new(&r);
55        assert_eq!(jr.data.value, 42);
56    }
57
58    #[test]
59    fn test_json_resource_resolve() {
60        let r = DummyResource { value: 7 };
61        let jr = JsonResource::new(&r);
62        let v = jr.resolve();
63        assert_eq!(v["value"], 7);
64    }
65
66    struct ComplexResource {
67        id: u64,
68        name: String,
69        tags: Vec<String>,
70        metadata: Option<Value>,
71    }
72
73    impl ApiResource for ComplexResource {
74        fn to_array(&self) -> Value {
75            json!({
76                "id": self.id,
77                "name": self.name,
78                "tags": self.tags,
79                "metadata": self.metadata,
80                "is_active": true,
81            })
82        }
83    }
84
85    #[test]
86    fn test_json_resource_resolve_complex() {
87        let r = ComplexResource {
88            id: 101,
89            name: "Alice".to_string(),
90            tags: vec!["admin".to_string(), "user".to_string()],
91            metadata: Some(json!({ "login_count": 5 })),
92        };
93        let jr = JsonResource::new(&r);
94        let v = jr.resolve();
95        assert_eq!(v["id"], 101);
96        assert_eq!(v["name"], "Alice");
97        assert_eq!(v["tags"].as_array().unwrap().len(), 2);
98        assert_eq!(v["tags"][0], "admin");
99        assert_eq!(v["metadata"]["login_count"], 5);
100        assert_eq!(v["is_active"], true);
101
102        let r_null = ComplexResource {
103            id: 102,
104            name: "Bob".to_string(),
105            tags: vec![],
106            metadata: None,
107        };
108        let jr_null = JsonResource::new(&r_null);
109        let v_null = jr_null.resolve();
110        assert!(v_null["metadata"].is_null());
111        assert_eq!(v_null["tags"].as_array().unwrap().len(), 0);
112    }
113
114    #[test]
115    fn test_resource_collection_new_stores_slice() {
116        let items = vec![DummyResource { value: 1 }, DummyResource { value: 2 }];
117        let rc = ResourceCollection::new(&items);
118        assert_eq!(rc.data.len(), 2);
119    }
120
121    #[test]
122    fn test_resource_collection_resolve_returns_array() {
123        let items = vec![DummyResource { value: 10 }, DummyResource { value: 20 }];
124        let rc = ResourceCollection::new(&items);
125        let v = rc.resolve();
126        assert!(v.is_array());
127        let arr = v.as_array().unwrap();
128        assert_eq!(arr.len(), 2);
129        assert_eq!(arr[0]["value"], 10);
130        assert_eq!(arr[1]["value"], 20);
131    }
132
133    #[test]
134    fn test_resource_collection_empty() {
135        let items: Vec<DummyResource> = vec![];
136        let rc = ResourceCollection::new(&items);
137        let v = rc.resolve();
138        assert_eq!(v.as_array().unwrap().len(), 0);
139    }
140
141    #[test]
142    fn test_resource_collection_single_item() {
143        let items = vec![DummyResource { value: 99 }];
144        let rc = ResourceCollection::new(&items);
145        let v = rc.resolve();
146        assert!(v.is_array());
147        let arr = v.as_array().unwrap();
148        assert_eq!(arr.len(), 1);
149        assert_eq!(arr[0]["value"], 99);
150    }
151
152    #[test]
153    fn test_resource_collection_complex_items() {
154        let items = vec![
155            ComplexResource {
156                id: 1,
157                name: "Alpha".to_string(),
158                tags: vec!["a".to_string()],
159                metadata: None,
160            },
161            ComplexResource {
162                id: 2,
163                name: "Beta".to_string(),
164                tags: vec!["b".to_string(), "c".to_string()],
165                metadata: Some(json!({"role": "admin"})),
166            },
167        ];
168        let rc = ResourceCollection::new(&items);
169        let v = rc.resolve();
170        let arr = v.as_array().unwrap();
171        assert_eq!(arr.len(), 2);
172        assert_eq!(arr[0]["name"], "Alpha");
173        assert_eq!(arr[1]["metadata"]["role"], "admin");
174        assert_eq!(arr[1]["tags"].as_array().unwrap().len(), 2);
175    }
176
177    #[test]
178    fn test_resource_collection_resolve_large() {
179        let items: Vec<DummyResource> = (0..10_000).map(|i| DummyResource { value: i }).collect();
180        let rc = ResourceCollection::new(&items);
181        let v = rc.resolve();
182        assert!(v.is_array());
183        let arr = v.as_array().unwrap();
184        assert_eq!(arr.len(), 10_000);
185        assert_eq!(arr[9_999]["value"], 9_999);
186    }
187}