Skip to main content

cel_runtime/
value_type.rs

1//! Describes complete recursive identities independently of interpreter descriptors.
2//!
3//! Witnesses name concrete Rust representations without requiring foreign types
4//! to implement a trait. Capability adapters are optional and checked separately:
5//!
6//! ```
7//! use cel_runtime::value_type::{ArrayOf, Leaf, ValueRepr, ValueType};
8//! let array = ValueType::array(ValueType::cloneable_leaf::<String>());
9//! assert!(array.same_shape(&ArrayOf::<Leaf<String>>::value_type()));
10//! ```
11
12use std::alloc::Layout;
13use std::any::TypeId;
14use std::fmt::{Debug, Write};
15use std::marker::PhantomData;
16use std::sync::Arc;
17
18use crate::array::RawArray;
19use crate::c_stack_list::CStackListHeadLimit;
20use crate::tuple_value::TupleLayout;
21use crate::{Array, CNil, CStackList};
22
23#[cfg(test)]
24thread_local! {
25    /// Counts descriptor comparisons on this test thread, including recursive calls.
26    pub(crate) static SHAPE_COMPARISONS: std::cell::Cell<usize> = const {
27        std::cell::Cell::new(0)
28    };
29}
30
31/// Seals representation witnesses and limits list tails to canonical lists.
32mod sealed {
33    use super::{AssociatedType, ValueRepr};
34
35    /// Prevents downstream implementations from inventing unsafe representations.
36    pub trait Sealed {}
37
38    /// Supplies source-ordered fields only for canonical list witnesses.
39    pub trait List: ValueRepr {
40        /// Appends this list's source-ordered fields.
41        ///
42        /// - Complexity: O(n) time and space for n fields.
43        fn fields(fields: &mut Vec<AssociatedType>);
44    }
45}
46
47/// Names a trusted concrete representation without wrapping its runtime value.
48///
49/// Only this crate implements the trait; use [`Leaf`] for any foreign host type.
50///
51/// # Examples
52///
53/// ```
54/// use cel_runtime::value_type::{ArrayOf, Leaf, ValueRepr};
55/// use cel_runtime::Array;
56/// let _: <ArrayOf<Leaf<i32>> as ValueRepr>::Value = Array::from_vec(vec![1]);
57/// ```
58pub trait ValueRepr: sealed::Sealed {
59    /// The concrete, owned Rust representation.
60    type Value: 'static;
61
62    /// Returns the complete identity, layout, and ownership plan.
63    ///
64    /// Leaves have no optional capabilities by default.
65    ///
66    /// - Complexity: O(n) time and space for n nodes in the descriptor tree.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use cel_runtime::value_type::{Leaf, ValueRepr, ValueType};
72    /// assert!(Leaf::<i32>::value_type().same_shape(&ValueType::leaf::<i32>()));
73    /// ```
74    fn value_type() -> ValueType;
75}
76
77/// Names an opaque host leaf of type `T`, including explicitly registered `()`.
78///
79/// Aggregate-looking host types remain opaque when explicitly named as leaves.
80///
81/// # Examples
82///
83/// ```
84/// use cel_runtime::value_type::{Leaf, ValueRepr};
85/// let _: <Leaf<String> as ValueRepr>::Value = String::new();
86/// ```
87pub struct Leaf<T>(PhantomData<fn() -> T>);
88
89/// Names a homogeneous array whose elements use witness `E`.
90///
91/// # Examples
92///
93/// ```
94/// use cel_runtime::value_type::{ArrayOf, Leaf, ValueRepr};
95/// use cel_runtime::Array;
96/// let _: <ArrayOf<Leaf<u8>> as ValueRepr>::Value = Array::from_vec(vec![1]);
97/// ```
98pub struct ArrayOf<E>(PhantomData<fn() -> E>);
99
100/// Names canonical source unit, represented by `CNil<()>`, not a host `()`.
101///
102/// # Examples
103///
104/// ```
105/// use cel_runtime::{IntoCStackList, value_type::{Nil, ValueRepr}};
106/// let _: <Nil as ValueRepr>::Value = ().into_c_stack_list();
107/// ```
108pub struct Nil;
109
110/// Names a source-first tuple head `H` followed by canonical list tail `T`.
111///
112/// # Examples
113///
114/// ```
115/// use cel_runtime::{IntoCStackList, value_type::{Cons, Leaf, Nil, ValueRepr}};
116/// let _: <Cons<Leaf<i32>, Nil> as ValueRepr>::Value = (1,).into_c_stack_list();
117/// ```
118///
119/// Noncanonical tails cannot authorize a representation:
120///
121/// ```compile_fail
122/// use cel_runtime::value_type::{Cons, Leaf, ValueRepr};
123/// let _ = Cons::<Leaf<i32>, Leaf<()>>::value_type();
124/// ```
125pub struct Cons<H, T>(PhantomData<fn() -> (H, T)>);
126
127/// Names a canonical tuple argument list, sealed to [`Nil`] and [`Cons`].
128///
129/// # Examples
130/// ```
131/// use cel_runtime::{ArgumentList, Cons, Leaf, Nil};
132/// fn list<A: ArgumentList>() {}
133/// list::<Cons<Leaf<i32>, Nil>>();
134/// ```
135pub trait ArgumentList: ValueRepr + sealed::List {}
136impl<T: sealed::List> ArgumentList for T {}
137
138/// Names a callable with a complete canonical parameter and result signature.
139///
140/// The shared carrier always clones, regardless of argument/result capabilities.
141/// Equality and default construction are not implied.
142///
143/// # Examples
144/// ```
145/// use cel_runtime::{FnOf, Nil, Leaf, ValueRepr, Callable, CNil};
146/// let _: <FnOf<Nil, Leaf<i32>> as ValueRepr>::Value =
147///     Callable::from_fn(|_: &CNil<()>| Ok(7));
148/// ```
149///
150/// Non-list arguments cannot authorize a callable representation:
151/// ```compile_fail
152/// use cel_runtime::{FnOf, Leaf, ValueRepr};
153/// let _ = FnOf::<Leaf<()>, Leaf<i32>>::value_type();
154/// ```
155pub struct FnOf<A, R>(PhantomData<fn() -> (A, R)>);
156
157impl<A: ArgumentList, R: ValueRepr> sealed::Sealed for FnOf<A, R> {}
158impl<A: ArgumentList, R: ValueRepr> ValueRepr for FnOf<A, R> {
159    type Value = crate::Callable<A::Value, R::Value>;
160
161    /// Describes every parameter and result node with canonical carrier ownership.
162    ///
163    /// - Complexity: O(n) time and storage for n signature nodes.
164    fn value_type() -> ValueType {
165        let args = A::value_type();
166        ValueType::callable(
167            args.tuple_elements()
168                .expect("sealed canonical argument list")
169                .iter()
170                .map(|field| field.value_type.clone())
171                .collect(),
172            R::value_type(),
173        )
174    }
175}
176
177impl<T: 'static> sealed::Sealed for Leaf<T> {}
178impl<T: 'static> ValueRepr for Leaf<T> {
179    /// Describes the explicitly registered opaque host representation.
180    fn value_type() -> ValueType {
181        ValueType::leaf::<T>()
182    }
183    type Value = T;
184}
185
186impl<E: ValueRepr> sealed::Sealed for ArrayOf<E> {}
187impl<E: ValueRepr> ValueRepr for ArrayOf<E> {
188    type Value = Array<E::Value>;
189    /// Describes this array and its complete concrete element representation.
190    ///
191    /// - Complexity: O(n) time and space for n element descriptor nodes.
192    fn value_type() -> ValueType {
193        ValueType::array(E::value_type())
194    }
195}
196
197impl sealed::Sealed for Nil {}
198impl ValueRepr for Nil {
199    type Value = CNil<()>;
200    /// Describes canonical source unit with its empty-list ownership plan.
201    fn value_type() -> ValueType {
202        ValueType::tuple(Vec::new()).expect("empty canonical tuple fits Layout")
203    }
204}
205impl sealed::List for Nil {
206    /// Appends no fields for canonical source unit.
207    fn fields(_: &mut Vec<AssociatedType>) {}
208}
209
210impl<H: ValueRepr, T: sealed::List> sealed::Sealed for Cons<H, T> where T::Value: CStackListHeadLimit
211{}
212impl<H: ValueRepr, T: sealed::List> ValueRepr for Cons<H, T>
213where
214    T::Value: CStackListHeadLimit,
215{
216    type Value = CStackList<H::Value, T::Value>;
217    /// Describes source-ordered fields using their canonical recursive layout.
218    ///
219    /// - Complexity: O(n) time and space for n descriptor nodes.
220    fn value_type() -> ValueType {
221        let mut fields = Vec::new();
222        <Self as sealed::List>::fields(&mut fields);
223        let descriptor = ValueType::tuple(fields).expect("concrete Rust list fits Layout");
224        debug_assert_eq!(descriptor.layout(), Layout::new::<Self::Value>());
225        descriptor
226    }
227}
228impl<H: ValueRepr, T: sealed::List> sealed::List for Cons<H, T>
229where
230    T::Value: CStackListHeadLimit,
231{
232    /// Appends the head descriptor followed by the canonical tail's descriptors.
233    ///
234    /// - Complexity: O(n) time and space for n descriptor nodes.
235    fn fields(fields: &mut Vec<AssociatedType>) {
236        fields.push(AssociatedType {
237            offset: 0,
238            value_type: H::value_type(),
239        });
240        T::fields(fields);
241    }
242}
243
244/// Identifies a value structurally, independently of aggregate storage markers.
245///
246/// Callable metadata includes every parameter and the result. Its private
247/// ownership plan uses the shared `DynClosure` carrier, exactly matching the
248/// transparent [`crate::Callable`] facade authorized by [`FnOf`].
249///
250/// # Examples
251///
252/// ```
253/// use cel_runtime::value_type::{ValueKind, ValueType};
254/// assert!(matches!(ValueType::leaf::<i32>().kind(), ValueKind::Leaf(_)));
255/// ```
256#[derive(Clone, Debug)]
257pub enum ValueKind {
258    /// A single explicitly registered opaque Rust type.
259    Leaf(TypeId),
260    /// Source-ordered fields with canonical physical offsets.
261    Tuple(Vec<AssociatedType>),
262    /// One complete homogeneous element descriptor.
263    Array(ValueType),
264    /// Complete semantic callable signature for the shared closure carrier.
265    Callable {
266        /// Parameter types in source order.
267        parameters: Vec<ValueType>,
268        /// The complete result type, including source unit or aggregates.
269        result: Box<ValueType>,
270    },
271}
272
273/// Associates a source-ordered tuple field with its canonical physical offset.
274///
275/// [`ValueType::tuple`] replaces supplied offsets; callers cannot forge layout.
276///
277/// # Examples
278///
279/// ```
280/// use cel_runtime::value_type::{AssociatedType, ValueType};
281/// let field = AssociatedType { offset: 0, value_type: ValueType::leaf::<i32>() };
282/// assert!(ValueType::tuple(vec![field]).is_ok());
283/// ```
284#[derive(Clone, Debug)]
285pub struct AssociatedType {
286    /// Byte offset relative to the enclosing canonical list.
287    pub offset: usize,
288    /// Complete field identity and ownership metadata.
289    pub value_type: ValueType,
290}
291
292/// Clones a live concrete value into aligned, disjoint uninitialized storage.
293type CloneHook = unsafe fn(*const u8, *mut u8);
294/// Compares two live values of one validated concrete representation.
295type EqualityHook = unsafe fn(*const u8, *const u8) -> bool;
296/// Formats a live value of one validated concrete representation.
297type DebugHook = unsafe fn(*const u8, &mut String);
298/// Destroys a live leaf of the registered concrete type exactly once.
299type DropHook = unsafe fn(*mut u8);
300
301/// Freezes one descriptor's ownership and independent capability plans.
302#[derive(Clone, Debug)]
303struct Plan {
304    kind: ValueKind,
305    layout: Layout,
306    leaf_drop: Option<DropHook>,
307    clone_hook: Option<CloneHook>,
308    equality_hook: Option<EqualityHook>,
309    debug_hook: Option<DebugHook>,
310    cloneable: bool,
311    comparable: bool,
312    debuggable: bool,
313    host_leaf: Option<crate::host_value_bridge::LeafBridge>,
314}
315
316/// Owns immutable recursive identity, canonical layout, and trusted operations.
317///
318/// Capabilities never change type identity. Cloning a descriptor shares its
319/// frozen plan; capability installation returns an independently updated plan.
320///
321/// # Examples
322///
323/// ```
324/// use cel_runtime::value_type::ValueType;
325/// let a = ValueType::array(ValueType::leaf::<i32>());
326/// let b = ValueType::array(ValueType::cloneable_leaf::<i32>());
327/// assert!(a.same_shape(&b));
328/// ```
329#[derive(Clone, Debug)]
330pub struct ValueType(Arc<Plan>);
331
332impl ValueType {
333    /// Sets an opaque leaf's diagnostic name without changing identity or capabilities.
334    ///
335    /// Structural descriptors retain their recursively defined names.
336    ///
337    /// # Examples
338    /// ```
339    /// let ty = cel_runtime::ValueType::leaf::<i32>().with_type_name("Integer");
340    /// assert_eq!(ty.type_name(), "Integer");
341    /// ```
342    pub fn with_type_name(mut self, name: impl Into<std::borrow::Cow<'static, str>>) -> Self {
343        if let Some(host) = Arc::make_mut(&mut self.0).host_leaf.as_mut() {
344            host.name = name.into();
345        }
346        self
347    }
348
349    /// Rejects erased whole-value owners as opaque canonical elements.
350    ///
351    /// # Errors
352    /// Rejects an `OwnedValue` leaf at any recursive node; owners require a checked whole-value boundary.
353    /// - Complexity: O(n) traversal for n descriptor nodes.
354    pub(crate) fn validate_canonical(&self) -> anyhow::Result<()> {
355        match self.kind() {
356            ValueKind::Leaf(id) => anyhow::ensure!(
357                *id != TypeId::of::<crate::OwnedValue>(),
358                "whole-value owners cannot be opaque canonical elements"
359            ),
360            ValueKind::Array(element) => element.validate_canonical()?,
361            ValueKind::Tuple(fields) => {
362                for field in fields {
363                    field.value_type.validate_canonical()?;
364                }
365            }
366            ValueKind::Callable { parameters, result } => {
367                for parameter in parameters {
368                    parameter.validate_canonical()?;
369                }
370                result.validate_canonical()?;
371            }
372        }
373        Ok(())
374    }
375
376    /// Returns whether the complete frozen plan supports borrowed argument cloning.
377    ///
378    /// # Examples
379    /// ```
380    /// assert!(cel_runtime::ValueType::cloneable_leaf::<i32>().can_clone_for_argument());
381    /// ```
382    pub fn can_clone_for_argument(&self) -> bool {
383        self.can_clone()
384    }
385    /// Returns a diagnostic carrier identity; structural casts require witnesses.
386    ///
387    /// # Examples
388    /// ```
389    /// assert_eq!(cel_runtime::ValueType::leaf::<i32>().type_id(), std::any::TypeId::of::<i32>());
390    /// ```
391    pub fn type_id(&self) -> TypeId {
392        match self.kind() {
393            ValueKind::Leaf(id) => *id,
394            ValueKind::Tuple(_) => TypeId::of::<crate::CNil<()>>(),
395            ValueKind::Array(_) => TypeId::of::<RawArray>(),
396            ValueKind::Callable { .. } => TypeId::of::<crate::DynClosure>(),
397        }
398    }
399
400    /// Returns a human-readable diagnostic representation name.
401    ///
402    /// # Examples
403    /// ```
404    /// assert_eq!(cel_runtime::ValueType::leaf::<i32>().type_name(), "i32");
405    /// ```
406    pub fn type_name(&self) -> &str {
407        match self.kind() {
408            ValueKind::Leaf(_) => self.host_leaf().map_or("opaque", |host| host.name()),
409            ValueKind::Tuple(_) => "canonical tuple",
410            ValueKind::Array(_) => "canonical array",
411            ValueKind::Callable { .. } => "callable",
412        }
413    }
414
415    /// Returns the canonical representation size.
416    ///
417    /// # Examples
418    /// ```
419    /// assert_eq!(cel_runtime::ValueType::leaf::<i32>().size(), 4);
420    /// ```
421    pub fn size(&self) -> usize {
422        self.layout().size()
423    }
424
425    /// Returns the canonical representation alignment.
426    ///
427    /// # Examples
428    /// ```
429    /// assert_eq!(cel_runtime::ValueType::leaf::<u8>().align(), 1);
430    /// ```
431    pub fn align(&self) -> usize {
432        self.layout().align()
433    }
434
435    /// Borrows source-ordered canonical tuple fields, including empty source unit.
436    ///
437    /// # Examples
438    /// ```
439    /// assert!(cel_runtime::ValueType::leaf::<i32>().tuple_elements().is_none());
440    /// ```
441    pub fn tuple_elements(&self) -> Option<&[AssociatedType]> {
442        match self.kind() {
443            ValueKind::Tuple(fields) => Some(fields),
444            _ => None,
445        }
446    }
447
448    /// Borrows the complete canonical array element descriptor.
449    ///
450    /// # Examples
451    /// ```
452    /// assert!(cel_runtime::ValueType::array(cel_runtime::ValueType::leaf::<i32>()).array_element().is_some());
453    /// ```
454    pub fn array_element(&self) -> Option<&ValueType> {
455        match self.kind() {
456            ValueKind::Array(element) => Some(element),
457            _ => None,
458        }
459    }
460
461    /// Registers a borrowed canonical argument read using this complete clone plan.
462    ///
463    /// # Errors
464    /// Rejects unavailable cloning or an unrepresentable destination frame.
465    /// - Complexity: O(n) registration for n existing stack slots.
466    ///
467    /// # Examples
468    /// ```
469    /// let mut body = cel_runtime::DynSegment::new::<()>();
470    /// cel_runtime::ValueType::cloneable_leaf::<i32>().push_argument(&mut body, 0).unwrap();
471    /// ```
472    pub fn push_argument(
473        &self,
474        segment: &mut crate::DynSegment,
475        index: usize,
476    ) -> anyhow::Result<()> {
477        segment.push_argument(index, self.clone())
478    }
479
480    /// Checks the borrowed whole-value clone capability.
481    ///
482    /// # Errors
483    /// Rejects a descriptor whose frozen plan cannot clone its representation.
484    pub(crate) fn validate_clone(&self) -> anyhow::Result<()> {
485        anyhow::ensure!(self.can_clone(), "argument clone capability unavailable");
486        Ok(())
487    }
488
489    /// Describes an opaque host leaf without requiring optional capabilities.
490    ///
491    /// # Examples
492    ///
493    /// ```
494    /// use cel_runtime::value_type::ValueType;
495    /// assert!(!ValueType::leaf::<i32>().same_shape(&ValueType::leaf::<u32>()));
496    /// ```
497    pub fn leaf<T: 'static>() -> Self {
498        Self(Arc::new(Plan {
499            kind: ValueKind::Leaf(TypeId::of::<T>()),
500            layout: Layout::new::<T>(),
501            leaf_drop: Some(drop_leaf::<T>),
502            clone_hook: None,
503            equality_hook: None,
504            debug_hook: None,
505            cloneable: false,
506            comparable: false,
507            debuggable: false,
508            host_leaf: Some(crate::host_value_bridge::LeafBridge::new::<T>()),
509        }))
510    }
511
512    /// Describes an opaque host leaf with cloning but no other capabilities.
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// use cel_runtime::value_type::ValueType;
518    /// let _ = ValueType::cloneable_leaf::<String>();
519    /// ```
520    pub fn cloneable_leaf<T: Clone + 'static>() -> Self {
521        Self::leaf::<T>()
522            .with_clone::<Leaf<T>>()
523            .expect("identical leaf representation")
524    }
525
526    /// Describes a known signature using the existing shared closure carrier.
527    ///
528    /// Cloning shares the compiled body, independent of parameter/result clone
529    /// capabilities. Equality is unavailable; formatting describes the carrier.
530    /// This constructor installs ownership directly from the statically known
531    /// carrier, not from an opaque leaf witness.
532    ///
533    /// - Complexity: O(1), transferring ownership of the signature.
534    ///
535    /// # Examples
536    /// ```
537    /// use cel_runtime::{ValueType, FnOf, Nil, Leaf, ValueRepr};
538    /// assert!(ValueType::callable(vec![], ValueType::leaf::<i32>())
539    ///     .same_shape(&FnOf::<Nil, Leaf<i32>>::value_type()));
540    /// ```
541    pub fn callable(parameters: Vec<ValueType>, result: ValueType) -> Self {
542        Self(Arc::new(Plan {
543            kind: ValueKind::Callable {
544                parameters,
545                result: Box::new(result),
546            },
547            layout: Layout::new::<crate::DynClosure>(),
548            leaf_drop: Some(drop_leaf::<crate::DynClosure>),
549            clone_hook: Some(clone_leaf::<crate::DynClosure>),
550            equality_hook: None,
551            debug_hook: Some(debug_leaf::<crate::DynClosure>),
552            cloneable: true,
553            comparable: false,
554            debuggable: true,
555            host_leaf: None,
556        }))
557    }
558
559    /// Describes a homogeneous array using the fixed owning header.
560    ///
561    /// Recursive capabilities are present exactly when the element supports them.
562    ///
563    /// # Examples
564    ///
565    /// ```
566    /// use cel_runtime::value_type::{ArrayOf, Leaf, ValueRepr, ValueType};
567    /// assert!(ValueType::array(ValueType::leaf::<i32>())
568    ///     .same_shape(&ArrayOf::<Leaf<i32>>::value_type()));
569    /// ```
570    pub fn array(element: ValueType) -> Self {
571        let cloneable = element.0.cloneable;
572        let comparable = element.0.comparable;
573        let debuggable = element.0.debuggable;
574        Self(Arc::new(Plan {
575            kind: ValueKind::Array(element),
576            layout: Layout::new::<RawArray>(),
577            leaf_drop: None,
578            clone_hook: None,
579            equality_hook: None,
580            debug_hook: None,
581            cloneable,
582            comparable,
583            debuggable,
584            host_leaf: None,
585        }))
586    }
587
588    /// Computes canonical tuple layout from source-ordered fields.
589    ///
590    /// Supplied offsets are ignored. Empty input describes canonical source unit.
591    ///
592    /// - Complexity: O(n) time and space for n immediate fields.
593    ///
594    /// # Errors
595    ///
596    /// Returns an error if the recursive padded layout exceeds [`Layout`]'s bounds.
597    ///
598    /// # Examples
599    ///
600    /// ```
601    /// use cel_runtime::value_type::{Nil, ValueRepr, ValueType};
602    /// assert!(ValueType::tuple(vec![]).unwrap().same_shape(&Nil::value_type()));
603    /// ```
604    pub fn tuple(mut elements: Vec<AssociatedType>) -> anyhow::Result<Self> {
605        let fields: Vec<_> = elements
606            .iter()
607            .map(|field| field.value_type.layout())
608            .collect();
609        let layout = TupleLayout::from_fields(&fields)?;
610        for (field, offset) in elements.iter_mut().zip(layout.offsets) {
611            field.offset = offset;
612        }
613        let cloneable = elements.iter().all(|field| field.value_type.0.cloneable);
614        let comparable = elements.iter().all(|field| field.value_type.0.comparable);
615        let debuggable = elements.iter().all(|field| field.value_type.0.debuggable);
616        Ok(Self(Arc::new(Plan {
617            kind: ValueKind::Tuple(elements),
618            layout: layout.layout,
619            leaf_drop: None,
620            clone_hook: None,
621            equality_hook: None,
622            debug_hook: None,
623            cloneable,
624            comparable,
625            debuggable,
626            host_leaf: None,
627        })))
628    }
629
630    /// Borrows the complete semantic shape without permitting mutation.
631    ///
632    /// # Examples
633    ///
634    /// ```
635    /// use cel_runtime::value_type::{Nil, ValueKind, ValueRepr};
636    /// assert!(matches!(Nil::value_type().kind(), ValueKind::Tuple(_)));
637    /// ```
638    pub fn kind(&self) -> &ValueKind {
639        &self.0.kind
640    }
641
642    /// Returns the validated complete physical layout.
643    ///
644    /// # Examples
645    ///
646    /// ```
647    /// use cel_runtime::value_type::ValueType;
648    /// assert_eq!(ValueType::leaf::<u64>().layout(), std::alloc::Layout::new::<u64>());
649    /// ```
650    pub fn layout(&self) -> Layout {
651        self.0.layout
652    }
653
654    /// Compares complete semantic identities and every physical field layout.
655    ///
656    /// Capability differences do not affect identity. Equal size and alignment
657    /// alone never authorize a cast.
658    ///
659    /// - Complexity: O(n) time and O(d) call space for n nodes and nesting depth d.
660    ///
661    /// # Examples
662    ///
663    /// ```
664    /// use cel_runtime::value_type::ValueType;
665    /// assert!(!ValueType::array(ValueType::leaf::<i32>())
666    ///     .same_shape(&ValueType::array(ValueType::leaf::<u32>())));
667    /// ```
668    pub fn same_shape(&self, other: &Self) -> bool {
669        #[cfg(test)]
670        SHAPE_COMPARISONS.with(|count| count.set(count.get().saturating_add(1)));
671        self.layout() == other.layout() && same_kind(self.kind(), other.kind())
672    }
673
674    /// Checks concrete identity for a legacy conversion that names only a host leaf.
675    ///
676    /// Structural values require explicit representation witnesses, regardless
677    /// of a shared carrier ID or equal layout. This checks metadata only and
678    /// does not change the existing typed segment conversion.
679    ///
680    /// # Errors
681    ///
682    /// Returns an error for structural descriptors or a different leaf identity.
683    ///
684    /// # Examples
685    ///
686    /// ```
687    /// use std::any::TypeId;
688    /// use cel_runtime::value_type::ValueType;
689    /// assert!(ValueType::leaf::<String>()
690    ///     .validate_opaque_leaf(TypeId::of::<String>()).is_ok());
691    /// assert!(ValueType::tuple(vec![]).unwrap()
692    ///     .validate_opaque_leaf(TypeId::of::<()>()).is_err());
693    /// ```
694    pub fn validate_opaque_leaf(&self, type_id: TypeId) -> anyhow::Result<()> {
695        anyhow::ensure!(
696            matches!(self.kind(), ValueKind::Leaf(id) if *id == type_id),
697            "value requires a matching opaque leaf or an explicit structural witness"
698        );
699        Ok(())
700    }
701
702    /// Installs a concrete clone adapter after validating the entire witness.
703    ///
704    /// - Complexity: O(n) time and space for n descriptor nodes.
705    ///
706    /// # Errors
707    ///
708    /// Returns an error on any semantic or physical representation mismatch.
709    ///
710    /// # Examples
711    ///
712    /// ```
713    /// use cel_runtime::value_type::{Leaf, ValueType};
714    /// assert!(ValueType::leaf::<i32>().with_clone::<Leaf<i32>>().is_ok());
715    /// ```
716    pub fn with_clone<R: ValueRepr>(mut self) -> anyhow::Result<Self>
717    where
718        R::Value: Clone,
719    {
720        self.validate::<R>()?;
721        let plan = Arc::make_mut(&mut self.0);
722        plan.clone_hook = Some(clone_leaf::<R::Value>);
723        plan.cloneable = true;
724        Ok(self)
725    }
726
727    /// Installs concrete equality independently of cloning and formatting.
728    ///
729    /// - Complexity: O(n) time and space for n descriptor nodes.
730    ///
731    /// # Errors
732    ///
733    /// Returns an error on any semantic or physical representation mismatch.
734    ///
735    /// # Examples
736    ///
737    /// ```
738    /// use cel_runtime::value_type::{Leaf, ValueType};
739    /// assert!(ValueType::leaf::<i32>().with_equality::<Leaf<i32>>().is_ok());
740    /// ```
741    pub fn with_equality<R: ValueRepr>(mut self) -> anyhow::Result<Self>
742    where
743        R::Value: PartialEq,
744    {
745        self.validate::<R>()?;
746        let plan = Arc::make_mut(&mut self.0);
747        plan.equality_hook = Some(equal_leaf::<R::Value>);
748        plan.comparable = true;
749        Ok(self)
750    }
751
752    /// Installs concrete debug formatting independently of other capabilities.
753    ///
754    /// - Complexity: O(n) time and space for n descriptor nodes.
755    ///
756    /// # Errors
757    ///
758    /// Returns an error on any semantic or physical representation mismatch.
759    ///
760    /// # Examples
761    ///
762    /// ```
763    /// use cel_runtime::value_type::{Leaf, ValueType};
764    /// assert!(ValueType::leaf::<i32>().with_debug::<Leaf<i32>>().is_ok());
765    /// ```
766    pub fn with_debug<R: ValueRepr>(mut self) -> anyhow::Result<Self>
767    where
768        R::Value: Debug,
769    {
770        self.validate::<R>()?;
771        let plan = Arc::make_mut(&mut self.0);
772        plan.debug_hook = Some(debug_leaf::<R::Value>);
773        plan.debuggable = true;
774        Ok(self)
775    }
776
777    /// Validates a concrete adapter before any raw operations are installed.
778    ///
779    /// - Complexity: O(n) time and space for n witness nodes.
780    ///
781    /// # Errors
782    ///
783    /// Returns an error if the full descriptor differs from the sealed witness.
784    pub(crate) fn validate<R: ValueRepr>(&self) -> anyhow::Result<()> {
785        anyhow::ensure!(
786            self.same_shape(&R::value_type()),
787            "value representation mismatch"
788        );
789        Ok(())
790    }
791
792    /// Returns whether the frozen plan can clone every required child.
793    pub(crate) fn can_clone(&self) -> bool {
794        self.0.cloneable
795    }
796
797    /// Returns whether this complete descriptor supplies value equality.
798    ///
799    /// # Examples
800    /// ```
801    /// assert!(!cel_runtime::ValueType::leaf::<i32>().can_compare());
802    /// ```
803    pub fn can_compare(&self) -> bool {
804        self.0.comparable
805    }
806
807    /// Returns whether the frozen plan can format every required child.
808    pub(crate) fn can_debug(&self) -> bool {
809        self.0.debuggable
810    }
811
812    /// Returns the optional prevalidated whole-representation clone adapter.
813    pub(crate) fn clone_hook(&self) -> Option<CloneHook> {
814        self.0.clone_hook
815    }
816
817    /// Returns the optional prevalidated whole-representation equality adapter.
818    pub(crate) fn equality_hook(&self) -> Option<EqualityHook> {
819        self.0.equality_hook
820    }
821
822    /// Returns the optional prevalidated whole-representation formatting adapter.
823    pub(crate) fn debug_hook(&self) -> Option<DebugHook> {
824        self.0.debug_hook
825    }
826
827    /// Returns the concrete leaf or callable destructor, absent for tuples and arrays.
828    pub(crate) fn leaf_drop(&self) -> Option<DropHook> {
829        self.0.leaf_drop
830    }
831
832    /// Borrows concrete host adapters installed while the leaf type is known.
833    pub(crate) fn host_leaf(&self) -> Option<&crate::host_value_bridge::LeafBridge> {
834        self.0.host_leaf.as_ref()
835    }
836}
837
838/// Compares recursive shapes, including callable argument and result identities.
839///
840/// - Complexity: O(n) time and O(d) call space for n nodes and depth d.
841fn same_kind(left: &ValueKind, right: &ValueKind) -> bool {
842    match (left, right) {
843        (ValueKind::Leaf(a), ValueKind::Leaf(b)) => a == b,
844        (ValueKind::Array(a), ValueKind::Array(b)) => a.same_shape(b),
845        (ValueKind::Tuple(a), ValueKind::Tuple(b)) => {
846            a.len() == b.len()
847                && a.iter()
848                    .zip(b)
849                    .all(|(a, b)| a.offset == b.offset && a.value_type.same_shape(&b.value_type))
850        }
851        (
852            ValueKind::Callable {
853                parameters: a,
854                result: ar,
855            },
856            ValueKind::Callable {
857                parameters: b,
858                result: br,
859            },
860        ) => {
861            a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.same_shape(b)) && ar.same_shape(br)
862        }
863        _ => false,
864    }
865}
866
867/// Destroys one live leaf.
868///
869/// - Complexity: The concrete type's destructor costs apply.
870///
871/// # Safety
872///
873/// `pointer` must address an exclusively owned, aligned, live `T`.
874unsafe fn drop_leaf<T>(pointer: *mut u8) {
875    unsafe { pointer.cast::<T>().drop_in_place() };
876}
877
878/// Clones a live value into a disjoint, aligned uninitialized destination.
879///
880/// - Complexity: The concrete type's clone time and allocation costs apply.
881///
882/// # Safety
883///
884/// `source` must address a live `T`; `destination` must hold uninitialized `T`
885/// storage. On panic no destination value is initialized.
886unsafe fn clone_leaf<T: Clone>(source: *const u8, destination: *mut u8) {
887    unsafe {
888        destination
889            .cast::<T>()
890            .write((&*source.cast::<T>()).clone())
891    };
892}
893
894/// Compares two live values without taking ownership.
895///
896/// - Complexity: The concrete type's equality costs apply.
897///
898/// # Safety
899///
900/// Both pointers must address aligned live values of `T` for this call.
901unsafe fn equal_leaf<T: PartialEq>(left: *const u8, right: *const u8) -> bool {
902    unsafe { *left.cast::<T>() == *right.cast::<T>() }
903}
904
905/// Appends one live value's debug representation without taking ownership.
906///
907/// - Complexity: The concrete formatter's time and output storage costs apply.
908///
909/// # Safety
910///
911/// `pointer` must address an aligned live value of `T` for this call.
912unsafe fn debug_leaf<T: Debug>(pointer: *const u8, output: &mut String) {
913    unsafe { write!(output, "{:?}", *pointer.cast::<T>()) }
914        .expect("debug formatter writes to a string");
915}
916
917#[cfg(test)]
918mod tests {
919    use super::{ValueKind, ValueType, same_kind};
920
921    /// Rejects structural descriptors when a legacy host conversion names only a leaf.
922    #[test]
923    fn complete_factory_legacy_leaf_validation_requires_concrete_identity() {
924        use std::any::TypeId;
925        assert!(
926            ValueType::leaf::<()>()
927                .validate_opaque_leaf(TypeId::of::<()>())
928                .is_ok()
929        );
930        assert!(
931            ValueType::leaf::<i32>()
932                .validate_opaque_leaf(TypeId::of::<u32>())
933                .is_err()
934        );
935        for (structural, marker) in [
936            (
937                ValueType::tuple(vec![]).unwrap(),
938                TypeId::of::<crate::CNil<()>>(),
939            ),
940            (
941                ValueType::array(ValueType::leaf::<i32>()),
942                TypeId::of::<crate::Array<i32>>(),
943            ),
944            (
945                ValueType::callable(vec![], ValueType::leaf::<()>()),
946                TypeId::of::<crate::DynClosure>(),
947            ),
948        ] {
949            assert!(structural.validate_opaque_leaf(marker).is_err());
950        }
951    }
952
953    /// Builds semantic callable metadata without constructing an execution carrier.
954    fn signature(parameter: ValueType, result: ValueType) -> ValueKind {
955        ValueKind::Callable {
956            parameters: vec![parameter],
957            result: Box::new(result),
958        }
959    }
960
961    /// Verifies complete callable parameter and result shapes participate in identity.
962    #[test]
963    fn callable_signatures_compare_every_shape() {
964        let signature_a = signature(
965            ValueType::array(ValueType::leaf::<i32>()),
966            ValueType::tuple(vec![]).unwrap(),
967        );
968        assert!(same_kind(
969            &signature_a,
970            &signature(
971                ValueType::array(ValueType::leaf::<i32>()),
972                ValueType::tuple(vec![]).unwrap(),
973            )
974        ));
975        assert!(!same_kind(
976            &signature_a,
977            &signature(
978                ValueType::array(ValueType::leaf::<u32>()),
979                ValueType::tuple(vec![]).unwrap(),
980            )
981        ));
982        assert!(!same_kind(
983            &signature_a,
984            &signature(
985                ValueType::array(ValueType::leaf::<i32>()),
986                ValueType::leaf::<()>(),
987            )
988        ));
989        assert!(!same_kind(
990            &signature_a,
991            &ValueKind::Callable {
992                parameters: vec![],
993                result: Box::new(ValueType::tuple(vec![]).unwrap()),
994            }
995        ));
996    }
997}