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