pysof 0.2.3__tar.gz → 0.2.4__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.
- {pysof-0.2.3 → pysof-0.2.4}/Cargo.toml +2 -2
- {pysof-0.2.3 → pysof-0.2.4}/PKG-INFO +1 -1
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/Cargo.toml +3 -3
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/r4.rs +10 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/r4b.rs +10 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/r5.rs +10 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/r6.rs +10 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/search/loader.rs +51 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir-macro/Cargo.toml +1 -1
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/Cargo.toml +3 -3
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/lib.rs +157 -51
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/not_function.rs +2 -3
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/reference_key_functions.rs +77 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/server.rs +9 -2
- pysof-0.2.4/crates/fhirpath/tests/nesting_depth.rs +56 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/Cargo.toml +3 -2
- pysof-0.2.4/crates/observability/src/composite_metrics.rs +101 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/lib.rs +12 -1
- pysof-0.2.4/crates/observability/src/shutdown.rs +96 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/Cargo.toml +2 -2
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/uv.lock +1 -1
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/Cargo.toml +4 -4
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/handlers.rs +44 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/lib.rs +197 -110
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/lint/tests.rs +1 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/lint.rs +9 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/server.rs +9 -2
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/mod.rs +82 -0
- pysof-0.2.4/crates/sof/tests/spec_examples.rs +220 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/README.md +13 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-CodeSystemHierarchy.json +43 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-ConditionFlat.json +72 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-EncounterFlat.json +76 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientAddresses.json +40 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientAndContactAddressUnion.json +62 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientDemographics.json +36 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-PatientNamesWithIndex.json +41 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-QuestionnaireResponseItems.json +71 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-ShareablePatientDemographics.json +51 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/ViewDefinition-UsCoreBloodPressures.json +88 -0
- pysof-0.2.4/crates/sof/tests/sql-on-fhir/examples/test-bundle.json +9 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_chunked_processing.rs +35 -0
- pysof-0.2.4/src/pysof/_pysof.cpython-314-x86_64-linux-gnu.so +4 -0
- {pysof-0.2.3 → pysof-0.2.4}/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/build.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment/loader.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r4.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r4b.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r5.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/compartment_expressions/r6.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/parameters.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/r6.rs.template +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/search/errors.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/search/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/search/registry.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/src/search/types.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/tests/integer_string_integration.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/tests/simple_null_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir/tests/test_contained_stack.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir-macro/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhir-macro/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/PRECISION_LIMITATION.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/benches/cli_benches.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/benches/evaluator_benches.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/benches/parser_benches.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/benches/server_benches.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/examples/test_ucum.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/grammar/fhirpath.g4 +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/server-api.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/aggregate_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/aggregate_math_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/bin/fhirpath-cli.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/bin/fhirpath-server.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/boolean_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/boundary_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/cli.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/collection_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/collection_navigation.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/contains_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/conversion_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/date_operation.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/datetime_impl.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/debug_trace.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/distinct_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/error.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/evaluator.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/extension_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/fhir_type_hierarchy.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/format_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/handlers.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/interval_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/json_utils.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/long_conversion.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/models.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/parse_debug.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/parser.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/polymorphic_access.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/repeat_all_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/repeat_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/resolve_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/resource_type.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/set_operations.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/subset_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/terminology_client.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/terminology_functions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/trace_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/type_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/type_inference.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/src/ucum.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/all_function_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/boundary_debug_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/boundary_function_integration_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/builtin_functions_evaluator_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/cli_version_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/comment_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/common/context.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/common/known_failures.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/common/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/common/parser.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/common/runner.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/context_trace_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/observation-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/observation-example.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/patient-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/patient-example.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/questionnaire-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/questionnaire-example.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/input/valueset-example-expansion.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/rust-known-failures.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r4/tests-fhir-r4.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/appointment-examplereq.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/ccda.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/codesystem-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/conceptmap-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/diagnosticreport-eric.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/explanationofbenefit-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/observation-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/observation-example.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/parameters-example-types.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-container-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example-name.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example-period.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/patient-name-extensions.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/questionnaire-example.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/input/valueset-example-expansion.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/known-test-failures.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/rust-known-failures.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/r5/tests-fhir-r5.xml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/data/testSchema.xsd +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/date_operation_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/datetime_boundary_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/debug_datetime_boundary.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/debug_string_boundary_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/define_variable_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/enhanced_variable_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/environment_variables_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/evaluator_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/extension_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/external_constants_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/fhir_boundary_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/http_compression.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/is_as_method_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/join_function_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/oftype_datetime_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/parse_debug_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/parse_expression_diagnostics_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/parse_expression_spanned_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/parser_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/polymorphic_r4_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/polymorphic_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/polymorphic_version_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/precision_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/primitive_extension_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/r4_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/r5_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/reference_key_debug.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/terminology_config_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/test_boundary_zero.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/trace_api_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/trace_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/tree_navigation_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/truncate_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/type_operation_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/type_preservation_integration_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/type_reflection_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/unicode_scalar_value_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/uri_type_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/uuid_type_preservation_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath/tests/valueless_primitive_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath-support/Cargo.toml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath-support/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath-support/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/fhirpath-support/src/type_info.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/dashboard.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/dashboard_counters.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/dashboard_metrics.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/metrics.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/middleware.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/mode.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/reqlog.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/subscriptions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/telemetry.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/src/uptime.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/tests/middleware.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/tests/middleware_full.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/observability/tests/middleware_off.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/.gitignore +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/Cargo.lock +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/Makefile +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/PYPI_CHECKLIST.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/WHEEL_BUILDING.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/build.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/__init__.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_content_types.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_core_functions.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_error_handling.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_fhir_versions.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_import.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_json_string_input.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_ndjson_exports.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_package_metadata.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_remote_resolve.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_source_errors.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/python-tests/test_threading.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/scripts/bench_threading.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/scripts/build-wheels.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/src/pysof/__init__.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/src/pysof/_pysof.pyi +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/src/pysof/py.typed +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/integration/content_types.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/integration/error_handling.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/integration/fhir_versions.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/integration/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/integration.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/lib_coverage_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/lib_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/multithreading_integration.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/pysof/tests/threading_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/serde-support/Cargo.toml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/serde-support/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/README.md +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/benches/parallel_processing_bench.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/scripts/bench_arrow_client.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/app.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/canonical.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/cli.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/compartment.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/constants.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/data_source.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/error.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/fhir_format.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/models.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/params.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/parquet_schema.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/parquet_zip.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/reference_collector.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/remote_fetch.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/remote_resolver.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/bind.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/engine.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/library.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/output.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/params.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/sqlquery/scan.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/src/traits.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/common/mod.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_boolean_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_column_ordering.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_datetime_instant_constants.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_datetime_type_info.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_enum_conversion.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_evaluation_result_conversion.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_extension_function.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_extension_macro_fix.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_extension_simple.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_fhir_resource_structure.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_foreach_combinations.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_inequality.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_instant_constant.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_instant_type_info.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_raw_resource.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/debug_reference_key_types.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/extension_debug_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/foreach_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/multiselect_test.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/resolve_remote_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/resolve_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/run_foreach_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/server_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/basic.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/collection.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/combinations.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/constant.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/constant_types.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fhirpath.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fhirpath_numbers.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_boundary.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_empty.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_extension.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_first.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_join.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_oftype.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/fn_reference_keys.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/foreach.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/logic.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/repeat.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/row_index.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/union.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/validate.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/view_resource.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql-on-fhir/tests/where.json +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/sql_on_fhir_tests.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_arrow_ipc_export.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_base64_binary_constant.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug2.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_boolean_constant_debug3.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_boolean_validation.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_cli_file_source.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_cli_version.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_csv_quote_handling.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_extension_fix_verification.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_extension_value_access.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_format_parameter_body.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_header_parameter_body.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_limit_parameter_body.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_ndjson_input.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_parallel_working.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_parameter_validation.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_parquet_export.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_parquet_large_dataset.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_parquet_server_options.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_patient_reference_formats.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_query_parameter_combinations.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_run_operation_parameters.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_runner_integration.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_shortened_format_names.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_where_clause_validation.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/crates/sof/tests/test_x_ndjson_support.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/pyproject.toml +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/src/lib.rs +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/src/pysof/__init__.py +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/src/pysof/_pysof.pyi +0 -0
- {pysof-0.2.3 → pysof-0.2.4}/src/pysof/py.typed +0 -0
|
@@ -17,8 +17,8 @@ crate-type = ["cdylib"]
|
|
|
17
17
|
|
|
18
18
|
[dependencies]
|
|
19
19
|
pyo3 = { version = ">=0.29", features = ["extension-module", "generate-import-lib"] }
|
|
20
|
-
helios-sof = { path = "../sof", version = "0.2.
|
|
21
|
-
helios-fhir = { path = "../fhir", version = "0.2.
|
|
20
|
+
helios-sof = { path = "../sof", version = "0.2.4", default-features = false }
|
|
21
|
+
helios-fhir = { path = "../fhir", version = "0.2.4", default-features = false }
|
|
22
22
|
serde = { workspace = true }
|
|
23
23
|
serde_json = { workspace = true }
|
|
24
24
|
chrono = { version = "0.4", features = ["serde"] }
|
|
@@ -24,9 +24,9 @@ xml = ["helios-serde-support/xml"]
|
|
|
24
24
|
serde = { workspace = true }
|
|
25
25
|
serde_json = { workspace = true, features = ["raw_value"] }
|
|
26
26
|
clap = { version = "4.0", features = ["derive"] }
|
|
27
|
-
helios-fhir-macro = { path = "../fhir-macro", version = "0.2.
|
|
28
|
-
helios-serde-support = { path = "../serde-support", version = "0.2.
|
|
29
|
-
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.
|
|
27
|
+
helios-fhir-macro = { path = "../fhir-macro", version = "0.2.4" }
|
|
28
|
+
helios-serde-support = { path = "../serde-support", version = "0.2.4" }
|
|
29
|
+
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.4" }
|
|
30
30
|
time = "0.3"
|
|
31
31
|
chrono = { workspace = true }
|
|
32
32
|
# Re-add serde-with-arbitrary-precision, keep macros
|
|
@@ -165598,6 +165598,15 @@ pub enum ViewDefinitionVersionAlgorithm {
|
|
|
165598
165598
|
summary_fields = "id,meta,implicit_rules,modifier_extension,url,identifier,version,version_algorithm,name,title,status,experimental,date,publisher,contact,use_context,jurisdiction,effective_period"
|
|
165599
165599
|
)]
|
|
165600
165600
|
pub struct ViewDefinition {
|
|
165601
|
+
/// Canonical of the definition of this additional resource
|
|
165602
|
+
///
|
|
165603
|
+
/// The versioned canonical URL of the StructureDefinition that defines this
|
|
165604
|
+
/// resource type. Instances of an additional resource - a resource type defined
|
|
165605
|
+
/// outside the core FHIR specification - carry it alongside resourceType.
|
|
165606
|
+
///
|
|
165607
|
+
/// ## Cardinality: Optional (0..1)
|
|
165608
|
+
#[fhir_serde(rename = "resourceDefinition")]
|
|
165609
|
+
pub resource_definition: Option<Canonical>,
|
|
165601
165610
|
/// Logical id of this artifact
|
|
165602
165611
|
///
|
|
165603
165612
|
/// The logical id of the resource, as used in the URL for the resource. Once
|
|
@@ -190545,6 +190554,7 @@ pub static FIELD_TYPES: &[(&str, &str, &str, bool)] = &[
|
|
|
190545
190554
|
("ViewDefinition", "purpose", "markdown", false),
|
|
190546
190555
|
("ViewDefinition", "relatedArtifact", "RelatedArtifact", true),
|
|
190547
190556
|
("ViewDefinition", "resource", "code", false),
|
|
190557
|
+
("ViewDefinition", "resourceDefinition", "canonical", false),
|
|
190548
190558
|
("ViewDefinition", "reviewer", "ContactDetail", true),
|
|
190549
190559
|
("ViewDefinition", "select", "ViewDefinitionSelect", true),
|
|
190550
190560
|
("ViewDefinition", "status", "code", false),
|
|
@@ -169276,6 +169276,15 @@ pub enum ViewDefinitionVersionAlgorithm {
|
|
|
169276
169276
|
summary_fields = "id,meta,implicit_rules,modifier_extension,url,identifier,version,version_algorithm,name,title,status,experimental,date,publisher,contact,use_context,jurisdiction,effective_period"
|
|
169277
169277
|
)]
|
|
169278
169278
|
pub struct ViewDefinition {
|
|
169279
|
+
/// Canonical of the definition of this additional resource
|
|
169280
|
+
///
|
|
169281
|
+
/// The versioned canonical URL of the StructureDefinition that defines this
|
|
169282
|
+
/// resource type. Instances of an additional resource - a resource type defined
|
|
169283
|
+
/// outside the core FHIR specification - carry it alongside resourceType.
|
|
169284
|
+
///
|
|
169285
|
+
/// ## Cardinality: Optional (0..1)
|
|
169286
|
+
#[fhir_serde(rename = "resourceDefinition")]
|
|
169287
|
+
pub resource_definition: Option<Canonical>,
|
|
169279
169288
|
/// Logical id of this artifact
|
|
169280
169289
|
///
|
|
169281
169290
|
/// The logical id of the resource, as used in the URL for the resource. Once
|
|
@@ -194576,6 +194585,7 @@ pub static FIELD_TYPES: &[(&str, &str, &str, bool)] = &[
|
|
|
194576
194585
|
("ViewDefinition", "purpose", "markdown", false),
|
|
194577
194586
|
("ViewDefinition", "relatedArtifact", "RelatedArtifact", true),
|
|
194578
194587
|
("ViewDefinition", "resource", "code", false),
|
|
194588
|
+
("ViewDefinition", "resourceDefinition", "canonical", false),
|
|
194579
194589
|
("ViewDefinition", "reviewer", "ContactDetail", true),
|
|
194580
194590
|
("ViewDefinition", "select", "ViewDefinitionSelect", true),
|
|
194581
194591
|
("ViewDefinition", "status", "code", false),
|
|
@@ -212700,6 +212700,15 @@ pub enum ViewDefinitionVersionAlgorithm {
|
|
|
212700
212700
|
summary_fields = "id,meta,implicit_rules,modifier_extension,url,identifier,version,version_algorithm,name,title,status,experimental,date,publisher,contact,use_context,jurisdiction,effective_period"
|
|
212701
212701
|
)]
|
|
212702
212702
|
pub struct ViewDefinition {
|
|
212703
|
+
/// Canonical of the definition of this additional resource
|
|
212704
|
+
///
|
|
212705
|
+
/// The versioned canonical URL of the StructureDefinition that defines this
|
|
212706
|
+
/// resource type. Instances of an additional resource - a resource type defined
|
|
212707
|
+
/// outside the core FHIR specification - carry it alongside resourceType.
|
|
212708
|
+
///
|
|
212709
|
+
/// ## Cardinality: Optional (0..1)
|
|
212710
|
+
#[fhir_serde(rename = "resourceDefinition")]
|
|
212711
|
+
pub resource_definition: Option<Canonical>,
|
|
212703
212712
|
/// Logical id of this artifact
|
|
212704
212713
|
///
|
|
212705
212714
|
/// The logical id of the resource, as used in the URL for the resource. Once
|
|
@@ -244724,6 +244733,7 @@ pub static FIELD_TYPES: &[(&str, &str, &str, bool)] = &[
|
|
|
244724
244733
|
("ViewDefinition", "purpose", "markdown", false),
|
|
244725
244734
|
("ViewDefinition", "relatedArtifact", "RelatedArtifact", true),
|
|
244726
244735
|
("ViewDefinition", "resource", "code", false),
|
|
244736
|
+
("ViewDefinition", "resourceDefinition", "canonical", false),
|
|
244727
244737
|
("ViewDefinition", "reviewer", "ContactDetail", true),
|
|
244728
244738
|
("ViewDefinition", "select", "ViewDefinitionSelect", true),
|
|
244729
244739
|
("ViewDefinition", "status", "code", false),
|
|
@@ -174780,6 +174780,15 @@ pub enum ViewDefinitionVersionAlgorithm {
|
|
|
174780
174780
|
summary_fields = "id,meta,implicit_rules,modifier_extension,url,identifier,version,version_algorithm,name,title,status,experimental,date,publisher,contact,use_context,jurisdiction,effective_period"
|
|
174781
174781
|
)]
|
|
174782
174782
|
pub struct ViewDefinition {
|
|
174783
|
+
/// Canonical of the definition of this additional resource
|
|
174784
|
+
///
|
|
174785
|
+
/// The versioned canonical URL of the StructureDefinition that defines this
|
|
174786
|
+
/// resource type. Instances of an additional resource - a resource type defined
|
|
174787
|
+
/// outside the core FHIR specification - carry it alongside resourceType.
|
|
174788
|
+
///
|
|
174789
|
+
/// ## Cardinality: Optional (0..1)
|
|
174790
|
+
#[fhir_serde(rename = "resourceDefinition")]
|
|
174791
|
+
pub resource_definition: Option<Canonical>,
|
|
174783
174792
|
/// Logical id of this artifact
|
|
174784
174793
|
///
|
|
174785
174794
|
/// The logical id of the resource, as used in the URL for the resource. Once
|
|
@@ -202780,6 +202789,7 @@ pub static FIELD_TYPES: &[(&str, &str, &str, bool)] = &[
|
|
|
202780
202789
|
("ViewDefinition", "purpose", "markdown", false),
|
|
202781
202790
|
("ViewDefinition", "relatedArtifact", "RelatedArtifact", true),
|
|
202782
202791
|
("ViewDefinition", "resource", "code", false),
|
|
202792
|
+
("ViewDefinition", "resourceDefinition", "canonical", false),
|
|
202783
202793
|
("ViewDefinition", "reviewer", "ContactDetail", true),
|
|
202784
202794
|
("ViewDefinition", "select", "ViewDefinitionSelect", true),
|
|
202785
202795
|
("ViewDefinition", "status", "code", false),
|
|
@@ -20,6 +20,21 @@ use super::registry::{
|
|
|
20
20
|
};
|
|
21
21
|
use super::types::SearchParamType;
|
|
22
22
|
|
|
23
|
+
/// Whether `code` is usable as a search parameter name on this server: one or
|
|
24
|
+
/// more ASCII letters, digits, `-` or `_`.
|
|
25
|
+
///
|
|
26
|
+
/// Every code the specification defines has this shape, and it is stricter
|
|
27
|
+
/// than R6's `spd-4` (no `.`, `$`, `|` or whitespace): a code is a query-string
|
|
28
|
+
/// key, is split on `:` for modifiers and `.` for chains, and names index rows,
|
|
29
|
+
/// so anything else either cannot be searched on or has no business reaching
|
|
30
|
+
/// a storage backend.
|
|
31
|
+
pub fn is_valid_search_parameter_code(code: &str) -> bool {
|
|
32
|
+
!code.is_empty()
|
|
33
|
+
&& code
|
|
34
|
+
.bytes()
|
|
35
|
+
.all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_')
|
|
36
|
+
}
|
|
37
|
+
|
|
23
38
|
/// Transforms FHIRPath expressions to replace `as` operator/function with `ofType`.
|
|
24
39
|
///
|
|
25
40
|
/// Per FHIRPath spec, `as(type)` requires singleton input and throws an error for
|
|
@@ -494,6 +509,15 @@ impl SearchParameterLoader {
|
|
|
494
509
|
url: Some(url.clone()),
|
|
495
510
|
})?
|
|
496
511
|
.to_string();
|
|
512
|
+
if !is_valid_search_parameter_code(&code) {
|
|
513
|
+
return Err(LoaderError::InvalidResource {
|
|
514
|
+
message: format!(
|
|
515
|
+
"SearchParameter.code {code:?} may contain only ASCII letters, digits, \
|
|
516
|
+
'-' and '_'"
|
|
517
|
+
),
|
|
518
|
+
url: Some(url),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
497
521
|
|
|
498
522
|
let type_str = resource
|
|
499
523
|
.get("type")
|
|
@@ -923,6 +947,33 @@ mod tests {
|
|
|
923
947
|
assert_eq!(param.status, SearchParameterStatus::Active);
|
|
924
948
|
}
|
|
925
949
|
|
|
950
|
+
/// A code outside `[A-Za-z0-9_-]` is refused, so it never reaches the
|
|
951
|
+
/// registry or a storage backend's query text.
|
|
952
|
+
#[test]
|
|
953
|
+
fn test_parse_resource_rejects_an_unsafe_code() {
|
|
954
|
+
let loader = SearchParameterLoader::new(FhirVersion::default());
|
|
955
|
+
for code in ["ev'il", "a b", "a.b", "a:b", "", "a\\b"] {
|
|
956
|
+
let resource = serde_json::json!({
|
|
957
|
+
"resourceType": "SearchParameter",
|
|
958
|
+
"url": "http://example.org/sp/x",
|
|
959
|
+
"code": code,
|
|
960
|
+
"base": ["Patient"],
|
|
961
|
+
"type": "string",
|
|
962
|
+
"expression": "Patient.name.family",
|
|
963
|
+
"status": "active",
|
|
964
|
+
});
|
|
965
|
+
assert!(
|
|
966
|
+
matches!(
|
|
967
|
+
loader.parse_resource(&resource),
|
|
968
|
+
Err(LoaderError::InvalidResource { .. })
|
|
969
|
+
),
|
|
970
|
+
"{code:?}"
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
assert!(is_valid_search_parameter_code("value-quantity"));
|
|
974
|
+
assert!(is_valid_search_parameter_code("_lastUpdated"));
|
|
975
|
+
}
|
|
976
|
+
|
|
926
977
|
#[test]
|
|
927
978
|
fn test_parse_resource_missing_field() {
|
|
928
979
|
let loader = SearchParameterLoader::new(FhirVersion::default());
|
|
@@ -20,4 +20,4 @@ proc-macro2 = "1.0"
|
|
|
20
20
|
serde = { workspace = true }
|
|
21
21
|
serde_json = { workspace = true }
|
|
22
22
|
heck = "0.5" # For case conversion
|
|
23
|
-
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.
|
|
23
|
+
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.4" }
|
|
@@ -21,9 +21,9 @@ R6 = ["helios-fhir/R6"]
|
|
|
21
21
|
otel = ["helios-observability/otel"]
|
|
22
22
|
|
|
23
23
|
[dependencies]
|
|
24
|
-
helios-fhir = { path = "../fhir", version = "0.2.
|
|
25
|
-
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.
|
|
26
|
-
helios-observability = { path = "../observability", version = "0.2.
|
|
24
|
+
helios-fhir = { path = "../fhir", version = "0.2.4", default-features = false }
|
|
25
|
+
helios-fhirpath-support = { path = "../fhirpath-support", version = "0.2.4" }
|
|
26
|
+
helios-observability = { path = "../observability", version = "0.2.4" }
|
|
27
27
|
chumsky = "0.10"
|
|
28
28
|
roxmltree = "0.20"
|
|
29
29
|
chrono = { workspace = true } # For date/time parsing and functions
|
|
@@ -368,23 +368,119 @@ pub fn evaluate_expression(
|
|
|
368
368
|
})
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
+
/// The maximum `(`/`[`/`{` nesting depth the parser accepts.
|
|
372
|
+
///
|
|
373
|
+
/// The FHIRPath grammar is recursive-descent, so an expression's nesting
|
|
374
|
+
/// depth bounds the parser's stack use. Left unchecked, a pathologically
|
|
375
|
+
/// nested expression (thousands of `(` deep) overflows the worker thread's
|
|
376
|
+
/// stack and aborts the whole process — there is no unwinding a stack
|
|
377
|
+
/// overflow. Every public parse entry point refuses input past this depth
|
|
378
|
+
/// with an ordinary parse error first. The limit is far above any real
|
|
379
|
+
/// expression: FHIRPath paths in the wild nest a handful deep, and the SQL
|
|
380
|
+
/// compiler, search extractor, patch paths and ViewDefinition columns that
|
|
381
|
+
/// feed untrusted text through here never approach it.
|
|
382
|
+
pub const MAX_NESTING_DEPTH: usize = 100;
|
|
383
|
+
|
|
384
|
+
/// Nesting depth safe to parse inline on any thread HFS runs on, including a
|
|
385
|
+
/// 2 MB tokio worker in a debug build. Real FHIRPath expressions nest at most
|
|
386
|
+
/// two or three deep (measured across the bundled spec search parameters), so
|
|
387
|
+
/// the inline fast path covers all of them.
|
|
388
|
+
const INLINE_PARSE_DEPTH: usize = 6;
|
|
389
|
+
|
|
390
|
+
/// Stack for the off-thread parse of a deeply — but legally, within
|
|
391
|
+
/// [`MAX_NESTING_DEPTH`] — nested expression. 32 MB parses depth 100 in a
|
|
392
|
+
/// debug build with room to spare; 64 MB is margin. The address space is
|
|
393
|
+
/// reserved, not committed, so the reservation is free until touched.
|
|
394
|
+
const DEEP_PARSE_STACK_BYTES: usize = 64 * 1024 * 1024;
|
|
395
|
+
|
|
396
|
+
/// The deepest `(`/`[`/`{` nesting in `expression`, ignoring brackets inside
|
|
397
|
+
/// single-quoted string literals and backtick-delimited identifiers (both
|
|
398
|
+
/// with `\` escapes). One linear, allocation-free pass; used to reject input
|
|
399
|
+
/// that would overflow the recursive-descent parser (see [`MAX_NESTING_DEPTH`]).
|
|
400
|
+
fn max_nesting_depth(expression: &str) -> usize {
|
|
401
|
+
let mut depth: usize = 0;
|
|
402
|
+
let mut max: usize = 0;
|
|
403
|
+
let mut quote: Option<char> = None;
|
|
404
|
+
let mut escaped = false;
|
|
405
|
+
for c in expression.chars() {
|
|
406
|
+
if let Some(q) = quote {
|
|
407
|
+
if escaped {
|
|
408
|
+
escaped = false;
|
|
409
|
+
} else if c == '\\' {
|
|
410
|
+
escaped = true;
|
|
411
|
+
} else if c == q {
|
|
412
|
+
quote = None;
|
|
413
|
+
}
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
match c {
|
|
417
|
+
'\'' | '`' => quote = Some(c),
|
|
418
|
+
'(' | '[' | '{' => {
|
|
419
|
+
depth += 1;
|
|
420
|
+
max = max.max(depth);
|
|
421
|
+
}
|
|
422
|
+
')' | ']' | '}' => depth = depth.saturating_sub(1),
|
|
423
|
+
_ => {}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
max
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/// Runs `parse` inline when `depth` is shallow, or on a dedicated large-stack
|
|
430
|
+
/// thread when it is deeper, so a deeply nested expression cannot overflow the
|
|
431
|
+
/// caller's (possibly 2 MB) stack. Depth past [`MAX_NESTING_DEPTH`] is the
|
|
432
|
+
/// caller's to reject before calling this. The recursive-descent parser's
|
|
433
|
+
/// stack use grows with nesting; before this guard a few-thousand-deep column
|
|
434
|
+
/// path in a ViewDefinition overflowed the tokio worker and aborted the whole
|
|
435
|
+
/// process, which a stack overflow gives no chance to unwind.
|
|
436
|
+
fn run_parse<T: Send>(depth: usize, parse: impl FnOnce() -> T + Send) -> T {
|
|
437
|
+
if depth <= INLINE_PARSE_DEPTH {
|
|
438
|
+
return parse();
|
|
439
|
+
}
|
|
440
|
+
std::thread::scope(|scope| {
|
|
441
|
+
std::thread::Builder::new()
|
|
442
|
+
.stack_size(DEEP_PARSE_STACK_BYTES)
|
|
443
|
+
.spawn_scoped(scope, parse)
|
|
444
|
+
.expect("spawn FHIRPath deep-parse thread")
|
|
445
|
+
.join()
|
|
446
|
+
.expect("FHIRPath deep-parse thread panicked")
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/// The [`ParseDiagnostic`] returned when an expression is nested past
|
|
451
|
+
/// [`MAX_NESTING_DEPTH`]: it spans the whole expression, since the depth is a
|
|
452
|
+
/// property of the input as a whole rather than of one position in it.
|
|
453
|
+
fn nesting_diagnostic(expression: &str) -> ParseDiagnostic {
|
|
454
|
+
ParseDiagnostic {
|
|
455
|
+
span: (0, expression.chars().count()),
|
|
456
|
+
message: format!("nesting exceeds the maximum depth of {MAX_NESTING_DEPTH}"),
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
371
460
|
/// Parse a FHIRPath expression source string into a typed [`parser::Expression`] AST.
|
|
372
461
|
///
|
|
373
462
|
/// Provides a chumsky-free entry point for consumers that need the AST
|
|
374
463
|
/// (e.g. compiling FHIRPath to SQL) without taking a dependency on the
|
|
375
464
|
/// parser-combinator crate.
|
|
376
465
|
pub fn parse_expression(expression: &str) -> Result<parser::Expression, String> {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
)
|
|
387
|
-
|
|
466
|
+
let depth = max_nesting_depth(expression);
|
|
467
|
+
if depth > MAX_NESTING_DEPTH {
|
|
468
|
+
return Err(format!(
|
|
469
|
+
"Failed to parse FHIRPath expression: nesting exceeds the maximum depth of {MAX_NESTING_DEPTH}"
|
|
470
|
+
));
|
|
471
|
+
}
|
|
472
|
+
run_parse(depth, || {
|
|
473
|
+
use chumsky::Parser;
|
|
474
|
+
parser::parser()
|
|
475
|
+
.parse(expression)
|
|
476
|
+
.into_result()
|
|
477
|
+
.map_err(|e| {
|
|
478
|
+
format!(
|
|
479
|
+
"Failed to parse FHIRPath expression '{}': {:?}",
|
|
480
|
+
expression, e
|
|
481
|
+
)
|
|
482
|
+
})
|
|
483
|
+
})
|
|
388
484
|
}
|
|
389
485
|
|
|
390
486
|
/// A single parse error from [`parse_expression_diagnostics`], with its span
|
|
@@ -435,26 +531,31 @@ pub struct ParseDiagnostic {
|
|
|
435
531
|
pub fn parse_expression_diagnostics(
|
|
436
532
|
expression: &str,
|
|
437
533
|
) -> Result<parser::Expression, Vec<ParseDiagnostic>> {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
534
|
+
let depth = max_nesting_depth(expression);
|
|
535
|
+
if depth > MAX_NESTING_DEPTH {
|
|
536
|
+
return Err(vec![nesting_diagnostic(expression)]);
|
|
537
|
+
}
|
|
538
|
+
run_parse(depth, || {
|
|
539
|
+
use chumsky::Parser;
|
|
540
|
+
parser::parser()
|
|
541
|
+
.parse(expression)
|
|
542
|
+
.into_result()
|
|
543
|
+
.map_err(|errors| {
|
|
544
|
+
errors
|
|
545
|
+
.iter()
|
|
546
|
+
.map(|error| {
|
|
547
|
+
let span = error.span();
|
|
548
|
+
ParseDiagnostic {
|
|
549
|
+
span: (
|
|
550
|
+
byte_to_char_offset(expression, span.start),
|
|
551
|
+
byte_to_char_offset(expression, span.end),
|
|
552
|
+
),
|
|
553
|
+
message: error.to_string(),
|
|
554
|
+
}
|
|
555
|
+
})
|
|
556
|
+
.collect()
|
|
557
|
+
})
|
|
558
|
+
})
|
|
458
559
|
}
|
|
459
560
|
|
|
460
561
|
/// Converts a UTF-8 byte offset into `s` (assumed to already fall on a
|
|
@@ -498,26 +599,31 @@ fn byte_to_char_offset(s: &str, byte_offset: usize) -> usize {
|
|
|
498
599
|
pub fn parse_expression_spanned(
|
|
499
600
|
expression: &str,
|
|
500
601
|
) -> Result<parser::SpannedExpression, Vec<ParseDiagnostic>> {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
602
|
+
let depth = max_nesting_depth(expression);
|
|
603
|
+
if depth > MAX_NESTING_DEPTH {
|
|
604
|
+
return Err(vec![nesting_diagnostic(expression)]);
|
|
605
|
+
}
|
|
606
|
+
run_parse(depth, || {
|
|
607
|
+
use chumsky::Parser;
|
|
608
|
+
parser::spanned_parser()
|
|
609
|
+
.parse(expression)
|
|
610
|
+
.into_result()
|
|
611
|
+
.map_err(|errors| {
|
|
612
|
+
errors
|
|
613
|
+
.iter()
|
|
614
|
+
.map(|error| {
|
|
615
|
+
let span = error.span();
|
|
616
|
+
ParseDiagnostic {
|
|
617
|
+
span: (
|
|
618
|
+
byte_to_char_offset(expression, span.start),
|
|
619
|
+
byte_to_char_offset(expression, span.end),
|
|
620
|
+
),
|
|
621
|
+
message: error.to_string(),
|
|
622
|
+
}
|
|
623
|
+
})
|
|
624
|
+
.collect()
|
|
625
|
+
})
|
|
626
|
+
})
|
|
521
627
|
}
|
|
522
628
|
|
|
523
629
|
/// Converts a byte-offset [`parser::ExprSpan`] (as produced by
|
|
@@ -73,12 +73,11 @@ pub fn not_function(
|
|
|
73
73
|
// Convert invocation_base to its 3-valued logic boolean form.
|
|
74
74
|
// This handles singletons (Boolean, Integer, String, etc.) and empty/singleton collections.
|
|
75
75
|
// Pass R4 compatibility flag based on FHIR version
|
|
76
|
-
use helios_fhir::FhirVersion;
|
|
77
76
|
let r4_compat = match context.fhir_version {
|
|
78
77
|
#[cfg(feature = "R4")]
|
|
79
|
-
FhirVersion::R4 => true,
|
|
78
|
+
helios_fhir::FhirVersion::R4 => true,
|
|
80
79
|
#[cfg(feature = "R4B")]
|
|
81
|
-
FhirVersion::R4B => true,
|
|
80
|
+
helios_fhir::FhirVersion::R4B => true,
|
|
82
81
|
#[allow(unreachable_patterns)]
|
|
83
82
|
_ => false,
|
|
84
83
|
};
|
|
@@ -100,6 +100,31 @@ pub fn get_reference_key_function(
|
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
match invocation_base {
|
|
103
|
+
// A repeating Reference element (e.g. Encounter.episodeOfCare) arrives as a
|
|
104
|
+
// collection, even when it holds a single item: map over the items and drop
|
|
105
|
+
// the ones that yield no key.
|
|
106
|
+
EvaluationResult::Collection {
|
|
107
|
+
items,
|
|
108
|
+
has_undefined_order,
|
|
109
|
+
..
|
|
110
|
+
} => {
|
|
111
|
+
let mut keys = Vec::new();
|
|
112
|
+
for item in items {
|
|
113
|
+
match get_reference_key_function(item, args)? {
|
|
114
|
+
EvaluationResult::Empty => {}
|
|
115
|
+
key => keys.push(key),
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
Ok(match keys.len() {
|
|
119
|
+
0 => EvaluationResult::Empty,
|
|
120
|
+
1 => keys.remove(0),
|
|
121
|
+
_ => EvaluationResult::Collection {
|
|
122
|
+
items: keys,
|
|
123
|
+
has_undefined_order: *has_undefined_order,
|
|
124
|
+
type_info: None,
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
}
|
|
103
128
|
EvaluationResult::Object { map, .. } => {
|
|
104
129
|
// Look for the reference field
|
|
105
130
|
if let Some(reference_value) = map.get("reference") {
|
|
@@ -220,6 +245,58 @@ mod tests {
|
|
|
220
245
|
assert!(matches!(result, EvaluationResult::Empty));
|
|
221
246
|
}
|
|
222
247
|
|
|
248
|
+
#[test]
|
|
249
|
+
fn test_get_reference_key_function_on_collection() {
|
|
250
|
+
let reference = |value: &str| {
|
|
251
|
+
let mut map = HashMap::new();
|
|
252
|
+
map.insert(
|
|
253
|
+
"reference".to_string(),
|
|
254
|
+
EvaluationResult::String(value.to_string(), None, None),
|
|
255
|
+
);
|
|
256
|
+
EvaluationResult::Object {
|
|
257
|
+
map,
|
|
258
|
+
type_info: None,
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
let collection = |items| EvaluationResult::Collection {
|
|
262
|
+
items,
|
|
263
|
+
has_undefined_order: false,
|
|
264
|
+
type_info: None,
|
|
265
|
+
};
|
|
266
|
+
let filter = EvaluationResult::String("EpisodeOfCare".to_string(), None, None);
|
|
267
|
+
|
|
268
|
+
// A single-item collection yields the bare key
|
|
269
|
+
let single = collection(vec![reference("EpisodeOfCare/eoc1")]);
|
|
270
|
+
let result = get_reference_key_function(&single, std::slice::from_ref(&filter)).unwrap();
|
|
271
|
+
assert!(matches!(result, EvaluationResult::String(ref key, _, _) if key == "eoc1"));
|
|
272
|
+
|
|
273
|
+
// Items that do not match the type filter are dropped
|
|
274
|
+
let mixed = collection(vec![
|
|
275
|
+
reference("EpisodeOfCare/eoc1"),
|
|
276
|
+
reference("Patient/p1"),
|
|
277
|
+
reference("EpisodeOfCare/eoc2"),
|
|
278
|
+
]);
|
|
279
|
+
let result = get_reference_key_function(&mixed, std::slice::from_ref(&filter)).unwrap();
|
|
280
|
+
match result {
|
|
281
|
+
EvaluationResult::Collection { items, .. } => {
|
|
282
|
+
let keys: Vec<_> = items
|
|
283
|
+
.iter()
|
|
284
|
+
.map(|item| match item {
|
|
285
|
+
EvaluationResult::String(key, _, _) => key.as_str(),
|
|
286
|
+
_ => panic!("Expected string item"),
|
|
287
|
+
})
|
|
288
|
+
.collect();
|
|
289
|
+
assert_eq!(keys, ["eoc1", "eoc2"]);
|
|
290
|
+
}
|
|
291
|
+
_ => panic!("Expected collection result"),
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Nothing matching yields Empty
|
|
295
|
+
let none = collection(vec![reference("Patient/p1")]);
|
|
296
|
+
let result = get_reference_key_function(&none, &[filter]).unwrap();
|
|
297
|
+
assert!(matches!(result, EvaluationResult::Empty));
|
|
298
|
+
}
|
|
299
|
+
|
|
223
300
|
#[test]
|
|
224
301
|
fn test_parse_reference() {
|
|
225
302
|
assert_eq!(
|
|
@@ -256,8 +256,15 @@ pub async fn run_server(config: ServerConfig) -> Result<(), Box<dyn std::error::
|
|
|
256
256
|
// Create the server
|
|
257
257
|
let listener = tokio::net::TcpListener::bind(addr).await?;
|
|
258
258
|
|
|
259
|
-
// Start the server
|
|
260
|
-
axum::serve(listener, app)
|
|
259
|
+
// Start the server; drain on Ctrl-C or SIGTERM.
|
|
260
|
+
axum::serve(listener, app)
|
|
261
|
+
.with_graceful_shutdown(async {
|
|
262
|
+
let signal = helios_observability::shutdown::signal().await;
|
|
263
|
+
info!(signal, "Shutdown signal received, draining connections");
|
|
264
|
+
})
|
|
265
|
+
.await?;
|
|
266
|
+
// After the drain, so spans from the draining requests are exported too.
|
|
267
|
+
helios_observability::telemetry::shutdown();
|
|
261
268
|
|
|
262
269
|
Ok(())
|
|
263
270
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//! A pathologically nested FHIRPath expression is refused with a parse error
|
|
2
|
+
//! rather than overflowing the recursive-descent parser's stack and aborting
|
|
3
|
+
//! the process. Found by fuzzing the SQL-on-FHIR ViewDefinition column path on
|
|
4
|
+
//! 2026-09-30: a column `path` a few thousand parentheses deep crashed the
|
|
5
|
+
//! whole `hfs` process ("thread 'tokio-rt-worker' has overflowed its stack"),
|
|
6
|
+
//! taking every in-flight request with it — a stack overflow cannot be caught.
|
|
7
|
+
|
|
8
|
+
use helios_fhirpath::{
|
|
9
|
+
MAX_NESTING_DEPTH, parse_expression, parse_expression_diagnostics, parse_expression_spanned,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/// `id` wrapped in `depth` layers of parentheses — valid FHIRPath that parses
|
|
13
|
+
/// to the same thing as `id`, but drives the parser `depth` levels deep.
|
|
14
|
+
fn nested(depth: usize) -> String {
|
|
15
|
+
format!("{}id{}", "(".repeat(depth), ")".repeat(depth))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#[test]
|
|
19
|
+
fn depth_at_the_limit_still_parses() {
|
|
20
|
+
assert!(parse_expression(&nested(MAX_NESTING_DEPTH)).is_ok());
|
|
21
|
+
assert!(parse_expression_diagnostics(&nested(MAX_NESTING_DEPTH)).is_ok());
|
|
22
|
+
assert!(parse_expression_spanned(&nested(MAX_NESTING_DEPTH)).is_ok());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[test]
|
|
26
|
+
fn depth_past_the_limit_is_a_parse_error_not_a_crash() {
|
|
27
|
+
// Deep enough to overflow the stack without the guard; the guard turns it
|
|
28
|
+
// into an ordinary error on every entry point.
|
|
29
|
+
let expr = nested(20_000);
|
|
30
|
+
|
|
31
|
+
let err = parse_expression(&expr).unwrap_err();
|
|
32
|
+
assert!(err.contains("nesting"), "{err}");
|
|
33
|
+
|
|
34
|
+
let diags = parse_expression_diagnostics(&expr).unwrap_err();
|
|
35
|
+
assert!(
|
|
36
|
+
diags.iter().any(|d| d.message.contains("nesting")),
|
|
37
|
+
"{diags:?}"
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
let diags = parse_expression_spanned(&expr).unwrap_err();
|
|
41
|
+
assert!(
|
|
42
|
+
diags.iter().any(|d| d.message.contains("nesting")),
|
|
43
|
+
"{diags:?}"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[test]
|
|
48
|
+
fn brackets_inside_a_string_literal_do_not_count_toward_depth() {
|
|
49
|
+
// A string literal full of parentheses nests the parser one level, not 500,
|
|
50
|
+
// so it must parse rather than trip the guard.
|
|
51
|
+
let expr = format!("'{}'", "(".repeat(500));
|
|
52
|
+
assert!(
|
|
53
|
+
parse_expression(&expr).is_ok(),
|
|
54
|
+
"string literal was miscounted"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -45,8 +45,9 @@ chrono.workspace = true
|
|
|
45
45
|
async-trait = "0.1"
|
|
46
46
|
|
|
47
47
|
# The dashboard snapshot cache refreshes in a background task ("rt") and paces
|
|
48
|
-
# its cold-start wait ("time"); see `dashboard::snapshot`.
|
|
49
|
-
|
|
48
|
+
# its cold-start wait ("time"); see `dashboard::snapshot`. `shutdown::signal`
|
|
49
|
+
# needs "signal" and "macros" (for `select!`).
|
|
50
|
+
tokio = { version = "1", features = ["rt", "time", "signal", "macros"] }
|
|
50
51
|
|
|
51
52
|
# OpenTelemetry (feature-gated). Versions pinned to a mutually compatible set:
|
|
52
53
|
# core 0.32 / tracing-opentelemetry 0.33 (runs one minor ahead of core).
|