use crate::script::*;
use crate::value::{Vector, VectorElement, VectorError};
#[derive(Debug, Clone, PartialEq)]
pub struct ScriptVector(pub(crate) Vector);
impl ScriptVector {
pub fn vector(&self) -> &Vector {
&self.0
}
}
pub(crate) fn vector_failure(name: &'static str, error: VectorError) -> Box<rhai::EvalAltResult> {
script_error(crate::value::vector::vector_error(name, error))
}
pub(crate) fn element_of(
name: &'static str,
kind: &str,
) -> Result<VectorElement, Box<rhai::EvalAltResult>> {
VectorElement::from_name(kind)
.ok_or_else(|| vector_failure(name, VectorError::unknown_element(kind)))
}
fn script_vector(items: rhai::Array) -> Result<ScriptVector, Box<rhai::EvalAltResult>> {
let mut values =
Vec::with_capacity(items.len().min(crate::value::vector::MAX_VECTOR_DIMENSION));
for (index, item) in items.iter().enumerate() {
let value = if let Ok(int) = item.as_int() {
int as f64
} else if let Ok(float) = item.as_float() {
float
} else {
return Err(vector_failure(
"vector",
VectorError::not_a_number(index, type_name_of(item)),
));
};
values.push(value);
}
Vector::from_f64(&values)
.map(ScriptVector)
.map_err(|error| vector_failure("vector", error))
}
fn script_vector_of(
items: rhai::Array,
kind: &str,
) -> Result<ScriptVector, Box<rhai::EvalAltResult>> {
let element = element_of("vector", kind)?;
let vector = script_vector(items)?;
vector
.0
.quantize(element)
.map(ScriptVector)
.map_err(|error| vector_failure("vector", error))
}
pub(crate) fn register_vector(registry: &mut crate::script::register::Registry) {
registry
.register_type_with_name::<ScriptVector>("Vector")
.register_fn("vector", script_vector)
.register_fn("vector", script_vector_of)
.register_fn("embed", |ctx: NativeCallContext, text: &str| {
crate::script::source::script_embed(&ctx, text, None)
})
.register_fn(
"embed",
|ctx: NativeCallContext, text: &str, options: rhai::Map| {
crate::script::source::script_embed(&ctx, text, Some(&options))
},
)
.register_fn_as(&["to_string", "to_debug"], |v: &mut ScriptVector| {
v.0.literal(Some(crate::value::literal::MAX_LITERAL_ITEMS))
})
.register_fn("==", |a: ScriptVector, b: ScriptVector| a == b)
.register_fn("!=", |a: ScriptVector, b: ScriptVector| a != b)
.register_fn("==", |_: ScriptVector, _: rhai::Array| false)
.register_fn("==", |_: rhai::Array, _: ScriptVector| false)
.register_fn("!=", |_: ScriptVector, _: rhai::Array| true)
.register_fn("!=", |_: rhai::Array, _: ScriptVector| true)
.register_get("element", |v: &mut ScriptVector| {
v.0.element().name().to_string()
})
.register_get("dimension", |v: &mut ScriptVector| v.0.dimension() as i64)
.register_fn("quantize", |v: &mut ScriptVector, kind: &str| {
let element = element_of("quantize", kind)?;
v.0.quantize(element)
.map(ScriptVector)
.map_err(|error| vector_failure("quantize", error))
})
.register_fn_as(&["to_list", "toList"], |v: &mut ScriptVector| {
v.0.iter_f32()
.map(|value| Dynamic::from_float(crate::value::vector::tagged::short_f64(value)))
.collect::<rhai::Array>()
});
}