| Crates.io | helios-fhirpath |
| lib.rs | helios-fhirpath |
| version | 0.1.16 |
| created_at | 2025-08-22 16:17:57.517105+00 |
| updated_at | 2025-09-11 12:54:44.006599+00 |
| description | This is an implementation of HL7's FHIRPath Specification. |
| homepage | https://github.com/HeliosSoftware/hfs/tree/main/crates/fhirpath |
| repository | https://github.com/HeliosSoftware/hfs |
| max_upload_size | |
| id | 1806571 |
| size | 2,128,318 |
This is an implementation of HL7's FHIRPath Specification - 3.0.0-ballot written in Rust.
FHIRPath is a path-based navigation and extraction language for healthcare data that is used in many different contexts within healthcare IT systems. Here are the main places where FHIRPath is implemented and used:
FHIRPath is used to define and express constraints and co-occurrence rules in FHIR resources within the FHIR specification.
Example (Validation Invariant):
reference.startsWith('#').not() or
($context.reference.substring(1) in $resource.contained.id)
This invariant ensures that a local reference in a resource actually points to a contained resource that exists, checking that the reference (if it starts with "#") points to a valid contained resource ID.
Relevant Specification Link:
FHIRPath defines what contents a search parameter refers to in FHIR resources.
Example (Search Parameter Path):
Patient.name.given
This path is used in a search parameter definition to specify that the search parameter applies to a patient's given names.
More Complex Example:
Patient.extension('http://example.org/myExtension').value
This path is used to create a search parameter that indexes values from a specific extension.
Relevant Specification Link:
FHIRPath is used to express constraints in implementation guides, particularly for profile definitions.
Example (Profile Constraint):
telecom.where(system='phone').exists() or telecom.where(system='email').exists()
This constraint requires that a resource has at least one telecom with either a phone or email system.
Example (Slicing Discriminator):
Observation.category
This path is used as a discriminator for slicing, meaning the category element will define uniqueness in sliced arrays.
Relevant Specification Link:
FHIRPath is used in clinical decision support systems, particularly within CDS Hooks and smart apps.
Example (CDS Hook Prefetch Template):
"prefetch": {
"patient": "Patient/{{context.patientId}}",
"medications": "MedicationRequest?patient={{context.patientId}}&status=active",
"conditions": "Condition?patient={{context.patientId}}&clinicalStatus=active&_fhirpath=code.memberOf('http://example.org/ValueSet/ChronicConditions')"
}
This prefetch template uses FHIRPath to filter conditions to only those with codes in a specific value set.
Example (Clinical Rule):
Observation.where(code.coding.system='http://loinc.org' and code.coding.code='8480-6')
.value.quantity > 140
This expression identifies systolic blood pressure observations with values above 140.
Relevant Specification Link:
FHIRPath provides access to terminology services through a %terminologies object. This implementation supports all standard terminology operations.
â ïļ IMPORTANT: Default Terminology Servers By default, this implementation uses test terminology servers:
https://tx.fhir.org/r4/https://tx.fhir.org/r5/DO NOT USE THESE DEFAULT SERVERS IN PRODUCTION! They are test servers with limited resources and no SLA.
Configuring a Terminology Server:
# Via environment variable
export FHIRPATH_TERMINOLOGY_SERVER=https://your-terminology-server.com/fhir
# Via CLI option
fhirpath-cli --terminology-server https://your-terminology-server.com/fhir ...
# Via server option
fhirpath-server --terminology-server https://your-terminology-server.com/fhir
Supported %terminologies Functions:
# Expand a ValueSet
%terminologies.expand('http://hl7.org/fhir/ValueSet/administrative-gender')
# Lookup code details
%terminologies.lookup(Observation.code.coding.first())
# Validate against ValueSet
%terminologies.validateVS('http://hl7.org/fhir/ValueSet/observation-vitalsignresult', Observation.code.coding.first())
# Validate against CodeSystem
%terminologies.validateCS('http://loinc.org', Observation.code.coding.first())
# Check code subsumption
%terminologies.subsumes('http://snomed.info/sct', '73211009', '5935008')
# Translate using ConceptMap
%terminologies.translate('http://hl7.org/fhir/ConceptMap/cm-address-use-v2', Patient.address.use)
memberOf Function:
# Check if a coding is member of a ValueSet
Observation.code.coding.where(memberOf('http://hl7.org/fhir/ValueSet/observation-vitalsignresult'))
Example with Parameters:
# Expand with count limit
%terminologies.expand('http://hl7.org/fhir/ValueSet/languages', {'count': '10'})
# Validate with language parameter
%terminologies.validateVS('http://hl7.org/fhir/ValueSet/condition-clinical',
Condition.clinicalStatus.coding.first(),
{'language': 'es'})
Relevant Specification Link:
FHIRPath is used to map between different FHIR versions or between FHIR and other formats.
Example (Mapping Rule):
source.telecom.where(system='phone').value
This expression might be used in a mapping language to extract phone numbers from a source resource.
Relevant Specification Link:
The SQL on FHIR specification leverages FHIRPath to define flattened tabular views of FHIR data that can be queried using standard SQL.
Example ViewDefinition:
{
"resourceType": "ViewDefinition",
"id": "patient-demographics",
"name": "PatientDemographics",
"title": "Basic Patient Demographics",
"description": "A flattened view of key patient demographic information",
"from": {
"resourceType": "Patient"
},
"select": [
{
"column": [
{"name": "id", "path": "getResourceKey()"},
{"name": "birth_date", "path": "birthDate"},
{"name": "gender", "path": "gender"},
{"name": "first_name", "path": "name.where(use='official').given.first()"},
{"name": "last_name", "path": "name.where(use='official').family"},
{"name": "ssn", "path": "identifier.where(system='http://hl7.org/fhir/sid/us-ssn').value"},
{"name": "email", "path": "telecom.where(system='email').value"},
{"name": "phone", "path": "telecom.where(system='phone' and use='mobile').value"},
{"name": "address_line", "path": "address.where(use='home').line.join(', ')"},
{"name": "city", "path": "address.where(use='home').city"},
{"name": "state", "path": "address.where(use='home').state"},
{"name": "postal_code", "path": "address.where(use='home').postalCode"}
]
}
]
}
Relevant Specification Link:
Legend:
[]: â
= (Equals): â
(Full support for all types including dates and quantities)~ (Equivalent): â
(Full equivalence checking)!= (Not Equals): â
!~ (Not Equivalent): â
> (Greater Than): â
(Full support including dates and numeric types)< (Less Than): â
(Full support including dates and numeric types)<= (Less or Equal): â
(Full support including dates and numeric types)>= (Greater or Equal): â
(Full support including dates and numeric types)| (Union): â
in (Membership): â
contains (Containership): â
* (Multiplication): â
/ (Division): â
+ (Addition): â
(Numeric, String)- (Subtraction): â
div (Integer Division): â
(Numeric)mod (Modulo): â
(Numeric)& (String Concatenation): â
// and multi-line /* */ comments)%variable: â
(Full variable resolution including built-in constants)%context: â
(Full context support with $this, $index, $total)type()) (STU): â
(Enhanced with namespace support and type hierarchy)This FHIRPath implementation is built using a modular architecture with clear separation of concerns:
parser.rs): Converts FHIRPath expressions into an Abstract Syntax Tree (AST)evaluator.rs): Evaluates AST nodes against FHIR resources with context managementfhir_type_hierarchy.rs): Manages FHIR and System type hierarchies with version-aware resource type checkingThe implementation supports multiple FHIR versions (R4, R4B, R5, R6) through:
FhirResourceTypeProvider trait automatically extracts resource types from generated Resource enumsThe EvaluationContext provides the runtime environment for FHIRPath evaluation:
use helios_fhirpath::evaluator::EvaluationContext;
use helios_fhir::FhirVersion;
// Create context with explicit FHIR version
let context = EvaluationContext::new_empty(FhirVersion::R4);
// Create context with resources (version auto-detected)
let context = EvaluationContext::new(fhir_resources);
// Create context with specific version and resources
let context = EvaluationContext::new_with_version(fhir_resources, FhirVersion::R5);
The context includes:
$this, $index, $total)select() and where()The type system handles both FHIR and System namespaces:
boolean, string, integer, decimal, date, dateTime, time, etc.Quantity, HumanName, CodeableConcept, Reference, etc.Patient, Observation, Condition, etc.Boolean, String, Integer, Decimal, Date, DateTime, Time, QuantityThe implementation uses the FhirResourceTypeProvider trait to automatically detect resource types for each FHIR version:
use helios_fhir::FhirVersion;
use helios_fhirpath::evaluator::EvaluationContext;
// Context automatically detects FHIR version from resources
let context = EvaluationContext::new(resources);
// Or specify version explicitly
let context = EvaluationContext::new_with_version(resources, FhirVersion::R4);
The implementation leverages procedural macros to automatically generate type information:
IntoEvaluationResult implementations for all FHIR typesFhirResourceTypeProvider trait implementations for Resource enumsThis approach ensures that:
Each FHIRPath function category is implemented in its own module:
aggregate_function.rs: Implementation of aggregate() with accumulator supportboolean_functions.rs: Boolean logic functions (allTrue, anyFalse, etc.)collection_functions.rs: Collection manipulation (where, select, count, etc.)collection_navigation.rs: Navigation functions (children, descendants)conversion_functions.rs: Type conversion functions (toInteger, toString, etc.)date_operation.rs: Date/time operations and arithmeticextension_function.rs: FHIR extension access functionspolymorphic_access.rs: Choice element and polymorphic type operationsrepeat_function.rs: Implementation of repeat() with cycle detectionresource_type.rs: Type checking operations (is, as, ofType)trace_function.rs: Implementation of trace() with projection supporttype_function.rs: Type reflection and type() functionThis modular approach enables:
This crate provides two executable targets for FHIRPath expression evaluation:
fhirpath-cli - Command Line InterfaceA feature-rich command-line tool for evaluating FHIRPath expressions against FHIR resources.
# Install from the workspace root
cargo install --path crates/helios-fhirpath --bin fhirpath-cli
# Or build directly
cargo build --release --bin fhirpath-cli
-e, --expression <EXPRESSION> FHIRPath expression to evaluate
-c, --context <CONTEXT> Context expression to evaluate first
-r, --resource <RESOURCE> Path to FHIR resource JSON file (use '-' for stdin)
-v, --variables <VARIABLES> Path to variables JSON file
--var <KEY=VALUE> Set a variable directly
-o, --output <OUTPUT> Output file path (defaults to stdout)
--parse-debug-tree Output parse debug tree as JSON
--parse-debug Output parse debug info
--trace Enable trace output
--fhir-version <VERSION> FHIR version [default: R4]
--validate Validate expression before execution
--terminology-server <URL> Terminology server URL
-h, --help Print help
# Evaluate expression against a resource
fhirpath-cli -e "Patient.name.family" -r patient.json
# Get first given name
fhirpath-cli -e "Patient.name.given.first()" -r patient.json
# Filter telecom by system
fhirpath-cli -e "Patient.telecom.where(system = 'email')" -r patient.json
# Evaluate with context
fhirpath-cli -c "Patient.name" -e "given.join(' ')" -r patient.json
# Context with filtering
fhirpath-cli -c "Patient.telecom.where(system = 'phone')" -e "value" -r patient.json
# Variable from command line
fhirpath-cli -e "value > %threshold" -r observation.json --var threshold=5.0
# Multiple variables
fhirpath-cli -e "%system = 'phone' and use = %use" -r patient.json \
--var system=phone --var use=mobile
# Variables from JSON file
cat > vars.json << EOF
{
"threshold": 140,
"unit": "mm[Hg]"
}
EOF
fhirpath-cli -e "value.value > %threshold and value.unit = %unit" \
-r observation.json -v vars.json
# Generate parse debug tree (JSON format)
fhirpath-cli -e "Patient.name.where(use = 'official').given.first()" \
--parse-debug-tree
# Generate parse debug text
fhirpath-cli -e "Patient.name.given.first() | Patient.name.family" \
--parse-debug
# Resource from stdin
cat patient.json | fhirpath-cli -e "Patient.name.family" -r -
# Pipe from other commands
curl -s https://example.com/fhir/Patient/123 | \
fhirpath-cli -e "name.family" -r -
# Output to file
fhirpath-cli -e "Patient.name" -r patient.json -o names.json
# Pretty printed JSON output (default)
fhirpath-cli -e "Patient.identifier" -r patient.json
fhirpath-server - HTTP ServerAn HTTP server providing FHIRPath expression evaluation via a REST API, compatible with fhirpath-lab.
# Install from the workspace root
cargo install --path crates/helios-fhirpath --bin fhirpath-server
# Or build directly
cargo build --release --bin fhirpath-server
The server can be configured via command-line arguments or environment variables:
| Environment Variable | CLI Argument | Description | Default |
|---|---|---|---|
FHIRPATH_SERVER_PORT |
--port |
Server port | 3000 |
FHIRPATH_SERVER_HOST |
--host |
Server host | 127.0.0.1 |
FHIRPATH_LOG_LEVEL |
--log-level |
Log level (error/warn/info/debug/trace) | info |
FHIRPATH_ENABLE_CORS |
--enable-cors |
Enable CORS | true |
FHIRPATH_CORS_ORIGINS |
--cors-origins |
Allowed origins (comma-separated) | * |
FHIRPATH_CORS_METHODS |
--cors-methods |
Allowed methods | GET,POST,OPTIONS |
FHIRPATH_CORS_HEADERS |
--cors-headers |
Allowed headers | Common headers |
# Start with defaults
fhirpath-server
# Custom port and host
fhirpath-server --port 8080 --host 0.0.0.0
# With environment variables
FHIRPATH_SERVER_PORT=8080 FHIRPATH_LOG_LEVEL=debug fhirpath-server
# Production configuration
fhirpath-server \
--host 0.0.0.0 \
--port 8080 \
--log-level warn \
--cors-origins "https://fhirpath-lab.com,https://dev.fhirpath-lab.com,https://fhirpath-lab.azurewebsites.net,https://fhirpath-lab-dev.azurewebsites.net/,http://localhost:3000"
Accepts a FHIR Parameters resource and returns evaluation results. Auto-detects the FHIR version from the resource.
Forces evaluation with a specific FHIR version (if compiled with the corresponding feature). Useful when you want to ensure your resource is processed with a specific FHIR version, overriding auto-detection.
Request Body (FHIR Parameters):
{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.name.given.first()"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"name": [{
"given": ["John", "James"],
"family": "Doe"
}]
}
}
]
}
Response (FHIR Parameters):
{
"resourceType": "Parameters",
"id": "fhirpath",
"parameter": [
{
"name": "parameters",
"part": [
{
"name": "evaluator",
"valueString": "Helios FHIRPath-0.1.0"
},
{
"name": "expression",
"valueString": "Patient.name.given.first()"
},
{
"name": "resource",
"resource": { "...": "..." }
}
]
},
{
"name": "result",
"valueString": "Resource",
"part": [
{
"name": "string",
"valueString": "John"
}
]
}
]
}
Supported Input Parameters:
expression (required): FHIRPath expression to evaluatecontext (optional): Context expression to evaluate firstresource (required): FHIR resource to evaluate againstvalidate (optional): Whether to validate the expressionvariables (optional): Variables to pass to the expressionterminologyServer (optional): Terminology server URLAdditional Output Parameters (when validate is true):
parseDebugTree: JSON representation of the expression ASTparseDebug: Text representation of the parse treeexpectedReturnType: Expected return type of the expressionReturns server health status.
curl http://localhost:3000/health
Response:
{
"status": "ok",
"service": "fhirpath-server"
}
# Auto-detect FHIR version
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.birthDate"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"birthDate": "1974-12-25"
}
}
]
}'
# Force R4 processing
curl -X POST http://localhost:3000/r4 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.birthDate"
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"birthDate": "1974-12-25"
}
}
]
}'
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "context",
"valueString": "Observation.component"
},
{
"name": "expression",
"valueString": "value > %threshold"
},
{
"name": "variables",
"part": [
{
"name": "threshold",
"valueString": "140"
}
]
},
{
"name": "resource",
"resource": {
"resourceType": "Observation",
"component": [
{"valueQuantity": {"value": 150}},
{"valueQuantity": {"value": 130}}
]
}
}
]
}'
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{
"resourceType": "Parameters",
"parameter": [
{
"name": "expression",
"valueString": "Patient.name.given.first() | Patient.name.family"
},
{
"name": "validate",
"valueBoolean": true
},
{
"name": "resource",
"resource": {
"resourceType": "Patient",
"name": [{"given": ["John"], "family": "Doe"}]
}
}
]
}'
The server is compatible with fhirpath-lab. To use your local server with fhirpath-lab:
Start the server with CORS enabled for fhirpath-lab domains:
fhirpath-server --cors-origins "https://fhirpath-lab.com,http://localhost:3000"
In fhirpath-lab, configure the custom server URL to point to your local instance
The server will properly handle all fhirpath-lab requests including parse debug tree generation
This implementation is designed for high performance FHIRPath expression evaluation. We use Criterion.rs for comprehensive performance benchmarking across all major components.
To run all benchmarks:
cargo bench
To run specific benchmark suites:
# Parser benchmarks only
cargo bench --bench parser_benches
# Evaluator benchmarks only
cargo bench --bench evaluator_benches
# CLI benchmarks only
cargo bench --bench cli_benches
# Server benchmarks only
cargo bench --bench server_benches
Benchmark results are saved in target/criterion/ with HTML reports for detailed analysis.
parser_benches)evaluator_benches)cli_benches)server_benches)The following results are from a typical development machine (results will vary based on hardware):
| Operation | Time (avg) | Description |
|---|---|---|
| Parser | ||
| Simple path | ~500 ns | Patient.name |
| Nested path | ~800 ns | Patient.name.family |
| Function call | ~1.2 Ξs | Patient.name.first() |
| Complex filter | ~3.5 Ξs | Patient.telecom.where(system = 'phone') |
| Evaluator | ||
| Field access | ~1.5 Ξs | Navigate to single field |
| Collection filter | ~4.2 Ξs | Filter telecom by system |
| String operation | ~2.8 Ξs | Upper case conversion |
| Type check | ~1.8 Ξs | Check resource type |
| CLI | ||
| Simple expression | ~150 Ξs | Full CLI execution |
| With variables | ~180 Ξs | Variable resolution |
| Bundle processing | ~450 Ξs | Process 10 resources |
| Server | ||
| Simple request | ~350 Ξs | Basic expression evaluation |
| Complex request | ~500 Ξs | With filtering and context |
| Large bundle | ~2.5 ms | Process 50 resources |
Expression Optimization
Resource Optimization
Server Optimization
Memory Usage
Our benchmarks follow these principles:
The benchmark suite is continuously expanded to cover new features and edge cases.