capability_skeleton/
skeleton_node_builder.rs

1// ---------------- [ File: capability-skeleton/src/skeleton_node_builder.rs ]
2crate::ix!();
3
4/// A builder so you can still do e.g.:
5///
6/// ```ignore
7/// let node = SkeletonNodeBuilder::default()
8///     .id(3)
9///     .child_ids(vec![4,5])
10///     .name("SomeAggregate")
11///     .build(NodeKind::Aggregate) // chooses the Aggregate variant
12///     .unwrap();
13/// ```
14#[derive(Debug, Default)]
15pub struct SkeletonNodeBuilder {
16    id:           Option<u16>,
17    parent_id:    Option<Option<u16>>,
18    child_ids:    Option<Vec<u16>>,
19    leaf_count:   Option<u16>,
20    capstone:     Option<bool>,
21    name:         Option<String>,
22    original_key: Option<String>,
23    ordering:     Option<Option<SubBranchOrdering>>,
24}
25
26/// A small enum controlling which variant we build (Dispatch vs Aggregate vs LeafHolder).
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
28pub enum NodeKind {
29    Dispatch,
30    Aggregate,
31    LeafHolder,
32}
33
34impl SkeletonNodeBuilder {
35    /// Decide which variant to produce by passing a `NodeKind`.
36    /// - For `LeafHolder`, we use `leaf_count` + `capstone` and ignore `child_ids`.
37    /// - For `Dispatch` or `Aggregate`, we use `child_ids`, ignore `leaf_count`/`capstone`.
38    pub fn build(self, kind: NodeKind) -> Result<SkeletonNode, derive_builder::UninitializedFieldError> {
39        let id_val = self.id.unwrap_or_default();
40        let parent_val = self.parent_id.unwrap_or_default();
41        let cids = self.child_ids.unwrap_or_default();
42        let leaves = self.leaf_count.unwrap_or_default();
43        let cap = self.capstone.unwrap_or(false);
44        let nm = self.name.unwrap_or_default();
45        let orig = self.original_key.unwrap_or_default();
46        let ord = self.ordering.unwrap_or_default();
47
48        // Ensure name is not empty
49        if nm.is_empty() {
50            tracing::trace!("SkeletonNodeBuilder => missing required 'name'");
51            return Err(derive_builder::UninitializedFieldError::new("name"));
52        }
53        let final_orig = if orig.is_empty() { nm.clone() } else { orig };
54
55        match kind {
56            NodeKind::Dispatch => Ok(SkeletonNode::Dispatch {
57                id: id_val,
58                parent_id: parent_val,
59                child_ids: cids,
60                name: nm,
61                original_key: final_orig,
62                ordering: ord,
63            }),
64            NodeKind::Aggregate => Ok(SkeletonNode::Aggregate {
65                id: id_val,
66                parent_id: parent_val,
67                child_ids: cids,
68                name: nm,
69                original_key: final_orig,
70                ordering: ord,
71            }),
72            NodeKind::LeafHolder => Ok(SkeletonNode::LeafHolder {
73                id: id_val,
74                parent_id: parent_val,
75                leaf_count: leaves,
76                capstone: cap,
77                name: nm,
78                original_key: final_orig,
79                ordering: ord,
80            }),
81        }
82    }
83
84    // Usual chainable setters:
85    pub fn id(mut self, val: u16) -> Self {
86        self.id = Some(val);
87        self
88    }
89    pub fn parent_id(mut self, val: Option<u16>) -> Self {
90        self.parent_id = Some(val);
91        self
92    }
93    pub fn child_ids(mut self, val: Vec<u16>) -> Self {
94        self.child_ids = Some(val);
95        self
96    }
97    pub fn leaf_count(mut self, val: u16) -> Self {
98        self.leaf_count = Some(val);
99        self
100    }
101    pub fn capstone(mut self, val: bool) -> Self {
102        self.capstone = Some(val);
103        self
104    }
105    pub fn name(mut self, val: impl Into<String>) -> Self {
106        self.name = Some(val.into());
107        self
108    }
109    pub fn original_key(mut self, val: impl Into<String>) -> Self {
110        self.original_key = Some(val.into());
111        self
112    }
113    pub fn ordering(mut self, val: Option<SubBranchOrdering>) -> Self {
114        self.ordering = Some(val);
115        self
116    }
117}