Engine

Struct Engine 

Source
pub struct Engine { /* private fields */ }
Expand description

Main FHIRPath engine

Requires a FHIR context for runtime type resolution from StructureDefinitions. The context is used during AST → HIR compilation to infer types for path navigation.

Optionally accepts a custom ResourceResolver for overriding the resolve() function behavior. This is useful for database-backed resolution or other custom logic.

Implementations§

Source§

impl Engine

Source

pub fn new( context: Arc<dyn FhirContext>, resolver: Option<Arc<dyn ResourceResolver>>, ) -> Self

Create a new engine with FHIR context and custom ResourceResolver

The FHIR context provides StructureDefinition lookup for type inference during HIR generation. This allows the engine to work with any Implementation Guide without requiring static compilation of all FHIR types.

The custom resolver will be used by the resolve() function to resolve FHIR references. This is useful for database-backed resolution or other custom logic.

§Example
use fhirpath_engine::{Engine, ResourceResolver};
use std::sync::Arc;

struct MyResolver { /* ... */ }
impl ResourceResolver for MyResolver { /* ... */ }

let resolver = Arc::new(MyResolver::new());
let engine = Engine::new_with_resolver(fhir_context, Some(resolver));
Source

pub async fn with_fhir_version(version: &str) -> Result<Self>

Create an engine with a default FHIR context loaded from registry cache (async).

The engine will attempt to load the base FHIR package for the specified version from the registry cache (~/.fhir/packages/). If the package is not found in cache, it will download from Simplifier.

Supported versions: “R4”, “R4B”, “R5”

§Example
use tlq_fhirpath::Engine;

// Load R5 context from cache or download
let engine = Engine::with_fhir_version("R5").await?;
Source

pub fn fhir_context(&self) -> &Arc<dyn FhirContext>

Source

pub fn resource_resolver(&self) -> Option<&Arc<dyn ResourceResolver>>

Get the custom resource resolver (if any)

Source

pub fn compile(&self, expr: &str, base_type: Option<&str>) -> Result<Arc<Plan>>

Compile a FHIRPath expression to a VM plan.

Optionally accepts a base type name for strict validation. When provided (e.g., Some("Patient")), the compiler will validate that all field accesses are valid according to the StructureDefinition.

For explicit (decoupled) strictness and base typing, use compile_with_options().

If the type is not found in the FHIR context or type registry, compilation will still proceed but with reduced type validation (the analyzer will use a fallback type). This allows compilation to work even with empty contexts or unknown types, which is useful for testing or when working without full FHIR package definitions.

§Example
use tlq_fhirpath::Engine;

let engine = Engine::with_fhir_version("R5").await?;

// Compile without type validation
let plan1 = engine.compile("Patient.name.given", None)?;

// Compile with type validation
let plan2 = engine.compile("name.given", Some("Patient"))?;
Source

pub fn compile_with_options( &self, expr: &str, options: CompileOptions, ) -> Result<Arc<Plan>>

Compile a FHIRPath expression to a VM plan with explicit options.

Source

pub fn evaluate(&self, plan: &Plan, ctx: &Context) -> Result<Collection>

Evaluate a compiled plan against a context.

Source

pub fn evaluate_batch( &self, plan: &Plan, json_strings: &[&str], ) -> Result<Vec<Collection>>

Evaluate a compiled plan against multiple JSON string resources in batch.

OPTIMIZED: Accepts JSON strings directly to avoid double serialization. This is highly optimized for bulk operations:

  • Single FFI boundary crossing instead of N calls
  • Avoids JSON serialization overhead (resources already strings)
  • Tight loop in Rust for better CPU cache utilization
§Example
let plan = engine.compile("Patient.name.given")?;
let json_strings = vec!["{\"resourceType\":\"Patient\"...}", ...];
let results = engine.evaluate_batch(&plan, &json_strings)?;
Source

pub fn evaluate_expr( &self, expr: &str, ctx: &Context, base_type: Option<&str>, ) -> Result<Collection>

Evaluate an expression directly (compile + evaluate).

Optionally accepts a base type name for strict validation during compilation.

For explicit (decoupled) strictness and base typing, use evaluate_expr_with_options().

§Example
use tlq_fhirpath::{Engine, Context, Value};

let engine = Engine::with_fhir_version("R5").await?;
let ctx = Context::new(Value::empty());

// Evaluate without type validation
let result1 = engine.evaluate_expr("1 + 2", &ctx, None)?;

// Evaluate with type validation
let result2 = engine.evaluate_expr("name.given", &ctx, Some("Patient"))?;
Source

pub fn evaluate_expr_with_options( &self, expr: &str, ctx: &Context, options: EvalOptions, ) -> Result<Collection>

Evaluate an expression directly (compile + evaluate) with explicit options.

Source

pub fn evaluate_json( &self, expr: &str, resource: Value, base_type: Option<&str>, ) -> Result<Collection>

Evaluate an expression against a JSON resource.

Optionally accepts a base type name for strict validation during compilation.

§Example
use tlq_fhirpath::Engine;
use serde_json::json;

let engine = Engine::with_fhir_version("R5").await?;
let resource = json!({"resourceType": "Patient", "name": [{"given": ["John"]}]});

// Evaluate without type validation
let result1 = engine.evaluate_json("Patient.name.given", &resource, None)?;

// Evaluate with type validation
let result2 = engine.evaluate_json("name.given", &resource, Some("Patient"))?;
Source

pub fn evaluate_value( &self, expr: &str, resource: Value, base_type: Option<&str>, ) -> Result<Collection>

Evaluate an expression against a Value.

Optionally accepts a base type name for strict validation during compilation.

§Example
use tlq_fhirpath::{Engine, Value};

let engine = Engine::with_fhir_version("R5").await?;
let resource = Value::empty();

// Evaluate without type validation
let result1 = engine.evaluate_value("1 + 2", resource.clone(), None)?;

// Evaluate with type validation
let result2 = engine.evaluate_value("name.given", resource, Some("Patient"))?;
Source

pub fn is_fhir_type(&self, type_name: &str) -> bool

Check if a type name is a FHIR type (not a System type)

Source

pub fn visualize_pipeline( &self, expr: &str, format: VisualizationFormat, ) -> Result<PipelineVisualization>

Visualize the compilation pipeline for an expression

Returns AST, HIR, and VM Plan visualizations in the specified format.

§Example
use fhirpath_engine::{Engine, visualize::VisualizationFormat};

let engine = Engine::with_empty_context();
let viz = engine.visualize_pipeline("Patient.name", VisualizationFormat::AsciiTree)?;
println!("AST:\n{}", viz.ast);
println!("HIR:\n{}", viz.hir);
println!("Plan:\n{}", viz.plan);
Source

pub fn visualize_ast( &self, expr: &str, format: VisualizationFormat, ) -> Result<String>

Visualize just the AST for an expression

Source

pub fn visualize_hir( &self, expr: &str, format: VisualizationFormat, ) -> Result<String>

Visualize just the HIR for an expression

Source

pub fn visualize_plan( &self, expr: &str, format: VisualizationFormat, ) -> Result<String>

Visualize just the VM Plan for an expression

Auto Trait Implementations§

§

impl Freeze for Engine

§

impl !RefUnwindSafe for Engine

§

impl Send for Engine

§

impl Sync for Engine

§

impl Unpin for Engine

§

impl !UnwindSafe for Engine

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more