pub struct DynClosure(/* private fields */);Expand description
A first-class, callable CEL value: a compiled body plus its declared parameter/return types.
Holds no captured environment — only its own parameters resolve inside body. Calling it
twice with different args is exactly as fresh each time as calling any other DynSegment.
Rc-wrapped so Clone never requires DynSegment itself to implement Clone (it doesn’t —
see the design spec); RefCell because callers only ever reach a DynClosure through &self
(matching adam_rs::Filter/Method’s Fn, not FnMut, storage), while DynSegment’s own
call methods need &mut self.
Implementations§
Source§impl DynClosure
impl DynClosure
Sourcepub fn value_type(&self) -> Result<ValueType>
pub fn value_type(&self) -> Result<ValueType>
Returns the complete canonical callable descriptor after validating its current body.
§Errors
Rejects untyped closures, executing bodies, or bodies changed incompatibly through an unfrozen mutable dispatcher.
- Complexity: O(n) complete comparisons for n signature/body descriptor nodes.
§Examples
let mut body = cel_runtime::DynSegment::new::<()>(); body.just(7i32);
let closure = cel_runtime::DynClosure::typed(vec![], body).unwrap();
assert!(matches!(closure.value_type().unwrap().kind(), cel_runtime::ValueKind::Callable { .. }));Sourcepub fn new(
param_types: Vec<TypeId>,
return_type: TypeId,
body: DynSegment,
) -> Self
pub fn new( param_types: Vec<TypeId>, return_type: TypeId, body: DynSegment, ) -> Self
Wraps body as a closure value declaring param_types (in order) and return_type.
- Precondition:
bodywas compiled expecting exactlyparam_types.len()positional arguments (viapush_arg/push_argument), in that order, and produces exactly one result ofreturn_type.
§Examples
use cel_runtime::{DynClosure, DynSegment};
use std::any::TypeId;
let mut body = DynSegment::new::<()>();
body.push_arg::<i32>(0);
body.push_arg::<i32>(1);
body.op2(|a: i32, b: i32| a + b).unwrap();
let closure = DynClosure::new(
vec![TypeId::of::<i32>(), TypeId::of::<i32>()],
TypeId::of::<i32>(),
body,
);
assert_eq!(closure.param_types().len(), 2);Sourcepub fn typed(parameters: Vec<ValueType>, body: DynSegment) -> Result<Self>
pub fn typed(parameters: Vec<ValueType>, body: DynSegment) -> Result<Self>
Wraps a checked CEL body while retaining its full callable shape.
§Errors
Returns an error if the body does not produce exactly one value, requires preloaded arguments or a nonzero ambient stack origin, reads an undeclared or differently shaped argument, or reads a tuple whose leaves lack clone adapters. A zero-origin fragment is valid because its operations can access only its local operands and declared arguments.
- Complexity: O(number of parameters plus recursive nodes in body argument reads/result).
§Examples
use cel_runtime::{DynClosure, DynSegment, ValueType};
let mut body = DynSegment::new::<()>();
body.just(42i32);
let closure = DynClosure::typed(vec![], body).unwrap();
assert_eq!(closure.call::<i32>(&[]).unwrap(), 42);Sourcepub fn complete_value_type(
&self,
leaf: impl FnMut(TypeId) -> Option<ValueType>,
) -> Result<ValueType>
pub fn complete_value_type( &self, leaf: impl FnMut(TypeId) -> Option<ValueType>, ) -> Result<ValueType>
Enriches a complete canonical signature with explicitly supplied leaf factories.
leaf looks up descriptors built while each concrete Rust type was
known; a TypeId never synthesizes a Rust monomorphization.
Factory capabilities remain independent of identity. This changes metadata
only; Self::value_type needs no factories for the existing complete signature.
§Errors
Returns an error for an untyped closure (including Self::new), an
unknown nested callable signature, a missing or mismatched concrete leaf
factory, or an unrepresentable canonical tuple layout.
- Complexity: O(n) traversal time and output space for n signature nodes, excluding leaf factory costs.
§Examples
use cel_runtime::{DynClosure, DynSegment, value_type::{ValueKind, ValueType}};
use std::any::TypeId;
let mut body = DynSegment::new::<()>();
body.just(42i32);
let closure = DynClosure::typed(vec![], body).unwrap();
let complete = closure.complete_value_type(|id| {
(id == TypeId::of::<i32>()).then(ValueType::cloneable_leaf::<i32>)
}).unwrap();
assert!(matches!(complete.kind(), ValueKind::Callable { .. }));Sourcepub fn param_types(&self) -> &[TypeId]
pub fn param_types(&self) -> &[TypeId]
Returns this closure’s declared parameter types, in order.
§Examples
use cel_runtime::{DynClosure, DynSegment};
use std::any::TypeId;
let mut body = DynSegment::new::<()>();
body.push_arg::<i32>(0);
body.push_arg::<i32>(1);
body.op2(|a: i32, b: i32| a + b).unwrap();
let closure = DynClosure::new(
vec![TypeId::of::<i32>(), TypeId::of::<i32>()],
TypeId::of::<i32>(),
body,
);
assert_eq!(closure.param_types(), &[TypeId::of::<i32>(), TypeId::of::<i32>()]);Sourcepub fn return_type(&self) -> TypeId
pub fn return_type(&self) -> TypeId
Returns this closure’s declared return type.
§Examples
use cel_runtime::{DynClosure, DynSegment};
use std::any::TypeId;
let mut body = DynSegment::new::<()>();
body.push_arg::<i32>(0);
body.push_arg::<i32>(1);
body.op2(|a: i32, b: i32| a + b).unwrap();
let closure = DynClosure::new(
vec![TypeId::of::<i32>(), TypeId::of::<i32>()],
TypeId::of::<i32>(),
body,
);
assert_eq!(closure.return_type(), TypeId::of::<i32>());Sourcepub fn call<R: 'static>(&self, args: &[&dyn Any]) -> Result<R>
pub fn call<R: 'static>(&self, args: &[&dyn Any]) -> Result<R>
Invokes the closure’s body with args, positionally matched against param_types.
- Precondition:
args.len() == self.param_types().len()and eachargs[i]’s runtime type matchesparam_types()[i]— the caller (adam-lang’s generatedFilterwrapper, or any future caller) must guarantee this ahead of time; a violation is a caller bug, not user error (matchesDynSegment::push_arg’s own existing precondition, which this delegates to unchanged). - Precondition:
TypeId::of::<R>() == self.return_type(). - Complexity: whatever the body’s own evaluation complexity is.
§Examples
use cel_runtime::{DynClosure, DynSegment};
use std::any::TypeId;
let mut body = DynSegment::new::<()>();
body.push_arg::<i32>(0);
body.push_arg::<i32>(1);
body.op2(|a: i32, b: i32| a + b).unwrap();
let closure = DynClosure::new(
vec![TypeId::of::<i32>(), TypeId::of::<i32>()],
TypeId::of::<i32>(),
body,
);
let (a, b) = (2i32, 3i32);
let result: i32 = closure.call(&[&a, &b]).unwrap();
assert_eq!(result, 5);Sourcepub fn call_boxed(
&self,
args: &[&dyn Any],
call_dyn_fn: CallDynFn,
) -> Result<Box<dyn Any>>
pub fn call_boxed( &self, args: &[&dyn Any], call_dyn_fn: CallDynFn, ) -> Result<Box<dyn Any>>
Invokes the closure’s body with args, like call, for a caller that only
knows the return type dynamically (as a TypeId) rather than as a static Rust generic —
call_dyn_fn is a monomorphized dispatcher the caller already has for that type (e.g.
adam-lang’s per-type TypeRegistry::TypeEntry::call_dyn_fn).
- Precondition:
args.len() == self.param_types().len()and eachargs[i]’s runtime type matchesparam_types()[i], exactly as forcall. - Precondition:
call_dyn_fnis a dispatcher forself.return_type()(i.e. it callsDynSegment::call_dyn::<R>for the same concreteRthatTypeIdnames). - Complexity: whatever the body’s own evaluation complexity is.
§Errors
Returns an error without invoking call_dyn_fn while any trusted binding
leases this shared body, including through another clone. Mutable dispatch
resumes after the last lease drops. Otherwise propagates dispatcher errors.
§Examples
use cel_runtime::{DynClosure, DynSegment};
use std::any::{Any, TypeId};
let mut body = DynSegment::new::<()>();
body.push_arg::<i32>(0);
body.push_arg::<i32>(1);
body.op2(|a: i32, b: i32| a + b).unwrap();
let closure = DynClosure::new(
vec![TypeId::of::<i32>(), TypeId::of::<i32>()],
TypeId::of::<i32>(),
body,
);
fn dispatch_i32(seg: &mut DynSegment, inputs: &[&dyn Any]) -> anyhow::Result<Box<dyn Any>> {
let result: i32 = seg.call_dyn(inputs)?;
Ok(Box::new(result))
}
let (a, b) = (4i32, 5i32);
let result = closure.call_boxed(&[&a, &b], dispatch_i32).unwrap();
assert_eq!(*result.downcast_ref::<i32>().unwrap(), 9);Trait Implementations§
Source§impl Clone for DynClosure
impl Clone for DynClosure
Source§fn clone(&self) -> DynClosure
fn clone(&self) -> DynClosure
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more