Skip to content

Commit 8fa0f4c

Browse files
authored
feat(derive): Adds ignore_comments option to easily ignore comments in elements and values. (#120)
Practically a duplication of `ignore_whitespace`.
1 parent eb8365b commit 8fa0f4c

File tree

10 files changed

+96
-6
lines changed

10 files changed

+96
-6
lines changed

xmlity-derive/src/de/components/element_loop_accessor.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
derive::DeriveResult,
1212
options::{
1313
records::fields::{AttributeOpts, FieldOpts, FieldValueGroupOpts},
14-
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreWhitespace,
14+
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreComments, IgnoreWhitespace,
1515
},
1616
};
1717

@@ -28,12 +28,14 @@ impl ElementLoopAccessor {
2828
children_order: ElementOrder,
2929
attribute_order: ElementOrder,
3030
ignore_whitespace: IgnoreWhitespace,
31+
ignore_comments: IgnoreComments,
3132
) -> Self {
3233
Self {
3334
children_loop_accessor: SeqLoopAccessor::new(
3435
allow_unknown_children,
3536
children_order,
3637
ignore_whitespace,
38+
ignore_comments,
3739
),
3840
allow_unknown_attributes,
3941
attribute_order,

xmlity-derive/src/de/components/seq_loop_accessor.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,29 @@ use crate::{
1212
derive::{DeriveError, DeriveResult},
1313
options::{
1414
records::fields::{ChildOpts, FieldValueGroupOpts},
15-
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreWhitespace,
15+
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreComments, IgnoreWhitespace,
1616
},
1717
};
1818

1919
pub struct SeqLoopAccessor {
2020
allow_unknown_children: AllowUnknown,
2121
order: ElementOrder,
2222
ignore_whitespace: IgnoreWhitespace,
23+
ignore_comments: IgnoreComments,
2324
}
2425

2526
impl SeqLoopAccessor {
2627
pub fn new(
2728
allow_unknown_children: AllowUnknown,
2829
order: ElementOrder,
2930
ignore_whitespace: IgnoreWhitespace,
31+
ignore_comments: IgnoreComments,
3032
) -> Self {
3133
Self {
3234
allow_unknown_children,
3335
order,
3436
ignore_whitespace,
37+
ignore_comments,
3538
}
3639
}
3740

@@ -79,8 +82,8 @@ impl SeqLoopAccessor {
7982
let Self {
8083
allow_unknown_children,
8184
order,
82-
8385
ignore_whitespace,
86+
ignore_comments,
8487
} = self;
8588

8689
let whitespace_ty: syn::Type = parse_quote! {::xmlity::types::utils::Whitespace};
@@ -98,6 +101,21 @@ impl SeqLoopAccessor {
98101
}
99102
};
100103

104+
let comment_ty: syn::Type = parse_quote! {::xmlity::value::XmlComment};
105+
106+
let ignore_comments_expression: Vec<Stmt> = match ignore_comments {
107+
IgnoreComments::Any => {
108+
parse_quote! {
109+
if let Ok(Some(_)) = ::xmlity::de::SeqAccess::next_element::<#comment_ty>(#seq_access) {
110+
continue;
111+
}
112+
}
113+
}
114+
IgnoreComments::None => {
115+
vec![]
116+
}
117+
};
118+
101119
let ignored_any_ty: syn::Type = parse_quote! {::xmlity::types::utils::IgnoredAny};
102120

103121
match order {
@@ -245,6 +263,7 @@ impl SeqLoopAccessor {
245263
Ok(parse_quote! {
246264
loop {
247265
#(#ignore_whitespace_expression)*
266+
#(#ignore_comments_expression)*
248267
#(#if_statements)*
249268
}
250269
})
@@ -317,6 +336,7 @@ impl SeqLoopAccessor {
317336
Ok(parse_quote! {
318337
loop {
319338
#(#ignore_whitespace_expression)*
339+
#(#ignore_comments_expression)*
320340
#(#field_visits)*
321341
#(#skip_unknown)*
322342
}

xmlity-derive/src/de/deserialize/elements.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
builders::{DeserializeBuilder, VisitorBuilder, VisitorBuilderExt},
1515
components::ElementLoopAccessor,
1616
},
17-
options::{AllowUnknown, ElementOrder, IgnoreWhitespace},
17+
options::{AllowUnknown, ElementOrder, IgnoreComments, IgnoreWhitespace},
1818
DeriveError,
1919
};
2020

@@ -23,6 +23,7 @@ use super::RecordInput;
2323
pub struct RecordDeserializeElementBuilder<'a, T: Fn(syn::Expr) -> syn::Expr> {
2424
pub input: &'a RecordInput<'a, T>,
2525
pub ignore_whitespace: IgnoreWhitespace,
26+
pub ignore_comments: IgnoreComments,
2627
pub required_expanded_name: Option<ExpandedName<'static>>,
2728
pub allow_unknown_attributes: AllowUnknown,
2829
pub allow_unknown_children: AllowUnknown,
@@ -72,6 +73,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> VisitorBuilder for RecordDeserializeElementB
7273
self.children_order,
7374
self.attribute_order,
7475
self.ignore_whitespace,
76+
self.ignore_comments,
7577
)
7678
});
7779

xmlity-derive/src/de/deserialize/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> DeserializeBuilder for RecordDeserializeBuil
4545
DeserializeRootOpts::Element(opts) => RecordDeserializeElementBuilder {
4646
input: self.input,
4747
ignore_whitespace: opts.ignore_whitespace,
48+
ignore_comments: opts.ignore_comments,
4849
required_expanded_name: opts.deserialize_any_name.not().then(|| {
4950
opts.expanded_name(&deserializer_ident.to_string())
5051
.into_owned()
@@ -64,6 +65,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> DeserializeBuilder for RecordDeserializeBuil
6465
input: self.input,
6566
value: opts.value.clone(),
6667
ignore_whitespace: opts.ignore_whitespace,
68+
ignore_comments: opts.ignore_comments,
6769
allow_unknown_children: opts.allow_unknown,
6870
children_order: opts.order,
6971
deserialize_with: opts.deserialize_with(),
@@ -72,6 +74,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> DeserializeBuilder for RecordDeserializeBuil
7274
DeserializeRootOpts::None => RecordDeserializeValueBuilder {
7375
input: self.input,
7476
ignore_whitespace: Default::default(),
77+
ignore_comments: Default::default(),
7578
allow_unknown_children: Default::default(),
7679
children_order: Default::default(),
7780
deserialize_with: None,

xmlity-derive/src/de/deserialize/none.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
self,
1616
fields::{FieldOpts, FieldValueGroupOpts},
1717
},
18-
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreWhitespace,
18+
AllowUnknown, ElementOrder, FieldWithOpts, IgnoreComments, IgnoreWhitespace,
1919
},
2020
DeriveError,
2121
};
@@ -25,6 +25,7 @@ use super::{parse_enum_variant_derive_input, variant::DeserializeVariantBuilder,
2525
pub struct RecordDeserializeValueBuilder<'a, T: Fn(syn::Expr) -> syn::Expr> {
2626
pub input: &'a RecordInput<'a, T>,
2727
pub ignore_whitespace: IgnoreWhitespace,
28+
pub ignore_comments: IgnoreComments,
2829
pub allow_unknown_children: AllowUnknown,
2930
pub children_order: ElementOrder,
3031
pub value: Option<String>,
@@ -213,6 +214,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> VisitorBuilder for RecordDeserializeValueBui
213214
self.allow_unknown_children,
214215
self.children_order,
215216
self.ignore_whitespace,
217+
self.ignore_comments,
216218
)
217219
});
218220

xmlity-derive/src/de/deserialize/single_child_element.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
de::builders::{DeserializeBuilder, VisitorBuilder, VisitorBuilderExt},
1111
options::{
1212
records::fields::{ChildOpts, ElementOpts, FieldOpts, GroupOpts, ValueOpts},
13-
AllowUnknown, ElementOrder, Extendable, FieldWithOpts, IgnoreWhitespace,
13+
AllowUnknown, ElementOrder, Extendable, FieldWithOpts, IgnoreComments, IgnoreWhitespace,
1414
WithExpandedNameExt,
1515
},
1616
DeriveError,
@@ -120,6 +120,7 @@ impl VisitorBuilder for DeserializeSingleChildElementBuilder<'_> {
120120
let builder = RecordDeserializeElementBuilder {
121121
input: &input,
122122
ignore_whitespace: IgnoreWhitespace::default(),
123+
ignore_comments: IgnoreComments::default(),
123124
required_expanded_name: self.required_expanded_name.clone(),
124125
allow_unknown_attributes: AllowUnknown::default(),
125126
allow_unknown_children: AllowUnknown::default(),

xmlity-derive/src/de/deserialize/variant.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl<T: Fn(syn::Expr) -> syn::Expr> DeserializeBuilder for DeserializeVariantBui
7171
records::roots::DeserializeRootOpts::Value(records::roots::RootValueOpts {
7272
value: opts.value,
7373
ignore_whitespace: opts.ignore_whitespace,
74+
ignore_comments: opts.ignore_comments,
7475
allow_unknown: opts.allow_unknown,
7576
order: opts.order,
7677
with: None,

xmlity-derive/src/options.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,23 @@ impl FromMeta for IgnoreWhitespace {
147147
}
148148
}
149149

150+
#[derive(Debug, Clone, Copy, Default, PartialEq)]
151+
pub enum IgnoreComments {
152+
#[default]
153+
Any,
154+
None,
155+
}
156+
157+
impl FromMeta for IgnoreComments {
158+
fn from_string(value: &str) -> darling::Result<Self> {
159+
match value {
160+
"any" => Ok(Self::Any),
161+
"none" => Ok(Self::None),
162+
_ => Err(darling::Error::unknown_value(value)),
163+
}
164+
}
165+
}
166+
150167
#[derive(Debug, Clone, Copy, Default, FromMeta, PartialEq)]
151168
pub enum TextSerializationFormat {
152169
CData,
@@ -226,6 +243,9 @@ pub mod records {
226243
#[darling(default)]
227244
/// Deserialize only
228245
pub ignore_whitespace: IgnoreWhitespace,
246+
#[darling(default)]
247+
/// Deserialize only
248+
pub ignore_comments: IgnoreComments,
229249
}
230250

231251
impl RootElementOpts {
@@ -313,6 +333,9 @@ pub mod records {
313333
pub ignore_whitespace: IgnoreWhitespace,
314334
#[darling(default)]
315335
/// Deserialize only
336+
pub ignore_comments: IgnoreComments,
337+
#[darling(default)]
338+
/// Deserialize only
316339
pub allow_unknown: AllowUnknown,
317340
#[darling(default)]
318341
pub order: ElementOrder,
@@ -1013,6 +1036,9 @@ pub mod enums {
10131036
pub ignore_whitespace: IgnoreWhitespace,
10141037
#[darling(default)]
10151038
/// Deserialize only
1039+
pub ignore_comments: IgnoreComments,
1040+
#[darling(default)]
1041+
/// Deserialize only
10161042
pub allow_unknown: AllowUnknown,
10171043
#[darling(default)]
10181044
pub order: ElementOrder,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use xmlity::{Deserialize, Serialize};
2+
3+
use crate::define_test;
4+
5+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
6+
#[xelement(name = "a")]
7+
pub struct A;
8+
9+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
10+
#[xelement(name = "b", ignore_comments = "any")]
11+
pub struct B(pub A);
12+
13+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
14+
#[xelement(name = "c", ignore_comments = "none")]
15+
pub struct C(pub A);
16+
17+
define_test!(
18+
ignore_any_comments,
19+
[
20+
(B(A), "<b><a/></b>", "<b><!-- comment --><a/></b>"),
21+
(C(A), "<c><a/></c>")
22+
]
23+
);
24+
25+
#[test]
26+
fn error_on_whitespace_in_c() {
27+
let xml = "<c><!-- comment --><a/><!-- comment --></c>";
28+
29+
let err = xmlity_quick_xml::from_str::<C>(xml).unwrap_err();
30+
31+
println!("{err}");
32+
}

xmlity-quick-xml/tests/elements/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod basic;
44
pub mod default;
55
pub mod extendable;
66
pub mod generics;
7+
pub mod ignore_comments;
78
pub mod ignore_whitespace;
89
pub mod inline_attribute_declarations;
910
pub mod inline_blend;

0 commit comments

Comments
 (0)