haste-pointer 0.127.6

Pointer utilities for Haste Health.
Documentation

haste-pointer

Pointers into FHIR values, built on MetaValue from haste-reflect. A Path is a JSON Pointer style string such as /name/0/family/value: extend it with descend, split it with ascend into the parent path and the last Key, and resolve it against any &dyn MetaValue with get or get_typed::<T>. Field names containing / or ~ are escaped the JSON Pointer way (~1 and ~0). A TypedPointer<Root, T> pairs a shared root (Arc<Root>) with a position inside it: it knows its path and its current value, and descend::<Child>(&Key) only moves when the child really has that type.

haste-fhir-profiling reports validation failures at a Path, haste-testscript-runner walks fixtures with a TypedPointer, and the haste-access-control rule engine uses one to address the rules inside an AccessPolicyV2.

Install

cargo add haste-pointer

Usage

use std::sync::Arc;

use haste_fhir_model::r4::generated::{
    resources::Patient,
    types::{FHIRString, HumanName},
};
use haste_pointer::{Key, Path, TypedPointer};

let patient = Arc::new(Patient {
    name: Some(vec![HumanName {
        family: Some(Box::new(FHIRString {
            value: Some("Doe".to_string()),
            ..Default::default()
        })),
        ..Default::default()
    }]),
    ..Default::default()
});

// Untyped: build a path and resolve it against any MetaValue.
let path = Path::new().descend("name").descend("0").descend("family").descend("value");
assert_eq!(path.to_string(), "/name/0/family/value");
assert_eq!(path.get_typed::<String>(patient.as_ref()), Some(&"Doe".to_string()));

// Typed: each step names the type it expects and answers None otherwise.
let family = TypedPointer::<Patient, Patient>::new(patient)
    .descend::<Vec<HumanName>>(&Key::Field("name".to_string()))
    .and_then(|p| p.descend::<HumanName>(&Key::Index(0)))
    .and_then(|p| p.descend::<Box<FHIRString>>(&Key::Field("family".to_string())))
    .unwrap();
assert_eq!(family.path(), "/name/0/family");
assert_eq!(family.value().and_then(|f| f.value.as_deref()), Some("Doe"));

Key::parse reads a segment as Key::Index when it is a number and Key::Field otherwise, and TypedPointer::root() returns to the top of the resource.

Links

Part of Haste Health, licensed under Apache-2.0.