Skip to main content

DynClosure

Struct DynClosure 

Source
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

Source

pub fn value_type(&self) -> Result<ValueType, Error>

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 { .. }));
Source

pub fn new( param_types: Vec<TypeId>, return_type: TypeId, body: DynSegment, ) -> DynClosure

Wraps body as a closure value declaring param_types (in order) and return_type.

  • Precondition: body was compiled expecting exactly param_types.len() positional arguments (via push_arg/push_argument), in that order, and produces exactly one result of 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.param_types().len(), 2);
Source

pub fn typed( parameters: Vec<ValueType>, body: DynSegment, ) -> Result<DynClosure, Error>

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);
Source

pub fn complete_value_type( &self, leaf: impl FnMut(TypeId) -> Option<ValueType>, ) -> Result<ValueType, Error>

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 { .. }));
Source

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>()]);
Source

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>());
Source

pub fn call<R>(&self, args: &[&(dyn Any + 'static)]) -> Result<R, Error>
where R: 'static,

Invokes the closure’s body with args, positionally matched against param_types.

  • Precondition: args.len() == self.param_types().len() and each args[i]’s runtime type matches param_types()[i] — the caller (adam-lang’s generated Filter wrapper, or any future caller) must guarantee this ahead of time; a violation is a caller bug, not user error (matches DynSegment::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);
Source

pub fn call_boxed( &self, args: &[&(dyn Any + 'static)], call_dyn_fn: fn(&mut DynSegment, &[&(dyn Any + 'static)]) -> Result<Box<dyn Any>, Error>, ) -> Result<Box<dyn Any>, Error>

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 each args[i]’s runtime type matches param_types()[i], exactly as for call.
  • Precondition: call_dyn_fn is a dispatcher for self.return_type() (i.e. it calls DynSegment::call_dyn::<R> for the same concrete R that TypeId names).
  • 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

Source§

fn clone(&self) -> DynClosure

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DynClosure

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.