Skip to content

Commit 2adc731

Browse files
Merge pull request #207 from jondo2010/serialize_vec_as_attribute
Support serializing Vec<T> as an attribute
2 parents 2018ee5 + e6f27d9 commit 2adc731

14 files changed

Lines changed: 429 additions & 46 deletions

File tree

examples/src/bbigras_namespace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(dead_code)]
12
// related to issue https://github.com/media-io/yaserde/issues/15
23
use yaserde::*;
34

examples/src/boscop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(dead_code)]
12
// related to issue https://github.com/media-io/yaserde/issues/3
23
use yaserde::*;
34

examples/src/generic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(dead_code)]
12
use yaserde::*;
23

34
#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]

examples/src/ln_dom.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(dead_code)]
12
// related to issue https://github.com/media-io/yaserde/issues/11
23
use yaserde::*;
34

examples/src/same_element_different_namespaces.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(dead_code)]
12
// related to issue https://github.com/media-io/yaserde/issues/186
23
use yaserde::*;
34

examples/tests/data/svd.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="UTF-8"?>
22
<device schemaversion="foo" xmlns="http://www.w3.org/2001/XMLSchema-instance" xsnonamespaceschemalocation="CMSIS-SVD.xsd">
33
<devattributes>
44
<vendor>Renesas</vendor>

yaserde/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ macro_rules! serialize_and_validate {
328328
log::debug!("serialize_and_validate @ {}:{}", file!(), line!());
329329
let data: Result<String, String> = yaserde::ser::to_string(&$model);
330330

331-
let content = &format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, $content);
331+
let content = &format!(r#"<?xml version="1.0" encoding="UTF-8"?>{}"#, $content);
332332
assert_eq!(
333333
data,
334334
Ok(content.split("\n").map(|s| s.trim()).collect::<String>())

yaserde/tests/cdata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn test_cdata_serialization() {
1818
msgdata: "<tag>Some unescaped content</tag>".to_string(),
1919
};
2020
let xml_output = yaserde::ser::to_string(&test_data).expect("Serialization failed");
21-
let expected_output = r#"<?xml version="1.0" encoding="utf-8"?><teststruct><msgdata><![CDATA[<tag>Some unescaped content</tag>]]></msgdata></teststruct>"#;
21+
let expected_output = r#"<?xml version="1.0" encoding="UTF-8"?><teststruct><msgdata><![CDATA[<tag>Some unescaped content</tag>]]></msgdata></teststruct>"#;
2222
assert_eq!(xml_output, expected_output);
2323
}
2424

yaserde/tests/deserializer.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ fn de_enum() {
493493
Black,
494494
}
495495

496+
#[allow(dead_code)]
496497
#[derive(YaDeserialize, PartialEq, Debug)]
497498
pub struct RGBColor {
498499
red: String,
@@ -1101,13 +1102,84 @@ fn de_attribute_sequence() {
11011102
deserialize_and_validate!(content, model, Outer);
11021103
}
11031104

1105+
#[test]
1106+
fn de_option_vec_as_attribute() {
1107+
init();
1108+
1109+
#[derive(YaDeserialize, PartialEq, Debug)]
1110+
#[yaserde(rename = "TestTag")]
1111+
pub struct OptionVecAttributeStruct {
1112+
#[yaserde(attribute = true)]
1113+
field: Option<Vec<u32>>,
1114+
}
1115+
1116+
// Test case 1: Some(populated_vec) -> field="1 2 3 4"
1117+
let content = r#"<TestTag field="1 2 3 4" />"#;
1118+
let model = OptionVecAttributeStruct {
1119+
field: Some(vec![1, 2, 3, 4]),
1120+
};
1121+
convert_and_validate!(content, OptionVecAttributeStruct, model);
1122+
1123+
// Test case 2: Some(empty_vec) -> field=""
1124+
let content = r#"<TestTag field="" />"#;
1125+
let model = OptionVecAttributeStruct {
1126+
field: Some(vec![]),
1127+
};
1128+
convert_and_validate!(content, OptionVecAttributeStruct, model);
1129+
1130+
// Test case 3: None -> no attribute
1131+
let content = r#"<TestTag />"#;
1132+
let model = OptionVecAttributeStruct { field: None };
1133+
convert_and_validate!(content, OptionVecAttributeStruct, model);
1134+
}
1135+
1136+
#[test]
1137+
fn de_option_vec_enum_as_attribute() {
1138+
init();
1139+
1140+
#[derive(YaDeserialize, PartialEq, Debug, Default)]
1141+
enum MyEnum {
1142+
#[default]
1143+
One,
1144+
Two,
1145+
Three,
1146+
}
1147+
1148+
#[derive(YaDeserialize, PartialEq, Debug)]
1149+
#[yaserde(rename = "TestTag")]
1150+
pub struct OptionVecEnumAttributeStruct {
1151+
#[yaserde(attribute = true)]
1152+
field: Option<Vec<MyEnum>>,
1153+
}
1154+
1155+
// Test case 1: Some(vec![MyEnum::One, MyEnum::Two, MyEnum::Three]) -> field="One Two Three"
1156+
let content = r#"<TestTag field="One Two Three" />"#;
1157+
let model = OptionVecEnumAttributeStruct {
1158+
field: Some(vec![MyEnum::One, MyEnum::Two, MyEnum::Three]),
1159+
};
1160+
convert_and_validate!(content, OptionVecEnumAttributeStruct, model);
1161+
1162+
// Test case 2: Some(empty_vec) -> field=""
1163+
let content = r#"<TestTag field="" />"#;
1164+
let model = OptionVecEnumAttributeStruct {
1165+
field: Some(vec![]),
1166+
};
1167+
convert_and_validate!(content, OptionVecEnumAttributeStruct, model);
1168+
1169+
// Test case 3: None -> no attribute
1170+
let content = r#"<TestTag />"#;
1171+
let model = OptionVecEnumAttributeStruct { field: None };
1172+
convert_and_validate!(content, OptionVecEnumAttributeStruct, model);
1173+
}
1174+
11041175
#[test]
11051176
fn de_nested_macro_rules() {
11061177
init();
11071178

11081179
macro_rules! float_attrs {
11091180
($type:ty) => {
11101181
#[derive(PartialEq, Debug, YaDeserialize)]
1182+
#[allow(dead_code)]
11111183
pub struct Outer {
11121184
#[yaserde(attribute = true)]
11131185
pub inner: Option<$type>,

yaserde/tests/serializer.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,138 @@ fn ser_custom() {
415415
let content = "<Date><Year>2020</Year><Month>1</Month><DoubleDay>10</DoubleDay></Date>";
416416
serialize_and_validate!(model, content);
417417
}
418+
419+
#[test]
420+
fn ser_vec_as_attribute() {
421+
#[derive(YaSerialize, PartialEq, Debug)]
422+
#[yaserde(rename = "TestTag")]
423+
pub struct VecAttributeStruct {
424+
#[yaserde(attribute = true)]
425+
numbers: Vec<u32>,
426+
#[yaserde(attribute = true)]
427+
strings: Vec<String>,
428+
#[yaserde(attribute = true)]
429+
bools: Vec<bool>,
430+
#[yaserde(attribute = true)]
431+
floats: Vec<f64>,
432+
}
433+
434+
let model = VecAttributeStruct {
435+
numbers: vec![1, 2, 3, 4],
436+
strings: vec!["hello".to_string(), "world".to_string()],
437+
bools: vec![true, false, true],
438+
floats: vec![6.14, 2.71],
439+
};
440+
441+
// Expected XML with space-separated attribute values
442+
let content = r#"<TestTag numbers="1 2 3 4" strings="hello world" bools="true false true" floats="6.14 2.71" />"#;
443+
serialize_and_validate!(model, content);
444+
}
445+
446+
#[test]
447+
fn ser_vec_as_attribute_nested() {
448+
#[derive(YaSerialize, PartialEq, Debug)]
449+
#[yaserde(rename = "TestTag")]
450+
struct VecAttributeStruct {
451+
#[yaserde(attribute = true)]
452+
outer: Vec<Inner>,
453+
}
454+
455+
#[derive(YaSerialize, PartialEq, Debug)]
456+
#[yaserde(rename = "TestTag")]
457+
enum Inner {
458+
One,
459+
Two,
460+
}
461+
462+
let model = VecAttributeStruct {
463+
outer: vec![Inner::One, Inner::Two],
464+
};
465+
466+
// Expected XML with space-separated attribute values
467+
let content = r#"<TestTag outer="One Two" />"#;
468+
serialize_and_validate!(model, content);
469+
}
470+
471+
#[test]
472+
fn ser_option_vec_as_attribute() {
473+
#[derive(YaSerialize, PartialEq, Debug)]
474+
#[yaserde(rename = "TestTag")]
475+
pub struct OptionVecAttributeStruct {
476+
#[yaserde(attribute = true)]
477+
field: Option<Vec<u32>>,
478+
}
479+
480+
// Expected XML with space-separated attribute values
481+
let model = OptionVecAttributeStruct {
482+
field: Some(vec![1, 2, 3, 4]),
483+
};
484+
let content = r#"<TestTag field="1 2 3 4" />"#;
485+
serialize_and_validate!(model, content);
486+
487+
let model = OptionVecAttributeStruct {
488+
field: Some(vec![]),
489+
};
490+
let content = r#"<TestTag field="" />"#;
491+
serialize_and_validate!(model, content);
492+
493+
// Expected XML with no attributes
494+
let model = OptionVecAttributeStruct { field: None };
495+
let content = r#"<TestTag />"#;
496+
serialize_and_validate!(model, content);
497+
}
498+
499+
#[test]
500+
fn ser_option_vec_complex() {
501+
#[derive(Default, PartialEq, Debug, YaSerialize)]
502+
pub struct Start {
503+
#[yaserde(attribute = true, rename = "value")]
504+
pub value: String,
505+
}
506+
507+
#[derive(Default, PartialEq, Debug, YaSerialize)]
508+
#[yaserde(rename = "String")]
509+
pub struct StringStruct {
510+
#[yaserde(rename = "Start")]
511+
pub start: Option<Vec<Start>>,
512+
}
513+
514+
// Test serialization with Some(vec)
515+
let model = StringStruct {
516+
start: Some(vec![
517+
Start {
518+
value: "First string".to_string(),
519+
},
520+
Start {
521+
value: "Second string".to_string(),
522+
},
523+
Start {
524+
value: "Third string".to_string(),
525+
},
526+
]),
527+
};
528+
529+
let content = yaserde::ser::to_string(&model).unwrap();
530+
assert_eq!(
531+
content,
532+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><String><Start value=\"First string\" /><Start value=\"Second string\" /><Start value=\"Third string\" /></String>"
533+
);
534+
535+
// Test serialization with None
536+
let model_none = StringStruct { start: None };
537+
let content_none = yaserde::ser::to_string(&model_none).unwrap();
538+
assert_eq!(
539+
content_none,
540+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><String />"
541+
);
542+
543+
// Test serialization with Some(empty_vec)
544+
let model_empty = StringStruct {
545+
start: Some(vec![]),
546+
};
547+
let content_empty = yaserde::ser::to_string(&model_empty).unwrap();
548+
assert_eq!(
549+
content_empty,
550+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><String />"
551+
);
552+
}

0 commit comments

Comments
 (0)