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> {
19 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str)?;
20 Ok(QuillValue(json_val))
21 }
22
23 pub fn as_json(&self) -> &serde_json::Value {
25 &self.0
26 }
27
28 pub fn into_json(self) -> serde_json::Value {
30 self.0
31 }
32
33 pub fn from_json(json_val: serde_json::Value) -> Self {
35 QuillValue(json_val)
36 }
37
38 pub fn string(s: impl Into<String>) -> Self {
40 QuillValue(serde_json::Value::String(s.into()))
41 }
42
43 pub fn integer(n: i64) -> Self {
45 QuillValue(serde_json::Value::Number(n.into()))
46 }
47
48 pub fn bool(b: bool) -> Self {
50 QuillValue(serde_json::Value::Bool(b))
51 }
52
53 pub fn null() -> Self {
55 QuillValue(serde_json::Value::Null)
56 }
57}
58
59impl Deref for QuillValue {
60 type Target = serde_json::Value;
61
62 fn deref(&self) -> &Self::Target {
63 &self.0
64 }
65}
66
67impl QuillValue {
69 pub fn is_null(&self) -> bool {
71 self.0.is_null()
72 }
73
74 pub fn as_str(&self) -> Option<&str> {
76 self.0.as_str()
77 }
78
79 pub fn as_bool(&self) -> Option<bool> {
81 self.0.as_bool()
82 }
83
84 pub fn as_i64(&self) -> Option<i64> {
86 self.0.as_i64()
87 }
88
89 pub fn as_u64(&self) -> Option<u64> {
91 self.0.as_u64()
92 }
93
94 pub fn as_f64(&self) -> Option<f64> {
96 self.0.as_f64()
97 }
98
99 pub fn as_array(&self) -> Option<&Vec<serde_json::Value>> {
101 self.0.as_array()
102 }
103
104 pub fn as_object(&self) -> Option<&serde_json::Map<String, serde_json::Value>> {
106 self.0.as_object()
107 }
108
109 pub fn get(&self, key: &str) -> Option<QuillValue> {
111 self.0.get(key).map(|v| QuillValue(v.clone()))
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_from_yaml_value() {
121 let yaml_str = r#"
122 package:
123 name: test
124 version: 1.0.0
125 "#;
126 let json_val: serde_json::Value = serde_saphyr::from_str(yaml_str).unwrap();
127 let quill_val = QuillValue::from_json(json_val);
128
129 assert!(quill_val.as_object().is_some());
130 assert_eq!(
131 quill_val
132 .get("package")
133 .unwrap()
134 .get("name")
135 .unwrap()
136 .as_str(),
137 Some("test")
138 );
139 }
140
141 #[test]
142 fn test_from_yaml_str() {
143 let yaml_str = r#"
144 title: Test Document
145 author: John Doe
146 count: 42
147 "#;
148 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
149
150 assert_eq!(
151 quill_val.get("title").as_ref().and_then(|v| v.as_str()),
152 Some("Test Document")
153 );
154 assert_eq!(
155 quill_val.get("author").as_ref().and_then(|v| v.as_str()),
156 Some("John Doe")
157 );
158 assert_eq!(
159 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
160 Some(42)
161 );
162 }
163
164 #[test]
165 fn test_delegating_methods() {
166 let quill_val = QuillValue::from_json(serde_json::json!({
167 "name": "test",
168 "count": 42,
169 "active": true,
170 "items": [1, 2, 3]
171 }));
172
173 assert_eq!(
174 quill_val.get("name").as_ref().and_then(|v| v.as_str()),
175 Some("test")
176 );
177 assert_eq!(
178 quill_val.get("count").as_ref().and_then(|v| v.as_i64()),
179 Some(42)
180 );
181 assert_eq!(
182 quill_val.get("active").as_ref().and_then(|v| v.as_bool()),
183 Some(true)
184 );
185 assert!(quill_val
186 .get("items")
187 .as_ref()
188 .and_then(|v| v.as_array())
189 .is_some());
190 }
191
192 #[test]
193 fn test_yaml_custom_tags_ignored_at_value_level() {
194 let yaml_str = "memo_from: !fill 2d lt example";
200 let quill_val = QuillValue::from_yaml_str(yaml_str).unwrap();
201
202 assert_eq!(
203 quill_val.get("memo_from").as_ref().and_then(|v| v.as_str()),
204 Some("2d lt example")
205 );
206 }
207}
208