capability-skeleton 0.1.0

A Rust library for managing and building complex hierarchical tree structures such as skill trees. Supports serialization, error handling, and deep tree metrics.
Documentation
// ---------------- [ File: capability-skeleton/src/skeleton_node.rs ]
crate::ix!();

impl Default for SkeletonNode {
    fn default() -> Self {
        Self::LeafHolder {
            id:           0,
            parent_id:    None,
            leaf_count:   0,
            capstone:     false,
            name:         String::new(),
            original_key: String::new(),
            ordering:     None,
        }
    }
}

/// A single node in our skeleton, identified by:
/// - **id** (u16)
/// - optional **parent_id**
/// - a mandatory **name**
/// - an optional **original_key** (defaults to `name` if unset)
/// - an optional **ordering** (sub-branch ordering)
///
/// We store it as an **enum** with three variants corresponding to how sub-branches (if any) are used:
///
/// 1) **Dispatch**: has child nodes but **no** leaves. Semantically, we pick exactly **one** branch
///    among its children (like an enum).
///
/// 2) **Aggregate**: has child nodes but **no** leaves. Semantically, we include **all** branches
///    simultaneously (like a struct).
///
/// 3) **LeafHolder**: has no child nodes but **does** store a `leaf_count` (the number of leaves),
///    plus a `capstone` flag if relevant. No children are directly attached—only leaves.
///
/// The BFS or measurement logic can still do `node.child_ids()`—this returns `&[]` if it’s a `LeafHolder`
/// (no children) or the actual child list if it’s `Dispatch` or `Aggregate`. 
/// Similarly, `node.leaf_count()` is zero for `Dispatch`/`Aggregate` and nonzero only for `LeafHolder`.
#[derive(SaveLoad, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "node_variant")] // to round-trip via TOML/JSON
pub enum SkeletonNode {

    /// **Dispatch**: no leaves, but has child nodes. 
    /// Semantically we pick exactly one sub-branch at runtime.
    Dispatch {
        /// Unique numeric ID for BFS, etc.
        #[serde(default)]
        id: u16,

        /// Optional parent in numeric form
        #[serde(default)]
        parent_id: Option<u16>,

        /// A list of child node IDs
        #[serde(default)]
        child_ids: Vec<u16>,

        /// Required name. Must not be empty
        #[serde(default)]
        name: String,

        /// Defaults to `name` if not explicitly set
        #[serde(default)]
        original_key: String,

        /// Sub-branch ordering approach
        #[serde(default)]
        ordering: Option<SubBranchOrdering>,
    },

    /// **Aggregate**: has children but no leaves. 
    /// Semantically, we include **all** sub-branches simultaneously.
    Aggregate {
        /// Unique numeric ID
        #[serde(default)]
        id: u16,

        /// Optional parent
        #[serde(default)]
        parent_id: Option<u16>,

        /// Child node IDs
        #[serde(default)]
        child_ids: Vec<u16>,

        /// Required name
        #[serde(default)]
        name: String,

        /// Defaults to `name` if unset
        #[serde(default)]
        original_key: String,

        /// Sub-branch ordering
        #[serde(default)]
        ordering: Option<SubBranchOrdering>,
    },

    /// **LeafHolder**: no children, but does store a `leaf_count` plus an optional `capstone`.
    LeafHolder {
        /// Numeric ID
        #[serde(default)]
        id: u16,

        /// Optional parent
        #[serde(default)]
        parent_id: Option<u16>,

        /// Number of leaves for BFS/measurement
        #[serde(default)]
        leaf_count: u16,

        /// Whether this node is special or “capstone”
        #[serde(default)]
        capstone: bool,

        /// Required name
        #[serde(default)]
        name: String,

        /// Original key if it differs from name
        #[serde(default)]
        original_key: String,

        /// Ordering (not always relevant for leaves, but we keep it for uniformity)
        #[serde(default)]
        ordering: Option<SubBranchOrdering>,
    },
}