use crate::arena::{ContextStack, DataValue};
use crate::{CompiledNode, Engine, Result};
use bumpalo::Bump;
#[inline]
fn resolve_object<'a>(
args: &'a [CompiledNode],
ctx: &mut ContextStack<'a>,
engine: &Engine,
arena: &'a Bump,
) -> Result<Option<&'a [(&'a str, DataValue<'a>)]>> {
if args.is_empty() {
return Err(crate::Error::invalid_args());
}
match engine.dispatch_node(&args[0], ctx, arena)? {
DataValue::Object([]) => Ok(None),
DataValue::Object(pairs) => Ok(Some(pairs)),
DataValue::Null => Ok(None),
_ => Err(crate::Error::invalid_args()),
}
}
#[inline]
pub(crate) fn evaluate_keys<'a>(
args: &'a [CompiledNode],
ctx: &mut ContextStack<'a>,
engine: &Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>> {
let Some(pairs) = resolve_object(args, ctx, engine, arena)? else {
return Ok(crate::arena::singletons::singleton_empty_array());
};
let slice = arena.alloc_slice_fill_iter(pairs.iter().map(|(k, _)| DataValue::String(k)));
Ok(arena.alloc(DataValue::Array(slice)))
}
#[inline]
pub(crate) fn evaluate_values<'a>(
args: &'a [CompiledNode],
ctx: &mut ContextStack<'a>,
engine: &Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>> {
let Some(pairs) = resolve_object(args, ctx, engine, arena)? else {
return Ok(crate::arena::singletons::singleton_empty_array());
};
let slice = arena.alloc_slice_fill_iter(pairs.iter().map(|(_, v)| *v));
Ok(arena.alloc(DataValue::Array(slice)))
}
#[inline]
pub(crate) fn evaluate_entries<'a>(
args: &'a [CompiledNode],
ctx: &mut ContextStack<'a>,
engine: &Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>> {
let Some(pairs) = resolve_object(args, ctx, engine, arena)? else {
return Ok(crate::arena::singletons::singleton_empty_array());
};
let slice = arena.alloc_slice_fill_iter(pairs.iter().map(|(k, v)| {
let row = arena.alloc([("key", DataValue::String(k)), ("value", *v)]);
DataValue::Object(&row[..])
}));
Ok(arena.alloc(DataValue::Array(slice)))
}