polyxml 0.15.0__tar.gz → 0.16.0__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.
Files changed (54) hide show
  1. {polyxml-0.15.0 → polyxml-0.16.0}/Cargo.lock +5 -5
  2. {polyxml-0.15.0 → polyxml-0.16.0}/Cargo.toml +1 -1
  3. {polyxml-0.15.0 → polyxml-0.16.0}/PKG-INFO +1 -1
  4. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/cpp/mod.rs +156 -4
  5. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/mod.rs +1 -1
  6. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_cpp_codegen.rs +140 -2
  7. {polyxml-0.15.0 → polyxml-0.16.0}/pyproject.toml +1 -1
  8. {polyxml-0.15.0 → polyxml-0.16.0}/README.md +0 -0
  9. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/Cargo.toml +0 -0
  10. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/README.md +0 -0
  11. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
  12. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/csharp/mod.rs +0 -0
  13. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/go/mod.rs +0 -0
  14. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
  15. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/python/mod.rs +0 -0
  16. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/rust/mod.rs +0 -0
  17. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
  18. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/converters.rs +0 -0
  19. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/error.rs +0 -0
  20. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/ir/mod.rs +0 -0
  21. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
  22. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/json.rs +0 -0
  23. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/lib.rs +0 -0
  24. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/parser.rs +0 -0
  25. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/schema.rs +0 -0
  26. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/schema_parser/mod.rs +0 -0
  27. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/serializer.rs +0 -0
  28. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/transcoder.rs +0 -0
  29. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/src/value.rs +0 -0
  30. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_conformance.rs +0 -0
  31. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_core.rs +0 -0
  32. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_csharp_codegen.rs +0 -0
  33. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
  34. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
  35. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_json.rs +0 -0
  36. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
  37. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
  38. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
  39. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
  40. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_security.rs +0 -0
  41. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
  42. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
  43. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/Cargo.toml +0 -0
  44. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/README.md +0 -0
  45. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/src/lib.rs +0 -0
  46. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/tests/test_conformance.py +0 -0
  47. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/tests/test_generated_models.py +0 -0
  48. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/tests/test_json.py +0 -0
  49. {polyxml-0.15.0 → polyxml-0.16.0}/crates/polyxml-python/tests/test_polyxml.py +0 -0
  50. {polyxml-0.15.0 → polyxml-0.16.0}/python/polyxml/AGENT_GUIDE.md +0 -0
  51. {polyxml-0.15.0 → polyxml-0.16.0}/python/polyxml/__init__.py +0 -0
  52. {polyxml-0.15.0 → polyxml-0.16.0}/python/polyxml/compat/__init__.py +0 -0
  53. {polyxml-0.15.0 → polyxml-0.16.0}/python/polyxml/compat/xsdata.py +0 -0
  54. {polyxml-0.15.0 → polyxml-0.16.0}/python/polyxml/py.typed +0 -0
@@ -549,7 +549,7 @@ dependencies = [
549
549
 
550
550
  [[package]]
551
551
  name = "polyxml"
552
- version = "0.15.0"
552
+ version = "0.16.0"
553
553
  dependencies = [
554
554
  "criterion",
555
555
  "heck",
@@ -567,14 +567,14 @@ dependencies = [
567
567
 
568
568
  [[package]]
569
569
  name = "polyxml-c"
570
- version = "0.15.0"
570
+ version = "0.16.0"
571
571
  dependencies = [
572
572
  "polyxml",
573
573
  ]
574
574
 
575
575
  [[package]]
576
576
  name = "polyxml-cli"
577
- version = "0.15.0"
577
+ version = "0.16.0"
578
578
  dependencies = [
579
579
  "clap",
580
580
  "glob",
@@ -588,7 +588,7 @@ dependencies = [
588
588
 
589
589
  [[package]]
590
590
  name = "polyxml-js"
591
- version = "0.15.0"
591
+ version = "0.16.0"
592
592
  dependencies = [
593
593
  "napi",
594
594
  "napi-build",
@@ -598,7 +598,7 @@ dependencies = [
598
598
 
599
599
  [[package]]
600
600
  name = "polyxml-python"
601
- version = "0.15.0"
601
+ version = "0.16.0"
602
602
  dependencies = [
603
603
  "lexical-core",
604
604
  "polyxml",
@@ -3,7 +3,7 @@ resolver = "2"
3
3
  members = ["crates/polyxml-core", "crates/polyxml-python"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.15.0"
6
+ version = "0.16.0"
7
7
  edition = "2021"
8
8
  rust-version = "1.80"
9
9
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyxml
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -20,6 +20,40 @@ pub enum CppMode {
20
20
  Module,
21
21
  }
22
22
 
23
+ impl CppMode {
24
+ pub fn from_str_loose(s: &str) -> Option<Self> {
25
+ match s.to_lowercase().trim() {
26
+ "header" | "headeronly" | "header-only" | "headers" | "hpp" => Some(Self::HeaderOnly),
27
+ "module" | "modules" | "cppm" | "c++20-modules" => Some(Self::Module),
28
+ _ => None,
29
+ }
30
+ }
31
+ }
32
+
33
+ /// Target backend for C++ serialization/reflection metadata.
34
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
35
+ pub enum CppBackend {
36
+ /// Zero-dependency standard C++20 (default)
37
+ #[default]
38
+ Standard,
39
+ /// Glaze compile-time reflectionless serde (`glz::meta`)
40
+ Glaze,
41
+ }
42
+
43
+ impl CppBackend {
44
+ pub fn from_str_loose(s: &str) -> Option<Self> {
45
+ match s.to_lowercase().trim() {
46
+ "standard" | "std" | "default" | "none" => Some(Self::Standard),
47
+ "glaze" | "glz" => Some(Self::Glaze),
48
+ _ => None,
49
+ }
50
+ }
51
+
52
+ pub fn is_glaze(self) -> bool {
53
+ matches!(self, Self::Glaze)
54
+ }
55
+ }
56
+
23
57
  /// Options configuring modern C++20/C++23 code generation.
24
58
  #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25
59
  pub struct CppOptions {
@@ -27,6 +61,8 @@ pub struct CppOptions {
27
61
  pub namespace: String,
28
62
  /// Header-only (.hpp) or C++20 Module (.cppm) mode (default: HeaderOnly)
29
63
  pub mode: CppMode,
64
+ /// Target serialization and metadata backend (default: Standard)
65
+ pub backend: CppBackend,
30
66
  /// Standard language dialect (default: "c++20")
31
67
  pub standard: String,
32
68
  /// Emit C++20 defaulted equality operators `bool operator==(const T&) const = default;` (default: true)
@@ -48,6 +84,7 @@ impl Default for CppOptions {
48
84
  Self {
49
85
  namespace: "polyxml::generated".to_string(),
50
86
  mode: CppMode::HeaderOnly,
87
+ backend: CppBackend::Standard,
51
88
  standard: "c++20".to_string(),
52
89
  emit_equality_operators: true,
53
90
  emit_enum_converters: true,
@@ -229,6 +266,11 @@ impl CppCodegen {
229
266
  self.emit_root_aliases(&mut out, ir);
230
267
 
231
268
  writeln!(out, "\n}} // namespace {}", ns).unwrap();
269
+
270
+ if self.options.backend.is_glaze() {
271
+ self.emit_glaze_meta(&mut out, ir);
272
+ }
273
+
232
274
  out
233
275
  }
234
276
 
@@ -261,6 +303,11 @@ impl CppCodegen {
261
303
  self.emit_root_aliases(&mut out, ir);
262
304
 
263
305
  writeln!(out, "\n}} // namespace {}", ns).unwrap();
306
+
307
+ if self.options.backend.is_glaze() {
308
+ self.emit_glaze_meta(&mut out, ir);
309
+ }
310
+
264
311
  out
265
312
  }
266
313
 
@@ -314,8 +361,26 @@ impl CppCodegen {
314
361
  /// Generate CMakeLists.txt definition for integration via add_subdirectory or FetchContent.
315
362
  pub fn generate_cmake(&self, project_name: &str) -> String {
316
363
  let safe_name = AsSnakeCase(project_name).to_string();
317
- format!(
318
- r#"cmake_minimum_required(VERSION 3.20)
364
+ if self.options.mode == CppMode::Module {
365
+ format!(
366
+ r#"cmake_minimum_required(VERSION 3.28)
367
+ project({safe_name}_models LANGUAGES CXX)
368
+
369
+ set(CMAKE_CXX_STANDARD 20)
370
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
371
+
372
+ add_library({safe_name})
373
+ target_sources({safe_name}
374
+ PUBLIC
375
+ FILE_SET CXX_MODULES FILES
376
+ {safe_name}.cppm
377
+ )
378
+ target_compile_features({safe_name} PUBLIC cxx_std_20)
379
+ "#
380
+ )
381
+ } else {
382
+ format!(
383
+ r#"cmake_minimum_required(VERSION 3.20)
319
384
  project({safe_name}_models LANGUAGES CXX)
320
385
 
321
386
  set(CMAKE_CXX_STANDARD 20)
@@ -328,7 +393,8 @@ target_include_directories({safe_name} INTERFACE
328
393
  )
329
394
  target_compile_features({safe_name} INTERFACE cxx_std_20)
330
395
  "#
331
- )
396
+ )
397
+ }
332
398
  }
333
399
 
334
400
  /// Generate standalone PolyXMLConfig.cmake for `find_package(PolyXML)`.
@@ -372,7 +438,93 @@ endif()
372
438
  writeln!(out, "#include <string>").unwrap();
373
439
  writeln!(out, "#include <string_view>").unwrap();
374
440
  writeln!(out, "#include <variant>").unwrap();
375
- writeln!(out, "#include <vector>\n").unwrap();
441
+ writeln!(out, "#include <vector>").unwrap();
442
+
443
+ if self.options.backend.is_glaze() {
444
+ writeln!(out, "#include <glaze/glaze.hpp>").unwrap();
445
+ }
446
+ writeln!(out).unwrap();
447
+ }
448
+
449
+ fn emit_glaze_meta(&self, out: &mut String, ir: &SchemaIR) {
450
+ let ns = to_cpp_namespace(&self.options.namespace);
451
+ writeln!(out, "\n// Glaze compile-time reflection metadata\n").unwrap();
452
+
453
+ // 1. Enums
454
+ for type_def in ir.types.values() {
455
+ if let TypeDef::Enum(enum_def) = type_def {
456
+ let enum_name = to_cpp_type_name(&enum_def.qname.local);
457
+ let full_type = format!("{}::{}", ns, enum_name);
458
+ writeln!(out, "template <>").unwrap();
459
+ writeln!(out, "struct glz::meta<{}> {{", full_type).unwrap();
460
+ writeln!(out, " using T = {};", full_type).unwrap();
461
+ if enum_def.variants.is_empty() {
462
+ writeln!(out, " static constexpr auto value = enumerate();").unwrap();
463
+ } else {
464
+ writeln!(out, " static constexpr auto value = enumerate(").unwrap();
465
+ for (i, v) in enum_def.variants.iter().enumerate() {
466
+ let var_name = to_cpp_enum_variant(&v.name);
467
+ let comma = if i + 1 < enum_def.variants.len() {
468
+ ","
469
+ } else {
470
+ ""
471
+ };
472
+ writeln!(out, " {:?}, T::{}{}", v.value, var_name, comma).unwrap();
473
+ }
474
+ writeln!(out, " );").unwrap();
475
+ }
476
+ writeln!(out, "}};\n").unwrap();
477
+ }
478
+ }
479
+
480
+ // 2. Structs
481
+ let sorted_qnames = self.topological_sort_types(ir);
482
+ for qname in sorted_qnames {
483
+ if let Some(TypeDef::Struct(s)) = ir.types.get(&qname) {
484
+ let struct_name = to_cpp_type_name(&s.qname.local);
485
+ let full_type = format!("{}::{}", ns, struct_name);
486
+ writeln!(out, "template <>").unwrap();
487
+ writeln!(out, "struct glz::meta<{}> {{", full_type).unwrap();
488
+ writeln!(out, " using T = {};", full_type).unwrap();
489
+
490
+ let mut field_bindings = Vec::new();
491
+
492
+ // Check for simple_content_base "value"
493
+ if let Some(ref base_qname) = s.base_type {
494
+ let has_value_field = s
495
+ .fields
496
+ .iter()
497
+ .any(|f| f.name == "value" || f.kind == crate::ir::FieldKind::Text);
498
+ if !has_value_field
499
+ && (PrimitiveType::from_xsd_name(&base_qname.local).is_some()
500
+ || matches!(ir.types.get(base_qname), Some(TypeDef::Simple(_))))
501
+ {
502
+ field_bindings.push(r#""value", &T::value"#.to_string());
503
+ }
504
+ }
505
+
506
+ for f in &s.fields {
507
+ let field_name = to_cpp_field_name(&f.name);
508
+ field_bindings.push(format!("{:?}, &T::{}", f.xml_name, field_name));
509
+ }
510
+
511
+ if field_bindings.is_empty() {
512
+ writeln!(out, " static constexpr auto value = object();").unwrap();
513
+ } else {
514
+ writeln!(out, " static constexpr auto value = object(").unwrap();
515
+ for (i, fb) in field_bindings.iter().enumerate() {
516
+ let comma = if i + 1 < field_bindings.len() {
517
+ ","
518
+ } else {
519
+ ""
520
+ };
521
+ writeln!(out, " {}{}", fb, comma).unwrap();
522
+ }
523
+ writeln!(out, " );").unwrap();
524
+ }
525
+ writeln!(out, "}};\n").unwrap();
526
+ }
527
+ }
376
528
  }
377
529
 
378
530
  fn emit_utilities(&self, out: &mut String) {
@@ -13,7 +13,7 @@ pub mod python;
13
13
  pub mod rust;
14
14
  pub mod typescript;
15
15
 
16
- pub use cpp::{CppCodegen, CppMode, CppOptions};
16
+ pub use cpp::{CppBackend, CppCodegen, CppMode, CppOptions};
17
17
  pub use csharp::{CSharpCodegen, CSharpOptions, CSharpRecordKind};
18
18
  pub use go::{GoCodegen, GoOptions};
19
19
  pub use java::{JavaBackend, JavaCodegen, JavaOptions};
@@ -3,8 +3,8 @@ use std::process::Command;
3
3
  use tempfile::tempdir;
4
4
 
5
5
  use polyxml::codegen::cpp::{
6
- to_cpp_enum_variant, to_cpp_field_name, to_cpp_namespace, to_cpp_type_name, CppCodegen,
7
- CppMode, CppOptions,
6
+ to_cpp_enum_variant, to_cpp_field_name, to_cpp_namespace, to_cpp_type_name, CppBackend,
7
+ CppCodegen, CppMode, CppOptions,
8
8
  };
9
9
  use polyxml::ir::{
10
10
  Cardinality, EnumDef, EnumValue, FieldDef, FieldKind, PrimitiveType, QName, RestrictionFacets,
@@ -154,6 +154,7 @@ fn test_cpp_struct_and_enum_codegen_compilation() {
154
154
  let options = CppOptions {
155
155
  namespace: "crm::models".to_string(),
156
156
  mode: CppMode::HeaderOnly,
157
+ backend: CppBackend::Standard,
157
158
  standard: "c++20".to_string(),
158
159
  emit_equality_operators: true,
159
160
  emit_enum_converters: true,
@@ -862,3 +863,140 @@ int main() {
862
863
  "ISO 20022 test binary execution failed"
863
864
  );
864
865
  }
866
+
867
+ #[test]
868
+ fn test_cpp_mode_and_backend_from_str_loose() {
869
+ assert_eq!(CppMode::from_str_loose("header"), Some(CppMode::HeaderOnly));
870
+ assert_eq!(
871
+ CppMode::from_str_loose("header-only"),
872
+ Some(CppMode::HeaderOnly)
873
+ );
874
+ assert_eq!(CppMode::from_str_loose("hpp"), Some(CppMode::HeaderOnly));
875
+ assert_eq!(CppMode::from_str_loose("modules"), Some(CppMode::Module));
876
+ assert_eq!(CppMode::from_str_loose("module"), Some(CppMode::Module));
877
+ assert_eq!(CppMode::from_str_loose("cppm"), Some(CppMode::Module));
878
+ assert_eq!(CppMode::from_str_loose("unknown"), None);
879
+
880
+ assert_eq!(
881
+ CppBackend::from_str_loose("standard"),
882
+ Some(CppBackend::Standard)
883
+ );
884
+ assert_eq!(
885
+ CppBackend::from_str_loose("default"),
886
+ Some(CppBackend::Standard)
887
+ );
888
+ assert_eq!(CppBackend::from_str_loose("glaze"), Some(CppBackend::Glaze));
889
+ assert_eq!(CppBackend::from_str_loose("glz"), Some(CppBackend::Glaze));
890
+ assert_eq!(CppBackend::from_str_loose("unknown"), None);
891
+ }
892
+
893
+ #[test]
894
+ fn test_cpp_glaze_backend_meta_generation() {
895
+ let mut ir = SchemaIR::new().with_target_namespace("https://example.com/shop");
896
+
897
+ // Enum
898
+ ir.add_type(TypeDef::Enum(EnumDef {
899
+ qname: QName::new(Some("https://example.com/shop"), "OrderStatus"),
900
+ base_type: TypeRef::Primitive(PrimitiveType::String),
901
+ variants: vec![
902
+ EnumValue {
903
+ name: "pending".into(),
904
+ value: "pending".into(),
905
+ documentation: None,
906
+ },
907
+ EnumValue {
908
+ name: "shipped".into(),
909
+ value: "shipped".into(),
910
+ documentation: None,
911
+ },
912
+ ],
913
+ documentation: None,
914
+ }));
915
+
916
+ // Struct
917
+ ir.add_type(TypeDef::Struct(StructDef {
918
+ qname: QName::new(Some("https://example.com/shop"), "Order"),
919
+ base_type: None,
920
+ is_abstract: false,
921
+ fields: vec![
922
+ FieldDef {
923
+ name: "order_id".into(),
924
+ xml_name: "orderId".into(),
925
+ namespace: None,
926
+ kind: FieldKind::Element,
927
+ type_ref: TypeRef::Primitive(PrimitiveType::Int),
928
+ cardinality: Cardinality::required_one(),
929
+ nillable: false,
930
+ default_value: None,
931
+ fixed_value: None,
932
+ documentation: None,
933
+ facets: None,
934
+ is_cycle_cut: false,
935
+ },
936
+ FieldDef {
937
+ name: "status".into(),
938
+ xml_name: "status".into(),
939
+ namespace: None,
940
+ kind: FieldKind::Element,
941
+ type_ref: TypeRef::Named(QName::new(
942
+ Some("https://example.com/shop"),
943
+ "OrderStatus",
944
+ )),
945
+ cardinality: Cardinality::required_one(),
946
+ nillable: false,
947
+ default_value: None,
948
+ fixed_value: None,
949
+ documentation: None,
950
+ facets: None,
951
+ is_cycle_cut: false,
952
+ },
953
+ ],
954
+ documentation: None,
955
+ }));
956
+
957
+ let options = CppOptions {
958
+ namespace: "shop".to_string(),
959
+ backend: CppBackend::Glaze,
960
+ ..Default::default()
961
+ };
962
+
963
+ let codegen = CppCodegen::new(options);
964
+ let header_code = codegen.generate_header(&ir);
965
+
966
+ // Includes Glaze header
967
+ assert!(header_code.contains("#include <glaze/glaze.hpp>"));
968
+
969
+ // Glaze enum reflection
970
+ assert!(header_code.contains("template <>"));
971
+ assert!(header_code.contains("struct glz::meta<shop::OrderStatus> {"));
972
+ assert!(header_code.contains("using T = shop::OrderStatus;"));
973
+ assert!(header_code.contains("static constexpr auto value = enumerate("));
974
+ assert!(header_code.contains("\"pending\", T::Pending,"));
975
+ assert!(header_code.contains("\"shipped\", T::Shipped"));
976
+
977
+ // Glaze struct reflection
978
+ assert!(header_code.contains("struct glz::meta<shop::Order> {"));
979
+ assert!(header_code.contains("using T = shop::Order;"));
980
+ assert!(header_code.contains("static constexpr auto value = object("));
981
+ assert!(header_code.contains("\"orderId\", &T::order_id,"));
982
+ assert!(header_code.contains("\"status\", &T::status"));
983
+ }
984
+
985
+ #[test]
986
+ fn test_cpp_cmake_modules_file_set() {
987
+ let _ir = SchemaIR::new();
988
+
989
+ let options = CppOptions {
990
+ namespace: "telemetry".to_string(),
991
+ mode: CppMode::Module,
992
+ emit_cmake: true,
993
+ ..Default::default()
994
+ };
995
+
996
+ let codegen = CppCodegen::new(options);
997
+ let cmake = codegen.generate_cmake("telemetry");
998
+
999
+ assert!(cmake.contains("cmake_minimum_required(VERSION 3.28)"));
1000
+ assert!(cmake.contains("FILE_SET CXX_MODULES FILES"));
1001
+ assert!(cmake.contains("telemetry.cppm"));
1002
+ }
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "polyxml"
7
- version = "0.15.0"
7
+ version = "0.16.0"
8
8
  description = "High-performance, polyglot XML data-binding engine built in Rust"
9
9
  authors = [
10
10
  { name = "Bailey Nguyen", email = "bailey.tan.nguyen@gmail.com" }
File without changes