shape_vm/executor/utils/extraction_helpers.rs
1//! Extraction helpers to reduce duplication across method handlers.
2//!
3//! Common patterns like "get array from first arg" and "coerce ValueWord to string"
4//! are centralized here so every call site is a single function call.
5
6use shape_value::{ArrayView, VMError, ValueWord};
7
8/// Extract a unified array view from the first element of `args`.
9/// Handles all array variants: generic Array, IntArray, FloatArray, BoolArray.
10#[inline]
11pub(crate) fn require_any_array_arg<'a>(args: &'a [ValueWord]) -> Result<ArrayView<'a>, VMError> {
12 args.first()
13 .ok_or(VMError::StackUnderflow)?
14 .as_any_array()
15 .ok_or_else(|| VMError::TypeError {
16 expected: "array",
17 got: "other",
18 })
19}
20
21/// Coerce a ValueWord value to a String representation.
22///
23/// Handles: string, f64, i64, bool, none → "null", fallback → Debug format.
24/// This replaces the 13-line pattern found in join_str, array_sort, etc.
25#[inline]
26pub(crate) fn nb_to_string_coerce(nb: &ValueWord) -> String {
27 if let Some(s) = nb.as_str() {
28 s.to_string()
29 } else if let Some(n) = nb.as_f64() {
30 n.to_string()
31 } else if let Some(i) = nb.as_i64() {
32 i.to_string()
33 } else if let Some(b) = nb.as_bool() {
34 b.to_string()
35 } else if nb.is_none() {
36 "null".to_string()
37 } else {
38 format!("{:?}", nb)
39 }
40}