1use std::collections::BTreeMap as Map;
2
3use super::Play;
4
5pub type Slot = u32;
7
8#[derive(Clone, PartialEq)]
9pub struct Tree {
10 next: Slot,
11 slots: Map<Slot, Play>,
12 start: Vec<Slot>,
13}
14
15#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Eq, Ord)]
17pub enum Node {
18 #[default]
19 Start,
20 Play(Slot),
21}
22
23impl Default for Tree {
24 fn default() -> Self {
25 Tree::new()
26 }
27}
28
29impl Tree {
30 pub const fn new() -> Self {
31 Self { next: 0, slots: Map::new(), start: Vec::new() }
32 }
33
34 pub fn contains(&self, slot: Slot) -> bool {
35 self.slots.contains_key(&slot)
36 }
37
38 pub fn play(&self, slot: Slot) -> Option<&Play> {
39 self.slots.get(&slot)
40 }
41
42 pub(super) fn play_mut(&mut self, slot: Slot) -> Option<&mut Play> {
43 self.slots.get_mut(&slot)
44 }
45
46 pub fn slots(&self) -> impl Iterator<Item = Slot> + '_ {
47 self.slots.keys().copied()
48 }
49
50 pub fn plays(&self) -> impl Iterator<Item = &Play> {
51 self.slots.values()
52 }
53
54 #[allow(dead_code)]
56 pub(super) fn plays_mut(&mut self) -> impl Iterator<Item = &mut Play> {
57 self.slots.values_mut()
58 }
59
60 pub fn start(&self) -> &[Slot] {
61 &self.start
62 }
63
64 pub(super) fn start_mut(&mut self) -> &mut Vec<Slot> {
65 &mut self.start
66 }
67
68 pub fn options(&self, node: Node) -> &[Slot] {
69 match node {
70 Node::Start => self.start(),
71 Node::Play(slot) => &self.play(slot).expect("slot exists").options,
72 }
73 }
74
75 pub(super) fn options_mut(&mut self, node: Node) -> &mut Vec<Slot> {
76 match node {
77 Node::Start => self.start_mut(),
78 Node::Play(slot) => &mut self.play_mut(slot).expect("slot exists").options,
79 }
80 }
81
82 pub(super) fn insert(&mut self, f: impl FnOnce(Slot) -> Play) -> Slot {
84 let slot = self.next;
85 self.next += 1;
86
87 let play = f(slot);
88 debug_assert_eq!(slot, play.slot);
89 self.slots.insert(slot, play);
90 slot
91 }
92
93 pub(super) fn remove(&mut self, slot: Slot) -> bool {
96 let Some(play) = self.slots.remove(&slot) else { return false };
97 for option in &play.options {
98 self.remove(*option);
99 }
100 true
101 }
102}
103
104impl Node {
105 pub fn is_start(&self) -> bool {
106 matches!(self, Self::Start)
107 }
108}
109
110#[cfg(feature = "serde")]
111impl serde::Serialize for Node {
112 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 match self {
117 Self::Start => Option::<Slot>::None.serialize(serializer),
118 Self::Play(slot) => Some(*slot).serialize(serializer),
119 }
120 }
121}
122
123#[cfg(feature = "serde")]
124impl<'de> serde::Deserialize<'de> for Node {
125 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
126 where
127 D: serde::Deserializer<'de>,
128 {
129 Ok(match Option::<Slot>::deserialize(deserializer)? {
130 Some(slot) => Self::Play(slot),
131 None => Self::Start,
132 })
133 }
134}