1#![warn(rustdoc::missing_crate_level_docs)]
27
28pub mod constants;
29pub mod decode;
30pub mod encode;
31pub mod tui;
32pub mod types;
33pub mod utils;
34
35pub use decode::{
36 decode,
37 decode_default,
38 decode_no_coerce,
39 decode_no_coerce_with_options,
40 decode_strict,
41 decode_strict_with_options,
42};
43pub use encode::{
44 encode,
45 encode_array,
46 encode_default,
47 encode_object,
48};
49pub use types::{
50 DecodeOptions,
51 Delimiter,
52 EncodeOptions,
53 Indent,
54 ToonError,
55};
56pub use utils::{
57 literal::{
58 is_keyword,
59 is_literal_like,
60 },
61 normalize,
62 string::{
63 escape_string,
64 is_valid_unquoted_key,
65 needs_quoting,
66 },
67};
68
69#[cfg(test)]
70mod tests {
71 use serde_json::{
72 json,
73 Value,
74 };
75
76 use crate::{
77 constants::is_keyword,
78 decode::{
79 decode_default,
80 decode_strict,
81 },
82 encode::{
83 encode,
84 encode_default,
85 },
86 types::{
87 Delimiter,
88 EncodeOptions,
89 },
90 utils::{
91 escape_string,
92 is_literal_like,
93 needs_quoting,
94 normalize,
95 },
96 };
97
98 #[test]
99 fn test_round_trip_simple() {
100 let original = json!({"name": "Alice", "age": 30});
101 let encoded = encode_default(&original).unwrap();
102 let decoded: Value = decode_default(&encoded).unwrap();
103 assert_eq!(original, decoded);
104 }
105
106 #[test]
107 fn test_round_trip_array() {
108 let original = json!({"tags": ["reading", "gaming", "coding"]});
109 let encoded = encode_default(&original).unwrap();
110 let decoded: Value = decode_default(&encoded).unwrap();
111 assert_eq!(original, decoded);
112 }
113
114 #[test]
115 fn test_round_trip_tabular() {
116 let original = json!({
117 "users": [
118 {"id": 1, "name": "Alice", "role": "admin"},
119 {"id": 2, "name": "Bob", "role": "user"}
120 ]
121 });
122 let encoded = encode_default(&original).unwrap();
123 let decoded: Value = decode_default(&encoded).unwrap();
124 assert_eq!(original, decoded);
125 }
126
127 #[test]
128 fn test_custom_delimiter() {
129 let original = json!({"tags": ["a", "b", "c"]});
130 let opts = EncodeOptions::new().with_delimiter(Delimiter::Pipe);
131 let encoded = encode(&original, &opts).unwrap();
132 assert!(encoded.contains("|"));
133
134 let decoded: Value = decode_default(&encoded).unwrap();
135 assert_eq!(original, decoded);
136 }
137
138 #[test]
139 fn test_decode_strict_helper() {
140 let input = "items[2]: a,b";
141 assert!(decode_strict::<Value>(input).is_ok());
142
143 let input = "items[3]: a,b";
144 assert!(decode_strict::<Value>(input).is_err());
145 }
146
147 #[test]
148 fn test_normalize_exported() {
149 let value = json!(f64::NAN);
150 let normalized = normalize(value.into());
151 assert_eq!(serde_json::Value::from(normalized), json!(null));
152 }
153
154 #[test]
155 fn test_utilities_exported() {
156 assert!(is_keyword("null"));
157 assert!(is_literal_like("true"));
158 assert_eq!(escape_string("hello\nworld"), "hello\\nworld");
159 assert!(needs_quoting("true", Delimiter::Comma.as_char()));
160 }
161
162 use serde::{
164 Deserialize,
165 Serialize,
166 };
167
168 #[derive(Debug, Serialize, Deserialize, PartialEq)]
169 struct TestUser {
170 name: String,
171 age: u32,
172 active: bool,
173 }
174
175 #[test]
176 fn test_encode_decode_simple_struct() {
177 use crate::{
178 decode_default,
179 encode_default,
180 };
181
182 let user = TestUser {
183 name: "Alice".to_string(),
184 age: 30,
185 active: true,
186 };
187
188 let toon = encode_default(&user).unwrap();
189 assert!(toon.contains("name: Alice"));
190 assert!(toon.contains("age: 30"));
191 assert!(toon.contains("active: true"));
192
193 let decoded: TestUser = decode_default(&toon).unwrap();
194 assert_eq!(user, decoded);
195 }
196
197 #[derive(Debug, Serialize, Deserialize, PartialEq)]
198 struct TestProduct {
199 id: u64,
200 name: String,
201 tags: Vec<String>,
202 }
203
204 #[test]
205 fn test_encode_decode_with_array() {
206 use crate::{
207 decode_default,
208 encode_default,
209 };
210
211 let product = TestProduct {
212 id: 42,
213 name: "Widget".to_string(),
214 tags: vec!["electronics".to_string(), "gadgets".to_string()],
215 };
216
217 let toon = encode_default(&product).unwrap();
218 let decoded: TestProduct = decode_default(&toon).unwrap();
219 assert_eq!(product, decoded);
220 }
221
222 #[test]
223 fn test_encode_decode_vec_of_structs() {
224 use crate::{
225 decode_default,
226 encode_default,
227 };
228
229 let users = vec![
230 TestUser {
231 name: "Alice".to_string(),
232 age: 30,
233 active: true,
234 },
235 TestUser {
236 name: "Bob".to_string(),
237 age: 25,
238 active: false,
239 },
240 ];
241
242 let toon = encode_default(&users).unwrap();
243 let decoded: Vec<TestUser> = decode_default(&toon).unwrap();
244 assert_eq!(users, decoded);
245 }
246
247 #[derive(Debug, Serialize, Deserialize, PartialEq)]
248 struct Nested {
249 outer: OuterStruct,
250 }
251
252 #[derive(Debug, Serialize, Deserialize, PartialEq)]
253 struct OuterStruct {
254 inner: InnerStruct,
255 value: i32,
256 }
257
258 #[derive(Debug, Serialize, Deserialize, PartialEq)]
259 struct InnerStruct {
260 data: String,
261 }
262
263 #[test]
264 fn test_encode_decode_nested_structs() {
265 use crate::{
266 decode_default,
267 encode_default,
268 };
269
270 let nested = Nested {
271 outer: OuterStruct {
272 inner: InnerStruct {
273 data: "test".to_string(),
274 },
275 value: 42,
276 },
277 };
278
279 let toon = encode_default(&nested).unwrap();
280 let decoded: Nested = decode_default(&toon).unwrap();
281 assert_eq!(nested, decoded);
282 }
283}