fhirpathrs 0.1.0

Fhirpath implementation in Rust
Documentation
use serde_json::{json, Value};

use crate::parser::expression::Expression;

use super::{
    equality::values_are_equal,
    target::Target,
    utils::{get_arrays, unique_array_elements},
    EvaluateResult, ResourceNode,
};

pub fn union<'a, 'b>(
    input: &'a ResourceNode<'a, 'b>,
    expressions: &Vec<Box<Expression>>,
    arity: Target,
) -> EvaluateResult<ResourceNode<'a, 'b>> {
    let (array, mut second_array) = get_arrays(input, expressions, arity)?;

    let mut union_array: Vec<Value> = array
        .into_iter()
        .filter(|item| {
            second_array
                .iter()
                .find(|second_item| values_are_equal(item, *second_item))
                .is_none()
        })
        .collect();

    union_array.append(&mut second_array);

    Ok(ResourceNode::from_node(
        input,
        json!(unique_array_elements(&union_array)),
    ))
}

pub fn combine<'a, 'b>(
    input: &'a ResourceNode<'a, 'b>,
    expressions: &Vec<Box<Expression>>,
) -> EvaluateResult<ResourceNode<'a, 'b>> {
    let (mut first_array, mut second_array) = get_arrays(input, expressions, Target::AnyAtRoot)?;

    first_array.append(&mut second_array);

    Ok(ResourceNode::from_node(input, json!(first_array)))
}

#[cfg(test)]
mod test {
    use serde_json::json;
    use crate::error::FhirpathError;
    use crate::evaluate::test::test::{run_tests, Expected, TestCase};

    #[test]
    fn test_union_path() {
        let patient = json!({
            "resourceType": "Patient",
            "a": [1],
            "b": [],
            "c": [1, 2, 3],
        });

        let test_cases: Vec<TestCase> = vec![
            TestCase {
                path: "Patient.a | Patient.c".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([1, 2, 3])),
                options: None,
            },
            TestCase {
                path: "Patient.a.union(Patient.c)".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([1, 2, 3])),
                options: None,
            },
            TestCase {
                path: "Patient.b.union(Patient.b)".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([])),
                options: None,
            },
            TestCase {
                path: "Patient.a | Patient.b".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([1])),
                options: None,
            },
        ];

        run_tests(test_cases);
    }

    #[test]
    fn test_combine_path() {
        let patient = json!({
            "resourceType": "Patient",
            "a": [1],
            "b": [],
            "c": [1, 2, 3],
        });

        let test_cases: Vec<TestCase> = vec![
            TestCase {
                path: "Patient.a.combine(Patient.c)".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([1, 1, 2, 3])),
                options: None,
            },
            TestCase {
                path: "Patient.b.combine(Patient.b)".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([])),
                options: None,
            },
            TestCase {
                path: "Patient.a.combine(Patient.b)".to_string(),
                input: patient.clone(),
                expected: Expected::Value(json!([1])),
                options: None,
            },
        ];

        run_tests(test_cases);
    }
}