hamelin_lib 0.15.5

Core library for Hamelin query language
Documentation
//! Array and map access/indexing functions

use std::any::TypeId;

use anyhow::bail;

use crate::func::def::{FunctionDef, ParameterBindingProvider, Parameters};
use crate::types::array::Array;
use crate::types::matcher::{AnyMatcher, ArrayMatcher, ExactMatcher, MapMatcher};
use crate::types::{Type, INT, STRING, VARIANT};

/// get(array, index) - Returns the element at the given index.
#[derive(Default, Clone)]
pub struct GetArray;

impl FunctionDef for GetArray {
    fn name(&self) -> &'static str {
        "get"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new()
            .with("array", ArrayMatcher::default())
            .with("index", ExactMatcher::of(INT))
    }

    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        match bindings.get_by_name("array")?.typ() {
            Type::Array(arr) => Ok((*arr.element_type).clone()),
            _ => bail!("array parameter must be an array"),
        }
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// array_variant_get(array, path) - Extract a variant field from every element of an array.
///
/// Internal function used by transform lowering. Applies `variant_get` element-wise
/// to an array of variants, avoiding the explode/reaggregate pipeline.
#[derive(Default, Clone)]
pub struct ArrayVariantGet;

impl FunctionDef for ArrayVariantGet {
    fn name(&self) -> &'static str {
        "array_variant_get"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new()
            .with("array", ArrayMatcher::of(ExactMatcher::of(VARIANT)))
            .with("path", ExactMatcher::of(STRING))
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(Array::new(VARIANT).into())
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// get(map, key) - Returns the value for the given key.
#[derive(Default, Clone)]
pub struct GetMap;

impl FunctionDef for GetMap {
    fn name(&self) -> &'static str {
        "get"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new()
            .with("map", MapMatcher::default())
            .with("key", AnyMatcher::default())
    }

    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        match bindings.get_by_name("map")?.typ() {
            Type::Map(map) => Ok((*map.value_type).clone()),
            _ => bail!("map parameter must be a map"),
        }
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}