capability_skeleton/
skeleton_node.rs

1// ---------------- [ File: capability-skeleton/src/skeleton_node.rs ]
2crate::ix!();
3
4impl Default for SkeletonNode {
5    fn default() -> Self {
6        Self::LeafHolder {
7            id:           0,
8            parent_id:    None,
9            leaf_count:   0,
10            capstone:     false,
11            name:         String::new(),
12            original_key: String::new(),
13            ordering:     None,
14        }
15    }
16}
17
18/// A single node in our skeleton, identified by:
19/// - **id** (u16)
20/// - optional **parent_id**
21/// - a mandatory **name**
22/// - an optional **original_key** (defaults to `name` if unset)
23/// - an optional **ordering** (sub-branch ordering)
24///
25/// We store it as an **enum** with three variants corresponding to how sub-branches (if any) are used:
26///
27/// 1) **Dispatch**: has child nodes but **no** leaves. Semantically, we pick exactly **one** branch
28///    among its children (like an enum).
29///
30/// 2) **Aggregate**: has child nodes but **no** leaves. Semantically, we include **all** branches
31///    simultaneously (like a struct).
32///
33/// 3) **LeafHolder**: has no child nodes but **does** store a `leaf_count` (the number of leaves),
34///    plus a `capstone` flag if relevant. No children are directly attached—only leaves.
35///
36/// The BFS or measurement logic can still do `node.child_ids()`—this returns `&[]` if it’s a `LeafHolder`
37/// (no children) or the actual child list if it’s `Dispatch` or `Aggregate`. 
38/// Similarly, `node.leaf_count()` is zero for `Dispatch`/`Aggregate` and nonzero only for `LeafHolder`.
39#[derive(SaveLoad, Debug, Clone, PartialEq, Serialize, Deserialize)]
40#[serde(tag = "node_variant")] // to round-trip via TOML/JSON
41pub enum SkeletonNode {
42
43    /// **Dispatch**: no leaves, but has child nodes. 
44    /// Semantically we pick exactly one sub-branch at runtime.
45    Dispatch {
46        /// Unique numeric ID for BFS, etc.
47        #[serde(default)]
48        id: u16,
49
50        /// Optional parent in numeric form
51        #[serde(default)]
52        parent_id: Option<u16>,
53
54        /// A list of child node IDs
55        #[serde(default)]
56        child_ids: Vec<u16>,
57
58        /// Required name. Must not be empty
59        #[serde(default)]
60        name: String,
61
62        /// Defaults to `name` if not explicitly set
63        #[serde(default)]
64        original_key: String,
65
66        /// Sub-branch ordering approach
67        #[serde(default)]
68        ordering: Option<SubBranchOrdering>,
69    },
70
71    /// **Aggregate**: has children but no leaves. 
72    /// Semantically, we include **all** sub-branches simultaneously.
73    Aggregate {
74        /// Unique numeric ID
75        #[serde(default)]
76        id: u16,
77
78        /// Optional parent
79        #[serde(default)]
80        parent_id: Option<u16>,
81
82        /// Child node IDs
83        #[serde(default)]
84        child_ids: Vec<u16>,
85
86        /// Required name
87        #[serde(default)]
88        name: String,
89
90        /// Defaults to `name` if unset
91        #[serde(default)]
92        original_key: String,
93
94        /// Sub-branch ordering
95        #[serde(default)]
96        ordering: Option<SubBranchOrdering>,
97    },
98
99    /// **LeafHolder**: no children, but does store a `leaf_count` plus an optional `capstone`.
100    LeafHolder {
101        /// Numeric ID
102        #[serde(default)]
103        id: u16,
104
105        /// Optional parent
106        #[serde(default)]
107        parent_id: Option<u16>,
108
109        /// Number of leaves for BFS/measurement
110        #[serde(default)]
111        leaf_count: u16,
112
113        /// Whether this node is special or “capstone”
114        #[serde(default)]
115        capstone: bool,
116
117        /// Required name
118        #[serde(default)]
119        name: String,
120
121        /// Original key if it differs from name
122        #[serde(default)]
123        original_key: String,
124
125        /// Ordering (not always relevant for leaves, but we keep it for uniformity)
126        #[serde(default)]
127        ordering: Option<SubBranchOrdering>,
128    },
129}