From 82df2e15b955e9ae7ff0ea9a81f04f95e3307a0a Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Tue, 6 Feb 2024 00:36:58 +0100 Subject: [PATCH] feat!: remove requirement to Default issue #175 #144 --- examples/src/bbigras_namespace.rs | 8 +- examples/src/boscop.rs | 26 +++--- examples/src/ln_dom.rs | 10 +- examples/src/svd.rs | 12 +-- yaserde/src/lib.rs | 4 +- yaserde/tests/default.rs | 2 +- yaserde/tests/deserializer.rs | 97 ++++++++------------ yaserde/tests/flatten.rs | 34 +++---- yaserde/tests/namespace.rs | 7 +- yaserde/tests/option.rs | 42 ++++++++- yaserde_derive/src/de/build_default_value.rs | 22 +++-- yaserde_derive/src/de/expand_struct.rs | 85 +++++++++-------- 12 files changed, 190 insertions(+), 159 deletions(-) diff --git a/examples/src/bbigras_namespace.rs b/examples/src/bbigras_namespace.rs index 41ed061..3a24435 100644 --- a/examples/src/bbigras_namespace.rs +++ b/examples/src/bbigras_namespace.rs @@ -1,7 +1,7 @@ // related to issue https://github.com/media-io/yaserde/issues/15 use yaserde::*; -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] #[yaserde( prefix = "ss", namespace = "x: urn:schemas-microsoft-com:office:excel", @@ -14,7 +14,7 @@ struct Workbook { worksheet: Worksheet, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] #[yaserde( prefix = "ss", namespace = "x: urn:schemas-microsoft-com:office:excel", @@ -29,7 +29,7 @@ struct Worksheet { ws_name: String, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] #[yaserde( prefix = "ss", namespace = "x: urn:schemas-microsoft-com:office:excel", @@ -57,7 +57,7 @@ struct Table { rows: Vec, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] #[yaserde( prefix = "ss", namespace = "x: urn:schemas-microsoft-com:office:excel", diff --git a/examples/src/boscop.rs b/examples/src/boscop.rs index cb94b05..474cbb2 100644 --- a/examples/src/boscop.rs +++ b/examples/src/boscop.rs @@ -1,7 +1,7 @@ // related to issue https://github.com/media-io/yaserde/issues/3 use yaserde::*; -#[derive(Default, Debug, Clone, PartialEq, YaDeserialize)] +#[derive(Debug, Clone, PartialEq, YaDeserialize)] #[yaserde(root = "layout")] pub struct Layout { #[yaserde(attribute)] @@ -17,7 +17,7 @@ pub struct Layout { pub tabpage: Vec, } -#[derive(Default, Debug, Clone, PartialEq, YaDeserialize)] +#[derive(Debug, Clone, PartialEq, YaDeserialize)] pub struct Tabpage { #[yaserde(attribute, rename = "name")] pub named: String, @@ -48,7 +48,7 @@ pub struct Tabpage { pub control: Vec, } -#[derive(Default, Debug, Clone, PartialEq, YaDeserialize)] +#[derive(Debug, Clone, PartialEq, YaDeserialize)] pub struct Control { #[yaserde(attribute, rename = "name")] pub named: String, @@ -63,27 +63,27 @@ pub struct Control { #[yaserde(attribute)] pub color: String, #[yaserde(attribute)] - pub scalef: f32, + pub scalef: Option, #[yaserde(attribute)] - pub scalet: f32, + pub scalet: Option, #[yaserde(attribute)] - pub local_off: bool, + pub local_off: Option, #[yaserde(attribute)] - pub sp: bool, + pub sp: Option, #[yaserde(attribute)] - pub sr: bool, + pub sr: Option, pub midi: Vec, #[yaserde(attribute)] - pub response: String, + pub response: Option, #[yaserde(attribute)] - pub inverted: String, + pub inverted: Option, #[yaserde(attribute)] - pub centered: String, + pub centered: Option, #[yaserde(attribute)] - pub norollover: String, + pub norollover: Option, } -#[derive(Default, Debug, Clone, PartialEq, YaDeserialize)] +#[derive(Debug, Clone, PartialEq, YaDeserialize)] pub struct Midi { #[yaserde(attribute)] pub var: String, diff --git a/examples/src/ln_dom.rs b/examples/src/ln_dom.rs index a1adf3f..baf8154 100644 --- a/examples/src/ln_dom.rs +++ b/examples/src/ln_dom.rs @@ -1,7 +1,7 @@ // related to issue https://github.com/media-io/yaserde/issues/11 use yaserde::*; -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] #[yaserde(root = "DOMSymbolItem")] struct Level { #[yaserde(attribute)] @@ -11,13 +11,13 @@ struct Level { timeline: Timeline, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] struct Timeline { #[yaserde(rename = "DOMTimeline")] timeline: DOMTimeline, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] struct DOMTimeline { #[yaserde(attribute, rename = "name")] named: String, @@ -28,13 +28,13 @@ struct DOMTimeline { layers: Layers, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] struct Layers { #[yaserde(rename = "DOMLayer")] dom_layer: Vec, } -#[derive(YaDeserialize, Default, Debug, PartialEq)] +#[derive(YaDeserialize, Debug, PartialEq)] struct DOMLayer { #[yaserde(attribute, rename = "name")] named: String, diff --git a/examples/src/svd.rs b/examples/src/svd.rs index 74e951f..2a8d72b 100644 --- a/examples/src/svd.rs +++ b/examples/src/svd.rs @@ -1,6 +1,6 @@ use yaserde::YaSerialize; -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] struct CpuDef { #[yaserde(child)] name: String, @@ -18,7 +18,7 @@ struct CpuDef { vendorsystickconfig: bool, } -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] struct Field { name: String, #[yaserde(child)] @@ -29,7 +29,7 @@ struct Field { access: String, } -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] struct Register { #[yaserde(child)] name: String, @@ -49,7 +49,7 @@ struct Register { fields: Vec, } -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] struct Peripheral { #[yaserde(child)] name: String, @@ -69,7 +69,7 @@ struct Peripheral { registers: Vec, } -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] struct DevAttrs { #[yaserde(child)] vendor: String, @@ -103,7 +103,7 @@ struct DevAttrs { peripherals: Vec, } -#[derive(Default, PartialEq, Debug, YaSerialize)] +#[derive(PartialEq, Debug, YaSerialize)] #[yaserde(rename = "device")] struct Device { #[yaserde(attribute)] diff --git a/yaserde/src/lib.rs b/yaserde/src/lib.rs index c1ad4b4..971ce48 100644 --- a/yaserde/src/lib.rs +++ b/yaserde/src/lib.rs @@ -16,7 +16,7 @@ //!```rust //! use yaserde_derive::YaSerialize; //! -//! #[derive(Default, PartialEq, Debug, YaSerialize)] +//! #[derive(PartialEq, Debug, YaSerialize)] //! #[yaserde(rename = "device")] //! struct Device { //! #[yaserde(attribute)] @@ -29,7 +29,7 @@ //! attributes: DeviceAttributes //! } //! -//! #[derive(Default, PartialEq, Debug, YaSerialize)] +//! #[derive(PartialEq, Debug, YaSerialize)] //! struct DeviceAttributes { //! #[yaserde(child)] //! vendor: String, diff --git a/yaserde/tests/default.rs b/yaserde/tests/default.rs index 510e990..2ea9e75 100644 --- a/yaserde/tests/default.rs +++ b/yaserde/tests/default.rs @@ -125,7 +125,7 @@ fn module_inclusion() { init(); mod module { - #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] #[yaserde(rename = "module")] pub struct Module { #[yaserde(attribute)] diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index fbc8612..de218c6 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -115,7 +115,7 @@ fn de_multiple_segments() { init(); mod other_mod { - #[derive(YaDeserialize, PartialEq, Debug, Default)] + #[derive(YaDeserialize, PartialEq, Debug)] pub struct Page { pub number: i32, pub text: String, @@ -216,14 +216,6 @@ fn de_attributes() { subitem: String, } - impl Default for SubStruct { - fn default() -> SubStruct { - SubStruct { - subitem: "".to_string(), - } - } - } - let content = ""; convert_and_validate!( content, @@ -246,7 +238,7 @@ fn de_attributes_custom_deserializer() { use xml::reader::XmlEvent; - #[derive(Debug, Default, PartialEq)] + #[derive(Debug, PartialEq)] pub struct Attributes { pub items: Vec, } @@ -274,7 +266,7 @@ fn de_attributes_custom_deserializer() { } } - #[derive(Default, YaDeserialize, PartialEq, Debug)] + #[derive(YaDeserialize, PartialEq, Debug)] pub struct Struct { #[yaserde(attribute)] attr_option_string: Option, @@ -318,7 +310,7 @@ fn de_attributes_complex() { } } - #[derive(Default, YaDeserialize, PartialEq, Debug)] + #[derive(YaDeserialize, PartialEq, Debug)] pub struct Struct { #[yaserde(attribute)] attr_option_string: Option, @@ -349,7 +341,7 @@ fn de_attributes_complex() { fn de_attributes_with_same_name_field() { init(); - #[derive(Default, YaDeserialize, PartialEq, Debug)] + #[derive(YaDeserialize, PartialEq, Debug)] pub struct Struct { #[yaserde(attribute, rename = "content")] attribute: Option, @@ -406,14 +398,6 @@ fn de_rename() { subitem: String, } - impl Default for SubStruct { - fn default() -> SubStruct { - SubStruct { - subitem: "".to_string(), - } - } - } - let content = "2.0.1"; convert_and_validate!( content, @@ -450,15 +434,6 @@ fn de_text_content_with_attributes() { text: String, } - impl Default for SubStruct { - fn default() -> SubStruct { - SubStruct { - subitem: "".to_string(), - text: "".to_string(), - } - } - } - let content = "text_content"; convert_and_validate!( @@ -525,16 +500,6 @@ fn de_enum() { blue: String, } - impl Default for RGBColor { - fn default() -> RGBColor { - RGBColor { - red: "0".to_string(), - green: "0".to_string(), - blue: "0".to_string(), - } - } - } - let content = "Black"; convert_and_validate!( @@ -593,7 +558,7 @@ fn de_complex_enum() { background: Color, } - #[derive(YaDeserialize, PartialEq, Debug, Default)] + #[derive(YaDeserialize, PartialEq, Debug)] pub struct OtherStruct { fi: i32, se: i32, @@ -824,7 +789,7 @@ fn de_name_issue_21() { fn de_custom() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] struct Date { #[yaserde(rename = "Year")] year: i32, @@ -834,7 +799,7 @@ fn de_custom() { day: Day, } - #[derive(Default, PartialEq, Debug)] + #[derive(PartialEq, Debug)] struct Day { value: i32, } @@ -883,7 +848,7 @@ fn de_custom() { fn de_subitem_issue_12() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { id: i32, } @@ -906,12 +871,12 @@ fn de_subitem_issue_12() { fn de_subitem_issue_12_with_sub() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct SubStruct { id: i32, } - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { id: i32, #[yaserde(rename = "SubStruct")] @@ -939,7 +904,7 @@ fn de_subitem_issue_12_with_sub() { fn de_subitem_issue_12_attributes() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { #[yaserde(attribute)] id: i32, @@ -960,13 +925,13 @@ fn de_subitem_issue_12_attributes() { fn de_subitem_issue_12_attributes_with_sub() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct SubStruct { #[yaserde(attribute)] id: i32, } - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { #[yaserde(attribute)] id: i32, @@ -994,17 +959,23 @@ fn de_subitem_issue_12_attributes_with_sub() { fn de_same_field_name_sub() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct SubStruct { sub: Option, } - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { sub: SubStruct, } - convert_and_validate!("", Struct, Struct::default()); + convert_and_validate!( + "", + Struct, + Struct { + sub: SubStruct { sub: None } + } + ); convert_and_validate!( "42", @@ -1019,22 +990,28 @@ fn de_same_field_name_sub() { fn de_same_field_name_sub_sub() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct SubSubStruct { sub: i32, } - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct SubStruct { sub: Option, } - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Struct { sub: SubStruct, } - convert_and_validate!("", Struct, Struct::default()); + convert_and_validate!( + "", + Struct, + Struct { + sub: SubStruct { sub: None } + } + ); convert_and_validate!( " @@ -1059,7 +1036,7 @@ fn de_same_field_name_sub_sub() { fn de_same_field_name_but_some_other_fields_or_something() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] #[yaserde(rename = "foo")] pub struct FooOuter { pub other: bool, @@ -1067,7 +1044,7 @@ fn de_same_field_name_but_some_other_fields_or_something() { pub foo: Option, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] pub struct FooInner { pub blah: bool, } @@ -1103,7 +1080,7 @@ fn de_attribute_sequence() { Bar, } - #[derive(Default, Debug, PartialEq, YaDeserialize)] + #[derive(Debug, PartialEq, YaDeserialize)] pub struct Outer { #[yaserde(attribute, rename = "seq1")] seq1: Vec, @@ -1130,7 +1107,7 @@ fn de_nested_macro_rules() { macro_rules! float_attrs { ($type:ty) => { - #[derive(Default, PartialEq, Debug, YaDeserialize)] + #[derive(PartialEq, Debug, YaDeserialize)] pub struct Outer { #[yaserde(attribute)] pub inner: Option<$type>, diff --git a/yaserde/tests/flatten.rs b/yaserde/tests/flatten.rs index 34f9c51..f1ffe51 100644 --- a/yaserde/tests/flatten.rs +++ b/yaserde/tests/flatten.rs @@ -11,7 +11,7 @@ fn init() { fn basic_flatten() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct DateTime { #[yaserde(flatten)] date: Date, @@ -20,7 +20,7 @@ fn basic_flatten() { kind: DateKind, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct Date { year: i32, month: i32, @@ -31,18 +31,18 @@ fn basic_flatten() { optional_extra: Option, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] pub struct Extra { week: i32, century: i32, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] pub struct OptionalExtra { lunar_day: i32, } - #[derive(PartialEq, Debug, YaDeserialize, YaSerialize, Default)] + #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] pub enum DateKind { #[yaserde(rename = "holidays")] Holidays(Vec), @@ -150,7 +150,7 @@ fn root_flatten_enum() { fn flatten_attribute() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct HtmlText { #[yaserde(flatten)] text_attributes: TextAttributes, @@ -158,7 +158,7 @@ fn flatten_attribute() { display: String, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct TextAttributes { #[yaserde(attribute)] bold: bool, @@ -166,7 +166,7 @@ fn flatten_attribute() { font: FontAttributes, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] #[yaserde(namespace = "ns: http://www.sample.com/ns/domain")] pub struct FontAttributes { #[yaserde(attribute, prefix = "ns")] @@ -192,20 +192,20 @@ fn flatten_attribute() { fn flatten_attribute_and_child() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct Node { #[yaserde(flatten)] base: Base, value: StringValue, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct Base { #[yaserde(attribute)] id: String, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct StringValue { #[yaserde(text)] string: String, @@ -230,14 +230,14 @@ fn flatten_attribute_and_child() { fn flatten_name_in_unknown_child() { init(); - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] pub struct Node { #[yaserde(flatten)] base: Base, value: Value, } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] struct Base { #[yaserde(attribute)] id: String, @@ -248,15 +248,15 @@ fn flatten_name_in_unknown_child() { Foo(FooStruct), } - #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] - struct FooStruct {} - impl Default for Value { fn default() -> Self { - Self::Foo(FooStruct::default()) + Self::Foo(FooStruct {}) } } + #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] + struct FooStruct {} + let model = Node { base: Base { id: "Foo".to_owned(), diff --git a/yaserde/tests/namespace.rs b/yaserde/tests/namespace.rs index 3c28aed..6996165 100644 --- a/yaserde/tests/namespace.rs +++ b/yaserde/tests/namespace.rs @@ -145,7 +145,7 @@ fn struct_sub_namespace_definition() { fn struct_namespace_nested() { init(); - #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")] struct A { #[yaserde(prefix = "nsa")] @@ -180,7 +180,7 @@ fn struct_namespace_nested() { fn struct_namespace_nested_defined_at_root() { init(); - #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")] struct A { #[yaserde(prefix = "nsa")] @@ -326,13 +326,12 @@ fn struct_default_namespace_via_attribute_with_prefix() { fn enum_namespace() { init(); - #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] #[yaserde( rename = "root", prefix = "ns", namespace = "ns: http://www.sample.com/ns/domain" )] - #[derive(Default)] pub enum XmlStruct { #[yaserde(prefix = "ns")] #[default] diff --git a/yaserde/tests/option.rs b/yaserde/tests/option.rs index 17fa1bd..2166f19 100644 --- a/yaserde/tests/option.rs +++ b/yaserde/tests/option.rs @@ -85,7 +85,7 @@ fn option_struct() { field: SubTest, } - #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] struct SubTest { content: Option, } @@ -111,7 +111,7 @@ fn option_bool_no_crash_on_bad_input() { field: SubTest, } - #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] + #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] struct SubTest { #[yaserde(attribute)] content: Option, @@ -122,3 +122,41 @@ fn option_bool_no_crash_on_bad_input() { assert!(result.is_err()); } + +#[cfg(test)] +mod tests { + use super::*; + use yaserde::de::from_str; + + #[derive(Debug, YaDeserialize, YaSerialize)] + pub struct Car { + #[yaserde(rename = "CarColor")] + color: String, + #[yaserde(rename = "CarBrand")] + brand: String, + } + + #[derive(Debug, YaDeserialize, YaSerialize)] + pub struct Person { + #[yaserde(flatten)] + pub car: Option, + } + + #[test] + fn deserialize_without_car() { + let person = r#" + + brown + 25 + true + false + + "#; + + let person: Person = from_str(person).unwrap(); + + let expected_person = Person { car: None }; + + assert_eq!(person.car.is_none(), expected_person.car.is_none()); + } +} diff --git a/yaserde_derive/src/de/build_default_value.rs b/yaserde_derive/src/de/build_default_value.rs index 3dcd0fb..0ad14e0 100644 --- a/yaserde_derive/src/de/build_default_value.rs +++ b/yaserde_derive/src/de/build_default_value.rs @@ -5,14 +5,24 @@ use quote::quote; pub fn build_default_value( field: &YaSerdeField, field_type: Option, - value: TokenStream, ) -> Option { let label = field.get_value_label(); - let default_value = field - .get_default_function() - .map(|default_function| quote!(#default_function())) - .unwrap_or_else(|| quote!(#value)); + let field_type = field_type + .map(|field_type| quote!(: Option::<#field_type>)) + .unwrap_or_default(); + + Some(quote! { + #[allow(unused_mut)] + let mut #label #field_type = None; + }) +} + +pub fn build_default_vec_value( + field: &YaSerdeField, + field_type: Option, +) -> Option { + let label = field.get_value_label(); let field_type = field_type .map(|field_type| quote!(: #field_type)) @@ -20,6 +30,6 @@ pub fn build_default_value( Some(quote! { #[allow(unused_mut)] - let mut #label #field_type = #default_value; + let mut #label #field_type = vec![]; }) } diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index a33aeab..f002e5c 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -1,7 +1,5 @@ -use crate::{ - common::{Field, YaSerdeAttribute, YaSerdeField}, - de::build_default_value::build_default_value, -}; +use super::build_default_value::{build_default_value, build_default_vec_value}; +use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{DataStruct, Ident}; @@ -24,38 +22,25 @@ pub fn parse( .iter() .map(|field| YaSerdeField::new(field.clone())) .filter_map(|field| match field.get_type() { - Field::FieldStruct { struct_name } => build_default_value( - &field, - Some(quote!(#struct_name)), - quote!(<#struct_name as ::std::default::Default>::default()), - ), - Field::FieldOption { .. } => { - build_default_value(&field, None, quote!(::std::option::Option::None)) - } + Field::FieldStruct { struct_name } => build_default_value(&field, Some(quote!(#struct_name))), + Field::FieldOption { .. } => build_default_value(&field, None), Field::FieldVec { data_type } => match *data_type { - Field::FieldStruct { ref struct_name } => build_default_value( - &field, - Some(quote!(::std::vec::Vec<#struct_name>)), - quote!(::std::vec![]), - ), + Field::FieldStruct { ref struct_name } => { + build_default_vec_value(&field, Some(quote!(::std::vec::Vec<#struct_name>))) + } Field::FieldOption { .. } | Field::FieldVec { .. } => { - unimplemented!("Option or Vec nested in Vec<>"); + unimplemented!("Option or Vec nested in Vec<>"); } simple_type => { let type_token: TokenStream = simple_type.into(); - build_default_value( - &field, - Some(quote!(::std::vec::Vec<#type_token>)), - quote!(::std::vec![]), - ) + build_default_vec_value(&field, Some(quote!(::std::vec::Vec<#type_token>))) } }, simple_type => { let type_token: TokenStream = simple_type.into(); - let value_builder = quote!(<#type_token as ::std::default::Default>::default()); - build_default_value(&field, Some(type_token), value_builder) + build_default_value(&field, Some(type_token)) } }) .collect(); @@ -74,6 +59,9 @@ pub fn parse( let visitor_label = field.get_visitor_ident(Some(&struct_name)); + let xml_opening = format!("<{struct_id}>"); + let xml_closing = format!(""); + Some(quote! { #[allow(non_snake_case, non_camel_case_types)] struct #visitor_label; @@ -84,7 +72,7 @@ pub fn parse( self, v: &str, ) -> ::std::result::Result { - let content = "<".to_string() + #struct_id + ">" + v + ""; + let content = format!("{}{}{}", #xml_opening, v, #xml_closing); ::yaserde::de::from_str(&content) } } @@ -185,12 +173,14 @@ pub fn parse( }; match field.get_type() { - Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }), + Field::FieldStruct { struct_name } => { + visit_struct(struct_name, quote! { = ::std::option::Option::Some(value) }) + } Field::FieldOption { data_type } => { visit_sub(data_type, quote! { = ::std::option::Option::Some(value) }) } Field::FieldVec { data_type } => visit_sub(data_type, quote! { .push(value) }), - simple_type => visit_simple(simple_type, quote! { = value }), + simple_type => visit_simple(simple_type, quote! { = ::std::option::Option::Some(value) }), } }) .collect(); @@ -205,7 +195,7 @@ pub fn parse( match field.get_type() { Field::FieldStruct { .. } => quote! { - #value_label = ::yaserde::de::from_str(&unused_xml_elements)?; + #value_label = Some(::yaserde::de::from_str(&unused_xml_elements)?); }, Field::FieldOption { data_type } => match *data_type { Field::FieldStruct { .. } => quote! { @@ -258,7 +248,7 @@ pub fn parse( Some(quote! { for attr in attributes { if attr.name.local_name == #label_name { - #label = attr.value.to_owned(); + #label = Some(attr.value.to_owned()); } } }) @@ -304,8 +294,8 @@ pub fn parse( &visitor_label, ), }, - Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }), - simple_type => visit_simple(simple_type, quote! { = value }), + Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = Some(value) }), + simple_type => visit_simple(simple_type, quote! { = Some(value) }), } }) .collect(); @@ -318,15 +308,13 @@ pub fn parse( let label = field.get_value_label(); let set_text = |action: &TokenStream| { - if field.is_text_content() { - Some(quote! { #label = #action; }) - } else { - None - } + field + .is_text_content() + .then_some(quote! { #label = #action; }) }; match field.get_type() { - Field::FieldString => set_text("e! { text_content.to_owned() }), + Field::FieldString => set_text("e! { Some(text_content.to_owned()) }), Field::FieldOption { data_type } => match *data_type { Field::FieldString => set_text( "e! { if text_content.is_empty() { None } else { Some(text_content.to_owned()) }}, @@ -350,7 +338,26 @@ pub fn parse( let label = &field.label(); let value_label = field.get_value_label(); - quote! { #label: #value_label, } + match field.get_type() { + Field::FieldOption { .. } | Field::FieldVec { .. } => { + quote! { #label: #value_label, } + } + _ => { + if let Some(default_function) = field.get_default_function() { + quote! { #label: #value_label.unwrap_or_else(|| #default_function()), } + } else { + let error = format!( + "{} is a required field", + label + .as_ref() + .map(|label| label.to_string()) + .unwrap_or_default() + ); + + quote! { #label: #value_label.ok_or_else(|| #error.to_string())?, } + } + } + } }) .collect();