1use serde::{Deserialize, Serialize};
7use std::ops::Deref;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct QuillValue(serde_json::Value);
15
16impl QuillValue {
17 pub fn from_yaml_str(yaml_str: &str) -> Result<Self, serde_saphyr::Error> {
21 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str)?;
22 Ok(QuillValue(json_val))
23 }
24
25 pub fn as_json(&self) -> &serde_json::Value {
27 &self.0
28 }
29
30 pub fn into_json(self) -> serde_json::Value {
32 self.0
33 }
34
35 pub fn from_json(json_val: serde_json::Value) -> Self {
37 QuillValue(json_val)
38 }
39}
40
41impl Deref for QuillValue {
42 type Target = serde_json::Value;
43
44 fn deref(&self) -> &Self::Target {
45 &self.0
46 }
47}
48
49impl QuillValue {
51 pub fn is_null(&self) -> bool {
53 self.0.is_null()
54 }
55
56 pub fn as_str(&self) -> Option<&str> {
58 self.0.as_str()
59 }
60
61 pub fn as_bool(&self) -> Option<bool> {
63 self.0.as_bool()
64 }
65
66 pub fn as_i64(&self) -> Option<i64> {
68 self.0.as_i64()
69 }
70
71 pub fn as_u64(&self) -> Option<u64> {
73 self.0.as_u64()
74 }
75
76 pub fn as_f64(&self) -> Option<f64> {
78 self.0.as_f64()
79 }
80
81 pub fn as_array(&self) -> Option<&Vec<serde_json::Value>> {
83 self.0.as_array()
84 }
85
86 pub fn as_sequence(&self) -> Option<&Vec<serde_json::Value>> {
88 self.0.as_array()
89 }
90
91 pub fn as_object(&self) -> Option<&serde_json::Map<String, serde_json::Value>> {
93 self.0.as_object()
94 }
95
96 pub fn get(&self, key: &str) -> Option<QuillValue> {
98 self.0.get(key).map(|v| QuillValue(v.clone()))
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_from_yaml_value() {
108 let yaml_str = r#"
109 package:
110 name: test
111 version: 1.0.0
112 "#;
113 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str).unwrap();
114 let quill_val = QuillValue::from_json(json_val);
115
116 assert!(quill_val.as_object().is_some());
117 assert_eq!(
118 quill_val
119 .get("package")
120 .unwrap()
121 .get("name")
122 .unwrap()
123 .as_str(),
124 Some("test")
125 );
126 }
127
128 #[test]
129 fn test_from_yaml_str() {
130 let yaml_str = r#"
131 title: Test Document
132 author: John Doe
133 count: 42
134 "#;
135 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
136
137 assert_eq!(
138 quill_val.get("title").as_ref().and_then(|v| v.as_str()),
139 Some("Test Document")
140 );
141 assert_eq!(
142 quill_val.get("author").as_ref().and_then(|v| v.as_str()),
143 Some("John Doe")
144 );
145 assert_eq!(
146 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
147 Some(42)
148 );
149 }
150
151 #[test]
152 fn test_as_json() {
153 let json_val = serde_json::json!({"key": "value"});
154 let quill_val = QuillValue::from_json(json_val.clone());
155
156 assert_eq!(quill_val.as_json(), &json_val);
157 }
158
159 #[test]
160 fn test_into_json() {
161 let json_val = serde_json::json!({"key": "value"});
162 let quill_val = QuillValue::from_json(json_val.clone());
163
164 assert_eq!(quill_val.into_json(), json_val);
165 }
166
167 #[test]
168 fn test_delegating_methods() {
169 let quill_val = QuillValue::from_json(serde_json::json!({
170 "name": "test",
171 "count": 42,
172 "active": true,
173 "items": [1, 2, 3]
174 }));
175
176 assert_eq!(
177 quill_val.get("name").as_ref().and_then(|v| v.as_str()),
178 Some("test")
179 );
180 assert_eq!(
181 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
182 Some(42)
183 );
184 assert_eq!(
185 quill_val.get("active").as_ref().and_then(|v| v.as_bool()),
186 Some(true)
187 );
188 assert!(quill_val
189 .get("items")
190 .as_ref()
191 .and_then(|v| v.as_array())
192 .is_some());
193 }
194
195 #[test]
196 fn test_yaml_with_tags() {
197 let yaml_str = r#"
199 value: 42
200 "#;
201 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
202
203 assert!(quill_val.as_object().is_some());
205 }
206
207 #[test]
208 fn test_null_value() {
209 let quill_val = QuillValue::from_json(serde_json::Value::Null);
210 assert!(quill_val.is_null());
211 }
212
213 #[test]
214 fn test_yaml_custom_tags_ignored() {
215 let yaml_str = "memo_from: !fill 2d lt example";
218 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
219
220 assert_eq!(
222 quill_val.get("memo_from").as_ref().and_then(|v| v.as_str()),
223 Some("2d lt example")
224 );
225 }
226}