Skip to content

Commit 025e40e

Browse files
authored
Merge pull request #606 from epage/ser
fix(toml): Don't lose data when re-formatting
2 parents 39eea9e + b2879d6 commit 025e40e

File tree

2 files changed

+124
-13
lines changed

2 files changed

+124
-13
lines changed

crates/toml/src/fmt.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[derive(Copy, Clone, Default)]
22
pub(crate) struct DocumentFormatter {
33
pub(crate) multiline_array: bool,
4+
is_value: bool,
45
}
56

67
impl toml_edit::visit_mut::VisitMut for DocumentFormatter {
@@ -9,21 +10,26 @@ impl toml_edit::visit_mut::VisitMut for DocumentFormatter {
910
}
1011

1112
fn visit_item_mut(&mut self, node: &mut toml_edit::Item) {
12-
let other = std::mem::take(node);
13-
let other = match other.into_table().map(toml_edit::Item::Table) {
14-
Ok(i) => i,
15-
Err(i) => i,
16-
};
17-
let other = match other
18-
.into_array_of_tables()
19-
.map(toml_edit::Item::ArrayOfTables)
20-
{
21-
Ok(i) => i,
22-
Err(i) => i,
23-
};
24-
*node = other;
13+
let is_parent_value = self.is_value;
14+
if !is_parent_value {
15+
let other = std::mem::take(node);
16+
let other = match other.into_table().map(toml_edit::Item::Table) {
17+
Ok(i) => i,
18+
Err(i) => i,
19+
};
20+
let other = match other
21+
.into_array_of_tables()
22+
.map(toml_edit::Item::ArrayOfTables)
23+
{
24+
Ok(i) => i,
25+
Err(i) => i,
26+
};
27+
self.is_value = other.is_value();
28+
*node = other;
29+
}
2530

2631
toml_edit::visit_mut::visit_item_mut(self, node);
32+
self.is_value = is_parent_value;
2733
}
2834

2935
fn visit_table_mut(&mut self, node: &mut toml_edit::Table) {

crates/toml/tests/testsuite/serde.rs

+105
Original file line numberDiff line numberDiff line change
@@ -1115,3 +1115,108 @@ fn serialize_array_with_none_value() {
11151115
let err = toml::to_string(&input).unwrap_err();
11161116
snapbox::assert_eq("unsupported None value", err.to_string());
11171117
}
1118+
1119+
#[test]
1120+
fn serialize_array_with_optional_struct_field() {
1121+
#[derive(Debug, Deserialize, Serialize)]
1122+
struct Document {
1123+
values: Vec<OptionalField>,
1124+
}
1125+
1126+
#[derive(Debug, Deserialize, Serialize)]
1127+
struct OptionalField {
1128+
x: u8,
1129+
y: Option<u8>,
1130+
}
1131+
1132+
let input = Document {
1133+
values: vec![
1134+
OptionalField { x: 0, y: Some(4) },
1135+
OptionalField { x: 2, y: Some(5) },
1136+
OptionalField { x: 3, y: Some(7) },
1137+
],
1138+
};
1139+
let expected = "\
1140+
[[values]]
1141+
x = 0
1142+
y = 4
1143+
1144+
[[values]]
1145+
x = 2
1146+
y = 5
1147+
1148+
[[values]]
1149+
x = 3
1150+
y = 7
1151+
";
1152+
let raw = toml::to_string(&input).unwrap();
1153+
snapbox::assert_eq(expected, raw);
1154+
1155+
let input = Document {
1156+
values: vec![
1157+
OptionalField { x: 0, y: Some(4) },
1158+
OptionalField { x: 2, y: None },
1159+
OptionalField { x: 3, y: Some(7) },
1160+
],
1161+
};
1162+
let expected = "\
1163+
[[values]]
1164+
x = 0
1165+
y = 4
1166+
1167+
[[values]]
1168+
x = 2
1169+
1170+
[[values]]
1171+
x = 3
1172+
y = 7
1173+
";
1174+
let raw = toml::to_string(&input).unwrap();
1175+
snapbox::assert_eq(expected, raw);
1176+
}
1177+
1178+
#[test]
1179+
fn serialize_array_with_enum_of_optional_struct_field() {
1180+
#[derive(Debug, Deserialize, Serialize)]
1181+
struct Document {
1182+
values: Vec<Choice>,
1183+
}
1184+
1185+
#[derive(Debug, Deserialize, Serialize)]
1186+
enum Choice {
1187+
Optional(OptionalField),
1188+
Empty,
1189+
}
1190+
1191+
#[derive(Debug, Deserialize, Serialize)]
1192+
struct OptionalField {
1193+
x: u8,
1194+
y: Option<u8>,
1195+
}
1196+
1197+
let input = Document {
1198+
values: vec![
1199+
Choice::Optional(OptionalField { x: 0, y: Some(4) }),
1200+
Choice::Empty,
1201+
Choice::Optional(OptionalField { x: 2, y: Some(5) }),
1202+
Choice::Optional(OptionalField { x: 3, y: Some(7) }),
1203+
],
1204+
};
1205+
let expected = "values = [{ Optional = { x = 0, y = 4 } }, \"Empty\", { Optional = { x = 2, y = 5 } }, { Optional = { x = 3, y = 7 } }]
1206+
";
1207+
let raw = toml::to_string(&input).unwrap();
1208+
snapbox::assert_eq(expected, raw);
1209+
1210+
let input = Document {
1211+
values: vec![
1212+
Choice::Optional(OptionalField { x: 0, y: Some(4) }),
1213+
Choice::Empty,
1214+
Choice::Optional(OptionalField { x: 2, y: None }),
1215+
Choice::Optional(OptionalField { x: 3, y: Some(7) }),
1216+
],
1217+
};
1218+
let expected = "values = [{ Optional = { x = 0, y = 4 } }, \"Empty\", { Optional = { x = 2 } }, { Optional = { x = 3, y = 7 } }]
1219+
";
1220+
let raw = toml::to_string(&input).unwrap();
1221+
snapbox::assert_eq(expected, raw);
1222+
}

0 commit comments

Comments
 (0)