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_object(&self) -> Option<&serde_json::Map<String, serde_json::Value>> {
88 self.0.as_object()
89 }
90
91 pub fn get(&self, key: &str) -> Option<QuillValue> {
93 self.0.get(key).map(|v| QuillValue(v.clone()))
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_from_yaml_value() {
103 let yaml_str = r#"
104 package:
105 name: test
106 version: 1.0.0
107 "#;
108 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str).unwrap();
109 let quill_val = QuillValue::from_json(json_val);
110
111 assert!(quill_val.as_object().is_some());
112 assert_eq!(
113 quill_val
114 .get("package")
115 .unwrap()
116 .get("name")
117 .unwrap()
118 .as_str(),
119 Some("test")
120 );
121 }
122
123 #[test]
124 fn test_from_yaml_str() {
125 let yaml_str = r#"
126 title: Test Document
127 author: John Doe
128 count: 42
129 "#;
130 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
131
132 assert_eq!(
133 quill_val.get("title").as_ref().and_then(|v| v.as_str()),
134 Some("Test Document")
135 );
136 assert_eq!(
137 quill_val.get("author").as_ref().and_then(|v| v.as_str()),
138 Some("John Doe")
139 );
140 assert_eq!(
141 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
142 Some(42)
143 );
144 }
145
146 #[test]
147 fn test_as_json() {
148 let json_val = serde_json::json!({"key": "value"});
149 let quill_val = QuillValue::from_json(json_val.clone());
150
151 assert_eq!(quill_val.as_json(), &json_val);
152 }
153
154 #[test]
155 fn test_into_json() {
156 let json_val = serde_json::json!({"key": "value"});
157 let quill_val = QuillValue::from_json(json_val.clone());
158
159 assert_eq!(quill_val.into_json(), json_val);
160 }
161
162 #[test]
163 fn test_delegating_methods() {
164 let quill_val = QuillValue::from_json(serde_json::json!({
165 "name": "test",
166 "count": 42,
167 "active": true,
168 "items": [1, 2, 3]
169 }));
170
171 assert_eq!(
172 quill_val.get("name").as_ref().and_then(|v| v.as_str()),
173 Some("test")
174 );
175 assert_eq!(
176 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
177 Some(42)
178 );
179 assert_eq!(
180 quill_val.get("active").as_ref().and_then(|v| v.as_bool()),
181 Some(true)
182 );
183 assert!(quill_val
184 .get("items")
185 .as_ref()
186 .and_then(|v| v.as_array())
187 .is_some());
188 }
189
190 #[test]
191 fn test_yaml_with_tags() {
192 let yaml_str = r#"
194 value: 42
195 "#;
196 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
197
198 assert!(quill_val.as_object().is_some());
200 }
201
202 #[test]
203 fn test_null_value() {
204 let quill_val = QuillValue::from_json(serde_json::Value::Null);
205 assert!(quill_val.is_null());
206 }
207
208 #[test]
209 fn test_yaml_custom_tags_ignored_at_value_level() {
210 let yaml_str = "memo_from: !fill 2d lt example";
216 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
217
218 assert_eq!(
219 quill_val.get("memo_from").as_ref().and_then(|v| v.as_str()),
220 Some("2d lt example")
221 );
222 }
223}