1use std::{any::Any, borrow::Cow};23use jrsonnet_gcmodule::Trace;4use jrsonnet_interner::IStr;56use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};7use crate::{error::Result, gc::TraceBox, tb, Context, Val};891011#[derive(Clone, Trace)]12pub struct ParamName(Option<Cow<'static, str>>);13impl ParamName {14 pub const ANONYMOUS: Self = Self(None);15 pub const fn new_static(name: &'static str) -> Self {16 Self(Some(Cow::Borrowed(name)))17 }18 pub fn new_dynamic(name: String) -> Self {19 Self(Some(Cow::Owned(name)))20 }21 pub fn as_str(&self) -> Option<&str> {22 self.0.as_deref()23 }24 pub fn is_anonymous(&self) -> bool {25 self.0.is_none()26 }27}28impl PartialEq<IStr> for ParamName {29 fn eq(&self, other: &IStr) -> bool {30 match &self.0 {31 Some(s) => s.as_bytes() == other.as_bytes(),32 None => false,33 }34 }35}3637#[derive(Clone, Trace)]38pub struct BuiltinParam {39 name: ParamName,40 has_default: bool,41}42impl BuiltinParam {43 pub const fn new(name: ParamName, has_default: bool) -> Self {44 Self { name, has_default }45 }46 47 pub fn name(&self) -> &ParamName {48 &self.name49 }50 51 pub fn has_default(&self) -> bool {52 self.has_default53 }54}5556575859pub trait Builtin: Trace {60 61 fn name(&self) -> &str;62 63 fn params(&self) -> &[BuiltinParam];64 65 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val>;6667 fn as_any(&self) -> &dyn Any;68}6970pub trait StaticBuiltin: Builtin + Send + Sync71where72 Self: 'static,73{74 75 76}7778#[derive(Trace)]79pub struct NativeCallback {80 pub(crate) params: Vec<BuiltinParam>,81 handler: TraceBox<dyn NativeCallbackHandler>,82}83impl NativeCallback {84 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]85 pub fn new(params: Vec<String>, handler: impl NativeCallbackHandler) -> Self {86 Self {87 params: params88 .into_iter()89 .map(|n| BuiltinParam {90 name: ParamName::new_dynamic(n.to_string()),91 has_default: false,92 })93 .collect(),94 handler: tb!(handler),95 }96 }97}9899impl Builtin for NativeCallback {100 fn name(&self) -> &str {101 102 103 "<native>"104 }105106 fn params(&self) -> &[BuiltinParam] {107 &self.params108 }109110 fn call(&self, ctx: Context, _loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {111 let args = parse_builtin_call(ctx, &self.params, args, true)?;112 let args = args113 .into_iter()114 .map(|a| a.expect("legacy natives have no default params"))115 .map(|a| a.evaluate())116 .collect::<Result<Vec<Val>>>()?;117 self.handler.call(&args)118 }119120 fn as_any(&self) -> &dyn Any {121 self122 }123}124125pub trait NativeCallbackHandler: Trace {126 fn call(&self, args: &[Val]) -> Result<Val>;127}