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::{gc::TraceBox, tb, Context, Result, 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 self.031 .as_ref()32 .map_or(false, |s| s.as_bytes() == other.as_bytes())33 }34}3536#[derive(Clone, Trace)]37pub struct BuiltinParam {38 name: ParamName,39 has_default: bool,40}41impl BuiltinParam {42 pub const fn new(name: ParamName, has_default: bool) -> Self {43 Self { name, has_default }44 }45 46 pub fn name(&self) -> &ParamName {47 &self.name48 }49 50 pub fn has_default(&self) -> bool {51 self.has_default52 }53}5455565758pub trait Builtin: Trace {59 60 fn name(&self) -> &str;61 62 fn params(&self) -> &[BuiltinParam];63 64 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val>;6566 fn as_any(&self) -> &dyn Any;67}6869pub trait StaticBuiltin: Builtin + Send + Sync70where71 Self: 'static,72{73 74 75}7677#[derive(Trace)]78pub struct NativeCallback {79 pub(crate) params: Vec<BuiltinParam>,80 handler: TraceBox<dyn NativeCallbackHandler>,81}82impl NativeCallback {83 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]84 pub fn new(params: Vec<String>, handler: impl NativeCallbackHandler) -> Self {85 Self {86 params: params87 .into_iter()88 .map(|n| BuiltinParam {89 name: ParamName::new_dynamic(n),90 has_default: false,91 })92 .collect(),93 handler: tb!(handler),94 }95 }96}9798impl Builtin for NativeCallback {99 fn name(&self) -> &str {100 101 102 "<native>"103 }104105 fn params(&self) -> &[BuiltinParam] {106 &self.params107 }108109 fn call(&self, ctx: Context, _loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {110 let args = parse_builtin_call(ctx, &self.params, args, true)?;111 let args = args112 .into_iter()113 .map(|a| a.expect("legacy natives have no default params"))114 .map(|a| a.evaluate())115 .collect::<Result<Vec<Val>>>()?;116 self.handler.call(&args)117 }118119 fn as_any(&self) -> &dyn Any {120 self121 }122}123124pub trait NativeCallbackHandler: Trace {125 fn call(&self, args: &[Val]) -> Result<Val>;126}