1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Integration tests for Option field handling.
use indoc::indoc;
use serde::{Deserialize, Serialize};
// Test macros
macro_rules! deser_ok {
($name:ident, $ty:ty, $input:expr, $expected:expr) => {
#[test]
fn $name() {
let val: $ty = serde_kdl2::from_str($input).unwrap();
assert_eq!(val, $expected);
}
};
}
// ── Option fields ──────────────────────────────────────────────────────
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct OptionalFields {
required: String,
optional: Option<String>,
}
deser_ok!(
deserialize_option_present,
OptionalFields,
indoc! {r#"
required "hello"
optional "world"
"#},
OptionalFields {
required: String::from("hello"),
optional: Some(String::from("world"))
}
);
deser_ok!(
deserialize_option_absent,
OptionalFields,
r#"required "hello""#,
OptionalFields {
required: String::from("hello"),
optional: None
}
);
deser_ok!(
deserialize_option_null,
OptionalFields,
indoc! {r#"
required "hello"
optional #null
"#},
OptionalFields {
required: String::from("hello"),
optional: None
}
);
#[test]
fn serialize_option() {
let with = OptionalFields {
required: String::from("hello"),
optional: Some(String::from("world")),
};
let output = serde_kdl2::to_string(&with).unwrap();
assert!(output.contains("optional"));
let rt: OptionalFields = serde_kdl2::from_str(&output).unwrap();
assert_eq!(with, rt);
let without = OptionalFields {
required: String::from("hello"),
optional: None,
};
let output = serde_kdl2::to_string(&without).unwrap();
assert!(
!output.contains("optional"),
"None options should not serialize"
);
let rt: OptionalFields = serde_kdl2::from_str(&output).unwrap();
assert_eq!(without, rt);
}