rill_protocol/
pathfinder.rs1use crate::io::provider::{EntryId, Path};
2use derive_more::{Deref, DerefMut};
3use std::collections::HashMap;
4
5#[derive(Debug, Deref, DerefMut)]
7pub struct Pathfinder<T> {
8 root: Record<T>,
9}
10
11impl<T> Pathfinder<T> {
12 pub fn new() -> Self {
13 Self {
14 root: Record::default(),
15 }
16 }
17}
18
19impl<T> Default for Pathfinder<T> {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25#[derive(Debug)]
26pub struct Record<T> {
27 subs: HashMap<EntryId, Record<T>>,
28 link: Option<T>,
29}
30
31impl<T> Default for Record<T> {
32 fn default() -> Self {
33 Self {
34 subs: HashMap::new(),
35 link: None,
36 }
37 }
38}
39
40pub struct Discovered<'a, T> {
41 pub remained_path: Path,
42 pub record: &'a Record<T>,
43}
44
45impl<T> Record<T> {
46 pub fn dig(&mut self, path: Path) -> &mut Self {
51 let mut record = self;
52 let entries: Vec<_> = path.into();
53 for element in entries {
54 record = record.subs.entry(element).or_default();
55 }
56 record
57 }
58
59 pub fn discover(&self, path: &Path) -> Discovered<'_, T> {
63 let mut record = self;
64 let mut iter = path.as_ref().iter();
65 let mut remained = Vec::new();
66 for element in &mut iter {
67 if let Some(next_record) = record.subs.get(element) {
68 record = next_record;
69 } else {
70 remained.push(element.clone());
71 break;
72 }
73 }
74 remained.extend(iter.cloned());
75 Discovered {
76 remained_path: Path::from(remained),
77 record,
78 }
79 }
80
81 pub fn remove(&mut self, path: &Path) -> Option<Self> {
82 let mut record = self;
83 let mut iter = path.as_ref().iter();
84 while let Some(element) = iter.next() {
85 if iter.len() == 0 {
86 return record.subs.remove(element);
87 } else if let Some(next_record) = record.subs.get_mut(element) {
88 record = next_record;
89 } else {
90 break;
91 }
92 }
93 None
94 }
95
96 pub fn find(&self, path: &Path) -> Option<&Self> {
99 let mut record = self;
100 for element in path.as_ref() {
101 if let Some(next_record) = record.subs.get(element) {
102 record = next_record;
103 } else {
104 return None;
105 }
106 }
107 Some(record)
108 }
109
110 pub fn find_mut(&mut self, path: &Path) -> Option<&mut Self> {
111 let mut record = self;
112 for element in path.as_ref() {
113 if let Some(next_record) = record.subs.get_mut(element) {
114 record = next_record;
115 } else {
116 return None;
117 }
118 }
119 Some(record)
120 }
121
122 pub fn list(&self) -> impl Iterator<Item = (EntryId, Option<&T>)> {
123 self.subs.iter().map(|(id, record)| {
124 let id = id.to_owned();
125 (id, record.link.as_ref())
126 })
127 }
128
129 pub fn set_link(&mut self, link: T) -> Option<T> {
130 let mut cell = Some(link);
131 std::mem::swap(&mut self.link, &mut cell);
132 cell
133 }
134
135 pub fn take_link(&mut self) -> Option<T> {
136 self.link.take()
137 }
138
139 pub fn get_link(&self) -> Option<&T> {
140 self.link.as_ref()
141 }
142
143 pub fn get_link_mut(&mut self) -> Option<&mut T> {
144 self.link.as_mut()
145 }
146
147 pub fn has_link(&self) -> bool {
148 self.link.is_some()
149 }
150}