pysof 0.1.32__tar.gz → 0.1.42__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 (266) hide show
  1. pysof-0.1.42/Cargo.toml +40 -0
  2. {pysof-0.1.32 → pysof-0.1.42}/PKG-INFO +6 -4
  3. {pysof-0.1.32/crates/pysof → pysof-0.1.42}/README.md +3 -3
  4. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/Cargo.toml +5 -4
  5. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/build.rs +81 -16
  6. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/lib.rs +180 -14
  7. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/parameters.rs +2 -13
  8. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/r4.rs +1097 -199
  9. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/r4b.rs +1072 -195
  10. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/r5.rs +1214 -236
  11. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/r6.rs +1446 -1951
  12. pysof-0.1.42/crates/fhir/tests/test_contained_stack.rs +113 -0
  13. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir-macro/Cargo.toml +2 -1
  14. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir-macro/src/lib.rs +586 -245
  15. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/Cargo.toml +3 -2
  16. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/README.md +68 -6
  17. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/benches/server_benches.rs +0 -2
  18. pysof-0.1.42/crates/fhirpath/src/debug_trace.rs +175 -0
  19. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/evaluator.rs +194 -14
  20. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/handlers.rs +167 -35
  21. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/lib.rs +5 -5
  22. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/models.rs +120 -7
  23. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/parse_debug.rs +257 -1
  24. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/parser.rs +1036 -34
  25. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/context_trace_test.rs +4 -2
  26. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/tests-fhir-r5.xml +13 -5
  27. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/debug_datetime_boundary.rs +2 -2
  28. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/debug_string_boundary_tests.rs +3 -1
  29. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/evaluator_tests.rs +269 -10
  30. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/fhir_boundary_tests.rs +7 -5
  31. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/join_function_test.rs +15 -5
  32. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/r4_tests.rs +3 -2
  33. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/r5_tests.rs +12 -0
  34. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/reference_key_debug.rs +1 -1
  35. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath-support/Cargo.toml +1 -0
  36. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath-support/src/lib.rs +20 -2
  37. pysof-0.1.42/crates/pysof/Cargo.toml +41 -0
  38. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/PYPI_CHECKLIST.md +4 -4
  39. {pysof-0.1.32 → pysof-0.1.42/crates/pysof}/README.md +3 -3
  40. {pysof-0.1.32 → pysof-0.1.42/crates/pysof}/src/lib.rs +9 -9
  41. pysof-0.1.42/crates/serde-support/Cargo.toml +17 -0
  42. pysof-0.1.42/crates/serde-support/src/lib.rs +684 -0
  43. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/Cargo.toml +4 -3
  44. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/README.md +51 -1
  45. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/cli.rs +4 -3
  46. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/data_source.rs +15 -10
  47. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/server.rs +4 -3
  48. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_boolean_test.rs +3 -1
  49. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_datetime_instant_constants.rs +3 -1
  50. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_extension_function.rs +1 -1
  51. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_extension_macro_fix.rs +1 -1
  52. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_fhir_resource_structure.rs +2 -2
  53. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_inequality.rs +1 -1
  54. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_instant_constant.rs +3 -1
  55. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/extension_debug_test.rs +1 -1
  56. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_boolean_constant_debug2.rs +1 -1
  57. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_boolean_constant_debug3.rs +1 -1
  58. {pysof-0.1.32 → pysof-0.1.42}/pyproject.toml +1 -0
  59. {pysof-0.1.32/crates/pysof → pysof-0.1.42}/src/lib.rs +9 -9
  60. pysof-0.1.32/Cargo.toml +0 -34
  61. pysof-0.1.32/crates/fhir/tests/test_examples.rs +0 -420
  62. pysof-0.1.32/crates/fhir/tests/test_serde.rs +0 -1922
  63. pysof-0.1.32/crates/pysof/Cargo.toml +0 -35
  64. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/README.md +0 -0
  65. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/src/r6.rs.template +0 -0
  66. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/tests/integer_string_integration.rs +0 -0
  67. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir/tests/simple_null_test.rs +0 -0
  68. {pysof-0.1.32 → pysof-0.1.42}/crates/fhir-macro/README.md +0 -0
  69. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/PRECISION_LIMITATION.md +0 -0
  70. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/benches/cli_benches.rs +0 -0
  71. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/benches/evaluator_benches.rs +0 -0
  72. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/benches/parser_benches.rs +0 -0
  73. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/examples/test_ucum.rs +0 -0
  74. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/grammar/fhirpath.g4 +0 -0
  75. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/server-api.md +0 -0
  76. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/aggregate_function.rs +0 -0
  77. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/bin/fhirpath-cli.rs +0 -0
  78. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/bin/fhirpath-server.rs +0 -0
  79. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/boolean_functions.rs +0 -0
  80. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/boundary_functions.rs +0 -0
  81. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/cli.rs +0 -0
  82. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/collection_functions.rs +0 -0
  83. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/collection_navigation.rs +0 -0
  84. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/contains_function.rs +0 -0
  85. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/conversion_functions.rs +0 -0
  86. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/date_operation.rs +0 -0
  87. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/datetime_impl.rs +0 -0
  88. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/distinct_functions.rs +0 -0
  89. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/error.rs +0 -0
  90. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/extension_function.rs +0 -0
  91. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/fhir_type_hierarchy.rs +0 -0
  92. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/json_utils.rs +0 -0
  93. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/long_conversion.rs +0 -0
  94. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/not_function.rs +0 -0
  95. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/polymorphic_access.rs +0 -0
  96. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/reference_key_functions.rs +0 -0
  97. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/repeat_function.rs +0 -0
  98. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/resource_type.rs +0 -0
  99. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/server.rs +0 -0
  100. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/set_operations.rs +0 -0
  101. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/subset_functions.rs +0 -0
  102. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/terminology_client.rs +0 -0
  103. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/terminology_functions.rs +0 -0
  104. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/trace_function.rs +0 -0
  105. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/type_function.rs +0 -0
  106. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/type_inference.rs +0 -0
  107. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/src/ucum.rs +0 -0
  108. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/all_function_tests.rs +0 -0
  109. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/boundary_debug_tests.rs +0 -0
  110. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/boundary_function_integration_tests.rs +0 -0
  111. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/comment_test.rs +0 -0
  112. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/common/context.rs +0 -0
  113. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/common/mod.rs +0 -0
  114. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/common/parser.rs +0 -0
  115. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/common/runner.rs +0 -0
  116. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/observation-example.json +0 -0
  117. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/observation-example.xml +0 -0
  118. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/patient-example.json +0 -0
  119. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/patient-example.xml +0 -0
  120. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/questionnaire-example.json +0 -0
  121. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/questionnaire-example.xml +0 -0
  122. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.json +0 -0
  123. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.xml +0 -0
  124. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r4/tests-fhir-r4.xml +0 -0
  125. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/appointment-examplereq.json +0 -0
  126. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/ccda.json +0 -0
  127. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/codesystem-example.json +0 -0
  128. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/conceptmap-example.json +0 -0
  129. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/explanationofbenefit-example.json +0 -0
  130. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/observation-example.json +0 -0
  131. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/observation-example.xml +0 -0
  132. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/parameters-example-types.json +0 -0
  133. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/patient-container-example.json +0 -0
  134. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/patient-example-name.json +0 -0
  135. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/patient-example-period.json +0 -0
  136. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/patient-example.json +0 -0
  137. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/patient-name-extensions.json +0 -0
  138. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/questionnaire-example.json +0 -0
  139. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/input/valueset-example-expansion.json +0 -0
  140. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/r5/known-test-failures.json +0 -0
  141. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/data/testSchema.xsd +0 -0
  142. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/date_operation_tests.rs +0 -0
  143. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/datetime_boundary_tests.rs +0 -0
  144. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/define_variable_test.rs +0 -0
  145. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/enhanced_variable_tests.rs +0 -0
  146. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/extension_tests.rs +0 -0
  147. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/is_as_method_tests.rs +0 -0
  148. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/oftype_datetime_tests.rs +0 -0
  149. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/parse_debug_test.rs +0 -0
  150. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/parser_tests.rs +0 -0
  151. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/polymorphic_r4_tests.rs +0 -0
  152. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/polymorphic_tests.rs +0 -0
  153. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/precision_tests.rs +0 -0
  154. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/test_boundary_zero.rs +0 -0
  155. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/trace_api_test.rs +0 -0
  156. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/trace_tests.rs +0 -0
  157. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/tree_navigation_tests.rs +0 -0
  158. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/truncate_tests.rs +0 -0
  159. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/type_operation_tests.rs +0 -0
  160. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/type_preservation_integration_test.rs +0 -0
  161. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/type_reflection_tests.rs +0 -0
  162. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/uri_type_test.rs +0 -0
  163. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath/tests/uuid_type_preservation_test.rs +0 -0
  164. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath-support/README.md +0 -0
  165. {pysof-0.1.32 → pysof-0.1.42}/crates/fhirpath-support/src/type_info.rs +0 -0
  166. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/.gitignore +0 -0
  167. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/Cargo.lock +0 -0
  168. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/Makefile +0 -0
  169. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/WHEEL_BUILDING.md +0 -0
  170. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/multithreading_example.py +0 -0
  171. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/__init__.py +0 -0
  172. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_content_types.py +0 -0
  173. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_core_functions.py +0 -0
  174. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_error_handling.py +0 -0
  175. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_fhir_versions.py +0 -0
  176. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_import.py +0 -0
  177. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_package_metadata.py +0 -0
  178. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/python-tests/test_source_errors.py +0 -0
  179. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/scripts/build-wheels.py +0 -0
  180. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/src/pysof/__init__.py +0 -0
  181. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/src/pysof/_pysof.pyi +0 -0
  182. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/src/pysof/py.typed +0 -0
  183. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/test_multithreading.py +0 -0
  184. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/integration/content_types.rs +0 -0
  185. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/integration/error_handling.rs +0 -0
  186. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/integration/fhir_versions.rs +0 -0
  187. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/integration/mod.rs +0 -0
  188. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/integration.rs +0 -0
  189. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/lib_coverage_tests.rs +0 -0
  190. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/lib_tests.rs +0 -0
  191. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/multithreading_integration.rs +0 -0
  192. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/tests/threading_test.rs +0 -0
  193. {pysof-0.1.32 → pysof-0.1.42}/crates/pysof/uv.lock +0 -0
  194. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/benches/parallel_processing_bench.rs +0 -0
  195. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/error.rs +0 -0
  196. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/handlers.rs +0 -0
  197. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/lib.rs +0 -0
  198. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/mod.rs +0 -0
  199. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/models.rs +0 -0
  200. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/parquet_schema.rs +0 -0
  201. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/streaming.rs +0 -0
  202. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/src/traits.rs +0 -0
  203. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/common/mod.rs +0 -0
  204. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_column_ordering.rs +0 -0
  205. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_datetime_type_info.rs +0 -0
  206. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_enum_conversion.rs +0 -0
  207. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_evaluation_result_conversion.rs +0 -0
  208. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_extension_simple.rs +0 -0
  209. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_foreach_combinations.rs +0 -0
  210. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_instant_type_info.rs +0 -0
  211. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_raw_resource.rs +0 -0
  212. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/debug_reference_key_types.rs +0 -0
  213. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/foreach_test.rs +0 -0
  214. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/multiselect_test.rs +0 -0
  215. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/run_foreach_tests.rs +0 -0
  216. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/server_tests.rs +0 -0
  217. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/basic.json +0 -0
  218. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/collection.json +0 -0
  219. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/combinations.json +0 -0
  220. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/constant.json +0 -0
  221. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/constant_types.json +0 -0
  222. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fhirpath.json +0 -0
  223. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fhirpath_numbers.json +0 -0
  224. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_boundary.json +0 -0
  225. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_empty.json +0 -0
  226. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_extension.json +0 -0
  227. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_first.json +0 -0
  228. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_join.json +0 -0
  229. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_oftype.json +0 -0
  230. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/fn_reference_keys.json +0 -0
  231. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/foreach.json +0 -0
  232. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/logic.json +0 -0
  233. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/repeat.json +0 -0
  234. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/union.json +0 -0
  235. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/validate.json +0 -0
  236. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/view_resource.json +0 -0
  237. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql-on-fhir-v2/tests/where.json +0 -0
  238. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/sql_on_fhir_tests.rs +0 -0
  239. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_base64_binary_constant.rs +0 -0
  240. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_boolean_constant_debug.rs +0 -0
  241. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_boolean_validation.rs +0 -0
  242. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_chunked_processing.rs +0 -0
  243. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_cli_file_source.rs +0 -0
  244. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_csv_quote_handling.rs +0 -0
  245. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_extension_fix_verification.rs +0 -0
  246. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_extension_value_access.rs +0 -0
  247. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_format_parameter_body.rs +0 -0
  248. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_header_parameter_body.rs +0 -0
  249. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_limit_parameter_body.rs +0 -0
  250. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_ndjson_input.rs +0 -0
  251. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_parallel_working.rs +0 -0
  252. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_parameter_validation.rs +0 -0
  253. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_parquet_export.rs +0 -0
  254. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_parquet_large_dataset.rs +0 -0
  255. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_parquet_server_options.rs +0 -0
  256. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_patient_reference_formats.rs +0 -0
  257. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_query_parameter_combinations.rs +0 -0
  258. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_run_operation_parameters.rs +0 -0
  259. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_runner_integration.rs +0 -0
  260. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_shortened_format_names.rs +0 -0
  261. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_where_clause_validation.rs +0 -0
  262. {pysof-0.1.32 → pysof-0.1.42}/crates/sof/tests/test_x_ndjson_support.rs +0 -0
  263. {pysof-0.1.32 → pysof-0.1.42}/src/pysof/__init__.py +0 -0
  264. {pysof-0.1.32 → pysof-0.1.42}/src/pysof/_pysof.cpython-311-darwin.so +0 -0
  265. {pysof-0.1.32 → pysof-0.1.42}/src/pysof/_pysof.pyi +0 -0
  266. {pysof-0.1.32 → pysof-0.1.42}/src/pysof/py.typed +0 -0
@@ -0,0 +1,40 @@
1
+ [package]
2
+ name = "pysof"
3
+ version.workspace = true
4
+ edition = "2024"
5
+ description = "Python bindings for helios-sof using PyO3"
6
+ license.workspace = true
7
+ authors.workspace = true
8
+ repository.workspace = true
9
+ homepage = "https://github.com/HeliosSoftware/hfs/tree/main/crates/pysof"
10
+ rust-version.workspace = true
11
+ keywords = ["helios-software", "hl7", "fhir", "helios-fhir-server", "sql-on-fhir"]
12
+
13
+ # PyO3 extension metadata
14
+ [lib]
15
+ name = "pysof"
16
+ crate-type = ["cdylib"]
17
+
18
+ [dependencies]
19
+ pyo3 = { version = ">=0.27", features = ["extension-module", "generate-import-lib"] }
20
+ helios-sof = { path = "../sof", version = "0.1.42" }
21
+ helios-fhir = { path = "../fhir", version = "0.1.42" }
22
+ serde = { workspace = true }
23
+ serde_json = { workspace = true }
24
+ chrono = { version = "0.4", features = ["serde"] }
25
+ pythonize = "0.27"
26
+ csv = "1.3"
27
+
28
+ [features]
29
+ default = ["R4"]
30
+ R4 = ["helios-sof/R4", "helios-fhir/R4"]
31
+ R4B = ["helios-sof/R4B", "helios-fhir/R4B"]
32
+ R5 = ["helios-sof/R5", "helios-fhir/R5"]
33
+ R6 = ["helios-sof/R6", "helios-fhir/R6"]
34
+
35
+ # Vendor OpenSSL when cross-compiling for Linux ARM64
36
+ [target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies]
37
+ openssl = { version = "0.10", features = ["vendored"] }
38
+
39
+ [build-dependencies]
40
+ pyo3-build-config = "0.27"
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysof
3
- Version: 0.1.32
3
+ Version: 0.1.42
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.10
6
6
  Classifier: Programming Language :: Python :: 3.11
7
7
  Classifier: Programming Language :: Python :: 3.12
8
8
  Classifier: Programming Language :: Python :: 3.13
9
+ Classifier: Programming Language :: Python :: 3.14
9
10
  Classifier: License :: OSI Approved :: MIT License
10
11
  Classifier: Operating System :: OS Independent
11
12
  Classifier: Development Status :: 4 - Beta
@@ -15,6 +16,7 @@ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
15
16
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
17
  Summary: Python wrapper for the Helios Software SOF (SQL on FHIR) toolkit.
17
18
  Keywords: SQL on FHIR,FHIR,healthcare,sof,Helios Software
19
+ Home-Page: https://github.com/HeliosSoftware/hfs/tree/main/crates/pysof
18
20
  Author-email: Helios Software <team@heliossoftware.com>
19
21
  License: MIT
20
22
  Requires-Python: >=3.10
@@ -77,7 +79,7 @@ pip install pysof
77
79
  - **Linux**: x86_64 (glibc and musl)
78
80
  - **Windows**: x86_64 (MSVC)
79
81
  - **macOS**: AArch64 (Apple Silicon)
80
- - **Python**: 3.10, 3.11, 3.12, 3.13
82
+ - **Python**: 3.10, 3.11, 3.12, 3.13, 3.14
81
83
 
82
84
  ### From GitHub Releases
83
85
 
@@ -346,7 +348,7 @@ Use `pysof.get_supported_fhir_versions()` to check available versions in your bu
346
348
 
347
349
  ### Requirements
348
350
 
349
- - Python 3.10 or later (3.10, 3.11, 3.12, 3.13 supported)
351
+ - Python 3.10 or later (3.10, 3.11, 3.12, 3.13, 3.14 supported)
350
352
  - uv (package and environment manager)
351
353
  - Rust toolchain (for building from source)
352
354
 
@@ -378,7 +380,7 @@ For Python development, it's recommended to use `maturin` via `uv`:
378
380
  cd crates/pysof
379
381
 
380
382
  # Create a venv with your preferred Python version (3.10+)
381
- uv venv --python 3.11 # or 3.10, 3.12, 3.13
383
+ uv venv --python 3.11 # or 3.10, 3.12, 3.13, 3.14
382
384
 
383
385
  # Install the project dev dependencies
384
386
  uv sync --group dev
@@ -50,7 +50,7 @@ pip install pysof
50
50
  - **Linux**: x86_64 (glibc and musl)
51
51
  - **Windows**: x86_64 (MSVC)
52
52
  - **macOS**: AArch64 (Apple Silicon)
53
- - **Python**: 3.10, 3.11, 3.12, 3.13
53
+ - **Python**: 3.10, 3.11, 3.12, 3.13, 3.14
54
54
 
55
55
  ### From GitHub Releases
56
56
 
@@ -319,7 +319,7 @@ Use `pysof.get_supported_fhir_versions()` to check available versions in your bu
319
319
 
320
320
  ### Requirements
321
321
 
322
- - Python 3.10 or later (3.10, 3.11, 3.12, 3.13 supported)
322
+ - Python 3.10 or later (3.10, 3.11, 3.12, 3.13, 3.14 supported)
323
323
  - uv (package and environment manager)
324
324
  - Rust toolchain (for building from source)
325
325
 
@@ -351,7 +351,7 @@ For Python development, it's recommended to use `maturin` via `uv`:
351
351
  cd crates/pysof
352
352
 
353
353
  # Create a venv with your preferred Python version (3.10+)
354
- uv venv --python 3.11 # or 3.10, 3.12, 3.13
354
+ uv venv --python 3.11 # or 3.10, 3.12, 3.13, 3.14
355
355
 
356
356
  # Install the project dev dependencies
357
357
  uv sync --group dev
@@ -8,6 +8,7 @@ authors.workspace = true
8
8
  repository.workspace = true
9
9
  homepage = "https://github.com/HeliosSoftware/hfs/tree/main/crates/fhir"
10
10
  readme = "README.md"
11
+ keywords = ["helios-software", "hl7", "fhir", "helios-fhir-server", "healthcare"]
11
12
  exclude = ["tests/data/**"]
12
13
 
13
14
  [features]
@@ -17,13 +18,15 @@ R4B = []
17
18
  R5 = []
18
19
  R6 = []
19
20
  skip-r6-download = []
21
+ xml = ["helios-serde-support/xml"]
20
22
 
21
23
  [dependencies]
22
24
  serde = { workspace = true }
23
25
  serde_json = { workspace = true, features = ["raw_value"] }
24
26
  clap = { version = "4.0", features = ["derive"] }
25
- helios-fhir-macro = { path = "../fhir-macro", version = "0.1.32" }
26
- helios-fhirpath-support = { path = "../fhirpath-support", version = "0.1.32" }
27
+ helios-fhir-macro = { path = "../fhir-macro", version = "0.1.42" }
28
+ helios-serde-support = { path = "../serde-support", version = "0.1.42" }
29
+ helios-fhirpath-support = { path = "../fhirpath-support", version = "0.1.42" }
27
30
  time = "0.3"
28
31
  chrono = { workspace = true }
29
32
  # Re-add serde-with-arbitrary-precision, keep macros
@@ -39,5 +42,3 @@ zip = "0.6"
39
42
  [package.metadata.docs.rs]
40
43
  all-features = true
41
44
  rustdoc-args = ["--cfg", "docsrs"]
42
-
43
-
@@ -18,16 +18,34 @@ fn main() {
18
18
  return;
19
19
  }
20
20
 
21
- println!("cargo:warning=Downloading R6 test data from HL7 build server");
22
-
23
- let resources_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/R6");
21
+ let json_resources_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/json/R6");
22
+ let xml_resources_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/xml/R6");
23
+
24
+ // Create the resources directories if they don't exist
25
+ fs::create_dir_all(&json_resources_dir).expect("Failed to create JSON resources directory");
26
+ fs::create_dir_all(&xml_resources_dir).expect("Failed to create XML resources directory");
27
+
28
+ // Check if test data is recent (skip download if less than 24 hours old)
29
+ // Use a marker file to track when we last downloaded
30
+ let marker_path = json_resources_dir.join(".download_marker");
31
+ if let Ok(metadata) = fs::metadata(&marker_path) {
32
+ if let Ok(modified) = metadata.modified() {
33
+ if let Ok(duration) = modified.elapsed() {
34
+ if duration.as_secs() < 86400 {
35
+ println!("cargo:warning=R6 test data is recent, skipping download");
36
+ return;
37
+ }
38
+ }
39
+ }
40
+ }
24
41
 
25
- // Create the resources directory if it doesn't exist
26
- fs::create_dir_all(&resources_dir).expect("Failed to create resources directory");
42
+ println!("cargo:warning=Downloading R6 test data from HL7 build server");
27
43
 
28
- let url = "https://build.fhir.org/examples-json.zip";
44
+ let json_url = "https://build.fhir.org/examples-json.zip";
45
+ let xml_url = "https://build.fhir.org/examples.zip";
29
46
 
30
- let output_path = resources_dir.join("examples.json.zip");
47
+ let json_output_path = json_resources_dir.join("examples.json.zip");
48
+ let xml_output_path = xml_resources_dir.join("examples.xml.zip");
31
49
 
32
50
  println!("Downloading test data ...");
33
51
 
@@ -40,12 +58,15 @@ fn main() {
40
58
 
41
59
  // Try downloading with retries
42
60
  const MAX_RETRIES: u32 = 3;
61
+
62
+ // Download JSON examples
63
+ println!("Downloading JSON examples...");
43
64
  let mut last_error = None;
44
65
 
45
66
  for attempt in 1..=MAX_RETRIES {
46
- println!("Download attempt {} of {}", attempt, MAX_RETRIES);
67
+ println!("JSON download attempt {} of {}", attempt, MAX_RETRIES);
47
68
 
48
- match download_with_retry(&client, url, &output_path) {
69
+ match download_with_retry(&client, json_url, &json_output_path) {
49
70
  Ok(bytes) => {
50
71
  println!("Downloaded {} bytes", bytes);
51
72
  last_error = None;
@@ -66,13 +87,59 @@ fn main() {
66
87
 
67
88
  if let Some(error) = last_error {
68
89
  panic!(
69
- "Failed to download file after {} attempts: {}",
90
+ "Failed to download JSON file after {} attempts: {}",
70
91
  MAX_RETRIES, error
71
92
  );
72
93
  }
73
94
 
95
+ // Extract JSON examples
96
+ extract_and_clean(&json_output_path, &json_resources_dir, "examples.json.zip");
97
+
98
+ // Download XML examples
99
+ println!("Downloading XML examples...");
100
+ last_error = None;
101
+
102
+ for attempt in 1..=MAX_RETRIES {
103
+ println!("XML download attempt {} of {}", attempt, MAX_RETRIES);
104
+
105
+ match download_with_retry(&client, xml_url, &xml_output_path) {
106
+ Ok(bytes) => {
107
+ println!("Downloaded {} bytes", bytes);
108
+ last_error = None;
109
+ break;
110
+ }
111
+ Err(e) => {
112
+ println!("Attempt {} failed: {}", attempt, e);
113
+ last_error = Some(e);
114
+
115
+ if attempt < MAX_RETRIES {
116
+ let wait_time = Duration::from_secs(5 * attempt as u64);
117
+ println!("Waiting {:?} before retry...", wait_time);
118
+ thread::sleep(wait_time);
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ if let Some(error) = last_error {
125
+ panic!(
126
+ "Failed to download XML file after {} attempts: {}",
127
+ MAX_RETRIES, error
128
+ );
129
+ }
130
+
131
+ // Extract XML examples
132
+ extract_and_clean(&xml_output_path, &xml_resources_dir, "examples.xml.zip");
133
+
134
+ // Write marker file to track download time
135
+ fs::write(&marker_path, "").expect("Failed to write download marker");
136
+
137
+ println!("FHIR test data downloaded successfully");
138
+ }
139
+
140
+ fn extract_and_clean(zip_path: &PathBuf, resources_dir: &PathBuf, zip_filename: &str) {
74
141
  // Verify and extract the downloaded file
75
- let file = fs::File::open(&output_path).expect("Failed to open downloaded file");
142
+ let file = fs::File::open(zip_path).expect("Failed to open downloaded file");
76
143
  let metadata = file.metadata().expect("Failed to get file metadata");
77
144
  println!("File size on disk: {} bytes", metadata.len());
78
145
 
@@ -84,12 +151,12 @@ fn main() {
84
151
 
85
152
  // Clean out the resources directory before extracting (removes old files that may no longer exist in the zip)
86
153
  println!("cargo:warning=Cleaning resources directory before extraction...");
87
- for entry in fs::read_dir(&resources_dir).unwrap() {
154
+ for entry in fs::read_dir(resources_dir).unwrap() {
88
155
  let entry = entry.unwrap();
89
156
  let path = entry.path();
90
157
 
91
158
  // Skip the zip file itself
92
- if path.file_name() == Some(std::ffi::OsStr::new("examples.json.zip")) {
159
+ if path.file_name() == Some(std::ffi::OsStr::new(zip_filename)) {
93
160
  continue;
94
161
  }
95
162
 
@@ -122,9 +189,7 @@ fn main() {
122
189
  }
123
190
 
124
191
  // Delete the zip file after extraction
125
- fs::remove_file(output_path).expect("Failed to delete zip file");
126
-
127
- println!("FHIR test data downloaded successfully");
192
+ fs::remove_file(zip_path).expect("Failed to delete zip file");
128
193
  }
129
194
 
130
195
  fn download_with_retry(
@@ -43,6 +43,9 @@
43
43
 
44
44
  use chrono::{DateTime as ChronoDateTime, NaiveDate, NaiveTime, Utc};
45
45
  use helios_fhirpath_support::{EvaluationResult, IntoEvaluationResult, TypeInfoResult};
46
+ #[cfg(feature = "xml")]
47
+ use helios_serde_support::SingleOrVec;
48
+
46
49
  use rust_decimal::Decimal;
47
50
  use serde::{
48
51
  Deserialize, Serialize,
@@ -1432,6 +1435,8 @@ pub mod parameters;
1432
1435
  // Re-export commonly used types from parameters module
1433
1436
  pub use parameters::{ParameterValueAccessor, VersionIndependentParameters};
1434
1437
 
1438
+ // Internal helpers used by the derive macro; not part of the public API
1439
+ #[doc(hidden)]
1435
1440
  /// Multi-version FHIR resource container supporting version-agnostic operations.
1436
1441
  ///
1437
1442
  /// This enum provides a unified interface for working with FHIR resources across
@@ -1471,7 +1476,7 @@ pub use parameters::{ParameterValueAccessor, VersionIndependentParameters};
1471
1476
  /// };
1472
1477
  ///
1473
1478
  /// // Wrap in version-agnostic container
1474
- /// let resource = FhirResource::R4(Box::new(helios_fhir::r4::Resource::Patient(patient)));
1479
+ /// let resource = FhirResource::R4(Box::new(helios_fhir::r4::Resource::Patient(Box::new(patient))));
1475
1480
  /// assert_eq!(resource.version(), FhirVersion::R4);
1476
1481
  /// }
1477
1482
  /// ```
@@ -1618,7 +1623,7 @@ impl FhirResource {
1618
1623
  /// version: FhirVersion,
1619
1624
  /// }
1620
1625
  /// ```
1621
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1626
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1622
1627
  pub enum FhirVersion {
1623
1628
  /// FHIR 4.0.1 (normative) - The current normative version
1624
1629
  #[cfg(feature = "R4")]
@@ -1674,6 +1679,155 @@ impl FhirVersion {
1674
1679
  FhirVersion::R6 => "R6",
1675
1680
  }
1676
1681
  }
1682
+
1683
+ /// Parse from MIME-type parameter value (e.g., "4.0", "5.0").
1684
+ ///
1685
+ /// Per FHIR spec: <https://hl7.org/fhir/http.html#version-parameter>
1686
+ ///
1687
+ /// # Arguments
1688
+ ///
1689
+ /// * `value` - The MIME-type parameter value (e.g., "4.0", "4.3", "5.0", "6.0")
1690
+ ///
1691
+ /// # Returns
1692
+ ///
1693
+ /// The corresponding `FhirVersion` if the value matches an enabled version,
1694
+ /// or `None` if not recognized or the version feature is not enabled.
1695
+ ///
1696
+ /// # Examples
1697
+ ///
1698
+ /// ```rust
1699
+ /// use helios_fhir::FhirVersion;
1700
+ ///
1701
+ /// # #[cfg(feature = "R4")]
1702
+ /// assert_eq!(FhirVersion::from_mime_param("4.0"), Some(FhirVersion::R4));
1703
+ /// # #[cfg(feature = "R5")]
1704
+ /// assert_eq!(FhirVersion::from_mime_param("5.0"), Some(FhirVersion::R5));
1705
+ /// assert_eq!(FhirVersion::from_mime_param("invalid"), None);
1706
+ /// ```
1707
+ pub fn from_mime_param(value: &str) -> Option<Self> {
1708
+ match value.trim() {
1709
+ #[cfg(feature = "R4")]
1710
+ "4.0" => Some(FhirVersion::R4),
1711
+ #[cfg(feature = "R4B")]
1712
+ "4.3" => Some(FhirVersion::R4B),
1713
+ #[cfg(feature = "R5")]
1714
+ "5.0" => Some(FhirVersion::R5),
1715
+ #[cfg(feature = "R6")]
1716
+ "6.0" => Some(FhirVersion::R6),
1717
+ _ => None,
1718
+ }
1719
+ }
1720
+
1721
+ /// Returns the MIME-type parameter value for this version.
1722
+ ///
1723
+ /// This value is used in Content-Type and Accept headers per FHIR spec.
1724
+ /// Example: `application/fhir+json; fhirVersion=4.0`
1725
+ ///
1726
+ /// # Examples
1727
+ ///
1728
+ /// ```rust
1729
+ /// use helios_fhir::FhirVersion;
1730
+ ///
1731
+ /// # #[cfg(feature = "R4")]
1732
+ /// assert_eq!(FhirVersion::R4.as_mime_param(), "4.0");
1733
+ /// # #[cfg(feature = "R5")]
1734
+ /// assert_eq!(FhirVersion::R5.as_mime_param(), "5.0");
1735
+ /// ```
1736
+ pub fn as_mime_param(&self) -> &'static str {
1737
+ match self {
1738
+ #[cfg(feature = "R4")]
1739
+ FhirVersion::R4 => "4.0",
1740
+ #[cfg(feature = "R4B")]
1741
+ FhirVersion::R4B => "4.3",
1742
+ #[cfg(feature = "R5")]
1743
+ FhirVersion::R5 => "5.0",
1744
+ #[cfg(feature = "R6")]
1745
+ FhirVersion::R6 => "6.0",
1746
+ }
1747
+ }
1748
+
1749
+ /// Returns the full version string (e.g., "4.0.1", "5.0.0").
1750
+ ///
1751
+ /// This is the complete version identifier used in CapabilityStatement.fhirVersion.
1752
+ ///
1753
+ /// # Examples
1754
+ ///
1755
+ /// ```rust
1756
+ /// use helios_fhir::FhirVersion;
1757
+ ///
1758
+ /// # #[cfg(feature = "R4")]
1759
+ /// assert_eq!(FhirVersion::R4.full_version(), "4.0.1");
1760
+ /// # #[cfg(feature = "R5")]
1761
+ /// assert_eq!(FhirVersion::R5.full_version(), "5.0.0");
1762
+ /// ```
1763
+ pub fn full_version(&self) -> &'static str {
1764
+ match self {
1765
+ #[cfg(feature = "R4")]
1766
+ FhirVersion::R4 => "4.0.1",
1767
+ #[cfg(feature = "R4B")]
1768
+ FhirVersion::R4B => "4.3.0",
1769
+ #[cfg(feature = "R5")]
1770
+ FhirVersion::R5 => "5.0.0",
1771
+ #[cfg(feature = "R6")]
1772
+ FhirVersion::R6 => "6.0.0",
1773
+ }
1774
+ }
1775
+
1776
+ /// Parse from database storage string.
1777
+ ///
1778
+ /// Accepts both MIME format ("4.0") and short format ("R4") for flexibility.
1779
+ /// This is useful when loading version information from the database.
1780
+ ///
1781
+ /// # Arguments
1782
+ ///
1783
+ /// * `value` - The storage value (e.g., "4.0", "R4", "r4")
1784
+ ///
1785
+ /// # Returns
1786
+ ///
1787
+ /// The corresponding `FhirVersion` if recognized, or `None` otherwise.
1788
+ ///
1789
+ /// # Examples
1790
+ ///
1791
+ /// ```rust
1792
+ /// use helios_fhir::FhirVersion;
1793
+ ///
1794
+ /// # #[cfg(feature = "R4")]
1795
+ /// {
1796
+ /// assert_eq!(FhirVersion::from_storage("4.0"), Some(FhirVersion::R4));
1797
+ /// assert_eq!(FhirVersion::from_storage("R4"), Some(FhirVersion::R4));
1798
+ /// assert_eq!(FhirVersion::from_storage("r4"), Some(FhirVersion::R4));
1799
+ /// }
1800
+ /// ```
1801
+ pub fn from_storage(value: &str) -> Option<Self> {
1802
+ // Try MIME format first
1803
+ Self::from_mime_param(value).or_else(|| match value.to_uppercase().as_str() {
1804
+ #[cfg(feature = "R4")]
1805
+ "R4" => Some(FhirVersion::R4),
1806
+ #[cfg(feature = "R4B")]
1807
+ "R4B" => Some(FhirVersion::R4B),
1808
+ #[cfg(feature = "R5")]
1809
+ "R5" => Some(FhirVersion::R5),
1810
+ #[cfg(feature = "R6")]
1811
+ "R6" => Some(FhirVersion::R6),
1812
+ _ => None,
1813
+ })
1814
+ }
1815
+
1816
+ /// Returns all enabled FHIR versions.
1817
+ ///
1818
+ /// This is useful for listing supported versions (e.g., in `$versions` operation).
1819
+ pub fn enabled_versions() -> &'static [FhirVersion] {
1820
+ &[
1821
+ #[cfg(feature = "R4")]
1822
+ FhirVersion::R4,
1823
+ #[cfg(feature = "R4B")]
1824
+ FhirVersion::R4B,
1825
+ #[cfg(feature = "R5")]
1826
+ FhirVersion::R5,
1827
+ #[cfg(feature = "R6")]
1828
+ FhirVersion::R6,
1829
+ ]
1830
+ }
1677
1831
  }
1678
1832
 
1679
1833
  /// Implements `Display` trait for user-friendly output formatting.
@@ -1843,7 +1997,15 @@ where
1843
1997
  if extension.is_some() {
1844
1998
  return Err(de::Error::duplicate_field("extension"));
1845
1999
  }
1846
- extension = Some(map.next_value()?);
2000
+ #[cfg(feature = "xml")]
2001
+ {
2002
+ let single_or_vec: SingleOrVec<E> = map.next_value()?;
2003
+ extension = Some(single_or_vec.into());
2004
+ }
2005
+ #[cfg(not(feature = "xml"))]
2006
+ {
2007
+ extension = Some(map.next_value()?);
2008
+ }
1847
2009
  }
1848
2010
  "value" => {
1849
2011
  if value.is_some() {
@@ -1928,10 +2090,11 @@ pub struct Element<V, E> {
1928
2090
  }
1929
2091
 
1930
2092
  impl<V, E> Element<V, E> {
1931
- /// Returns `true` if no value, id, or extensions are present.
1932
- #[inline]
2093
+ /// Returns true when no value, id, or extensions are present.
1933
2094
  pub fn is_empty(&self) -> bool {
1934
- self.value.is_none() && self.id.is_none() && self.extension.is_none()
2095
+ self.value.is_none()
2096
+ && self.id.is_none()
2097
+ && self.extension.as_ref().is_none_or(|ext| ext.is_empty())
1935
2098
  }
1936
2099
  }
1937
2100
 
@@ -2422,12 +2585,6 @@ impl<E> DecimalElement<E> {
2422
2585
  value: Some(precise_value),
2423
2586
  }
2424
2587
  }
2425
-
2426
- /// Returns `true` if the element has no value, id, or extensions.
2427
- #[inline]
2428
- pub fn is_empty(&self) -> bool {
2429
- self.value.is_none() && self.id.is_none() && self.extension.is_none()
2430
- }
2431
2588
  }
2432
2589
 
2433
2590
  // Custom Deserialize for DecimalElement<E> using intermediate Value
@@ -2501,8 +2658,17 @@ where
2501
2658
  if extension.is_some() {
2502
2659
  return Err(de::Error::duplicate_field("extension"));
2503
2660
  }
2504
- // Deserialize extension directly from its Value
2505
- extension = Deserialize::deserialize(v).map_err(de::Error::custom)?;
2661
+ #[cfg(feature = "xml")]
2662
+ {
2663
+ let single_or_vec: SingleOrVec<E> =
2664
+ Deserialize::deserialize(v).map_err(de::Error::custom)?;
2665
+ extension = Some(single_or_vec.into());
2666
+ }
2667
+ #[cfg(not(feature = "xml"))]
2668
+ {
2669
+ extension =
2670
+ Deserialize::deserialize(v).map_err(de::Error::custom)?;
2671
+ }
2506
2672
  }
2507
2673
  "value" => {
2508
2674
  if value.is_some() {
@@ -25,27 +25,16 @@ use serde::{Deserialize, Serialize};
25
25
  ///
26
26
  /// ```rust
27
27
  /// use helios_fhir::VersionIndependentParameters;
28
- /// # #[cfg(feature = "R4")]
29
- /// use helios_fhir::r4::Parameters;
30
28
  ///
31
29
  /// # #[cfg(feature = "R4")]
32
30
  /// # {
33
- /// // Parse from JSON
34
- /// let json = r#"{
35
- /// "resourceType": "Parameters",
36
- /// "parameter": [{
37
- /// "name": "expression",
38
- /// "valueString": "Patient.name"
39
- /// }]
40
- /// }"#;
41
- ///
42
- /// let params: Parameters = serde_json::from_str(json)?;
31
+ /// // Create Parameters directly (avoids stack overflow on Windows from deep serde recursion)
32
+ /// let params = helios_fhir::r4::Parameters::default();
43
33
  /// let version_independent = VersionIndependentParameters::R4(params);
44
34
  ///
45
35
  /// // Check version
46
36
  /// assert_eq!(version_independent.version(), helios_fhir::FhirVersion::R4);
47
37
  /// # }
48
- /// # Ok::<(), Box<dyn std::error::Error>>(())
49
38
  /// ```
50
39
  #[derive(Debug, Clone, Serialize, Deserialize)]
51
40
  #[serde(untagged)]