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 pub fn string(s: impl Into<String>) -> Self {
42 QuillValue(serde_json::Value::String(s.into()))
43 }
44
45 pub fn integer(n: i64) -> Self {
47 QuillValue(serde_json::Value::Number(n.into()))
48 }
49
50 pub fn bool(b: bool) -> Self {
52 QuillValue(serde_json::Value::Bool(b))
53 }
54
55 pub fn null() -> Self {
57 QuillValue(serde_json::Value::Null)
58 }
59}
60
61impl Deref for QuillValue {
62 type Target = serde_json::Value;
63
64 fn deref(&self) -> &Self::Target {
65 &self.0
66 }
67}
68
69impl QuillValue {
71 pub fn is_null(&self) -> bool {
73 self.0.is_null()
74 }
75
76 pub fn as_str(&self) -> Option<&str> {
78 self.0.as_str()
79 }
80
81 pub fn as_bool(&self) -> Option<bool> {
83 self.0.as_bool()
84 }
85
86 pub fn as_i64(&self) -> Option<i64> {
88 self.0.as_i64()
89 }
90
91 pub fn as_u64(&self) -> Option<u64> {
93 self.0.as_u64()
94 }
95
96 pub fn as_f64(&self) -> Option<f64> {
98 self.0.as_f64()
99 }
100
101 pub fn as_array(&self) -> Option<&Vec<serde_json::Value>> {
103 self.0.as_array()
104 }
105
106 pub fn as_object(&self) -> Option<&serde_json::Map<String, serde_json::Value>> {
108 self.0.as_object()
109 }
110
111 pub fn get(&self, key: &str) -> Option<QuillValue> {
113 self.0.get(key).map(|v| QuillValue(v.clone()))
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_from_yaml_value() {
123 let yaml_str = r#"
124 package:
125 name: test
126 version: 1.0.0
127 "#;
128 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str).unwrap();
129 let quill_val = QuillValue::from_json(json_val);
130
131 assert!(quill_val.as_object().is_some());
132 assert_eq!(
133 quill_val
134 .get("package")
135 .unwrap()
136 .get("name")
137 .unwrap()
138 .as_str(),
139 Some("test")
140 );
141 }
142
143 #[test]
144 fn test_from_yaml_str() {
145 let yaml_str = r#"
146 title: Test Document
147 author: John Doe
148 count: 42
149 "#;
150 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
151
152 assert_eq!(
153 quill_val.get("title").as_ref().and_then(|v| v.as_str()),
154 Some("Test Document")
155 );
156 assert_eq!(
157 quill_val.get("author").as_ref().and_then(|v| v.as_str()),
158 Some("John Doe")
159 );
160 assert_eq!(
161 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
162 Some(42)
163 );
164 }
165
166 #[test]
167 fn test_as_json() {
168 let json_val = serde_json::json!({"key": "value"});
169 let quill_val = QuillValue::from_json(json_val.clone());
170
171 assert_eq!(quill_val.as_json(), &json_val);
172 }
173
174 #[test]
175 fn test_into_json() {
176 let json_val = serde_json::json!({"key": "value"});
177 let quill_val = QuillValue::from_json(json_val.clone());
178
179 assert_eq!(quill_val.into_json(), json_val);
180 }
181
182 #[test]
183 fn test_delegating_methods() {
184 let quill_val = QuillValue::from_json(serde_json::json!({
185 "name": "test",
186 "count": 42,
187 "active": true,
188 "items": [1, 2, 3]
189 }));
190
191 assert_eq!(
192 quill_val.get("name").as_ref().and_then(|v| v.as_str()),
193 Some("test")
194 );
195 assert_eq!(
196 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
197 Some(42)
198 );
199 assert_eq!(
200 quill_val.get("active").as_ref().and_then(|v| v.as_bool()),
201 Some(true)
202 );
203 assert!(quill_val
204 .get("items")
205 .as_ref()
206 .and_then(|v| v.as_array())
207 .is_some());
208 }
209
210 #[test]
211 fn test_yaml_with_tags() {
212 let yaml_str = r#"
214 value: 42
215 "#;
216 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
217
218 assert!(quill_val.as_object().is_some());
220 }
221
222 #[test]
223 fn test_null_value() {
224 let quill_val = QuillValue::from_json(serde_json::Value::Null);
225 assert!(quill_val.is_null());
226 }
227
228 #[test]
229 fn test_yaml_custom_tags_ignored_at_value_level() {
230 let yaml_str = "memo_from: !fill 2d lt example";
236 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
237
238 assert_eq!(
239 quill_val.get("memo_from").as_ref().and_then(|v| v.as_str()),
240 Some("2d lt example")
241 );
242 }
243}