This is an implementation of HL7's FHIRPath Specification - 3.0.0-ballot written in Rust.
This implementation is available for testing in Brian Postlethwaite's FHIRPath Lab.
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.
- R4/R4B:
https://tx.fhir.org/r4/ - R5:
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/fhirSupported %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:
- ✅ Implemented
- 🟡 Partially Implemented (Basic functionality, known limitations)
- ❌ Not Implemented
- 🚧 In Progress
- (STU) - Standard for Trial Use in the specification
- Literals
- Boolean: ✅
- String: ✅
- Integer: ✅
- Long (STU): 🟡 (Parser support, runtime implementation gaps)
- Decimal: ✅
- Date: ✅ (Full parsing and arithmetic support)
- Time: ✅ (Full parsing and comparison support)
- DateTime: ✅ (Full parsing, timezone and arithmetic support)
- Quantity: 🟡 (Basic value/unit storage, limited unit conversion)
- Time-valued Quantities: 🟡 (Keywords parsed, conversion implementation needed)
- Existence
- empty(): ✅
- exists(): ✅
- all(): ✅
- allTrue(): ✅
- anyTrue(): ✅
- allFalse(): ✅
- anyFalse(): ✅
- subsetOf(): ✅
- supersetOf(): ✅
- count(): ✅
- distinct(): ✅
- isDistinct(): ✅
- Filtering and Projection
- where(): ✅
- select(): ✅
- sort() (STU): ✅ (Sort with optional key selector)
- repeat(): ✅ (With cycle detection)
- repeatAll() (STU): ✅
- ofType(): ✅ (Full namespace qualification support)
- coalesce() (STU): ✅
- Subsetting
- Indexer
[]: ✅ - single(): ✅
- first(): ✅
- last(): ✅
- tail(): ✅
- skip(): ✅
- take(): ✅
- intersect(): ✅
- exclude(): ✅
- Indexer
- Combining
- Conversion
- Implicit Conversions: ✅ (Integer/Decimal)
- iif(): ✅
- toBoolean(): ✅
- convertsToBoolean(): ✅
- toInteger(): ✅
- convertsToInteger(): ✅
- toLong() (STU): ✅
- convertsToLong() (STU): ✅
- toDate(): ✅ (Including optional
formatparameter) - convertsToDate(): ✅
- toDateTime(): ✅ (Including optional
formatparameter) - convertsToDateTime(): ✅
- toDecimal(): ✅
- convertsToDecimal(): ✅
- toQuantity(): 🟡 (Basic types, no unit conversion)
- convertsToQuantity(): 🟡 (Basic types, no unit conversion)
- toString(): ✅ (Including optional
formatparameter) - convertsToString(): ✅
- toTime(): ✅
- convertsToTime(): ✅
- Date Conversion Functions (STU)
- Date/DateTime/Time string format codes (
yyyy,MM,dd, etc.): ✅
- Date/DateTime/Time string format codes (
- String Manipulation
- indexOf(): ✅
- lastIndexOf() (STU): ✅
- substring(): ✅
- startsWith(): ✅
- endsWith(): ✅
- contains(): ✅
- upper(): ✅
- lower(): ✅
- replace(): ✅
- matches(): ✅ (Including optional
flagsparameter:s,m,i,x) - matchesFull() (STU): ✅ (Including optional
flagsparameter) - replaceMatches(): ✅ (Including optional
flagsparameter) - length(): ✅
- toChars(): ✅
- encode(): ✅
- decode(): ✅
- Additional String Functions (STU): ✅
- escape(): ✅ (html, json targets)
- unescape(): ✅ (html, json targets)
- split(): ✅
- join(): ✅
- trim(): ✅
- Math (STU): ✅
- Tree Navigation
- children(): ✅
- descendants(): ✅
- extension(): ✅ (Full support for object and primitive extensions with variable resolution)
- Utility Functions
- trace(): ✅ (With projection support)
- now(): ✅
- timeOfDay(): ✅
- today(): ✅
- defineVariable() (STU): ✅
- lowBoundary() (STU): ✅ (Full support for Decimal, Date, DateTime, and Time)
- highBoundary() (STU): ✅ (Full support for Decimal, Date, DateTime, and Time)
- precision() (STU): ✅ (See limitation for decimal trailing zeros)
- Date/DateTime/Time Component Extraction (STU): ✅ (All component functions implemented: yearOf, monthOf, dayOf, hourOf, minuteOf, secondOf, millisecondOf)
- Date and Time Interval Functions (STU)
- duration(): ✅
- difference(): ✅
- Equality
=(Equals): ✅ (Full support for all types including dates and quantities)~(Equivalent): ✅ (Full equivalence checking)!=(Not Equals): ✅!~(Not Equivalent): ✅
- Comparison
>(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)
- Types
- Collections
|(Union): ✅in(Membership): ✅contains(Containership): ✅- Collection Navigation: ✅ (Full polymorphic access and choice element support)
- Boolean Logic
- Math
*(Multiplication): ✅/(Division): ✅+(Addition): ✅ (Numeric, String)-(Subtraction): ✅div(Integer Division): ✅ (Numeric)mod(Modulo): ✅ (Numeric)&(String Concatenation): ✅
- Date/Time Arithmetic: ✅ (Full arithmetic support with timezone and precision handling)
- Unary Operators (
+and-): ✅ - Operator Precedence: ✅
Instance Selector (STU)
- Object creation syntax (
typename { element : value, ... }): ✅
- aggregate() (STU): ✅ (Full accumulator support)
- sum() (STU): ✅
- min() (STU): ✅
- max() (STU): ✅
- avg() (STU): ✅
- Lexical Elements: ✅ (Handled by parser)
- Comments: ✅ (Both single-line
//and multi-line/* */comments)
%variable: ✅ (Full variable resolution including built-in constants)%context: ✅ (Full context support with $this, $index, $total)
- Models: ✅ (Full namespace qualification and FHIR type hierarchy support)
- Reflection (
type()) (STU): ✅ (Enhanced with namespace support and type hierarchy)
- Type Safety / Strict Evaluation: ✅ (Configurable strict mode with proper error handling)
These functions extend the base FHIRPath specification with FHIR-specific capabilities.
-
- extension(): ✅ (Full support with variable URL resolution)
- hasValue(): ✅ (Tests if primitive has actual value beyond extensions)
- getValue(): ❌ Not Implemented
- resolve(): ❌ Not Implemented (Requires resource resolver integration)
- ofType(): ✅ (Full FHIR type support)
- elementDefinition(): ❌ Not Implemented
- slice(): ❌ Not Implemented
- checkModifiers(): ❌ Not Implemented
- conformsTo(): ❌ Not Implemented (Requires profile validation)
- memberOf(): ✅ (Via %terminologies integration)
- subsumes(): ❌ Not Implemented (Function form; %terminologies.subsumes available)
- subsumedBy(): ❌ Not Implemented
- htmlChecks(): ❌ Not Implemented (XHTML narrative validation)
- comparable(): ✅ (UCUM unit comparison)
- weight(): ❌ Not Implemented
-
- %factory.{primitive}(): ❌ Not Implemented
- %factory.Extension(): ❌ Not Implemented
- %factory.Identifier(): ❌ Not Implemented
- %factory.HumanName(): ❌ Not Implemented
- %factory.ContactPoint(): ❌ Not Implemented
- %factory.Address(): ❌ Not Implemented
- %factory.Quantity(): ❌ Not Implemented
- %factory.Coding(): ❌ Not Implemented
- %factory.CodeableConcept(): ❌ Not Implemented
- %factory.create(): ❌ Not Implemented
- %factory.withExtension(): ❌ Not Implemented
- %factory.withProperty(): ❌ Not Implemented
-
- %server.at(): ❌ Not Implemented
- %server.read(): ❌ Not Implemented
- %server.create(): ❌ Not Implemented
- %server.update(): ❌ Not Implemented
- %server.delete(): ❌ Not Implemented
- %server.patch(): ❌ Not Implemented
- %server.search(): ❌ Not Implemented
- %server.capabilities(): ❌ Not Implemented
- %server.validate(): ❌ Not Implemented
- %server.transform(): ❌ Not Implemented
- %server.everything(): ❌ Not Implemented
- %server.apply(): ❌ Not Implemented
This FHIRPath implementation is built using a modular architecture with clear separation of concerns:
- Parser (
parser.rs): Converts FHIRPath expressions into an Abstract Syntax Tree (AST) - Evaluator (
evaluator.rs): Evaluates AST nodes against FHIR resources with context management - Type System (
fhir_type_hierarchy.rs): Manages FHIR and System type hierarchies with version-aware resource type checking - Function Modules: Specialized modules for individual FHIRPath functions and operations
The implementation supports multiple FHIR versions (R4, R4B, R5, R6) through:
- Feature flags: Each FHIR version is enabled via Cargo features
- Version-aware type checking: Resource type validation uses the appropriate FHIR version's Resource enum
- Dynamic resource type discovery: The
FhirResourceTypeProvidertrait automatically extracts resource types from generated Resource enums
The 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:
- FHIR Version: Used for version-specific type checking and resource validation
- Resources: Available FHIR resources for evaluation
- Variables: Environment variables (including
$this,$index,$total) - Configuration: Strict mode, ordered function checking, etc.
- Variable Scoping: Parent context support for proper variable scoping in functions like
select()andwhere()
The type system handles both FHIR and System namespaces:
- Primitive types:
boolean,string,integer,decimal,date,dateTime,time, etc. - Complex types:
Quantity,HumanName,CodeableConcept,Reference, etc. - Resource types: Version-specific types like
Patient,Observation,Condition, etc.
- Primitive types:
Boolean,String,Integer,Decimal,Date,DateTime,Time,Quantity
The 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:
- FhirPath Macro: Automatically generates
IntoEvaluationResultimplementations for all FHIR types - Resource Type Provider: Automatically generates
FhirResourceTypeProvidertrait implementations for Resource enums - Dynamic Resource Discovery: Resource type information is extracted at compile time from the actual FHIR specification
This approach ensures that:
- Resource type lists are never hardcoded
- Each FHIR version gets accurate resource type information
- Type information stays in sync with the generated FHIR models
Each FHIRPath function category is implemented in its own module:
aggregate_function.rs: Implementation ofaggregate()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 ofrepeat()with cycle detectionresource_type.rs: Type checking operations (is,as,ofType)trace_function.rs: Implementation oftrace()with projection supporttype_function.rs: Type reflection andtype()function
This modular approach enables:
- Clear separation of concerns by function category
- Independent testing of each function group
- Easy addition of new functions
- Maintainable and organized code structure
This crate provides two executable targets for FHIRPath expression evaluation:
A 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- Expression Evaluation: Execute FHIRPath expressions against FHIR resources
- Context Support: Evaluate expressions with context for scoped evaluation
- Variables: Define variables via command line or JSON file
- Parse Debug: Generate AST visualizations for expression analysis
- FHIR Version Support: Handle resources from any supported FHIR version
- JSON Output: Results formatted as JSON for easy processing
-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.jsonAn 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- FHIRPath Evaluation API: POST endpoint accepting FHIR Parameters resources
- Parse Debug Tree: Generate and return AST visualizations
- Variable Support: Pass variables to expressions via Parameters
- Context Expressions: Support for context-based evaluation
- CORS Configuration: Flexible cross-origin resource sharing
- Health Check: Simple health status endpoint
- fhirpath-lab Compatible: Full compatibility with the fhirpath-lab tool
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 |
FHIRPATH_DEBUG_TRACE |
— | Enable step-by-step debug trace output | false |
# 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 URL
Additional Output Parameters (when validate is true):
parseDebugTree: JSON representation of the expression AST (includesPositionandLengthfor each node)parseDebug: Text representation of the parse treeexpectedReturnType: Expected return type of the expression
Additional Output Parameters (when FHIRPATH_DEBUG_TRACE=1):
debug-trace: Step-by-step execution trace showing every intermediate evaluation result. Each step includes the source position, length, function name, and the evaluated result. This is useful for debugging complex expressions in fhirpath-lab. Disabled by default for zero performance overhead.
Returns server health status.
curl http://localhost:3000/healthResponse:
{
"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 benchTo 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_benchesBenchmark results are saved in target/criterion/ with HTML reports for detailed analysis.
- Simple expressions: Basic paths, literals, and indexed access
- Function calls: Single functions, chained functions, nested calls
- Operators: Arithmetic, comparison, boolean logic, unions
- Complex expressions: Filters, type checking, extensions, aggregates
- Large expressions: Many conditions, deep nesting, multiple functions
- Navigation: Simple and nested field access, indexing
- Collections: where(), select(), exists(), count(), distinct()
- String operations: Concatenation, upper/lower, substring, regex
- Type operations: is(), ofType(), as(), type reflection
- Date/time: Comparisons, today(), now(), arithmetic
- Extensions: URL-based access, typed values
- Complex expressions: Multi-step filters, unions, quantity comparisons
- Simple expressions: Basic navigation with and without functions
- Context expressions: Simple and complex context evaluation
- Variables: Inline variables and file-based variables
- Bundle operations: Filtering and aggregation on bundles
- Debug features: Parse tree generation and validation
- Simple requests: Basic expressions and health checks
- Complex requests: Filters, context, and variables
- Validation: Parse debug tree generation
- Large resources: Bundle processing with many entries
- Concurrent requests: Parallel request handling
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
- Use specific paths instead of wildcards when possible
- Filter early in the expression chain
- Avoid redundant type checks
-
Resource Optimization
- Keep resource sizes reasonable
- Use appropriate FHIR version features
- Consider using context expressions for repeated navigation
-
Server Optimization
- Enable connection pooling for high load
- Use appropriate log levels in production
- Configure CORS for specific origins only
-
Memory Usage
- The evaluator uses streaming where possible
- Large collections are processed lazily
- Recursive expressions have cycle detection
Our benchmarks follow these principles:
- Use realistic FHIR resources and expressions
- Cover both simple and complex scenarios
- Measure end-to-end performance for CLI/server
- Include memory allocation patterns
- Test with various resource sizes
- Verify correctness alongside performance
The benchmark suite is continuously expanded to cover new features and edge cases.