haste-pointer 0.129.1

Pointer utilities for Haste Health.
Documentation
# haste-pointer

Pointers into FHIR values, built on `MetaValue` from [`haste-reflect`](https://crates.io/crates/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`](https://crates.io/crates/haste-fhir-profiling) reports validation failures at a `Path`, [`haste-testscript-runner`](https://crates.io/crates/haste-testscript-runner) walks fixtures with a `TypedPointer`, and the [`haste-access-control`](https://crates.io/crates/haste-access-control) rule engine uses one to address the rules inside an `AccessPolicyV2`.

## Install

```bash
cargo add haste-pointer
```

## Usage

```rust
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

- [API reference](https://rust.haste.health/haste_pointer/)
- [Source](https://github.com/HasteHealth/HasteHealth/tree/main/backend/crates/pointer)
- [Rust SDK overview](https://haste.health/docs/api/sdks/rust)
- Related crates: [haste-reflect](https://crates.io/crates/haste-reflect), [haste-fhir-model](https://crates.io/crates/haste-fhir-model)
- TypeScript equivalent: [@haste-health/fhir-pointer](https://www.npmjs.com/package/@haste-health/fhir-pointer)

Part of [Haste Health](https://haste.health), licensed under [Apache-2.0](https://github.com/HasteHealth/HasteHealth/blob/main/LICENSE).