Skip to main content

cranpose_core/
slot_backend.rs

1//! Slot storage backend selection and unified interface.
2
3use crate::{
4    chunked_slot_storage::ChunkedSlotStorage,
5    hierarchical_slot_storage::HierarchicalSlotStorage,
6    slot_storage::{GroupId, SlotStorage, StartGroup, ValueSlotId},
7    split_slot_storage::SplitSlotStorage,
8    Key, NodeId, Owned, ScopeId, SlotTable,
9};
10
11/// Factory function to create a backend of the specified kind.
12///
13/// This is the main entry point for creating slot storage backends at runtime.
14pub fn make_backend(kind: SlotBackendKind) -> SlotBackend {
15    SlotBackend::new(kind)
16}
17
18/// Available slot storage backend implementations.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
20pub enum SlotBackendKind {
21    /// Baseline gap-buffer implementation (default).
22    #[default]
23    Baseline,
24    /// Chunked storage to avoid large rotate operations.
25    Chunked,
26    /// Hierarchical storage where groups own child storage.
27    Hierarchical,
28    /// Split storage separating layout from payload.
29    Split,
30}
31
32/// Unified slot storage backend that can use any implementation.
33pub enum SlotBackend {
34    Baseline(SlotTable),
35    Chunked(ChunkedSlotStorage),
36    Hierarchical(HierarchicalSlotStorage),
37    Split(SplitSlotStorage),
38}
39
40impl SlotBackend {
41    /// Create a new backend of the specified kind.
42    ///
43    /// NOTE: Currently, all backend kinds map to the Baseline implementation
44    /// since the experimental backends (Chunked, Hierarchical, Split) are still
45    /// under development and don't pass all tests. This allows the backend
46    /// infrastructure to exist while development continues.
47    pub fn new(kind: SlotBackendKind) -> Self {
48        match kind {
49            SlotBackendKind::Baseline => Self::Baseline(SlotTable::new()),
50            SlotBackendKind::Chunked => Self::Chunked(ChunkedSlotStorage::new()),
51            SlotBackendKind::Hierarchical => Self::Hierarchical(HierarchicalSlotStorage::new()),
52            SlotBackendKind::Split => Self::Split(SplitSlotStorage::new()),
53        }
54    }
55}
56
57impl Default for SlotBackend {
58    fn default() -> Self {
59        Self::new(SlotBackendKind::default())
60    }
61}
62
63// Implement SlotStorage by delegating to the active backend
64impl SlotStorage for SlotBackend {
65    type Group = GroupId;
66    type ValueSlot = ValueSlotId;
67
68    fn begin_group(&mut self, key: Key) -> StartGroup<Self::Group> {
69        match self {
70            Self::Baseline(s) => SlotStorage::begin_group(s, key),
71            Self::Chunked(s) => SlotStorage::begin_group(s, key),
72            Self::Hierarchical(s) => SlotStorage::begin_group(s, key),
73            Self::Split(s) => SlotStorage::begin_group(s, key),
74        }
75    }
76
77    fn set_group_scope(&mut self, group: Self::Group, scope: ScopeId) {
78        match self {
79            Self::Baseline(s) => SlotStorage::set_group_scope(s, group, scope),
80            Self::Chunked(s) => SlotStorage::set_group_scope(s, group, scope),
81            Self::Hierarchical(s) => SlotStorage::set_group_scope(s, group, scope),
82            Self::Split(s) => SlotStorage::set_group_scope(s, group, scope),
83        }
84    }
85
86    fn end_group(&mut self) {
87        match self {
88            Self::Baseline(s) => s.end_group(),
89            Self::Chunked(s) => s.end_group(),
90            Self::Hierarchical(s) => s.end_group(),
91            Self::Split(s) => s.end_group(),
92        }
93    }
94
95    fn skip_current_group(&mut self) {
96        match self {
97            Self::Baseline(s) => s.skip_current_group(),
98            Self::Chunked(s) => s.skip_current_group(),
99            Self::Hierarchical(s) => s.skip_current_group(),
100            Self::Split(s) => s.skip_current_group(),
101        }
102    }
103
104    fn nodes_in_current_group(&self) -> Vec<NodeId> {
105        match self {
106            Self::Baseline(s) => s.nodes_in_current_group(),
107            Self::Chunked(s) => s.nodes_in_current_group(),
108            Self::Hierarchical(s) => s.nodes_in_current_group(),
109            Self::Split(s) => s.nodes_in_current_group(),
110        }
111    }
112
113    fn begin_recranpose_at_scope(&mut self, scope: ScopeId) -> Option<Self::Group> {
114        match self {
115            Self::Baseline(s) => s.begin_recranpose_at_scope(scope),
116            Self::Chunked(s) => s.begin_recranpose_at_scope(scope),
117            Self::Hierarchical(s) => s.begin_recranpose_at_scope(scope),
118            Self::Split(s) => s.begin_recranpose_at_scope(scope),
119        }
120    }
121
122    fn end_recompose(&mut self) {
123        match self {
124            Self::Baseline(s) => s.end_recompose(),
125            Self::Chunked(s) => s.end_recompose(),
126            Self::Hierarchical(s) => s.end_recompose(),
127            Self::Split(s) => s.end_recompose(),
128        }
129    }
130
131    fn alloc_value_slot<T: 'static>(&mut self, init: impl FnOnce() -> T) -> Self::ValueSlot {
132        match self {
133            Self::Baseline(s) => s.alloc_value_slot(init),
134            Self::Chunked(s) => s.alloc_value_slot(init),
135            Self::Hierarchical(s) => s.alloc_value_slot(init),
136            Self::Split(s) => s.alloc_value_slot(init),
137        }
138    }
139
140    fn read_value<T: 'static>(&self, slot: Self::ValueSlot) -> &T {
141        match self {
142            Self::Baseline(s) => SlotStorage::read_value(s, slot),
143            Self::Chunked(s) => SlotStorage::read_value(s, slot),
144            Self::Hierarchical(s) => SlotStorage::read_value(s, slot),
145            Self::Split(s) => SlotStorage::read_value(s, slot),
146        }
147    }
148
149    fn read_value_mut<T: 'static>(&mut self, slot: Self::ValueSlot) -> &mut T {
150        match self {
151            Self::Baseline(s) => SlotStorage::read_value_mut(s, slot),
152            Self::Chunked(s) => SlotStorage::read_value_mut(s, slot),
153            Self::Hierarchical(s) => SlotStorage::read_value_mut(s, slot),
154            Self::Split(s) => SlotStorage::read_value_mut(s, slot),
155        }
156    }
157
158    fn write_value<T: 'static>(&mut self, slot: Self::ValueSlot, value: T) {
159        match self {
160            Self::Baseline(s) => SlotStorage::write_value(s, slot, value),
161            Self::Chunked(s) => SlotStorage::write_value(s, slot, value),
162            Self::Hierarchical(s) => SlotStorage::write_value(s, slot, value),
163            Self::Split(s) => SlotStorage::write_value(s, slot, value),
164        }
165    }
166
167    fn remember<T: 'static>(&mut self, init: impl FnOnce() -> T) -> Owned<T> {
168        match self {
169            Self::Baseline(s) => s.remember(init),
170            Self::Chunked(s) => s.remember(init),
171            Self::Hierarchical(s) => s.remember(init),
172            Self::Split(s) => s.remember(init),
173        }
174    }
175
176    fn peek_node(&self) -> Option<NodeId> {
177        match self {
178            Self::Baseline(s) => s.peek_node(),
179            Self::Chunked(s) => s.peek_node(),
180            Self::Hierarchical(s) => s.peek_node(),
181            Self::Split(s) => s.peek_node(),
182        }
183    }
184
185    fn record_node(&mut self, id: NodeId) {
186        match self {
187            Self::Baseline(s) => s.record_node(id),
188            Self::Chunked(s) => s.record_node(id),
189            Self::Hierarchical(s) => s.record_node(id),
190            Self::Split(s) => s.record_node(id),
191        }
192    }
193
194    fn advance_after_node_read(&mut self) {
195        match self {
196            Self::Baseline(s) => s.advance_after_node_read(),
197            Self::Chunked(s) => s.advance_after_node_read(),
198            Self::Hierarchical(s) => s.advance_after_node_read(),
199            Self::Split(s) => s.advance_after_node_read(),
200        }
201    }
202
203    fn step_back(&mut self) {
204        match self {
205            Self::Baseline(s) => s.step_back(),
206            Self::Chunked(s) => s.step_back(),
207            Self::Hierarchical(s) => s.step_back(),
208            Self::Split(s) => s.step_back(),
209        }
210    }
211
212    fn finalize_current_group(&mut self) -> bool {
213        match self {
214            Self::Baseline(s) => s.finalize_current_group(),
215            Self::Chunked(s) => s.finalize_current_group(),
216            Self::Hierarchical(s) => s.finalize_current_group(),
217            Self::Split(s) => s.finalize_current_group(),
218        }
219    }
220
221    fn reset(&mut self) {
222        match self {
223            Self::Baseline(s) => s.reset(),
224            Self::Chunked(s) => s.reset(),
225            Self::Hierarchical(s) => s.reset(),
226            Self::Split(s) => s.reset(),
227        }
228    }
229
230    fn flush(&mut self) {
231        match self {
232            Self::Baseline(s) => s.flush(),
233            Self::Chunked(s) => s.flush(),
234            Self::Hierarchical(s) => s.flush(),
235            Self::Split(s) => s.flush(),
236        }
237    }
238}
239
240// Additional debug methods not in the SlotStorage trait
241impl SlotBackend {
242    pub fn debug_dump_groups(&self) -> Vec<(usize, Key, Option<ScopeId>, usize)> {
243        match self {
244            Self::Baseline(s) => s.debug_dump_groups(),
245            Self::Hierarchical(s) => s.debug_dump_groups(),
246            Self::Chunked(s) => s.debug_dump_groups(),
247            Self::Split(s) => s.debug_dump_groups(),
248        }
249    }
250
251    pub fn debug_dump_all_slots(&self) -> Vec<(usize, String)> {
252        match self {
253            Self::Baseline(s) => s.debug_dump_all_slots(),
254            Self::Hierarchical(s) => s.debug_dump_all_slots(),
255            Self::Chunked(s) => s.debug_dump_all_slots(),
256            Self::Split(s) => s.debug_dump_all_slots(),
257        }
258    }
259}