polyxml 0.34.4__tar.gz → 0.34.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyxml-0.34.4 → polyxml-0.34.6}/Cargo.lock +6 -6
- {polyxml-0.34.4 → polyxml-0.34.6}/Cargo.toml +1 -1
- {polyxml-0.34.4 → polyxml-0.34.6}/PKG-INFO +1 -1
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/csharp/mod.rs +232 -55
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/go/mod.rs +1 -7
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/rust/mod.rs +42 -5
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_csharp_codegen.rs +4 -1
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_go_codegen.rs +29 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_qualified_attributes.rs +92 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_rust_codegen.rs +82 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/pyproject.toml +1 -1
- {polyxml-0.34.4 → polyxml-0.34.6}/README.md +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/Cargo.toml +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/README.md +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/benches/tag_dispatch.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/cpp/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/java/codec.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/java/models.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/python/aot.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/python/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/converters.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/error.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/integer.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/ir/chunker.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/ir/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/ir/particle.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/json.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/lib.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/parser.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/schema.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/schema_parser/mod.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/schema_parser/upa.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/serializer.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/transcoder.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/src/value.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/fixtures/lexical_union.xsd +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/fixtures/mixed_content.xsd +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/fixtures/ts_mixed_content_inheritance.xsd +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_adversarial_identifiers.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_any_attribute.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_any_element.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_conformance.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_core.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_json.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_lexical_lists.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_lexical_union_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_mixed_content.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_pattern_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_schema_audit.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_security.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_temporal_union.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_ubl_csharp.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_unbounded_choice.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_upa.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_value_constraints.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-core/tests/test_xsi_type.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/Cargo.toml +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/README.md +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/benches/aot_vs_dataclass.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/src/lib.rs +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_conformance.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_generated_models.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_json.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_mixed_content.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_polyxml.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/crates/polyxml-python/tests/test_xsi_type.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/python/polyxml/AGENT_GUIDE.md +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/python/polyxml/__init__.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/python/polyxml/compat/__init__.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/python/polyxml/compat/xsdata.py +0 -0
- {polyxml-0.34.4 → polyxml-0.34.6}/python/polyxml/py.typed +0 -0
|
@@ -608,7 +608,7 @@ dependencies = [
|
|
|
608
608
|
|
|
609
609
|
[[package]]
|
|
610
610
|
name = "polyxml"
|
|
611
|
-
version = "0.34.
|
|
611
|
+
version = "0.34.6"
|
|
612
612
|
dependencies = [
|
|
613
613
|
"criterion",
|
|
614
614
|
"heck",
|
|
@@ -629,14 +629,14 @@ dependencies = [
|
|
|
629
629
|
|
|
630
630
|
[[package]]
|
|
631
631
|
name = "polyxml-c"
|
|
632
|
-
version = "0.34.
|
|
632
|
+
version = "0.34.6"
|
|
633
633
|
dependencies = [
|
|
634
634
|
"polyxml",
|
|
635
635
|
]
|
|
636
636
|
|
|
637
637
|
[[package]]
|
|
638
638
|
name = "polyxml-cli"
|
|
639
|
-
version = "0.34.
|
|
639
|
+
version = "0.34.6"
|
|
640
640
|
dependencies = [
|
|
641
641
|
"clap",
|
|
642
642
|
"glob",
|
|
@@ -650,7 +650,7 @@ dependencies = [
|
|
|
650
650
|
|
|
651
651
|
[[package]]
|
|
652
652
|
name = "polyxml-js"
|
|
653
|
-
version = "0.34.
|
|
653
|
+
version = "0.34.6"
|
|
654
654
|
dependencies = [
|
|
655
655
|
"napi",
|
|
656
656
|
"napi-build",
|
|
@@ -660,7 +660,7 @@ dependencies = [
|
|
|
660
660
|
|
|
661
661
|
[[package]]
|
|
662
662
|
name = "polyxml-python"
|
|
663
|
-
version = "0.34.
|
|
663
|
+
version = "0.34.6"
|
|
664
664
|
dependencies = [
|
|
665
665
|
"lexical-core",
|
|
666
666
|
"polyxml",
|
|
@@ -670,7 +670,7 @@ dependencies = [
|
|
|
670
670
|
|
|
671
671
|
[[package]]
|
|
672
672
|
name = "polyxml-wasm"
|
|
673
|
-
version = "0.34.
|
|
673
|
+
version = "0.34.6"
|
|
674
674
|
dependencies = [
|
|
675
675
|
"polyxml",
|
|
676
676
|
"quick-xml",
|
|
@@ -277,7 +277,7 @@ fn root_names(ir: &SchemaIR) -> HashMap<QName, String> {
|
|
|
277
277
|
names
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
fn
|
|
280
|
+
fn choice_variant_base(branch: &UnionBranch) -> String {
|
|
281
281
|
let name = to_csharp_type_name(&branch.variant_name);
|
|
282
282
|
if matches!(
|
|
283
283
|
name.as_str(),
|
|
@@ -290,6 +290,33 @@ fn choice_variant_name(branch: &UnionBranch) -> String {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
+
fn choice_variant_names(union: &UnionDef) -> Vec<String> {
|
|
294
|
+
let mut used = HashSet::from([type_ident(&union.qname)]);
|
|
295
|
+
for branch in &union.branches {
|
|
296
|
+
let mut ty = &branch.type_ref;
|
|
297
|
+
while let TypeRef::List(inner) | TypeRef::Boxed(inner) = ty {
|
|
298
|
+
ty = inner;
|
|
299
|
+
}
|
|
300
|
+
if let TypeRef::Named(name) = ty {
|
|
301
|
+
used.insert(type_ident(name));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
union
|
|
305
|
+
.branches
|
|
306
|
+
.iter()
|
|
307
|
+
.map(|branch| {
|
|
308
|
+
let base = choice_variant_base(branch);
|
|
309
|
+
let mut name = base.clone();
|
|
310
|
+
let mut suffix = 2;
|
|
311
|
+
while !used.insert(name.clone()) {
|
|
312
|
+
name = format!("{base}{suffix}");
|
|
313
|
+
suffix += 1;
|
|
314
|
+
}
|
|
315
|
+
name
|
|
316
|
+
})
|
|
317
|
+
.collect()
|
|
318
|
+
}
|
|
319
|
+
|
|
293
320
|
fn simple_value_target(base: &TypeRef, ir: &SchemaIR) -> String {
|
|
294
321
|
let mut target = "Value".to_string();
|
|
295
322
|
let mut current = base;
|
|
@@ -298,6 +325,10 @@ fn simple_value_target(base: &TypeRef, ir: &SchemaIR) -> String {
|
|
|
298
325
|
if !seen.insert(qname.clone()) {
|
|
299
326
|
break;
|
|
300
327
|
}
|
|
328
|
+
if matches!(ir.types.get(qname), Some(TypeDef::Enum(_))) {
|
|
329
|
+
target.push_str(".ToXmlValue()");
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
301
332
|
let Some(TypeDef::Simple(simple)) = ir.types.get(qname) else {
|
|
302
333
|
break;
|
|
303
334
|
};
|
|
@@ -340,6 +371,41 @@ impl CSharpCodegen {
|
|
|
340
371
|
|
|
341
372
|
/// Emits all types in the given SchemaIR as a single C# compilation unit.
|
|
342
373
|
pub fn generate_module(&self, ir: &SchemaIR) -> String {
|
|
374
|
+
let has_duplicate_items = ir.types.values().any(|def| {
|
|
375
|
+
let TypeDef::Union(union) = def else {
|
|
376
|
+
return false;
|
|
377
|
+
};
|
|
378
|
+
if !union.is_mixed_content() {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
let mut seen = HashSet::new();
|
|
382
|
+
union
|
|
383
|
+
.branches
|
|
384
|
+
.iter()
|
|
385
|
+
.any(|b| !seen.insert((&b.xml_name, &b.namespace, &b.type_ref)))
|
|
386
|
+
});
|
|
387
|
+
let mut canonical = if has_duplicate_items {
|
|
388
|
+
std::borrow::Cow::Owned(ir.clone())
|
|
389
|
+
} else {
|
|
390
|
+
std::borrow::Cow::Borrowed(ir)
|
|
391
|
+
};
|
|
392
|
+
if let std::borrow::Cow::Owned(canonical) = &mut canonical {
|
|
393
|
+
for def in canonical.types.values_mut() {
|
|
394
|
+
if let TypeDef::Union(union) = def {
|
|
395
|
+
if union.is_mixed_content() {
|
|
396
|
+
let mut seen = HashSet::new();
|
|
397
|
+
union.branches.retain(|b| {
|
|
398
|
+
seen.insert((
|
|
399
|
+
b.xml_name.clone(),
|
|
400
|
+
b.namespace.clone(),
|
|
401
|
+
b.type_ref.clone(),
|
|
402
|
+
))
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
let ir = canonical.as_ref();
|
|
343
409
|
set_type_name_map(build_type_name_map(ir, to_csharp_type_name));
|
|
344
410
|
let mut out = String::new();
|
|
345
411
|
|
|
@@ -438,6 +504,13 @@ impl CSharpCodegen {
|
|
|
438
504
|
writeln!(out, "}}").unwrap();
|
|
439
505
|
}
|
|
440
506
|
|
|
507
|
+
if out.contains(".Select(") || out.contains(".Any(") {
|
|
508
|
+
out = out.replacen(
|
|
509
|
+
"using System.Collections.Generic;",
|
|
510
|
+
"using System.Collections.Generic;\nusing System.Linq;",
|
|
511
|
+
1,
|
|
512
|
+
);
|
|
513
|
+
}
|
|
441
514
|
out
|
|
442
515
|
}
|
|
443
516
|
|
|
@@ -749,8 +822,7 @@ impl CSharpCodegen {
|
|
|
749
822
|
|
|
750
823
|
// XmlInclude attributes for element-choice polymorphism.
|
|
751
824
|
if self.options.emit_xml_attributes && !u.is_lexical() && !u.is_mixed_content() {
|
|
752
|
-
for
|
|
753
|
-
let variant_name = choice_variant_name(branch);
|
|
825
|
+
for variant_name in choice_variant_names(u) {
|
|
754
826
|
writeln!(
|
|
755
827
|
out,
|
|
756
828
|
"{}[XmlInclude(typeof({}.{}))]",
|
|
@@ -761,14 +833,11 @@ impl CSharpCodegen {
|
|
|
761
833
|
}
|
|
762
834
|
|
|
763
835
|
if !self.options.use_records && self.options.emit_json_attributes {
|
|
764
|
-
for branch in
|
|
836
|
+
for (branch, variant_name) in u.branches.iter().zip(choice_variant_names(u)) {
|
|
765
837
|
writeln!(
|
|
766
838
|
out,
|
|
767
839
|
"{}[JsonDerivedType(typeof({}.{}), {:?})]",
|
|
768
|
-
indent,
|
|
769
|
-
choice_name,
|
|
770
|
-
choice_variant_name(branch),
|
|
771
|
-
branch.xml_name
|
|
840
|
+
indent, choice_name, variant_name, branch.xml_name
|
|
772
841
|
)
|
|
773
842
|
.unwrap();
|
|
774
843
|
}
|
|
@@ -787,8 +856,7 @@ impl CSharpCodegen {
|
|
|
787
856
|
.unwrap();
|
|
788
857
|
writeln!(out, "{}{{", indent).unwrap();
|
|
789
858
|
|
|
790
|
-
for branch in
|
|
791
|
-
let variant_name = choice_variant_name(branch);
|
|
859
|
+
for (branch, variant_name) in u.branches.iter().zip(choice_variant_names(u)) {
|
|
792
860
|
let branch_type = self.context.map_type_ref(&branch.type_ref);
|
|
793
861
|
|
|
794
862
|
if let Some(ref doc) = branch.documentation {
|
|
@@ -864,8 +932,11 @@ impl CSharpCodegen {
|
|
|
864
932
|
);
|
|
865
933
|
let _ = writeln!(out, "{} {{", indent);
|
|
866
934
|
let _ = writeln!(out, "{} var value = text.Trim();", indent);
|
|
867
|
-
|
|
868
|
-
|
|
935
|
+
let mut exhaustive = false;
|
|
936
|
+
for (idx, (branch, variant_name)) in
|
|
937
|
+
u.branches.iter().zip(choice_variant_names(u)).enumerate()
|
|
938
|
+
{
|
|
939
|
+
let variant = variant_name;
|
|
869
940
|
let mapped = self.context.map_type_ref(&branch.type_ref);
|
|
870
941
|
if let TypeRef::Named(qname) = &branch.type_ref {
|
|
871
942
|
if let Some(TypeDef::Enum(def)) = ir.types.get(qname) {
|
|
@@ -894,6 +965,11 @@ impl CSharpCodegen {
|
|
|
894
965
|
} else {
|
|
895
966
|
format!("candidate{}", idx)
|
|
896
967
|
};
|
|
968
|
+
if matches!(base, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Union(nested)) if nested.is_lexical()))
|
|
969
|
+
{
|
|
970
|
+
writeln!(out, "{indent} try {{ var candidate{idx}={base_name}.Parse(value);return new {variant}({wrap}); }}catch(FormatException){{}}").unwrap();
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
897
973
|
if let Some(p) = super::unbounded_integer(&branch.type_ref, ir) {
|
|
898
974
|
let kind = match p {
|
|
899
975
|
PrimitiveType::PositiveInteger => 1,
|
|
@@ -927,6 +1003,8 @@ impl CSharpCodegen {
|
|
|
927
1003
|
"{} {{ var candidate{} = value; return new {}({}); }}",
|
|
928
1004
|
indent, idx, variant, wrap
|
|
929
1005
|
);
|
|
1006
|
+
exhaustive = true;
|
|
1007
|
+
break;
|
|
930
1008
|
}
|
|
931
1009
|
} else if base_name == "bool" {
|
|
932
1010
|
let _ = writeln!(out, "{} if (value == \"true\" || value == \"1\") {{ var candidate{} = true; return new {}({}); }}", indent, idx, variant, wrap);
|
|
@@ -943,16 +1021,18 @@ impl CSharpCodegen {
|
|
|
943
1021
|
);
|
|
944
1022
|
}
|
|
945
1023
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1024
|
+
if !exhaustive {
|
|
1025
|
+
let _ = writeln!(
|
|
1026
|
+
out,
|
|
1027
|
+
"{} throw new FormatException(\"No {} union member accepts the value\");",
|
|
1028
|
+
indent, name
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
951
1031
|
let _ = writeln!(out, "{} }}", indent);
|
|
952
1032
|
let _ = writeln!(out, "{indent} private string? _lexical;\n{indent} private string? _parsedCanonical;\n{indent} private static {name} Preserve({name} member, string lexical) {{ member._parsedCanonical = member.FormatXmlValue(); member._lexical = lexical; return member; }}\n{indent} public string ToXmlString() {{ var canonical = FormatXmlValue(); return canonical == _parsedCanonical ? _lexical! : canonical; }}\n{indent} private string FormatXmlValue() => this switch");
|
|
953
1033
|
let _ = writeln!(out, "{} {{", indent);
|
|
954
|
-
for branch in
|
|
955
|
-
let variant =
|
|
1034
|
+
for (branch, variant_name) in u.branches.iter().zip(choice_variant_names(u)) {
|
|
1035
|
+
let variant = variant_name;
|
|
956
1036
|
let value = if matches!(
|
|
957
1037
|
super::primitive_base(&branch.type_ref, ir),
|
|
958
1038
|
TypeRef::Primitive(PrimitiveType::Date)
|
|
@@ -970,6 +1050,7 @@ impl CSharpCodegen {
|
|
|
970
1050
|
"item.Value.ToString(\"HH:mm:ssK\", System.Globalization.CultureInfo.InvariantCulture)".to_string()
|
|
971
1051
|
} else {
|
|
972
1052
|
match &branch.type_ref {
|
|
1053
|
+
TypeRef::Named(qname) if matches!(ir.types.get(qname), Some(TypeDef::Union(nested)) if nested.is_lexical()) => "item.Value.ToXmlString()".to_string(),
|
|
973
1054
|
TypeRef::Named(qname) if matches!(ir.types.get(qname), Some(TypeDef::Enum(_))) => "item.Value.ToXmlValue()".to_string(),
|
|
974
1055
|
TypeRef::Named(qname) if matches!(ir.types.get(qname), Some(TypeDef::Simple(_))) => "Convert.ToString(item.Value.Value, System.Globalization.CultureInfo.InvariantCulture) ?? \"\"".to_string(),
|
|
975
1056
|
_ => "Convert.ToString(item.Value, System.Globalization.CultureInfo.InvariantCulture) ?? \"\"".to_string(),
|
|
@@ -1031,17 +1112,30 @@ impl CSharpCodegen {
|
|
|
1031
1112
|
"{indent} [XmlIgnore] {json}public {ty} {name} {{get;set;}} = {default};"
|
|
1032
1113
|
)
|
|
1033
1114
|
.unwrap();
|
|
1115
|
+
let optional = ty.ends_with('?');
|
|
1034
1116
|
let validation = if field.cardinality.is_list() {
|
|
1035
|
-
|
|
1036
|
-
|
|
1117
|
+
if optional {
|
|
1118
|
+
format!("{name}?.Select(v=>PolyxmlIntegerLexical.Validate(v,{kind})).ToList()")
|
|
1119
|
+
} else {
|
|
1120
|
+
format!("{name}.Select(v=>PolyxmlIntegerLexical.Validate(v,{kind})).ToList()")
|
|
1121
|
+
}
|
|
1122
|
+
} else if optional {
|
|
1037
1123
|
format!("{name} is null ? null : PolyxmlIntegerLexical.Validate({name},{kind})")
|
|
1124
|
+
} else {
|
|
1125
|
+
format!("PolyxmlIntegerLexical.Validate({name} ?? throw new InvalidOperationException(\"Missing required integer\"),{kind})")
|
|
1038
1126
|
};
|
|
1039
1127
|
let parse = if field.cardinality.is_list() {
|
|
1040
|
-
|
|
1128
|
+
if optional {
|
|
1129
|
+
format!("value?.Select(v=>PolyxmlIntegerLexical.Validate(v,{kind})).ToList()")
|
|
1130
|
+
} else {
|
|
1131
|
+
format!("value.Select(v=>PolyxmlIntegerLexical.Validate(v,{kind})).ToList()")
|
|
1132
|
+
}
|
|
1133
|
+
} else if optional {
|
|
1134
|
+
format!("value is null ? null : PolyxmlIntegerLexical.Validate(value,{kind})")
|
|
1041
1135
|
} else {
|
|
1042
|
-
format!("
|
|
1136
|
+
format!("PolyxmlIntegerLexical.Validate(value,{kind})")
|
|
1043
1137
|
};
|
|
1044
|
-
writeln!(out,"{indent} {attrs}{ignore}public {ty} {name}Xml {{ get => {validation}
|
|
1138
|
+
writeln!(out,"{indent} {attrs}{ignore}public {ty} {name}Xml {{ get => {validation}; set => {name} = {parse}; }}").unwrap();
|
|
1045
1139
|
true
|
|
1046
1140
|
}
|
|
1047
1141
|
|
|
@@ -1166,6 +1260,22 @@ impl CSharpCodegen {
|
|
|
1166
1260
|
}
|
|
1167
1261
|
let ty = self.map_field_type(field, ir);
|
|
1168
1262
|
let base = ty.trim_end_matches('?');
|
|
1263
|
+
let can_be_null = ty.ends_with('?')
|
|
1264
|
+
|| !(matches!(
|
|
1265
|
+
base,
|
|
1266
|
+
"bool"
|
|
1267
|
+
| "byte"
|
|
1268
|
+
| "sbyte"
|
|
1269
|
+
| "short"
|
|
1270
|
+
| "ushort"
|
|
1271
|
+
| "int"
|
|
1272
|
+
| "uint"
|
|
1273
|
+
| "long"
|
|
1274
|
+
| "ulong"
|
|
1275
|
+
| "float"
|
|
1276
|
+
| "double"
|
|
1277
|
+
| "decimal"
|
|
1278
|
+
) || matches!(&field.type_ref, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Enum(_)))));
|
|
1169
1279
|
let namespace = field
|
|
1170
1280
|
.namespace
|
|
1171
1281
|
.as_ref()
|
|
@@ -1199,8 +1309,13 @@ impl CSharpCodegen {
|
|
|
1199
1309
|
} else {
|
|
1200
1310
|
format!("object.Equals(value, {expected})")
|
|
1201
1311
|
};
|
|
1312
|
+
let present = if ty.ends_with('?') {
|
|
1313
|
+
"value is not null && "
|
|
1314
|
+
} else {
|
|
1315
|
+
""
|
|
1316
|
+
};
|
|
1202
1317
|
writeln!(out, "{indent} private {ty} _{name} = {initial};
|
|
1203
|
-
{indent} [XmlIgnore] public {ty} {name} {{ get => _{name}; set {{ if (
|
|
1318
|
+
{indent} [XmlIgnore] public {ty} {name} {{ get => _{name}; set {{ if ({present}!({equal})) throw new System.ComponentModel.DataAnnotations.ValidationException(\"Fixed value constraint violated for {name}\"); _{name} = value; }} }}").unwrap();
|
|
1204
1319
|
} else {
|
|
1205
1320
|
let initial = if field.kind == FieldKind::Attribute {
|
|
1206
1321
|
parse(&format!("{default:?}"))
|
|
@@ -1224,10 +1339,15 @@ impl CSharpCodegen {
|
|
|
1224
1339
|
field.xml_name
|
|
1225
1340
|
)
|
|
1226
1341
|
.unwrap();
|
|
1342
|
+
let null_guard = if can_be_null {
|
|
1343
|
+
format!("if ({name} is null) return null; ")
|
|
1344
|
+
} else {
|
|
1345
|
+
String::new()
|
|
1346
|
+
};
|
|
1227
1347
|
if let Some(kind) = integer_kind {
|
|
1228
|
-
writeln!(out,"{indent} get {{
|
|
1348
|
+
writeln!(out,"{indent} get {{ {null_guard} return PolyxmlIntegerLexical.Validate({name},{kind}); }}").unwrap();
|
|
1229
1349
|
} else {
|
|
1230
|
-
writeln!(out, "{indent} get {{
|
|
1350
|
+
writeln!(out, "{indent} get {{ {null_guard}var writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); new XmlSerializer(typeof({base}), new XmlRootAttribute(\"value\")).Serialize(writer, {name}); return System.Xml.Linq.XDocument.Parse(writer.ToString()).Root!.Value; }}").unwrap();
|
|
1231
1351
|
}
|
|
1232
1352
|
let text = if field.kind == FieldKind::Attribute {
|
|
1233
1353
|
"value".into()
|
|
@@ -1274,12 +1394,24 @@ impl CSharpCodegen {
|
|
|
1274
1394
|
};
|
|
1275
1395
|
let item_name = &prop_names[item_index];
|
|
1276
1396
|
let union_name = type_ident(&union.qname);
|
|
1397
|
+
let text_variant = union
|
|
1398
|
+
.branches
|
|
1399
|
+
.iter()
|
|
1400
|
+
.zip(choice_variant_names(union))
|
|
1401
|
+
.find(|(branch, _)| branch.xml_name == "#text")
|
|
1402
|
+
.map(|(_, name)| name)
|
|
1403
|
+
.expect("mixed union text branch");
|
|
1277
1404
|
let class_kind = if self.options.use_records {
|
|
1278
1405
|
"record"
|
|
1279
1406
|
} else {
|
|
1280
1407
|
"class"
|
|
1281
1408
|
};
|
|
1282
|
-
let
|
|
1409
|
+
let validation_interface = if self.options.emit_validation {
|
|
1410
|
+
", IValidatableObject"
|
|
1411
|
+
} else {
|
|
1412
|
+
""
|
|
1413
|
+
};
|
|
1414
|
+
let _ = writeln!(out, "{indent}public {class_kind} {struct_name} : System.Xml.Serialization.IXmlSerializable{validation_interface}\n{indent}{{");
|
|
1283
1415
|
for (field, prop_name) in s.fields.iter().zip(prop_names) {
|
|
1284
1416
|
let ty = self.map_field_type(field, ir);
|
|
1285
1417
|
if field.kind == FieldKind::Attribute {
|
|
@@ -1307,22 +1439,23 @@ impl CSharpCodegen {
|
|
|
1307
1439
|
if field.kind == FieldKind::Attribute {
|
|
1308
1440
|
let ty = self.map_field_type(field, ir);
|
|
1309
1441
|
let base_type = ty.trim_end_matches('?');
|
|
1310
|
-
let
|
|
1442
|
+
let namespace = field.namespace.as_deref().unwrap_or("");
|
|
1443
|
+
let _ = writeln!(out, " {{ var raw = reader.GetAttribute({:?}, {namespace:?}); if (raw is not null) {prop_name} = ({ty})new XmlSerializer(typeof({base_type}), new XmlRootAttribute(\"value\")).Deserialize(new System.IO.StringReader(\"<value>\" + System.Security.SecurityElement.Escape(raw) + \"</value>\"))!; }}", field.xml_name);
|
|
1311
1444
|
}
|
|
1312
1445
|
}
|
|
1313
1446
|
let _ = writeln!(out, " {item_name} = new List<{union_name}>();");
|
|
1314
1447
|
out.push_str(" bool empty = reader.IsEmptyElement;\n reader.ReadStartElement();\n if (empty) return;\n while (reader.NodeType != System.Xml.XmlNodeType.EndElement && !reader.EOF)\n {\n switch (reader.NodeType)\n {\n case System.Xml.XmlNodeType.Text:\n case System.Xml.XmlNodeType.CDATA:\n case System.Xml.XmlNodeType.Whitespace:\n case System.Xml.XmlNodeType.SignificantWhitespace:\n");
|
|
1315
1448
|
let _ = writeln!(
|
|
1316
1449
|
out,
|
|
1317
|
-
" {item_name}.Add(new {union_name}.
|
|
1450
|
+
" {item_name}.Add(new {union_name}.{text_variant}(reader.Value));"
|
|
1318
1451
|
);
|
|
1319
1452
|
out.push_str(" reader.Read();\n break;\n case System.Xml.XmlNodeType.Element:\n switch (reader.LocalName)\n {\n");
|
|
1320
|
-
for branch in
|
|
1453
|
+
for (branch, variant) in union.branches.iter().zip(choice_variant_names(union)) {
|
|
1321
1454
|
if branch.xml_name == "#text" {
|
|
1322
1455
|
continue;
|
|
1323
1456
|
}
|
|
1324
1457
|
let branch_type = self.context.map_type_ref(&branch.type_ref);
|
|
1325
|
-
|
|
1458
|
+
|
|
1326
1459
|
let namespace = branch.namespace.as_deref().unwrap_or("");
|
|
1327
1460
|
let _ = writeln!(out, " case {:?}:\n {{ var serializer = new XmlSerializer(typeof({branch_type}), new XmlRootAttribute({:?}) {{ Namespace = {:?} }}); {item_name}.Add(new {union_name}.{variant}(({branch_type})serializer.Deserialize(reader)!)); break; }}", branch.xml_name, branch.xml_name, namespace);
|
|
1328
1461
|
}
|
|
@@ -1334,12 +1467,34 @@ impl CSharpCodegen {
|
|
|
1334
1467
|
);
|
|
1335
1468
|
for (field, prop_name) in s.fields.iter().zip(prop_names) {
|
|
1336
1469
|
if field.kind == FieldKind::Attribute {
|
|
1337
|
-
let
|
|
1470
|
+
let ty = self.map_field_type(field, ir);
|
|
1471
|
+
let base = ty.trim_end_matches('?');
|
|
1472
|
+
let is_value = matches!(
|
|
1473
|
+
base,
|
|
1474
|
+
"bool"
|
|
1475
|
+
| "byte"
|
|
1476
|
+
| "sbyte"
|
|
1477
|
+
| "short"
|
|
1478
|
+
| "ushort"
|
|
1479
|
+
| "int"
|
|
1480
|
+
| "uint"
|
|
1481
|
+
| "long"
|
|
1482
|
+
| "ulong"
|
|
1483
|
+
| "float"
|
|
1484
|
+
| "double"
|
|
1485
|
+
| "decimal"
|
|
1486
|
+
) || matches!(&field.type_ref, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Enum(_))));
|
|
1487
|
+
let guard = if ty.ends_with('?') || !is_value {
|
|
1488
|
+
format!("if ({prop_name} is not null) ")
|
|
1489
|
+
} else {
|
|
1490
|
+
String::new()
|
|
1491
|
+
};
|
|
1492
|
+
let namespace = field.namespace.as_deref().unwrap_or("");
|
|
1493
|
+
let _ = writeln!(out, " {guard}{{ var text = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); new XmlSerializer(typeof({base}), new XmlRootAttribute(\"value\")).Serialize(text, {prop_name}); writer.WriteAttributeString({:?}, {namespace:?}, System.Xml.Linq.XDocument.Parse(text.ToString()).Root!.Value); }}", field.xml_name);
|
|
1338
1494
|
}
|
|
1339
1495
|
}
|
|
1340
1496
|
let _ = writeln!(out, " foreach (var item in {item_name})\n {{\n switch (item)\n {{");
|
|
1341
|
-
for branch in
|
|
1342
|
-
let variant = choice_variant_name(branch);
|
|
1497
|
+
for (branch, variant) in union.branches.iter().zip(choice_variant_names(union)) {
|
|
1343
1498
|
if branch.xml_name == "#text" {
|
|
1344
1499
|
let _ = writeln!(out, " case {union_name}.{variant} text: writer.WriteString(text.Value); break;");
|
|
1345
1500
|
} else {
|
|
@@ -1349,10 +1504,27 @@ impl CSharpCodegen {
|
|
|
1349
1504
|
}
|
|
1350
1505
|
}
|
|
1351
1506
|
out.push_str(" }\n }\n");
|
|
1352
|
-
let _ = writeln!(out, "{indent} }}
|
|
1507
|
+
let _ = writeln!(out, "{indent} }}");
|
|
1508
|
+
if self.options.emit_validation {
|
|
1509
|
+
self.emit_struct_validator(out, s, ir, prop_names, indent);
|
|
1510
|
+
}
|
|
1511
|
+
let _ = writeln!(out, "{indent}}}\n");
|
|
1353
1512
|
}
|
|
1354
1513
|
|
|
1355
1514
|
fn emit_struct(&self, out: &mut String, s: &StructDef, ir: &SchemaIR, indent: &str) {
|
|
1515
|
+
if ir.has_ordered_content(s) && s.base_type.is_some() {
|
|
1516
|
+
let fields = super::flatten_fields(s, ir);
|
|
1517
|
+
if fields.iter().any(|f| {
|
|
1518
|
+
matches!(&f.type_ref, TypeRef::Named(q)
|
|
1519
|
+
if matches!(ir.types.get(q), Some(TypeDef::Union(u)) if u.is_mixed_content()))
|
|
1520
|
+
}) {
|
|
1521
|
+
let mut flat = s.clone();
|
|
1522
|
+
flat.fields = fields.into_iter().cloned().collect();
|
|
1523
|
+
flat.base_type = None;
|
|
1524
|
+
self.emit_struct(out, &flat, ir, indent);
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1356
1528
|
// Reuse inherited XML members. Simple-content IR includes a text
|
|
1357
1529
|
// placeholder for non-inheriting targets; restrictions can repeat
|
|
1358
1530
|
// attribute declarations already present on the generated base.
|
|
@@ -1436,7 +1608,13 @@ impl CSharpCodegen {
|
|
|
1436
1608
|
.map(|f| self.unique_property_name(&f.name, &mut seen_props, Some(&struct_name)))
|
|
1437
1609
|
.collect();
|
|
1438
1610
|
|
|
1439
|
-
if ir.has_ordered_content(s)
|
|
1611
|
+
if ir.has_ordered_content(s)
|
|
1612
|
+
&& self.options.emit_xml_attributes
|
|
1613
|
+
&& s.fields.iter().any(|f| {
|
|
1614
|
+
matches!(&f.type_ref, TypeRef::Named(q)
|
|
1615
|
+
if matches!(ir.types.get(q), Some(TypeDef::Union(u)) if u.is_mixed_content()))
|
|
1616
|
+
})
|
|
1617
|
+
{
|
|
1440
1618
|
self.emit_mixed_struct(out, s, ir, indent, &struct_name, &prop_names);
|
|
1441
1619
|
return;
|
|
1442
1620
|
}
|
|
@@ -1769,16 +1947,15 @@ impl CSharpCodegen {
|
|
|
1769
1947
|
.as_ref()
|
|
1770
1948
|
.map(|b| matches!(ir.types.get(b), Some(TypeDef::Struct(_))))
|
|
1771
1949
|
.unwrap_or(false);
|
|
1772
|
-
let new_kw = if
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
}
|
|
1950
|
+
let new_kw = if self.options.use_records
|
|
1951
|
+
&& self.options.record_kind == CSharpRecordKind::Struct
|
|
1952
|
+
&& !ir.has_ordered_content(s)
|
|
1953
|
+
{
|
|
1954
|
+
""
|
|
1778
1955
|
} else if has_struct_base {
|
|
1779
|
-
"
|
|
1956
|
+
"override "
|
|
1780
1957
|
} else {
|
|
1781
|
-
""
|
|
1958
|
+
"virtual "
|
|
1782
1959
|
};
|
|
1783
1960
|
writeln!(
|
|
1784
1961
|
out,
|
|
@@ -1788,7 +1965,7 @@ impl CSharpCodegen {
|
|
|
1788
1965
|
.unwrap();
|
|
1789
1966
|
writeln!(out, "{} {{", indent).unwrap();
|
|
1790
1967
|
|
|
1791
|
-
if
|
|
1968
|
+
if has_struct_base {
|
|
1792
1969
|
writeln!(out, "{} foreach (var result in base.Validate(validationContext)) yield return result;", indent).unwrap();
|
|
1793
1970
|
}
|
|
1794
1971
|
let mut has_checks = false;
|
|
@@ -1872,11 +2049,12 @@ impl CSharpCodegen {
|
|
|
1872
2049
|
target: &str,
|
|
1873
2050
|
indent: &str,
|
|
1874
2051
|
) {
|
|
2052
|
+
let member = target.split('.').next().unwrap_or(target);
|
|
1875
2053
|
if let Some(min_len) = facets.min_length {
|
|
1876
2054
|
writeln!(
|
|
1877
2055
|
out,
|
|
1878
2056
|
"{}if ({}.Length < {}) yield return new ValidationResult(\"{} length must be >= {}\", [nameof({})]);",
|
|
1879
|
-
indent, target, min_len, target, min_len,
|
|
2057
|
+
indent, target, min_len, target, min_len, member
|
|
1880
2058
|
)
|
|
1881
2059
|
.unwrap();
|
|
1882
2060
|
}
|
|
@@ -1884,7 +2062,7 @@ impl CSharpCodegen {
|
|
|
1884
2062
|
writeln!(
|
|
1885
2063
|
out,
|
|
1886
2064
|
"{}if ({}.Length > {}) yield return new ValidationResult(\"{} length must be <= {}\", [nameof({})]);",
|
|
1887
|
-
indent, target, max_len, target, max_len,
|
|
2065
|
+
indent, target, max_len, target, max_len, member
|
|
1888
2066
|
)
|
|
1889
2067
|
.unwrap();
|
|
1890
2068
|
}
|
|
@@ -1895,7 +2073,7 @@ impl CSharpCodegen {
|
|
|
1895
2073
|
writeln!(
|
|
1896
2074
|
out,
|
|
1897
2075
|
"{}if (!Regex.IsMatch({}.ToString() ?? \"\", \"{}\")) yield return new ValidationResult(\"{} does not match pattern {}\", [nameof({})]);",
|
|
1898
|
-
indent, target, escaped, target, escaped,
|
|
2076
|
+
indent, target, escaped, target, escaped, member
|
|
1899
2077
|
)
|
|
1900
2078
|
.unwrap();
|
|
1901
2079
|
}
|
|
@@ -1903,7 +2081,7 @@ impl CSharpCodegen {
|
|
|
1903
2081
|
writeln!(
|
|
1904
2082
|
out,
|
|
1905
2083
|
"{}if ({} < {}) yield return new ValidationResult(\"{} must be >= {}\", [nameof({})]);",
|
|
1906
|
-
indent, target, min_inc, target, min_inc,
|
|
2084
|
+
indent, target, min_inc, target, min_inc, member
|
|
1907
2085
|
)
|
|
1908
2086
|
.unwrap();
|
|
1909
2087
|
}
|
|
@@ -1911,7 +2089,7 @@ impl CSharpCodegen {
|
|
|
1911
2089
|
writeln!(
|
|
1912
2090
|
out,
|
|
1913
2091
|
"{}if ({} > {}) yield return new ValidationResult(\"{} must be <= {}\", [nameof({})]);",
|
|
1914
|
-
indent, target, max_inc, target, max_inc,
|
|
2092
|
+
indent, target, max_inc, target, max_inc, member
|
|
1915
2093
|
)
|
|
1916
2094
|
.unwrap();
|
|
1917
2095
|
}
|
|
@@ -1919,7 +2097,7 @@ impl CSharpCodegen {
|
|
|
1919
2097
|
writeln!(
|
|
1920
2098
|
out,
|
|
1921
2099
|
"{}if ({} <= {}) yield return new ValidationResult(\"{} must be > {}\", [nameof({})]);",
|
|
1922
|
-
indent, target, min_exc, target, min_exc,
|
|
2100
|
+
indent, target, min_exc, target, min_exc, member
|
|
1923
2101
|
)
|
|
1924
2102
|
.unwrap();
|
|
1925
2103
|
}
|
|
@@ -1927,7 +2105,7 @@ impl CSharpCodegen {
|
|
|
1927
2105
|
writeln!(
|
|
1928
2106
|
out,
|
|
1929
2107
|
"{}if ({} >= {}) yield return new ValidationResult(\"{} must be < {}\", [nameof({})]);",
|
|
1930
|
-
indent, target, max_exc, target, max_exc,
|
|
2108
|
+
indent, target, max_exc, target, max_exc, member
|
|
1931
2109
|
)
|
|
1932
2110
|
.unwrap();
|
|
1933
2111
|
}
|
|
@@ -1984,8 +2162,7 @@ impl CSharpCodegen {
|
|
|
1984
2162
|
if let Some(qname) = named_qname {
|
|
1985
2163
|
if let Some(TypeDef::Union(u)) = ir.types.get(qname) {
|
|
1986
2164
|
let choice_name = type_ident(&u.qname);
|
|
1987
|
-
for branch in
|
|
1988
|
-
let variant_name = choice_variant_name(branch);
|
|
2165
|
+
for (branch, variant_name) in u.branches.iter().zip(choice_variant_names(u)) {
|
|
1989
2166
|
parts.push(format!(
|
|
1990
2167
|
"XmlElement(\"{}\", typeof({}.{}), Namespace = {:?})",
|
|
1991
2168
|
branch.xml_name,
|
|
@@ -419,13 +419,7 @@ impl GoCodegen {
|
|
|
419
419
|
if body.contains("xml.") {
|
|
420
420
|
imports.push("\"encoding/xml\"");
|
|
421
421
|
}
|
|
422
|
-
if
|
|
423
|
-
&& (!ir.content_models.is_empty()
|
|
424
|
-
|| ir
|
|
425
|
-
.types
|
|
426
|
-
.values()
|
|
427
|
-
.any(|def| matches!(def, TypeDef::Struct(s) if ir.has_ordered_content(s))))
|
|
428
|
-
{
|
|
422
|
+
if body.contains("bytes.") {
|
|
429
423
|
imports.push("\"bytes\"");
|
|
430
424
|
}
|
|
431
425
|
if has_fmt || body.contains("fmt.") {
|