frame_suite/virtuals.rs
1// SPDX-License-Identifier: MPL-2.0
2//
3// Part of Auguth Labs open-source softwares.
4// Built for the Substrate framework.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at https://mozilla.org/MPL/2.0/.
9//
10// Copyright (c) 2026 Auguth Labs (OPC) Pvt Ltd, India
11
12// ===============================================================================
13// ```````````````````````````````` VIRTUALS SUITE ```````````````````````````````
14// ===============================================================================
15
16//! Virtual struct system mapping discriminants (ZSTs) to behavior via
17//! trait-driven schemas.
18//!
19//! Traditional Rust data structures require committing upfront to:
20//! - a fixed shape (`Option<T>`, `Vec<T>`, `[T; N]`, struct fields)
21//! - a fixed cardinality (single vs multiple)
22//! - a fixed storage layout
23//!
24//! This makes evolution difficult:
25//! - structure and storage are tightly coupled
26//! - generic abstractions often hit coherence limits
27//! - external composition (plugins, schemas) is hard
28//! - changing a field (`None -> Some -> Many`) requires redesign
29//!
30//! This module introduces a system where **structure, interpretation,
31//! and storage are decoupled**, and resolved through types.
32//!
33//! ## Mental Model: Virtual Structs
34//!
35//! Think in terms of a **virtual struct**, whose fields are not stored
36//! directly, but defined through traits and discriminants:
37//!
38//! ```ignore
39//! struct <T as Trait>::Struct<K> {
40//! FieldTag: T::Field, // virtual field (identified by discriminant)
41//! ExtTag: K, // virtual extension (identified by discriminant)
42//! }
43//! ```
44//!
45//! This is not a concrete struct. Instead:
46//!
47//! - fields are accessed via trait implementations
48//! - each field is identified by a **discriminant (type-level key)**
49//! - storage is abstracted or external
50//!
51//! ## Discriminants (Field Identifiers)
52//!
53//! ```ignore
54//! struct FieldTag;
55//! struct ExtTag;
56//! ```
57//!
58//! Discriminants are zero-sized types used as **type-level field keys**.
59//!
60//! They act as:
61//! - field identifiers in the virtual struct
62//! - selectors for behavior and interpretation
63//! - disambiguators for generic implementations
64//!
65//! This ensures:
66//! - multiple fields can coexist without ambiguity
67//! - overlapping generic impls remain coherence-safe
68//!
69//! ## Trait as Schema
70//!
71//! ```ignore
72//! pub trait Trait {
73//! type Struct: VirtualDynField<FieldTag, Some = Self::Field>
74//! + VirtualDynExtension<ExtTag>;
75//!
76//! type Field;
77//! }
78//! ```
79//!
80//! - `Struct` is the container (virtual struct)
81//! - `FieldTag` identifies a logical field
82//! - `ExtTag` identifies an extension slot
83//! - `Field` defines the logical type of the field
84//!
85//! Traits define the **schema**, not the storage.
86//!
87//! ## Field Behavior (Cardinality Abstraction)
88//!
89//! A virtual field supports:
90//!
91//! - `None` - no value
92//! - `Some` - one value
93//! - `Many` - multiple values
94//!
95//! This replaces fixed representations like:
96//!
97//! ```ignore
98//! Option<T> / Vec<T>
99//! ```
100//!
101//! with a single abstraction that can evolve without redesign.
102//!
103//! ## Key Insight
104//!
105//! A virtual struct is not a fixed layout, but a **composition of
106//! discriminant-keyed behaviors**, where:
107//!
108//! - **discriminants** -> field identifiers
109//! - **traits** -> schema (what exists)
110//! - **implementations** -> storage (how/where it exists)
111//!
112//! Structure is resolved by types, not encoded directly.
113//!
114//! ## Core Primitives
115//!
116//! The system is built from:
117//!
118//! ### Virtual Fields
119//! - [`VirtualDynField`] - dynamic, vector-like semantics
120//! - [`VirtualStaticField`] - static, array-like semantics
121//!
122//! ### Virtual Extensions
123//! - [`VirtualDynExtension`] / [`VirtualStaticExtension`]
124//! - externally defined fields via schemas
125//!
126//! ### Schemas & Bounds
127//! - [`VirtualDynBound`] / [`VirtualStaticBound`]
128//! - constraints defined independently of storage
129//!
130//! ### Concrete Representations
131//! - [`SumDynType`] - bounded vector semantics (`None | Some | Many`)
132//! - [`SumStaticType`] - fixed array semantics
133//!
134//! ## Design Principles
135//!
136//! ### Discriminant-Keyed Design
137//!
138//! All components are keyed by a [`DiscriminantTag`].
139//!
140//! This:
141//! - avoids ambiguity in generic implementations
142//! - enables multiple independent fields on the same container
143//! - ensures coherence-safe extensibility
144//!
145//! ### Tagged Conversions
146//!
147//! Instead of `From` / `Into`, the system uses:
148//!
149//! - [`FromTag`], [`IntoTag`]
150//! - [`TryFromTag`], [`TryIntoTag`]
151//!
152//! Conversions are disambiguated by discriminants:
153//! - [`NoneTag`] - absence
154//! - [`SomeTag`] - single value
155//! - [`ManyTag`] - multiple values
156//!
157//! This avoids overlapping implementations in generic contexts.
158//!
159//! ### Layered Model
160//!
161//! The system separates:
162//!
163//! - **Type-level layer**
164//! - defines structure, schema, and behavior
165//!
166//! - **Value-level layer**
167//! - represents `None`, `Some`, `Many`
168//!
169//! This enables abstract structure with concrete representations.
170//!
171//! ### Dynamic vs Static
172//!
173//! #### Dynamic (Runtime Flexible)
174//! - vector-like semantics
175//! - runtime bounds (`Get<u32>`)
176//! - growable/shrinkable collections
177//!
178//! #### Static (Compile-Time Fixed)
179//! - array-like semantics
180//! - compile-time bounds (`const`)
181//! - zero-overhead representations
182//!
183//! ## Helpers
184//!
185//! Ergonomic helpers are provided for working with virtual components:
186//!
187//! - [`DynFieldHelpers`] / [`StaticFieldHelpers`]
188//! - [`DynExtHelpers`] / [`StaticExtHelpers`]
189//!
190//! ## Summary
191//!
192//! This system enables:
193//!
194//! - evolving data shapes without redesign
195//! - discriminant-keyed field composition
196//! - external composition via schemas and extensions
197//! - reuse of storage across multiple logical fields
198//! - coherence-safe generic abstractions
199//!
200//! It provides a **type-level virtualization layer** where:
201//!
202//! > A virtual struct is a mapping from **discriminants -> behaviors**,
203//! > resolved through traits and implemented via storage.
204
205// ===============================================================================
206// ``````````````````````````````````` IMPORTS ```````````````````````````````````
207// ===============================================================================
208
209// --- Local crate imports ---
210use crate::base::{Buffer, Collection, Delimited, Growable, Indexable, RuntimeError};
211
212// --- Core (Rust std replacement) ---
213use core::fmt::{self, Debug};
214
215// --- Scale-codec crates ---
216use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
217use scale_info::TypeInfo;
218
219// --- FRAME Support ---
220use frame_support::{
221 storage::types::{
222 EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator,
223 ReversibleKeyGenerator, TupleToEncodedIter,
224 },
225 IterableStorageMap, IterableStorageNMap, StorageMap, StorageNMap, StoragePrefixedMap,
226};
227
228// --- Substrate primitives ---
229use sp_core::{ConstU32, Get};
230use sp_runtime::{traits::Zero, BoundedVec, Vec};
231use sp_std::vec;
232
233// ===============================================================================
234// ```````````````````````````````` DISCRIMINANTS ````````````````````````````````
235// ===============================================================================
236
237/// Marker trait for type-level discriminants.
238///
239/// A `Discriminant` is a zero-sized type used to uniquely identify behavior,
240/// structure, or interpretation at the type level.
241///
242/// ## Guidelines
243///
244/// Implementors should:
245/// - be zero-sized types (ZST)
246/// - carry no runtime data
247/// - act purely as type-level identifiers
248///
249/// ## Motivation
250///
251/// In Rust, trait implementations involving generic or associated types can
252/// become ambiguous under the coherence rules:
253///
254/// - generic parameters may unify in unexpected ways
255/// - multiple impls may overlap when types are not fully concrete
256/// - the compiler must conservatively reject such cases
257///
258/// To avoid this, a **concrete type-level key** is introduced as a discriminant.
259///
260/// By adding a `Discriminant`:
261/// - each implementation becomes uniquely identifiable
262/// - ambiguity between generic impls is disposed
263/// - coherence is preserved without restricting expressiveness
264///
265/// ## Role in the System
266///
267/// Discriminants are used in some cases like
268/// - keys for [`VirtualDynField`]
269/// - identifiers for [`plugin`](crate::plugins) operations
270/// - selectors for tagged conversions ([`FromTag`], [`IntoTag`], etc.)
271///
272/// They allow multiple interpretations over the same underlying types
273/// without conflict.
274pub trait DiscriminantTag {}
275
276/// Default Discriminant implementation if no
277/// multiple interpretations are required.
278impl DiscriminantTag for () {}
279
280/// Defines one or more public zero-sized discriminant types.
281///
282/// A *discriminant* is a concrete type-level key used to uniquely identify
283/// behavior, structure, or interpretation in generic systems.
284///
285/// ## Why Discriminants?
286///
287/// In Rust, trait implementations over generic or associated types can become
288/// ambiguous under coherence rules:
289/// - generic types may unify in multiple ways
290/// - implementations may overlap when types are not fully concrete
291/// - the compiler must reject such cases conservatively
292///
293/// Discriminants solve this by introducing a **concrete, unique type**
294/// that disambiguates otherwise overlapping implementations.
295///
296/// This enables:
297/// - multiple interpretations over the same types
298/// - safe composition of generic abstractions
299/// - coherence-safe extensibility
300///
301/// ## Syntax
302///
303/// ```ignore
304/// discriminants!(
305/// /// Optional docs or attributes
306/// A,
307///
308/// B,
309///
310/// #[cfg(feature = "x")]
311/// C,
312/// );
313/// ```
314///
315/// ## Expansion
316///
317/// For each identifier, this macro generates:
318/// - a `pub` zero-sized struct
319/// - an implementation of [`DiscriminantTag`]
320///
321/// ## Properties
322///
323/// - zero runtime cost (ZSTs)
324/// - purely type-level identifiers
325/// - stable and unambiguous across generic contexts
326/// - reusable across virtual fields, extensions, and
327/// [`plugin`](crate::plugins) systems
328///
329/// ## Why Always Public
330///
331/// Discriminants appear in type signatures and generic bounds,
332/// making them part of the public type-level API.
333///
334/// Restricting visibility would:
335/// - prevent use in external generic constraints
336/// - break composability across modules or crates
337/// - force duplication of identical identifiers
338///
339/// In practice, discriminants are **type-level contracts**, not internal details.
340#[macro_export]
341macro_rules! discriminants {
342 (
343 $(
344 $(#[$meta:meta])*
345 $name:ident
346 ),* $(,)?
347 ) => {
348 $(
349 $(#[$meta])*
350 #[derive(Clone, Copy, Debug, Default)]
351 pub struct $name;
352
353 impl $crate::virtuals::DiscriminantTag for $name {}
354 )*
355 };
356}
357
358/// Implements [`DiscriminantTag`] for one or more existing types.
359///
360/// This macro allows pre-existing types to act as discriminants without
361/// redefining them.
362///
363/// ## Why Discriminants?
364///
365/// Discriminants provide a **concrete type-level key** that avoids ambiguity
366/// in generic trait resolution under Rust's coherence rules.
367///
368/// By associating behavior with a discriminant instead of relying solely
369/// on generic types, implementations become:
370/// - uniquely identifiable
371/// - non-overlapping
372/// - composable across abstraction boundaries
373///
374/// ## When to Use
375///
376/// Use this macro when:
377/// - a type already exists and should act as a discriminant
378/// - redefining it as a new ZST would be redundant or impossible
379///
380/// ## Syntax
381///
382/// ```ignore
383/// struct MyTag;
384/// struct OtherTag;
385///
386/// impl_discriminants!(MyTag, OtherTag);
387/// ```
388///
389/// ## Behavior
390///
391/// - Implements [`DiscriminantTag`] for each provided type
392/// - Preserves the original type definition
393///
394/// ## Notes
395///
396/// - Types are expected to behave like discriminants (typically ZSTs)
397/// - No runtime guarantees are enforced; this is a semantic contract
398///
399/// ## Summary
400///
401/// This macro extends the discriminant system to existing types,
402/// enabling reuse and integration without redefining identifiers.
403#[macro_export]
404macro_rules! impl_discriminants {
405 (
406 $(
407 $(#[$meta:meta])*
408 $ty:ty
409 ),* $(,)?
410 ) => {
411 $(
412 $(#[$meta])*
413 impl $crate::virtuals::DiscriminantTag for $ty {}
414 )*
415 };
416}
417
418// ===============================================================================
419// ````````````````````` FROM/INTO DISCRIMINANTED CONVERSIONS ````````````````````
420// ===============================================================================
421
422/// Converts a value `T` into `Self` under a given discriminant.
423///
424/// Unlike [`From`], this trait introduces an additional type parameter
425/// (`Discriminant` implementing [`DiscriminantTag`] via
426/// [`discriminants`] or [`impl_discriminants`])
427/// to distinguish between conversions that would otherwise overlap under
428/// Rust's coherence rules.
429///
430/// This is necessary because:
431/// - `T` and `Self` may be generic or associated types (i.e., not fully concrete)
432/// - such types may unify in the future
433/// - the compiler must conservatively reject potentially overlapping impls
434///
435/// By adding a concrete discriminant (tag), each conversion becomes uniquely
436/// identifiable at the type level.
437///
438/// ## Type Parameters
439/// - `T`: Source type (may be generic or non-concrete).
440/// - `Discriminant`: A concrete marker type used to disambiguate conversions.
441///
442/// ## Default Discriminant
443///
444/// - `Discriminant = ()`: uses the unit type as a default tag,
445/// meaning no additional disambiguation when a single interpretation exists.
446pub trait FromTag<T, Discriminant: DiscriminantTag = ()>: Sized {
447 fn from_tag(t: T) -> Self;
448}
449
450/// Fallible version of [`FromTag`].
451///
452/// Allows conversions that may fail, while still being disambiguated by a
453/// concrete discriminant.
454///
455/// ## Type Parameters
456/// - `T`: Source type (may be generic or non-concrete).
457/// - `Discriminant`: A concrete marker type used to disambiguate conversions.
458///
459/// ## Default Discriminant
460///
461/// - `Discriminant = ()`: uses the unit type as a default tag,
462/// meaning no additional disambiguation when a single interpretation exists.
463pub trait TryFromTag<T, Discriminant: DiscriminantTag = ()>: Sized {
464 type Error;
465
466 fn try_from_tag(t: T) -> Result<Self, Self::Error>;
467}
468
469/// Converts `self` into another representation under a given discriminant.
470///
471/// This is the method-based counterpart to [`FromTag`]. It exists for ergonomic
472/// use, similar to how [`Into`] complements [`From`].
473///
474/// The additional discriminant ensures that conversions remain unambiguous even
475/// when source and target types are not fully concrete.
476///
477/// ## Type Parameters
478/// - `R`: Target type (may be generic or non-concrete).
479/// - `Discriminant`: A concrete marker type used to disambiguate conversions.
480///
481/// ## Default Discriminant
482///
483/// - `Discriminant = ()`: uses the unit type as a default tag,
484/// meaning no additional disambiguation when a single interpretation exists.
485pub trait IntoTag<R, Discriminant: DiscriminantTag = ()> {
486 fn into_tag(self) -> R;
487}
488
489/// Fallible version of [`IntoTag`].
490///
491/// Attempts to convert `self` into another representation under a given
492/// discriminant, returning an error if the conversion fails.
493///
494/// ## Type Parameters
495/// - `R`: Target type (may be generic or non-concrete).
496/// - `Discriminant`: A concrete marker type used to disambiguate conversions.
497///
498/// ## Default Discriminant
499///
500/// - `Discriminant = ()`: uses the unit type as a default tag,
501/// meaning no additional disambiguation when a single interpretation exists.
502pub trait TryIntoTag<R, Discriminant: DiscriminantTag = ()> {
503 type Error;
504
505 fn try_into_tag(self) -> Result<R, Self::Error>;
506}
507
508/// Blanket implementation of [`IntoTag`] for any type that implements [`FromTag`].
509///
510/// This mirrors the relationship between [`Into`] and [`From`], while preserving
511/// disambiguation via the discriminant.
512///
513/// The discriminant ensures that even when `T` and `U` are not fully concrete,
514/// the conversion remains uniquely identifiable and does not violate coherence.
515impl<T, U, Tag> IntoTag<U, Tag> for T
516where
517 U: FromTag<T, Tag>,
518 Tag: DiscriminantTag,
519{
520 fn into_tag(self) -> U {
521 U::from_tag(self)
522 }
523}
524
525// ===============================================================================
526// `````````````````````````````````` SUM TYPES ``````````````````````````````````
527// ===============================================================================
528
529discriminants! {
530 /// A discriminant representing the absence of a value in tagged conversions.
531 ///
532 /// This is a zero-sized type used as a type-level primitive to select
533 /// conversion behavior. It acts as a compile-time discriminator,
534 /// allowing multiple interpretations over the same types.
535 NoneTag,
536
537 /// A discriminant representing a single value in tagged conversions.
538 ///
539 /// This is a zero-sized type used as a type-level primitive to select
540 /// conversion behavior. It distinguishes conversions operating on
541 /// a singular value.
542 SomeTag,
543
544 /// A discriminant representing multiple values in tagged conversions.
545 ///
546 /// This is a zero-sized type used as a type-level primitive to select
547 /// conversion behavior. It distinguishes conversions operating on
548 /// collections of values.
549 ManyTag,
550}
551
552/// A concrete representation of field cardinality: zero, one, or many values.
553///
554/// `SumDynType` unifies the possible shapes of a field into a single type:
555/// - absence (`None`)
556/// - a single value (`Some`)
557/// - multiple values (`Many`)
558///
559/// ## Context
560///
561/// In the virtual field system:
562/// - [`VirtualDynField`] defines field behavior abstractly (type-level)
563/// - `SumDynType` provides a concrete, value-level representation
564///
565/// It is commonly used as the backing representation (`Repr`) for
566/// dynamically shaped fields.
567///
568/// ## Representation Model
569///
570/// The `Many` variant is backed by a [`BoundedVec`], giving it
571/// **vector-like semantics**:
572/// - dynamically sized (up to a bound)
573/// - growable and shrinkable
574/// - capacity enforced via a type-level limit
575///
576/// This makes `SumDynType` suitable for:
577/// - flexible schemas
578/// - deferred structure
579/// - abstraction across boundaries where size is not fixed
580///
581/// ## Variants
582/// - `None`: no value
583/// - `Some(Type)`: exactly one value
584/// - `Many(BoundedVec<Type, S>)`: multiple values with vector semantics
585///
586/// ## Type Parameters
587/// - `Type`: element type
588/// - `S`: type-level capacity bound
589///
590/// ## Key Property
591///
592/// This is a **concrete (non-virtual) representation** using
593/// **bounded vector semantics**, allowing flexible cardinality
594/// within a constrained capacity.
595///
596/// ## Default Generics
597///
598/// - `Type = ()`: no meaningful value (unit type)
599/// - `S = ConstU32<0>`: zero capacity, `Many` cannot store elements
600///
601/// Together, this yields a **no-op, zero-capacity representation**,
602/// useful as a placeholder in generic contexts.
603#[derive(Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Clone, Default, Debug)]
604#[scale_info(skip_type_params(S))]
605pub enum SumDynType<Type = (), S = ConstU32<0>>
606where
607 Type: Delimited,
608 S: Get<u32> + Clone + Debug + 'static,
609{
610 #[default]
611 None,
612 Some(Type),
613 Many(BoundedVec<Type, S>),
614}
615
616impl<Type, S> PartialEq for SumDynType<Type, S>
617where
618 Type: Delimited,
619 S: Get<u32> + Clone + fmt::Debug,
620{
621 fn eq(&self, other: &Self) -> bool {
622 match (self, other) {
623 (Self::None, Self::None) => true,
624 (Self::Some(a), Self::Some(b)) => a == b,
625 (Self::Many(a), Self::Many(b)) => a == b,
626 _ => false,
627 }
628 }
629}
630
631impl<Type, S> Eq for SumDynType<Type, S>
632where
633 Type: Delimited,
634 S: Get<u32> + Clone + fmt::Debug,
635{
636}
637
638impl<Type, S> FromTag<(), NoneTag> for SumDynType<Type, S>
639where
640 Type: Delimited,
641 S: Get<u32> + Clone + Debug + 'static,
642{
643 fn from_tag(_t: ()) -> Self {
644 SumDynType::None
645 }
646}
647
648impl<Type, S> TryIntoTag<(), NoneTag> for SumDynType<Type, S>
649where
650 Type: Delimited,
651 S: Get<u32> + Clone + Debug + 'static,
652{
653 type Error = ();
654
655 fn try_into_tag(self) -> Result<(), Self::Error> {
656 match self {
657 SumDynType::None => Ok(()),
658 _ => Err(()),
659 }
660 }
661}
662
663impl<Type, S> FromTag<Type, SomeTag> for SumDynType<Type, S>
664where
665 Type: Delimited,
666 S: Get<u32> + Clone + Debug + 'static,
667{
668 fn from_tag(t: Type) -> Self {
669 SumDynType::Some(t)
670 }
671}
672
673impl<Type, S> TryIntoTag<Type, SomeTag> for SumDynType<Type, S>
674where
675 Type: Delimited,
676 S: Get<u32> + Clone + Debug + 'static,
677{
678 type Error = ();
679
680 fn try_into_tag(self) -> Result<Type, Self::Error> {
681 match self {
682 SumDynType::Some(v) => Ok(v),
683 _ => Err(()),
684 }
685 }
686}
687
688impl<Type, S> TryFromTag<Vec<Type>, ManyTag> for SumDynType<Type, S>
689where
690 Type: Delimited,
691 S: Get<u32> + Clone + Debug + 'static,
692{
693 type Error = ();
694
695 fn try_from_tag(t: Vec<Type>) -> Result<Self, Self::Error> {
696 Ok(SumDynType::Many(
697 BoundedVec::<Type, S>::try_from(t).map_err(|_| ())?,
698 ))
699 }
700}
701
702impl<Type, S> IntoTag<Vec<Type>, ManyTag> for SumDynType<Type, S>
703where
704 Type: Delimited,
705 S: Get<u32> + Clone + Debug + 'static,
706{
707 fn into_tag(self) -> Vec<Type> {
708 match self {
709 SumDynType::None => Vec::new(),
710 SumDynType::Some(v) => vec![v],
711 SumDynType::Many(vec) => vec.to_vec(),
712 }
713 }
714}
715
716/// A statically shaped representation of field cardinality.
717///
718/// `SumStaticType` encodes the possible shapes of a field:
719/// - absence (`None`)
720/// - a single value (`Some`)
721/// - multiple values (`Many`)
722///
723/// ## Context
724///
725/// In the virtual field system:
726/// - [`VirtualStaticField`] defines fields whose structure is
727/// fully determined at compile time
728/// - `SumStaticType` provides a matching concrete representation
729///
730/// ## Representation Model
731///
732/// The `Many` variant is backed by a fixed-size array (`[Type; N]`),
733/// giving it **array-like semantics**:
734/// - size is fixed at compile time
735/// - no resizing or allocation
736/// - capacity is encoded directly in the type
737///
738/// This makes `SumStaticType` suitable for:
739/// - compile-time enforced layouts
740/// - fixed schemas
741/// - zero-overhead representations
742///
743/// ## Variants
744/// - `None`: no value
745/// - `Some(Type)`: exactly one value
746/// - `Many([Type; N])`: fixed-size collection with array semantics
747///
748/// ## Type Parameters
749/// - `Type`: element type
750/// - `N`: compile-time capacity
751///
752/// ## Key Property
753///
754/// This is a **fully determined representation** using
755/// **array semantics**, where both cardinality and capacity
756/// are encoded directly in the type.
757///
758/// ## Default Generics
759///
760/// - `Type = ()`: no meaningful value (unit type)
761/// - `N = 0`: zero-sized array, `Many` holds no elements
762///
763/// Together, this yields a **no-op, zero-sized representation**,
764/// useful as a placeholder in generic contexts.
765#[derive(
766 Encode,
767 Decode,
768 DecodeWithMemTracking,
769 MaxEncodedLen,
770 TypeInfo,
771 Clone,
772 Default,
773 Debug,
774 PartialEq,
775 Eq,
776)]
777pub enum SumStaticType<Type = (), const N: usize = 0>
778where
779 Type: Delimited,
780{
781 #[default]
782 None,
783 Some(Type),
784 Many([Type; N]),
785}
786
787impl<Type, const N: usize> FromTag<(), NoneTag> for SumStaticType<Type, N>
788where
789 Type: Delimited,
790{
791 fn from_tag(_t: ()) -> Self {
792 SumStaticType::None
793 }
794}
795
796impl<Type, const N: usize> TryIntoTag<(), NoneTag> for SumStaticType<Type, N>
797where
798 Type: Delimited,
799{
800 type Error = ();
801
802 fn try_into_tag(self) -> Result<(), Self::Error> {
803 match self {
804 SumStaticType::None => Ok(()),
805 _ => Err(()),
806 }
807 }
808}
809
810impl<Type, const N: usize> FromTag<Type, SomeTag> for SumStaticType<Type, N>
811where
812 Type: Delimited,
813{
814 fn from_tag(t: Type) -> Self {
815 SumStaticType::Some(t)
816 }
817}
818
819impl<Type, const N: usize> TryIntoTag<Type, SomeTag> for SumStaticType<Type, N>
820where
821 Type: Delimited,
822{
823 type Error = ();
824
825 fn try_into_tag(self) -> Result<Type, Self::Error> {
826 match self {
827 SumStaticType::Some(v) => Ok(v),
828 _ => Err(()),
829 }
830 }
831}
832
833impl<Type, const N: usize> FromTag<[Type; N], ManyTag> for SumStaticType<Type, N>
834where
835 Type: Delimited,
836{
837 fn from_tag(t: [Type; N]) -> Self {
838 SumStaticType::Many(t)
839 }
840}
841
842impl<Type, const N: usize> TryIntoTag<[Type; N], ManyTag> for SumStaticType<Type, N>
843where
844 Type: Delimited,
845{
846 type Error = ();
847
848 fn try_into_tag(self) -> Result<[Type; N], Self::Error> {
849 match self {
850 SumStaticType::Many(v) => Ok(v),
851 _ => Err(()),
852 }
853 }
854}
855
856// ===============================================================================
857// ```````````````````````````````` VIRTUAL FIELDS ```````````````````````````````
858// ===============================================================================
859
860/// A discriminant-keyed virtual field abstraction with flexible cardinality
861/// (`None`, `Some`, or `Many`).
862///
863/// This trait models a field whose structure is **deferred** and resolved
864/// through types rather than fixed upfront.
865///
866/// ## Model
867///
868/// A `VirtualDynField` behaves like a field in a logical record, without
869/// committing to:
870///
871/// - a concrete container (`Option`, `Vec`, etc.)
872/// - a fixed cardinality
873/// - or a fixed storage layout
874///
875/// Instead:
876/// - the **implementor** defines the backing representation (`Repr`)
877/// - the **caller** selects the shape (`None`, `Some`, or `Many`)
878///
879/// ## Representation Semantics
880///
881/// The `Many` form is expected to have **vector-like semantics**:
882/// - dynamically sized (within bounds)
883/// - growable and shrinkable
884/// - capacity enforced but not encoded in the type shape
885///
886/// This makes `VirtualDynField` suitable for:
887/// - flexible schemas
888/// - deferred structure
889/// - abstraction across boundaries
890///
891/// ## Discriminant
892///
893/// The `Discriminant` acts as a type-level key, allowing multiple independent
894/// fields to coexist without ambiguity.
895///
896/// ## Design
897///
898/// Responsibilities are separated:
899///
900/// - **Implementor (Storage Layer)**
901/// - defines representation (`Repr`)
902/// - **Caller (Shape Layer)**
903/// - selects cardinality and interpretation
904///
905/// This decouples logical meaning from physical storage.
906///
907/// ## When to Use
908///
909/// Use this trait when:
910/// - structure must remain flexible
911/// - cardinality is not known upfront
912/// - storage must be abstract and composable
913///
914/// ## Default Discriminant
915///
916/// - `Discriminant = ()`: uses the unit type as a single field key,
917/// meaning only one virtual field exists (no disambiguation needed).
918pub trait VirtualDynField<Discriminant: DiscriminantTag = ()>: Default {
919 /// Representation of absence.
920 type None: Delimited;
921
922 /// The logical element type stored in the virtual field.
923 type Some: Delimited;
924
925 /// A collection of `Some`.
926 ///
927 /// Must support buffering and indexed access.
928 type Many: Buffer<Self::Some>;
929
930 /// Opaque storage backing the virtual field.
931 ///
932 /// Encodes the actual data and must support tagged conversions
933 /// to and from `None`, `Some`, and `Many`.
934 type Repr: Delimited
935 // Provides an initial empty representation,
936 // allowing deferred population via mutation.
937 + Default
938 // Construct representation from absence
939 + FromTag<Self::None, NoneTag>
940 // Extract absence from representation
941 + TryIntoTag<Self::None, NoneTag>
942 // Construct representation from a single value
943 + FromTag<Self::Some, SomeTag>
944 // Extract a single value from representation
945 + TryIntoTag<Self::Some, SomeTag>
946 // Attempt to construct representation from many values
947 + TryFromTag<Self::Many, ManyTag>
948 // Convert representation into many values
949 + IntoTag<Self::Many, ManyTag>;
950
951 /// Returns the current representation of the virtual field.
952 ///
953 /// Interaction is performed via tagged conversions.
954 fn access(&self) -> Self::Repr;
955
956 /// Replaces the current representation.
957 ///
958 /// The provided value must satisfy representation invariants.
959 fn mutate(&mut self, v: Self::Repr);
960
961 /// Returns the current number of elements represented.
962 ///
963 /// Interpreted as:
964 /// - `None` -> 0
965 /// - `Some` -> 1
966 /// - `Many` -> n
967 fn len(&self) -> usize;
968
969 /// Returns the minimum number of elements representable.
970 fn min(&self) -> usize;
971
972 /// Returns the maximum number of elements representable.
973 fn max(&self) -> usize;
974}
975
976/// Trivial `None` conversion for unit.
977impl FromTag<(), NoneTag> for () {
978 fn from_tag(_t: ()) -> Self {}
979}
980
981/// Trivial `Some` conversion for unit.
982impl FromTag<(), SomeTag> for () {
983 fn from_tag(_t: ()) -> Self {}
984}
985
986/// Trivial `Many` conversion for unit (always succeeds).
987impl TryFromTag<Vec<()>, ManyTag> for () {
988 type Error = core::convert::Infallible;
989
990 fn try_from_tag(_t: Vec<()>) -> Result<Self, Self::Error> {
991 Ok(())
992 }
993}
994
995/// Trivial extraction of `None` from unit.
996impl TryIntoTag<(), NoneTag> for () {
997 type Error = core::convert::Infallible;
998
999 fn try_into_tag(self) -> Result<Self, Self::Error> {
1000 Ok(())
1001 }
1002}
1003
1004/// Trivial extraction of `Some` from unit.
1005impl TryIntoTag<(), SomeTag> for () {
1006 type Error = core::convert::Infallible;
1007
1008 fn try_into_tag(self) -> Result<Self, Self::Error> {
1009 Ok(())
1010 }
1011}
1012
1013/// Converts unit into an empty `Many` representation.
1014impl IntoTag<Vec<()>, ManyTag> for () {
1015 fn into_tag(self) -> Vec<()> {
1016 Vec::<()>::new()
1017 }
1018}
1019
1020/// No-op `VirtualDynField` implementation for unit.
1021///
1022/// Represents an allocation with no storage and zero capacity.
1023impl VirtualDynField for () {
1024 type None = ();
1025 type Some = ();
1026 type Many = Vec<()>;
1027 type Repr = ();
1028
1029 fn access(&self) -> Self::Repr {
1030 ()
1031 }
1032
1033 fn mutate(&mut self, _: Self::Repr) {}
1034
1035 fn len(&self) -> usize {
1036 Zero::zero()
1037 }
1038
1039 fn min(&self) -> usize {
1040 Zero::zero()
1041 }
1042
1043 fn max(&self) -> usize {
1044 Zero::zero()
1045 }
1046}
1047
1048// ===============================================================================
1049// ```````````````````````` VIRTUAL FIELD DEFAULT-HELPERS ````````````````````````
1050// ===============================================================================
1051
1052/// A discriminant-keyed virtual field abstraction with statically
1053/// determined cardinality.
1054///
1055/// This trait models a field whose structure is **fully determined
1056/// at compile time**, rather than deferred.
1057///
1058/// ## Model
1059///
1060/// A `VirtualStaticField` behaves like a field in a logical record,
1061/// where:
1062///
1063/// - cardinality is fixed or constrained at compile time
1064/// - storage shape is predetermined
1065/// - no dynamic resizing or growth is expected
1066///
1067/// Similar to [`VirtualDynField`] (but not dynamically sized):
1068/// - the **implementor** defines the backing representation (`Repr`)
1069/// - the **caller** selects the interpretation (`None`, `Some`, `Many`)
1070///
1071/// ## Representation Semantics
1072///
1073/// The `Many` form is expected to have **array-like semantics**:
1074/// - fixed size
1075/// - no resizing or allocation
1076/// - capacity encoded directly in the type
1077///
1078/// This makes `VirtualStaticField` suitable for:
1079/// - compile-time enforced layouts
1080/// - fixed schemas
1081/// - zero-overhead representations
1082///
1083/// ## Discriminant
1084///
1085/// The `Discriminant` acts as a type-level key, allowing multiple independent
1086/// fields to coexist without ambiguity.
1087///
1088/// ## Design
1089///
1090/// As with dynamic fields, responsibilities are separated:
1091///
1092/// - **Implementor (Storage Layer)**
1093/// - defines representation (`Repr`)
1094/// - **Caller (Shape Layer)**
1095/// - selects cardinality and interpretation
1096///
1097/// The key difference is that structure is **not deferred**, but
1098/// fully determined at compile time.
1099///
1100/// ## When to Use
1101///
1102/// Use this trait when:
1103/// - structure is known and fixed upfront
1104/// - dynamic resizing is unnecessary or undesirable
1105/// - compile-time guarantees are preferred over flexibility
1106///
1107/// ## Default Discriminant
1108///
1109/// - `Discriminant = ()`: uses the unit type as a single field key,
1110/// meaning only one virtual field exists (no disambiguation needed).
1111pub trait VirtualStaticField<Discriminant: DiscriminantTag = ()>: Default {
1112 /// Representation of absence.
1113 type None: Delimited;
1114
1115 /// The logical element type stored in the virtual field.
1116 type Some: Delimited;
1117
1118 /// A collection of `Some`.
1119 ///
1120 /// Must support indexed access and have a statically
1121 /// determined size (array-like semantics).
1122 type Many: Collection<Self::Some>;
1123
1124 /// Opaque storage backing the virtual field.
1125 ///
1126 /// Encodes the field state and supports tagged conversions
1127 /// between `None`, `Some`, and `Many`.
1128 ///
1129 /// Unlike dynamic fields, this representation is expected to
1130 /// be fully determined at compile time and not rely on
1131 /// dynamic resizing or buffering.
1132 type Repr: Delimited
1133 // Provides an initial representation.
1134 + Default
1135 // Construct representation from absence
1136 + FromTag<Self::None, NoneTag>
1137 // Extract absence from representation
1138 + TryIntoTag<Self::None, NoneTag>
1139 // Construct representation from a single value
1140 + FromTag<Self::Some, SomeTag>
1141 // Extract a single value from representation
1142 + TryIntoTag<Self::Some, SomeTag>
1143 // Construct representation from many values
1144 + FromTag<Self::Many, ManyTag>
1145 // Extract many values from representation
1146 + TryIntoTag<Self::Many, ManyTag>;
1147
1148 /// Returns the current representation of the virtual field.
1149 ///
1150 /// Interaction is performed via tagged conversions.
1151 fn access(&self) -> Self::Repr;
1152
1153 /// Replaces the current representation.
1154 ///
1155 /// The provided value must satisfy representation invariants.
1156 fn mutate(&mut self, v: Self::Repr);
1157}
1158
1159/// Trivial `Many` conversion for unit using a zero-sized array.
1160impl FromTag<[(); 0], ManyTag> for () {
1161 fn from_tag(_t: [(); 0]) -> Self {}
1162}
1163
1164/// Trivial extraction of `Many` as a zero-sized array from unit.
1165impl TryIntoTag<[(); 0], ManyTag> for () {
1166 type Error = core::convert::Infallible;
1167
1168 fn try_into_tag(self) -> Result<[(); 0], Self::Error> {
1169 Ok([(); 0])
1170 }
1171}
1172
1173/// No-op `VirtualStaticField` implementation for unit.
1174///
1175/// Represents an allocation with no storage and zero capacity.
1176impl VirtualStaticField for () {
1177 type None = ();
1178 type Some = ();
1179 type Many = [(); 0];
1180 type Repr = ();
1181
1182 fn access(&self) -> Self::Repr {
1183 ()
1184 }
1185
1186 fn mutate(&mut self, _: Self::Repr) {}
1187}
1188
1189/// Helper methods for accessing and mutating values in a [`VirtualDynField`].
1190///
1191/// These helpers operate on **dynamically shaped fields** with
1192/// **vector-like semantics**:
1193/// - collections may grow or shrink (within bounds)
1194/// - indexing and iteration are supported
1195/// - mutations may reallocate or fail due to bounds
1196///
1197/// All operations are performed via tagged conversions.
1198///
1199/// ## Default Discriminant
1200///
1201/// - `K = ()`: operates on a single default field,
1202/// meaning one virtual field is assumed.
1203pub trait DynFieldHelpers<K = ()>: VirtualDynField<K>
1204where
1205 K: DiscriminantTag,
1206{
1207 /// Returns the element at `index` from the field interpreted as `Many`.
1208 ///
1209 /// ## Behavior
1210 /// - Returns `Some(V)` if the field contains a collection and `index` is in bounds
1211 /// - Returns `None` if the field is `None`, `Some`, or out of bounds
1212 fn index_get(&self, index: usize) -> Option<Self::Some>
1213 where
1214 Self::Some: Clone,
1215 {
1216 <Self as VirtualDynField<K>>::access(self)
1217 .into_tag()
1218 .as_ref()
1219 .get(index)
1220 .cloned()
1221 }
1222
1223 /// Returns an iterator over elements in the field interpreted as `Many`.
1224 ///
1225 /// If the field is not `Many`, the iterator will be empty.
1226 fn iter(&self) -> impl Iterator<Item = Self::Some>
1227 where
1228 Self::Some: Clone,
1229 {
1230 <Self as VirtualDynField<K>>::access(self)
1231 .into_tag()
1232 .into_iter()
1233 }
1234
1235 /// Applies a mutable operation to each element in the field interpreted as `Many`.
1236 ///
1237 /// After mutation, the updated collection is written back to the container.
1238 ///
1239 /// ## Errors
1240 /// - Returns `Err(())` if conversion back into the representation fails
1241 fn iter_mut<F>(&mut self, mut f: F) -> Result<(), ()>
1242 where
1243 F: FnMut(&mut Self::Some),
1244 {
1245 let mut vec = <Self as VirtualDynField<K>>::access(self).into_tag();
1246
1247 let len = vec.as_ref().len();
1248 for i in 0..len {
1249 f(&mut vec[i]);
1250 }
1251
1252 let repr = TryFromTag::try_from_tag(vec).map_err(|_| ())?;
1253 <Self as VirtualDynField<K>>::mutate(self, repr);
1254
1255 Ok(())
1256 }
1257
1258 /// Sets the element at `index` in the field interpreted as `Many`.
1259 ///
1260 /// If the field is not currently a collection or is too short,
1261 /// it is extended with default values.
1262 ///
1263 /// ## Errors
1264 /// - Returns `Err(())` if conversion back fails
1265 fn index_set(&mut self, index: usize, value: Self::Some) -> Result<(), ()>
1266 where
1267 Self::Some: Default,
1268 {
1269 let mut v = <Self as VirtualDynField<K>>::access(self).into_tag();
1270
1271 set_index(&mut v, index, value);
1272
1273 let repr = TryFromTag::try_from_tag(v).map_err(|_| ())?;
1274 <Self as VirtualDynField<K>>::mutate(self, repr);
1275
1276 Ok(())
1277 }
1278
1279 /// Retrieves the value of the field interpreted as `Some`.
1280 ///
1281 /// ## Behavior
1282 /// - Returns `Some(V)` if the field contains a single value
1283 /// - Returns `None` otherwise
1284 fn get(&self) -> Option<Self::Some> {
1285 let repr = <Self as VirtualDynField<K>>::access(self);
1286 TryIntoTag::<_, SomeTag>::try_into_tag(repr).ok()
1287 }
1288
1289 /// Sets the field to a single value (`Some`).
1290 ///
1291 /// Replaces any existing representation.
1292 fn set(&mut self, v: Self::Some)
1293 where
1294 Self::Some: Delimited,
1295 {
1296 <Self as VirtualDynField<K>>::mutate(self, v.into_tag());
1297 }
1298}
1299
1300/// Blanket impl for all [`VirtualDynField`] types.
1301///
1302/// This trait is not intended to be implemented manually.
1303/// It exists as an ergonomic replacement for free helper functions.
1304///
1305/// All methods have default implementations, making this
1306/// forward-compatible: new helpers can be added without
1307/// breaking existing code.
1308impl<T, K> DynFieldHelpers<K> for T
1309where
1310 T: VirtualDynField<K>,
1311 K: DiscriminantTag,
1312{
1313}
1314
1315/// Helper methods for accessing and mutating values in a [`VirtualStaticField`].
1316///
1317/// These helpers operate on **statically shaped fields** with
1318/// **array-like semantics**:
1319/// - collection size is fixed at compile time
1320/// - no resizing or extension is performed
1321/// - operations replace or read the entire structure
1322///
1323/// All operations are performed via tagged conversions.
1324///
1325/// ## Default Discriminant
1326///
1327/// - `K = ()`: operates on a single default field,
1328/// meaning one virtual static field is assumed.
1329pub trait StaticFieldHelpers<K = ()>: VirtualStaticField<K>
1330where
1331 K: DiscriminantTag,
1332{
1333 /// Retrieves the full collection from the field interpreted as `Many`.
1334 ///
1335 /// ## Behavior
1336 /// - Returns `Some(V)` if the field is in `Many` form
1337 /// - Returns `None` if the field is `None` or `Some`
1338 fn get_all(&self) -> Option<Self::Many> {
1339 let repr = <Self as VirtualStaticField<K>>::access(self);
1340 TryIntoTag::<_, ManyTag>::try_into_tag(repr).ok()
1341 }
1342
1343 /// Sets the field to a collection (`Many`).
1344 ///
1345 /// ## Behavior
1346 /// - Replaces the entire field with the provided collection
1347 /// - No resizing or partial updates are performed
1348 fn set_all(&mut self, v: Self::Many)
1349 where
1350 Self::Many: Delimited,
1351 {
1352 <Self as VirtualStaticField<K>>::mutate(self, v.into_tag());
1353 }
1354
1355 /// Retrieves the value of the field interpreted as `Some`.
1356 ///
1357 /// ## Behavior
1358 /// - Returns `Some(V)` if the field contains a single value
1359 /// - Returns `None` otherwise
1360 fn get(&self) -> Option<Self::Some> {
1361 let repr = <Self as VirtualStaticField<K>>::access(self);
1362 TryIntoTag::<_, SomeTag>::try_into_tag(repr).ok()
1363 }
1364
1365 /// Sets the field to a single value (`Some`).
1366 ///
1367 /// Replaces any existing representation.
1368 fn set(&mut self, v: Self::Some)
1369 where
1370 Self::Some: Delimited,
1371 {
1372 <Self as VirtualStaticField<K>>::mutate(self, v.into_tag());
1373 }
1374}
1375
1376/// Blanket impl for all [`VirtualStaticField`] types.
1377///
1378/// This trait is not intended to be implemented manually.
1379/// It exists as an ergonomic replacement for free helper functions.
1380///
1381/// All methods have default implementations, making this
1382/// forward-compatible: new helpers can be added without
1383/// breaking existing code.
1384impl<T, K> StaticFieldHelpers<K> for T
1385where
1386 T: VirtualStaticField<K>,
1387 K: DiscriminantTag,
1388{
1389}
1390
1391// ===============================================================================
1392// ````````````````````````````` VIRTUAL FIELD-BOUNDS ````````````````````````````
1393// ===============================================================================
1394
1395/// Provides the bounds associated with a [`VirtualDynField<Discriminant>`].
1396///
1397/// `VirtualDynBound` defines constraints (such as capacity limits)
1398/// without requiring the field itself to hardcode them.
1399///
1400/// ## Representation
1401///
1402/// The bound is provided as a type implementing [`Get<u32>`],
1403/// meaning the value is **resolved at runtime (or via type-level indirection)**.
1404///
1405/// This enables flexible, dynamically bounded behavior while still
1406/// enforcing limits.
1407///
1408/// ## Discriminant
1409///
1410/// The `Discriminant` links a field to its corresponding bound,
1411/// allowing multiple independent fields to coexist without ambiguity.
1412///
1413/// ## Default Discriminant
1414///
1415/// - `Discriminant = ()`: provides a single default bound,
1416/// meaning only one dynamically bounded field is assumed.
1417pub trait VirtualDynBound<Discriminant: DiscriminantTag = ()> {
1418 type Bound: Get<u32> + Clone + Debug + 'static;
1419}
1420
1421/// No-op bound with zero capacity.
1422impl VirtualDynBound for () {
1423 type Bound = ConstU32<0>;
1424}
1425
1426/// Provides the bounds associated with a [`VirtualStaticField<Discriminant>`].
1427///
1428/// `VirtualStaticBound` defines constraints (such as capacity limits)
1429/// that are **fully determined at compile time**.
1430///
1431/// ## Representation
1432///
1433/// The bound is provided as a `const`, meaning:
1434/// - it is a **compile-time constant**
1435/// - no runtime resolution or indirection is involved
1436///
1437/// This enables fully static, zero-overhead representations.
1438///
1439/// ## Discriminant
1440///
1441/// The `Discriminant` links a field to its corresponding bound,
1442/// allowing multiple independent fields to coexist without ambiguity.
1443///
1444/// ## Default Discriminant
1445///
1446/// - `Discriminant = ()`: provides a single default bound,
1447/// meaning only one dynamically bounded field is assumed.
1448pub trait VirtualStaticBound<Discriminant: DiscriminantTag = ()> {
1449 const BOUND: usize;
1450}
1451/// No-op bound provided with zero capacity.
1452impl VirtualStaticBound for () {
1453 const BOUND: usize = 0;
1454}
1455
1456// ===============================================================================
1457// ```````````````````````````````` VIRTUAL ERRORS ```````````````````````````````
1458// ===============================================================================
1459
1460/// Defines the error type associated with a virtual component
1461/// identified by a `Discriminant`.
1462///
1463/// `VirtualError` provides a way to associate a specific error type
1464/// with a [`VirtualDynField`] or related abstraction, without hardcoding
1465/// the error into the implementation.
1466///
1467/// ## Discriminant
1468///
1469/// The `Discriminant` acts as a key linking a virtual field (or related
1470/// abstraction) to its corresponding error type.
1471///
1472/// This ensures multiple independent virtual components can coexist
1473/// without ambiguity.
1474///
1475/// ## Default Discriminant
1476///
1477/// - `Discriminant = ()`: associates a single default error type,
1478/// meaning only one virtual component is assumed.
1479pub trait VirtualError<Discriminant: DiscriminantTag = ()> {
1480 type Error: RuntimeError;
1481}
1482
1483// ===============================================================================
1484// ``````````````````````````` DELEGATED VIRTUAL BOUNDS ``````````````````````````
1485// ===============================================================================
1486
1487/// Delegates bound resolution to an external [`VirtualDynBound`] provider.
1488///
1489/// This trait is used when a type participates in a [`VirtualDynField`]
1490/// but does not define or own its bounds.
1491///
1492/// Instead, bounds are supplied externally via `Provider`,
1493/// allowing constraints (such as capacity) to be defined independently
1494/// of the field or its storage.
1495///
1496/// ## Representation
1497///
1498/// The delegated bound is a **runtime-resolved value** (via [`Get<u32>`]),
1499/// enabling flexible, dynamically bounded behavior.
1500///
1501/// ## Roles
1502///
1503/// - **Container (`Self`)**
1504/// - provides storage for the field
1505///
1506/// - **Bounds (`Provider`)**
1507/// - supplies constraints for that field
1508///
1509/// This separation enables:
1510/// - composability
1511/// - reuse across contexts
1512/// - decoupling of storage and constraints
1513///
1514/// ## Default Discriminant
1515///
1516/// - `Discriminant = ()`: delegates a single default bound,
1517/// meaning one dynamically bounded field is assumed.
1518pub trait DelegateVirtualDynBound<Provider, Discriminant = ()>
1519where
1520 Provider: VirtualDynBound<Discriminant>,
1521 Discriminant: DiscriminantTag,
1522 Self: Sized,
1523{
1524}
1525
1526/// Blanket implementation enabling all types to delegate
1527/// dynamic bound resolution to a [`VirtualDynBound`] provider.
1528impl<Provider, Discriminant, T> DelegateVirtualDynBound<Provider, Discriminant> for T
1529where
1530 Provider: VirtualDynBound<Discriminant>,
1531 Discriminant: DiscriminantTag,
1532 T: Sized,
1533{
1534}
1535
1536/// Delegates bound resolution to an external [`VirtualStaticBound`] provider.
1537///
1538/// This trait is used when a type participates in a [`VirtualStaticField`]
1539/// but does not define or own its bounds.
1540///
1541/// Instead, bounds are supplied externally via `Provider`,
1542/// allowing constraints (such as capacity) to be defined independently
1543/// of the field or its storage.
1544///
1545/// ## Representation
1546///
1547/// The delegated bound is a **compile-time constant** (`usize`),
1548/// enabling fully static, zero-overhead representations.
1549///
1550/// ## Roles
1551///
1552/// - **Container (`Self`)**
1553/// - provides storage for the field
1554///
1555/// - **Bounds (`Provider`)**
1556/// - supplies compile-time constraints for that field
1557///
1558/// This separation enables:
1559/// - composability
1560/// - reuse across contexts
1561/// - decoupling of storage and constraints
1562///
1563/// ## Default Discriminant
1564///
1565/// - `Discriminant = ()`: delegates a single default bound,
1566/// meaning one statically bounded field is assumed.
1567pub trait DelegateVirtualStaticBound<Provider, Discriminant = ()>
1568where
1569 Provider: VirtualStaticBound<Discriminant>,
1570 Discriminant: DiscriminantTag,
1571 Self: Sized,
1572{
1573}
1574
1575/// Blanket implementation enabling all types to delegate
1576/// static bound resolution to a [`VirtualStaticBound`] provider.
1577impl<Provider, Discriminant, T> DelegateVirtualStaticBound<Provider, Discriminant> for T
1578where
1579 Provider: VirtualStaticBound<Discriminant>,
1580 Discriminant: DiscriminantTag,
1581 T: Sized,
1582{
1583}
1584
1585// ===============================================================================
1586// ````````````````````` DELEGATED VIRTUAL FIELDS AND BOUNDS `````````````````````
1587// ===============================================================================
1588
1589/// Constraint describing a virtual field whose bounds are delegated
1590/// to an external [`VirtualDynBound`] provider.
1591///
1592/// This composes:
1593/// - [`VirtualDynField`] - defines storage and representation
1594/// - [`DelegateVirtualDynBound`] - supplies bounds externally
1595///
1596/// ## Semantics
1597///
1598/// - **Container (`Self`)**
1599/// - provides storage for values of type `T`
1600///
1601/// - **Bounds (`Provider`)**
1602/// - supplies capacity constraints
1603///
1604/// - **Caller**
1605/// - selects field shape (`None`, `Some`, `Many`)
1606///
1607/// ## Representation
1608///
1609/// Bounds are resolved dynamically:
1610/// - provided via [`Get<u32>`]
1611/// - enable flexible, vector-like behavior within limits
1612///
1613/// This allows storage and constraints to remain decoupled.
1614///
1615/// ## Default Discriminant
1616///
1617/// - `Discriminant = ()`: applies a single default bounded field,
1618/// meaning one dynamically bounded field is assumed.
1619pub trait VirtualDynFieldWithDelegatedBounds<T, Provider, Discriminant = ()>:
1620 VirtualDynField<Discriminant, Some = T> + DelegateVirtualDynBound<Provider, Discriminant>
1621where
1622 Provider: VirtualDynBound<Discriminant>,
1623 Discriminant: DiscriminantTag,
1624{
1625}
1626
1627/// Blanket implementation for any compatible container.
1628impl<T, Provider, Discriminant, U> VirtualDynFieldWithDelegatedBounds<T, Provider, Discriminant>
1629 for U
1630where
1631 U: VirtualDynField<Discriminant, Some = T> + DelegateVirtualDynBound<Provider, Discriminant>,
1632 Provider: VirtualDynBound<Discriminant>,
1633 Discriminant: DiscriminantTag,
1634{
1635}
1636
1637/// Constraint describing a virtual field whose bounds are delegated
1638/// to an external [`VirtualStaticBound`] provider.
1639///
1640/// This composes:
1641/// - [`VirtualStaticField`] - defines storage and representation
1642/// - [`DelegateVirtualStaticBound`] - supplies bounds externally
1643///
1644/// ## Semantics
1645///
1646/// - **Container (`Self`)**
1647/// - provides storage for values of type `T`
1648///
1649/// - **Bounds (`Provider`)**
1650/// - supplies compile-time capacity constraints
1651///
1652/// - **Caller**
1653/// - selects field shape (`None`, `Some`, `Many`)
1654///
1655/// ## Representation
1656///
1657/// Bounds are compile-time constants:
1658/// - encoded directly in the type system (`usize`)
1659/// - enable fixed-size, array-like behavior
1660///
1661/// This ensures fully static, zero-overhead representations.
1662///
1663/// ## Default Discriminant
1664///
1665/// - `Discriminant = ()`: applies a single default bounded field,
1666/// meaning one statically bounded field is assumed.
1667pub trait VirtualStaticFieldWithDelegatedBounds<T, Provider, Discriminant = ()>:
1668 VirtualStaticField<Discriminant, Some = T> + DelegateVirtualStaticBound<Provider, Discriminant>
1669where
1670 Provider: VirtualStaticBound<Discriminant>,
1671 Discriminant: DiscriminantTag,
1672{
1673}
1674
1675/// Blanket implementation for any compatible container.
1676impl<T, Provider, Discriminant, U> VirtualStaticFieldWithDelegatedBounds<T, Provider, Discriminant>
1677 for U
1678where
1679 U: VirtualStaticField<Discriminant, Some = T>
1680 + DelegateVirtualStaticBound<Provider, Discriminant>,
1681 Provider: VirtualStaticBound<Discriminant>,
1682 Discriminant: DiscriminantTag,
1683{
1684}
1685
1686// ===============================================================================
1687// `````````````````````````````` VIRTUAL EXTENSIONS `````````````````````````````
1688// ===============================================================================
1689
1690/// Defines the schema for a [`VirtualDynExtension`] identified by a `Discriminant`.
1691///
1692/// A `VirtualDynExtensionSchema` describes the **structure and representation**
1693/// of an extension field whose type is supplied externally.
1694///
1695/// Unlike [`VirtualDynField`], the element type and layout are not defined
1696/// by the container, but provided through this schema.
1697///
1698/// ## Context
1699///
1700/// In the virtual system:
1701/// - [`VirtualDynField`] defines fields with internally known types
1702/// - `VirtualDynExtensionSchema` defines fields with externally supplied types
1703/// - [`VirtualDynExtension`] stores values using this schema
1704///
1705/// This allows containers to support fields whose types are:
1706/// - not known at implementation time
1707/// - injected via type-level composition
1708///
1709/// ## Representation
1710///
1711/// The `Many` form is expected to have **vector-like semantics**:
1712/// - dynamically sized (within bounds)
1713/// - supports buffering and indexed access
1714///
1715/// The schema itself is purely type-level:
1716/// - it does not store data
1717/// - it defines how data is represented and interpreted
1718///
1719/// ## Discriminant
1720///
1721/// The `Discriminant` links:
1722/// - the extension storage
1723/// - to its schema
1724///
1725/// allowing multiple independent extensions to coexist safely.
1726///
1727/// ## Default Discriminant
1728///
1729/// - `Discriminant = ()`: defines a single default extension schema,
1730/// meaning only one extension is assumed.
1731pub trait VirtualDynExtensionSchema<Discriminant: DiscriminantTag = ()> {
1732 /// Representation of absence.
1733 type None: Delimited;
1734
1735 /// The logical element type defined by the schema.
1736 ///
1737 /// This type is externally supplied.
1738 type Some: Delimited;
1739
1740 /// A collection of `Some` with vector-like semantics.
1741 type Many: Buffer<Self::Some> + Indexable<Self::Some>;
1742
1743 /// Opaque representation of the extension.
1744 ///
1745 /// Encodes `None`, `Some`, or `Many` and supports tagged conversions.
1746 type Repr: Delimited
1747 // Initial empty representation
1748 + Default
1749 // Construct from absence
1750 + FromTag<Self::None, NoneTag>
1751 // Extract absence
1752 + TryIntoTag<Self::None, NoneTag>
1753 // Construct from single value
1754 + FromTag<Self::Some, SomeTag>
1755 // Extract single value
1756 + TryIntoTag<Self::Some, SomeTag>
1757 // Construct from many values (may fail due to bounds)
1758 + TryFromTag<Self::Many, ManyTag>
1759 // Convert into many values
1760 + IntoTag<Self::Many, ManyTag>;
1761
1762 /// Returns the number of elements encoded in the representation.
1763 fn len(v: &Self::Repr) -> usize;
1764
1765 /// Returns the minimum number of elements representable.
1766 fn min(v: &Self::Repr) -> usize;
1767
1768 /// Returns the maximum number of elements representable.
1769 fn max(v: &Self::Repr) -> usize;
1770}
1771
1772/// Defines the schema for a [`VirtualStaticExtension`] identified by a `Discriminant`.
1773///
1774/// A `VirtualStaticExtensionSchema` describes the **structure and representation**
1775/// of an extension field whose type is supplied externally and fully
1776/// determined at compile time.
1777///
1778/// ## Context
1779///
1780/// In the static field model:
1781/// - [`VirtualStaticField`] defines fields with fixed structure
1782/// - `VirtualStaticExtensionSchema` defines externally supplied types and layout
1783/// - [`VirtualStaticExtension`] stores values using this schema
1784///
1785/// This allows containers to support externally defined fields
1786/// with compile-time determined structure.
1787///
1788/// ## Representation
1789///
1790/// The `Many` form is expected to have **array-like semantics**:
1791/// - fixed size
1792/// - no dynamic resizing or allocation
1793/// - capacity encoded in the type
1794///
1795/// The schema is purely type-level:
1796/// - it does not store data
1797/// - it defines how data is represented and interpreted
1798///
1799/// ## Discriminant
1800///
1801/// The `Discriminant` links:
1802/// - the extension storage
1803/// - to its schema
1804///
1805/// allowing multiple independent extensions to coexist safely.
1806///
1807/// ## Default Discriminant
1808///
1809/// - `Discriminant = ()`: defines a single default extension schema,
1810/// meaning only one static extension is assumed.
1811pub trait VirtualStaticExtensionSchema<Discriminant: DiscriminantTag = ()> {
1812 /// Representation of absence.
1813 type None: Delimited;
1814
1815 /// The logical element type defined by the schema.
1816 ///
1817 /// This type is externally supplied.
1818 type Some: Delimited;
1819
1820 /// A fixed-size collection of `Some` with array-like semantics.
1821 type Many: Collection<Self::Some>;
1822
1823 /// Opaque representation of the extension.
1824 ///
1825 /// Encodes `None`, `Some`, or `Many` and supports tagged conversions.
1826 ///
1827 /// All conversions are expected to be total (non-fallible),
1828 /// as structure is fully determined at compile time.
1829 type Repr: Delimited
1830 // Initial representation
1831 + Default
1832 // Construct from absence
1833 + FromTag<Self::None, NoneTag>
1834 // Extract absence
1835 + TryIntoTag<Self::None, NoneTag>
1836 // Construct from single value
1837 + FromTag<Self::Some, SomeTag>
1838 // Extract single value
1839 + TryIntoTag<Self::Some, SomeTag>
1840 // Construct from many values (total)
1841 + FromTag<Self::Many, ManyTag>
1842 // Extract many values (total)
1843 + TryIntoTag<Self::Many, ManyTag>;
1844}
1845
1846/// Allocation interface for virtual extensions whose type and schema
1847/// are defined externally.
1848///
1849/// This is a second-order abstraction over [`VirtualDynField`]:
1850/// instead of defining its own element type, the field delegates both
1851/// type and representation to an external schema.
1852///
1853/// ## Context
1854///
1855/// In the virtual system:
1856/// - [`VirtualDynField`] defines fields with internally known types
1857/// - [`VirtualDynExtensionSchema`] defines externally supplied types and layout
1858/// - `VirtualDynExtension` stores values using that schema
1859///
1860/// This allows a container (`Self`) to host fields whose types are:
1861/// - not known at implementation time
1862/// - supplied later via type-level composition
1863///
1864/// ## Representation
1865///
1866/// All operations are performed on the schema-defined representation:
1867/// - `TypesVia` defines `None`, `Some`, `Many`, and `Repr`
1868/// - `Many` is expected to have **vector-like semantics**
1869/// - size and bounds are resolved dynamically (within constraints)
1870///
1871/// ## Semantics
1872///
1873/// - **Container (`Self`)**
1874/// - owns storage
1875///
1876/// - **Schema (`TypesVia`)**
1877/// - defines element type and representation
1878///
1879/// This enables fields to remain fully generic over externally
1880/// defined and deferred types.
1881///
1882/// ## Key Property
1883///
1884/// Type and structure are **not fixed in the container**, but injected
1885/// externally and resolved at compile time.
1886///
1887/// ## Default Discriminant
1888///
1889/// - `Discriminant = ()`: defines a single default extension,
1890/// meaning only one dynamic extension is assumed.
1891pub trait VirtualDynExtension<Discriminant: DiscriminantTag = ()>: Default {
1892 /// External schema defining the extension.
1893 type TypesVia: VirtualDynExtensionSchema<Discriminant>;
1894
1895 /// Returns the underlying representation.
1896 fn access(&self) -> <Self::TypesVia as VirtualDynExtensionSchema<Discriminant>>::Repr;
1897
1898 /// Replaces the underlying representation.
1899 fn mutate(&mut self, v: <Self::TypesVia as VirtualDynExtensionSchema<Discriminant>>::Repr);
1900
1901 /// Returns the current number of elements.
1902 fn len(&self) -> usize {
1903 <Self::TypesVia as VirtualDynExtensionSchema<Discriminant>>::len(&Self::access(&self))
1904 }
1905
1906 /// Returns the minimum number of elements representable.
1907 fn min(&self) -> usize {
1908 <Self::TypesVia as VirtualDynExtensionSchema<Discriminant>>::min(&Self::access(&self))
1909 }
1910
1911 /// Returns the maximum number of elements representable.
1912 fn max(&self) -> usize {
1913 <Self::TypesVia as VirtualDynExtensionSchema<Discriminant>>::max(&Self::access(&self))
1914 }
1915}
1916
1917/// Allocation interface for virtual extensions whose type and schema
1918/// are defined externally and fully determined at compile time.
1919///
1920/// This is the static counterpart to [`VirtualDynExtension`], where
1921/// both type and structure are fixed via the schema.
1922///
1923/// ## Context
1924///
1925/// In the static field model:
1926/// - [`VirtualStaticField`] defines fields with fixed structure
1927/// - [`VirtualStaticExtensionSchema`] defines externally supplied types
1928/// and compile-time layout
1929/// - `VirtualStaticExtension` stores values using that schema
1930///
1931/// This allows a container (`Self`) to host externally defined fields
1932/// with statically determined structure.
1933///
1934/// ## Representation
1935///
1936/// All operations are performed on the schema-defined representation:
1937/// - `TypesVia` defines `None`, `Some`, `Many`, and `Repr`
1938/// - `Many` is expected to have **array-like semantics**
1939/// - size and capacity are encoded at compile time
1940///
1941/// ## Semantics
1942///
1943/// - **Container (`Self`)**
1944/// - owns storage
1945///
1946/// - **Schema (`TypesVia`)**
1947/// - defines element type and representation
1948///
1949/// ## Key Property
1950///
1951/// Both type and structure are **fully determined at compile time**,
1952/// enabling zero-overhead representations without dynamic checks.
1953///
1954/// ## Default Discriminant
1955///
1956/// - `Discriminant = ()`: defines a single default extension,
1957/// meaning only one static extension is assumed.
1958pub trait VirtualStaticExtension<Discriminant: DiscriminantTag = ()>: Default {
1959 /// External schema defining the extension.
1960 type TypesVia: VirtualStaticExtensionSchema<Discriminant>;
1961
1962 /// Returns the underlying representation.
1963 fn access(&self) -> <Self::TypesVia as VirtualStaticExtensionSchema<Discriminant>>::Repr;
1964
1965 /// Replaces the underlying representation.
1966 fn mutate(&mut self, v: <Self::TypesVia as VirtualStaticExtensionSchema<Discriminant>>::Repr);
1967}
1968
1969// ===============================================================================
1970// `````````````````````` VIRTUAL EXTENSION DEFAULT-HELPERS ``````````````````````
1971// ===============================================================================
1972
1973/// Helper methods for accessing and mutating values in a [`VirtualDynExtension`].
1974///
1975/// These helpers operate on **dynamically shaped extensions** with
1976/// **vector-like semantics**:
1977/// - collections may grow or shrink (within bounds)
1978/// - indexing and iteration are supported
1979/// - mutations may fail due to constraints
1980///
1981/// Structure and types are defined externally via [`VirtualDynExtensionSchema`],
1982/// while storage is handled by the container.
1983///
1984/// All operations are performed via tagged conversions.
1985///
1986/// ## Default Discriminant
1987///
1988/// - `K = ()`: operates on a single default extension,
1989/// meaning one dynamic extension is assumed.
1990pub trait DynExtHelpers<K = ()>: VirtualDynExtension<K>
1991where
1992 K: DiscriminantTag,
1993{
1994 /// Returns the element at `index` from the extension interpreted as `Many`.
1995 fn index_get(
1996 &self,
1997 index: usize,
1998 ) -> Option<<Self::TypesVia as VirtualDynExtensionSchema<K>>::Some>
1999 where
2000 <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some: Clone,
2001 {
2002 <Self as VirtualDynExtension<K>>::access(self)
2003 .into_tag()
2004 .as_ref()
2005 .get(index)
2006 .cloned()
2007 }
2008
2009 /// Returns an iterator over elements.
2010 fn iter(&self) -> impl Iterator<Item = <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some>
2011 where
2012 <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some: Clone,
2013 {
2014 <Self as VirtualDynExtension<K>>::access(self)
2015 .into_tag()
2016 .into_iter()
2017 }
2018
2019 /// Applies mutation over all elements.
2020 fn iter_mut<F>(&mut self, mut f: F) -> Result<(), ()>
2021 where
2022 F: FnMut(&mut <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some),
2023 {
2024 let mut repr = <Self as VirtualDynExtension<K>>::access(self).into_tag();
2025
2026 let len = repr.as_ref().len();
2027 for i in 0..len {
2028 f(&mut repr[i]);
2029 }
2030
2031 let repr = TryFromTag::try_from_tag(repr).map_err(|_| ())?;
2032 <Self as VirtualDynExtension<K>>::mutate(self, repr);
2033
2034 Ok(())
2035 }
2036
2037 /// Sets element at index.
2038 fn index_set(
2039 &mut self,
2040 index: usize,
2041 v: <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some,
2042 ) -> Result<(), ()>
2043 where
2044 <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some: Default,
2045 {
2046 let mut repr = <Self as VirtualDynExtension<K>>::access(self).into_tag();
2047
2048 set_index(&mut repr, index, v);
2049
2050 let repr = TryFromTag::try_from_tag(repr).map_err(|_| ())?;
2051 <Self as VirtualDynExtension<K>>::mutate(self, repr);
2052
2053 Ok(())
2054 }
2055
2056 /// Retrieves `Some`.
2057 fn get(&self) -> Option<<Self::TypesVia as VirtualDynExtensionSchema<K>>::Some> {
2058 let repr = <Self as VirtualDynExtension<K>>::access(self);
2059 TryIntoTag::<_, SomeTag>::try_into_tag(repr).ok()
2060 }
2061
2062 /// Sets `Some`.
2063 fn set(&mut self, v: <Self::TypesVia as VirtualDynExtensionSchema<K>>::Some) {
2064 <Self as VirtualDynExtension<K>>::mutate(self, v.into_tag());
2065 }
2066}
2067
2068/// Blanket impl for all [`VirtualDynExtension`] types.
2069///
2070/// This trait is not intended to be implemented manually.
2071/// It exists as an ergonomic replacement for free helper functions.
2072///
2073/// All methods have default implementations, making this
2074/// forward-compatible: new helpers can be added without
2075/// breaking existing code.
2076impl<T, K> DynExtHelpers<K> for T
2077where
2078 T: VirtualDynExtension<K>,
2079 K: DiscriminantTag,
2080{
2081}
2082
2083/// Helper methods for accessing and mutating values in a [`VirtualStaticExtension`].
2084///
2085/// These helpers operate on **statically shaped extensions** with
2086/// **array-like semantics**:
2087/// - collection size is fixed at compile time
2088/// - no resizing or extension is performed
2089/// - operations act on the entire structure
2090///
2091/// Structure and types are defined externally via [`VirtualStaticExtensionSchema`],
2092/// while storage is handled by the container.
2093///
2094/// All operations are performed via tagged conversions.
2095///
2096/// ## Default Discriminant
2097///
2098/// - `K = ()`: operates on a single default extension,
2099/// meaning one static extension is assumed.
2100pub trait StaticExtHelpers<K = ()>: VirtualStaticExtension<K>
2101where
2102 K: DiscriminantTag,
2103{
2104 /// Retrieves the full collection (`Many`).
2105 fn get_all(&self) -> Option<<Self::TypesVia as VirtualStaticExtensionSchema<K>>::Many> {
2106 let repr = <Self as VirtualStaticExtension<K>>::access(self);
2107 TryIntoTag::<_, ManyTag>::try_into_tag(repr).ok()
2108 }
2109
2110 /// Sets full collection.
2111 fn set_all(&mut self, v: <Self::TypesVia as VirtualStaticExtensionSchema<K>>::Many)
2112 where
2113 <Self::TypesVia as VirtualStaticExtensionSchema<K>>::Many: Delimited,
2114 {
2115 <Self as VirtualStaticExtension<K>>::mutate(self, v.into_tag());
2116 }
2117
2118 /// Retrieves `Some`.
2119 fn get(&self) -> Option<<Self::TypesVia as VirtualStaticExtensionSchema<K>>::Some> {
2120 let repr = <Self as VirtualStaticExtension<K>>::access(self);
2121 TryIntoTag::<_, SomeTag>::try_into_tag(repr).ok()
2122 }
2123
2124 /// Sets `Some`.
2125 fn set(&mut self, v: <Self::TypesVia as VirtualStaticExtensionSchema<K>>::Some) {
2126 <Self as VirtualStaticExtension<K>>::mutate(self, v.into_tag());
2127 }
2128}
2129
2130/// Blanket impl for all [`VirtualStaticExtension`] types.
2131///
2132/// This trait is not intended to be implemented manually.
2133/// It exists as an ergonomic replacement for free helper functions.
2134///
2135/// All methods have default implementations, making this
2136/// forward-compatible: new helpers can be added without
2137/// breaking existing code.
2138impl<T, K> StaticExtHelpers<K> for T
2139where
2140 T: VirtualStaticExtension<K>,
2141 K: DiscriminantTag,
2142{
2143}
2144
2145/// Sets the value at a given index in a collection.
2146///
2147/// If the index is out of bounds, the collection is automatically extended
2148/// with default values (`T::default()`) up to the required index.
2149///
2150/// ## Behavior
2151/// - If `index < current length`, the value is simply updated.
2152/// - If `index >= current length`, the collection is resized by filling
2153/// missing positions with default values, then the value is set.
2154///
2155/// ## Type Parameters
2156/// - `C`: A collection that supports indexing and extension.
2157/// - `T`: The element type, which must implement `Default`.
2158///
2159/// ## Example
2160/// If the collection has length 3 and you set index 5:
2161/// - Elements at index 3 and 4 will be filled with `T::default()`.
2162/// - Index 5 will be assigned the given `value`.
2163fn set_index<C, T>(v: &mut C, index: usize, value: T)
2164where
2165 C: Indexable<T> + Growable<T>,
2166 T: Default,
2167{
2168 let len = v.as_ref().len();
2169 if index >= len {
2170 v.extend(core::iter::repeat_with(T::default).take(index + 1 - len));
2171 }
2172 v[index] = value;
2173}
2174
2175/// Implements an empty virtual extension schema for a given extension.
2176///
2177/// This macro defines a no-op schema where the extension has **no storage**
2178/// and behaves as absent.
2179///
2180/// It supports two modes:
2181///
2182/// - **Dynamic (default)** -> implements [`VirtualDynExtensionSchema`]
2183/// - uses vector-like semantics (`Vec<()>`)
2184/// - size-related operations (`len`, `min`, `max`) return `0`
2185///
2186/// - **Static (`static` keyword)** -> implements [`VirtualStaticExtensionSchema`]
2187/// - uses array-like semantics (`[(); 0]`)
2188/// - fully determined at compile time
2189/// - no size-related operations are required
2190///
2191/// ## Semantics
2192///
2193/// In both modes:
2194/// - `None`, `Some`, and `Repr` are represented as `()`
2195/// - no data is stored
2196/// - the extension is effectively non-existent
2197///
2198/// This is useful when:
2199/// - a container participates in the extension system
2200/// - but a particular extension is unsupported or intentionally omitted
2201///
2202/// ## Syntax
2203///
2204/// ### Dynamic (default)
2205/// ```ignore
2206/// empty_virtual_extension!(
2207/// target: MyContainer,
2208/// tag: MyExtension,
2209/// schema: MySchema,
2210/// generics: [T, U],
2211/// bounds: [T: Clone, U: Default],
2212/// );
2213/// ```
2214///
2215/// ### Static
2216/// ```ignore
2217/// empty_virtual_extension!(
2218/// target: MyContainer,
2219/// tag: MyExtension,
2220/// schema: static MySchema,
2221/// );
2222/// ```
2223///
2224/// ## Parameters
2225///
2226/// - `target`: container type (conceptual owner of the extension)
2227/// - `tag`: discriminant identifying the extension
2228/// - `schema`: schema type to implement
2229/// - `generics` *(optional)*: generics for the impl
2230/// - `bounds` *(optional)*: additional `where` constraints
2231///
2232/// ## Behavior
2233///
2234/// - The extension is treated as non-existent
2235/// - Dynamic mode:
2236/// - uses `Vec<()>` (always empty)
2237/// - returns `0` for all size queries
2238/// - Static mode:
2239/// - uses `[(); 0]` (zero-length array)
2240/// - fully resolved at compile time
2241#[macro_export]
2242macro_rules! empty_virtual_extension {
2243 // STATIC VERSION
2244 (
2245 target: $target:ty,
2246 tag: $extension:ty,
2247 schema: static $schema:ty
2248 $(, generics: [$($gen:tt),* $(,)? ])?
2249 $(, bounds: [$($extra_bounds:tt)*])?
2250 $(,)?
2251 ) => {
2252 impl< $($($gen,)*)? >
2253 $crate::virtuals::VirtualStaticExtensionSchema<$extension>
2254 for $schema
2255 where
2256 $($($extra_bounds)*)?
2257 {
2258 type None = ();
2259 type Some = ();
2260 type Many = [(); 0];
2261 type Repr = ();
2262 }
2263 };
2264
2265 // DYNAMIC VERSION (default)
2266 (
2267 target: $target:ty,
2268 tag: $extension:ty,
2269 schema: $schema:ty
2270 $(, generics: [$($gen:tt),* $(,)? ])?
2271 $(, bounds: [$($extra_bounds:tt)*])?
2272 $(,)?
2273 ) => {
2274 impl< $($($gen,)*)? >
2275 $crate::virtuals::VirtualDynExtensionSchema<$extension>
2276 for $schema
2277 where
2278 $($($extra_bounds)*)?
2279 {
2280 type None = ();
2281 type Some = ();
2282 type Many = Vec<()>;
2283 type Repr = ();
2284
2285 fn len(_: &Self::Repr) -> usize {
2286 Zero::zero()
2287 }
2288
2289 fn min(_: &Self::Repr) -> usize {
2290 Zero::zero()
2291 }
2292
2293 fn max(_: &Self::Repr) -> usize {
2294 Zero::zero()
2295 }
2296 }
2297 };
2298}
2299
2300// ===============================================================================
2301// ````````````````````````` DELEGATED VIRTUAL EXTENSIONS ````````````````````````
2302// ===============================================================================
2303
2304/// Constraint for delegating a virtual extension to an external schema.
2305///
2306/// This trait ties a container to an externally provided
2307/// [`VirtualDynExtensionSchema`], without requiring the container
2308/// to define the extension's type or representation itself.
2309///
2310/// ## Roles
2311///
2312/// - **Container (`Self`)**
2313/// - stores the extension representation
2314///
2315/// - **Schema (`Provider`)**
2316/// - defines the element type and representation
2317///
2318/// - **Caller**
2319/// - selects the extension via the `Discriminant`
2320///
2321/// ## Representation
2322///
2323/// The delegated schema is dynamic:
2324/// - `Many` has vector-like semantics
2325/// - size and bounds are resolved at runtime (within limits)
2326///
2327/// ## Default Discriminant
2328///
2329/// - `Discriminant = ()`: delegates a single default extension,
2330/// meaning one dynamic extension is assumed.
2331pub trait DelegateVirtualDynExtension<Provider, Discriminant = ()>:
2332 VirtualDynExtension<Discriminant>
2333where
2334 Provider: VirtualDynExtensionSchema<Discriminant>,
2335 Discriminant: DiscriminantTag,
2336 Self: Sized,
2337{
2338}
2339
2340/// Blanket implementation enabling all types to delegate
2341/// extension schema resolution.
2342impl<Provider, Discriminant, T> DelegateVirtualDynExtension<Provider, Discriminant> for T
2343where
2344 T: VirtualDynExtension<Discriminant> + Sized,
2345 Discriminant: DiscriminantTag,
2346 Provider: VirtualDynExtensionSchema<Discriminant>,
2347{
2348}
2349
2350/// Constraint for delegating a virtual extension to an external
2351/// [`VirtualStaticExtensionSchema`].
2352///
2353/// This is the static counterpart to [`DelegateVirtualDynExtension`],
2354/// where the schema defines a fully determined, compile-time structure.
2355///
2356/// ## Roles
2357///
2358/// - **Container (`Self`)**
2359/// - stores the extension representation
2360///
2361/// - **Schema (`Provider`)**
2362/// - defines the element type and representation
2363///
2364/// - **Caller**
2365/// - selects the extension via the `Discriminant`
2366///
2367/// ## Representation
2368///
2369/// The delegated schema is static:
2370/// - `Many` has array-like semantics
2371/// - size and capacity are fixed at compile time
2372///
2373/// ## Default Discriminant
2374///
2375/// - `Discriminant = ()`: delegates a single default extension,
2376/// meaning one static extension is assumed.
2377pub trait DelegateVirtualStaticExtension<Provider, Discriminant = ()>:
2378 VirtualStaticExtension<Discriminant>
2379where
2380 Provider: VirtualStaticExtensionSchema<Discriminant>,
2381 Discriminant: DiscriminantTag,
2382 Self: Sized,
2383{
2384}
2385
2386/// Blanket implementation enabling all types to delegate
2387/// static extension schema resolution.
2388impl<Provider, Discriminant, T> DelegateVirtualStaticExtension<Provider, Discriminant> for T
2389where
2390 T: VirtualStaticExtension<Discriminant> + Sized,
2391 Discriminant: DiscriminantTag,
2392 Provider: VirtualStaticExtensionSchema<Discriminant>,
2393{
2394}
2395
2396// ===============================================================================
2397// `````````````````````````````` VIRTUAL COLLECTOR ``````````````````````````````
2398// ===============================================================================
2399
2400/// A virtual collector for values of type `T` under a discriminant.
2401///
2402/// A `VirtualCollector` represents a type that can:
2403/// - collect a value `T` into itself (via [`FromTag`])
2404/// - attempt to extract a value `T` back (via [`TryIntoTag`])
2405///
2406/// ## Virtual Field Context
2407///
2408/// In the virtual system:
2409/// - values may be interpreted differently depending on their role
2410/// - tagged conversions (`FromTag`, `TryIntoTag`) define those interpretations
2411/// - this trait groups types that support bidirectional interaction with `T`
2412///
2413/// ## Semantics
2414///
2415/// A `VirtualCollector` acts as a *tagged carrier* of `T`:
2416///
2417/// - `T -> Self`
2418/// - always succeeds (collection)
2419///
2420/// - `Self -> T`
2421/// - may fail depending on structure (extraction)
2422///
2423/// This is commonly implemented by enums where a specific variant
2424/// represents `T`.
2425///
2426/// ## Example Pattern
2427///
2428/// ```ignore
2429/// enum Value {
2430/// Number(u32),
2431/// Text(String),
2432/// }
2433///
2434/// // `Value` can act as a VirtualCollector<u32>
2435/// ```
2436///
2437/// ## Discriminant
2438///
2439/// The `Discriminant` ensures conversions remain unambiguous,
2440/// even when `T` or `Self` are generic or not fully concrete.
2441///
2442/// ## When to Use
2443///
2444/// Use this trait when:
2445/// - a type can *collect* values of `T`
2446/// - extraction may depend on internal structure
2447/// - tagged semantics are required for disambiguation
2448///
2449/// ## Default Discriminant
2450///
2451/// - `Discriminant = ()`: defines a single default interpretation,
2452/// meaning one collection/extraction behavior is assumed.
2453pub trait VirtualCollector<T, Discriminant: DiscriminantTag = ()>:
2454 FromTag<T, Discriminant> + TryIntoTag<T, Discriminant>
2455{
2456}
2457
2458/// Blanket implementation for all types supporting bidirectional tagged
2459/// conversion with `T`.
2460///
2461/// Any type that:
2462/// - can be constructed from `T` via [`FromTag`]
2463/// - can attempt to extract `T` via [`TryIntoTag`]
2464///
2465/// automatically implements [`VirtualCollector`].
2466///
2467/// This allows enums and similar container types to act as collectors
2468/// without requiring explicit implementations.
2469impl<T, Discriminant, U> VirtualCollector<T, Discriminant> for U
2470where
2471 U: FromTag<T, Discriminant> + TryIntoTag<T, Discriminant>,
2472 Discriminant: DiscriminantTag,
2473{
2474}
2475
2476// ===============================================================================
2477// ````````````````````````````` VIRTUAL STORAGE MAPS ````````````````````````````
2478// ===============================================================================
2479
2480/// A storage-backed virtual n-map owned by a container in the virtual structure system.
2481///
2482/// This trait defines a **map-like virtual component** that is logically owned
2483/// by a container (`For`), while its storage is delegated to an external
2484/// implementation (e.g. [`StorageNMap`]).
2485///
2486/// ## Virtual Structure Context
2487///
2488/// In the virtual system, a container (virtual struct) composes behavior through
2489/// independent, type-driven components:
2490///
2491/// - [`VirtualDynField`] / [`VirtualStaticField`] - field-level abstraction
2492/// over values and cardinality
2493/// - [`VirtualDynExtension`] / [`VirtualStaticExtension`] - externally defined
2494/// field schemas
2495/// - `VirtualNMap` - container-level map storage
2496///
2497/// These components are:
2498/// - **logically part of the container**
2499/// - but **not required to share a single physical representation**
2500///
2501/// ## Ownership and Delegation
2502///
2503/// The container (`For`) acts as the **owner** of the map:
2504/// - it defines the type context (e.g. key/value via associated types)
2505/// - it determines how the map is used
2506/// - but it does not store the map directly
2507///
2508/// Instead, storage is delegated to a native map implementation.
2509///
2510/// This separation allows:
2511/// - lightweight container representations
2512/// - efficient handling of large or frequently mutated data
2513/// - independent evolution of storage and structure
2514///
2515/// ## Type-Level Association
2516///
2517/// - `For`: the owning container (virtual struct)
2518/// - `Discriminant`: a type-level key identifying this map
2519///
2520/// This enables:
2521/// - multiple independent maps per container
2522/// - map definitions derived from container-level abstractions
2523/// - coherence-safe composition via distinct discriminants
2524///
2525/// ## Storage Model
2526///
2527/// - storage is provided by the implementor via [`StorageNMap`]
2528/// - keys are encoded using [`KeyGenerator`]
2529/// - iteration and prefix-based access are supported
2530///
2531/// The map is external in storage, but internal in ownership and usage.
2532///
2533/// ## When to Use
2534///
2535/// Use this trait when:
2536/// - a container logically owns map-like data
2537/// - key/value types depend on container-level abstractions
2538/// - data is large, dynamic, or frequently mutated
2539/// - embedding the map in a virtual field or representation is inefficient
2540///
2541/// ## Default Discriminant
2542///
2543/// - `Discriminant = ()`: defines a single default map,
2544/// meaning one virtual map is assumed per container.
2545pub trait VirtualNMap<For: Delimited, Discriminant: DiscriminantTag = ()> {
2546 /// Key used to address entries in the map.
2547 ///
2548 /// Must:
2549 /// - match the input shape expected by `KeyGen::KArg`
2550 /// - support tuple-style encoding for multi-key storage
2551 /// - allow iteration over encoded components
2552 type Key: Delimited + EncodeLikeTuple<<Self::KeyGen as KeyGenerator>::KArg> + TupleToEncodedIter;
2553
2554 /// Value stored in the map.
2555 ///
2556 /// Typically represents externally stored data associated with the container.
2557 type Value: Delimited;
2558
2559 /// Defines how `Key` is transformed into storage keys.
2560 ///
2561 /// Supports:
2562 /// - forward encoding into storage
2563 /// - reverse decoding for iteration and prefix traversal
2564 type KeyGen: KeyGenerator + ReversibleKeyGenerator;
2565
2566 /// Underlying storage map backing this abstraction.
2567 ///
2568 /// Must support:
2569 /// - basic CRUD operations
2570 /// - full iteration
2571 /// - prefix-based queries and draining
2572 type Map: StorageNMap<Self::KeyGen, Self::Value, Query = Self::Query>
2573 + IterableStorageNMap<Self::KeyGen, Self::Value, Query = Self::Query>
2574 + StoragePrefixedMap<Self::Value>;
2575
2576 /// Return type for read operations.
2577 ///
2578 /// Encodes presence/absence semantics (e.g. `Option<Value>`).
2579 type Query;
2580
2581 /// Fetch value associated with `key`.
2582 #[inline]
2583 fn get(key: Self::Key) -> Self::Query {
2584 Self::Map::get(key)
2585 }
2586
2587 /// Insert or overwrite value at `key`.
2588 #[inline]
2589 fn insert(key: Self::Key, value: Self::Value) {
2590 Self::Map::insert(key, value)
2591 }
2592
2593 /// Remove value at `key`.
2594 #[inline]
2595 fn remove(key: Self::Key) {
2596 Self::Map::remove(key)
2597 }
2598
2599 /// Remove and return value at `key`.
2600 #[inline]
2601 fn take(key: Self::Key) -> Self::Query {
2602 Self::Map::take(key)
2603 }
2604
2605 /// Check if `key` exists.
2606 #[inline]
2607 fn contains_key(key: Self::Key) -> bool {
2608 Self::Map::contains_key(key)
2609 }
2610
2611 /// Mutate value at `key` in-place.
2612 ///
2613 /// Provides `Option<Value>` to handle both insert/update/remove cases.
2614 #[inline]
2615 fn mutate<R>(key: Self::Key, f: impl FnOnce(&mut Option<Self::Value>) -> R) -> R {
2616 Self::Map::mutate_exists(key, f)
2617 }
2618
2619 /// Iterate over all `(full_key, value)` pairs.
2620 #[inline]
2621 fn iter() -> impl Iterator<Item = (<Self::KeyGen as KeyGenerator>::Key, Self::Value)> {
2622 Self::Map::iter()
2623 }
2624
2625 /// Iterate over all full keys.
2626 #[inline]
2627 fn iter_keys() -> impl Iterator<Item = <Self::KeyGen as KeyGenerator>::Key> {
2628 Self::Map::iter_keys()
2629 }
2630
2631 /// Iterate over all values.
2632 #[inline]
2633 fn iter_values() -> impl Iterator<Item = Self::Value> {
2634 Self::Map::iter_values()
2635 }
2636
2637 /// Drain entire map, yielding all `(key, value)` pairs.
2638 #[inline]
2639 fn drain() -> impl Iterator<Item = (<Self::KeyGen as KeyGenerator>::Key, Self::Value)> {
2640 Self::Map::drain()
2641 }
2642
2643 /// Count total number of entries.
2644 #[inline]
2645 fn count() -> usize {
2646 Self::Map::iter_keys().count()
2647 }
2648
2649 /// Iterate over values matching a prefix.
2650 ///
2651 /// Prefix corresponds to a partial key (leading components).
2652 #[inline]
2653 fn iter_prefix_values<P>(prefix: P) -> impl Iterator<Item = Self::Value>
2654 where
2655 Self::KeyGen: HasKeyPrefix<P>,
2656 {
2657 Self::Map::iter_prefix_values(prefix)
2658 }
2659
2660 /// Iterate over `(suffix, value)` under a prefix.
2661 ///
2662 /// `suffix` = remaining key components after the prefix.
2663 #[inline]
2664 fn iter_prefix<P>(
2665 prefix: P,
2666 ) -> impl Iterator<Item = (<Self::KeyGen as HasKeyPrefix<P>>::Suffix, Self::Value)>
2667 where
2668 Self::KeyGen: HasReversibleKeyPrefix<P>,
2669 {
2670 Self::Map::iter_prefix(prefix)
2671 }
2672
2673 /// Iterate over suffix keys under a prefix.
2674 #[inline]
2675 fn iter_key_prefix<P>(
2676 prefix: P,
2677 ) -> impl Iterator<Item = <Self::KeyGen as HasKeyPrefix<P>>::Suffix>
2678 where
2679 Self::KeyGen: HasReversibleKeyPrefix<P>,
2680 {
2681 Self::Map::iter_key_prefix(prefix)
2682 }
2683
2684 /// Drain entries under a prefix, yielding `(suffix, value)`.
2685 #[inline]
2686 fn drain_prefix<P>(
2687 prefix: P,
2688 ) -> impl Iterator<Item = (<Self::KeyGen as HasKeyPrefix<P>>::Suffix, Self::Value)>
2689 where
2690 Self::KeyGen: HasReversibleKeyPrefix<P>,
2691 {
2692 Self::Map::drain_prefix(prefix)
2693 }
2694}
2695
2696/// A storage-backed virtual map owned by a container in the virtual structure system.
2697///
2698/// This trait defines a **map-like virtual component** that is logically owned
2699/// by a container (`For`), while its storage is delegated to an external
2700/// implementation (e.g. [`StorageMap`]).
2701///
2702/// ## Virtual Structure Context
2703///
2704/// In the virtual system, a container (virtual struct) composes behavior through
2705/// independent, type-driven components:
2706///
2707/// - [`VirtualDynField`] / [`VirtualStaticField`] - field-level abstraction
2708/// over values and cardinality
2709/// - [`VirtualDynExtension`] / [`VirtualStaticExtension`] - externally defined
2710/// field schemas
2711/// - `VirtualMap` - container-level map storage
2712///
2713/// These components are logically part of the container, but are not required
2714/// to share a single physical representation.
2715///
2716/// ## Ownership and Delegation
2717///
2718/// The container (`For`) acts as the **owner** of the map:
2719/// - it provides the type context for the map (key/value via associated types)
2720/// - it determines how the map is used
2721/// - but it does not store the map directly
2722///
2723/// Instead, storage is delegated to a native map implementation.
2724///
2725/// This allows:
2726/// - avoiding encode/decode overhead from embedding maps in representations
2727/// - efficient handling of large or frequently mutated data
2728/// - separation of structure (types) from storage (runtime)
2729///
2730/// ## Type-Level Association
2731///
2732/// - `For`: the owning container (virtual struct)
2733/// - `Discriminant`: a type-level key identifying this map
2734///
2735/// This enables:
2736/// - multiple independent maps per container
2737/// - map definitions derived from container-level abstractions
2738/// - coherence-safe composition via distinct discriminants
2739///
2740/// ## Storage Model
2741///
2742/// - storage is provided by the implementor via [`StorageMap`]
2743/// - keys are encoded via [`KeyGenerator`]
2744/// - iteration and full traversal are supported
2745///
2746/// The map is external in storage, but internal in ownership and usage.
2747///
2748/// ## When to Use
2749///
2750/// Use this trait when:
2751/// - a container logically owns map-like data
2752/// - key/value types depend on container-level abstractions
2753/// - data is large, dynamic, or frequently mutated
2754/// - embedding the map in a virtual field or representation is inefficient
2755///
2756/// ## Default Discriminant
2757///
2758/// - `Discriminant = ()`: defines a single default map,
2759/// meaning one virtual map is assumed per container.
2760pub trait VirtualMap<For: Delimited, Discriminant: DiscriminantTag = ()> {
2761 /// Key used to address entries in the map.
2762 ///
2763 /// Must:
2764 /// - be encodable in the same form as `KeyGen`
2765 /// - support iteration over encoded components (for uniform handling)
2766 type Key: Delimited + EncodeLike<Self::KeyGen> + TupleToEncodedIter;
2767
2768 /// Value stored in the map.
2769 ///
2770 /// Represents externally stored data associated with the container.
2771 type Value: Delimited;
2772
2773 /// Defines how keys are encoded into storage and decoded back.
2774 ///
2775 /// Supports:
2776 /// - forward encoding into storage keys
2777 /// - reverse decoding during iteration
2778 type KeyGen: KeyGenerator + ReversibleKeyGenerator + EncodeLike;
2779
2780 /// Underlying storage map backing this abstraction.
2781 ///
2782 /// Must support:
2783 /// - basic CRUD operations
2784 /// - full iteration over keys and values
2785 /// - prefixed storage layout
2786 type Map: StorageMap<Self::KeyGen, Self::Value, Query = Self::Query>
2787 + IterableStorageMap<Self::KeyGen, Self::Value, Query = Self::Query>
2788 + StoragePrefixedMap<Self::Value>;
2789
2790 /// Return type for read operations.
2791 ///
2792 /// Typically `Option<Value>` or a query wrapper.
2793 type Query;
2794
2795 /// Fetch value associated with `key`.
2796 #[inline]
2797 fn get(key: Self::Key) -> Self::Query {
2798 Self::Map::get(key)
2799 }
2800
2801 /// Insert or overwrite value at `key`.
2802 #[inline]
2803 fn insert(key: Self::Key, value: Self::Value) {
2804 Self::Map::insert(key, value)
2805 }
2806
2807 /// Remove value at `key`.
2808 #[inline]
2809 fn remove(key: Self::Key) {
2810 Self::Map::remove(key)
2811 }
2812
2813 /// Remove and return value at `key`.
2814 #[inline]
2815 fn take(key: Self::Key) -> Self::Query {
2816 Self::Map::take(key)
2817 }
2818
2819 /// Check if `key` exists in the map.
2820 #[inline]
2821 fn contains_key(key: Self::Key) -> bool {
2822 Self::Map::contains_key(key)
2823 }
2824
2825 /// Mutate value at `key` in-place.
2826 ///
2827 /// Provides `Option<Value>` to handle insert/update/remove semantics.
2828 #[inline]
2829 fn mutate<R>(key: Self::Key, f: impl FnOnce(&mut Option<Self::Value>) -> R) -> R {
2830 Self::Map::mutate_exists(key, f)
2831 }
2832
2833 /// Iterate over all `(key, value)` pairs.
2834 #[inline]
2835 fn iter() -> impl Iterator<Item = (Self::KeyGen, Self::Value)> {
2836 Self::Map::iter()
2837 }
2838
2839 /// Iterate over all keys.
2840 #[inline]
2841 fn iter_keys() -> impl Iterator<Item = Self::KeyGen> {
2842 Self::Map::iter_keys()
2843 }
2844
2845 /// Iterate over all values.
2846 #[inline]
2847 fn iter_values() -> impl Iterator<Item = Self::Value> {
2848 Self::Map::iter_values()
2849 }
2850
2851 /// Drain entire map, yielding all `(key, value)` pairs.
2852 #[inline]
2853 fn drain() -> impl Iterator<Item = (Self::KeyGen, Self::Value)> {
2854 Self::Map::drain()
2855 }
2856
2857 /// Count total number of entries.
2858 #[inline]
2859 fn count() -> usize {
2860 Self::Map::iter_keys().count()
2861 }
2862}