1use std::hash::{Hash, Hasher};
38
39use crate::{
40 subtree_path_builder::{SubtreePathBuilder, SubtreePathRelative},
41 util::CowLike,
42 SubtreePathIter,
43};
44
45#[derive(Debug)]
47pub struct SubtreePath<'b, B> {
48 pub(crate) ref_variant: SubtreePathInner<'b, B>,
49}
50
51#[derive(Debug)]
53pub(crate) enum SubtreePathInner<'b, B> {
54 Slice(&'b [B]),
57 SubtreePath(&'b SubtreePathBuilder<'b, B>),
59 SubtreePathIter(SubtreePathIter<'b, B>),
67}
68
69impl<'bl, 'br, BL, BR> PartialEq<SubtreePath<'br, BR>> for SubtreePath<'bl, BL>
70where
71 BL: AsRef<[u8]>,
72 BR: AsRef<[u8]>,
73{
74 fn eq(&self, other: &SubtreePath<'br, BR>) -> bool {
75 self.clone()
76 .into_reverse_iter()
77 .eq(other.clone().into_reverse_iter())
78 }
79}
80
81impl<'b, B: AsRef<[u8]>> Eq for SubtreePath<'b, B> {}
82
83impl<'b, B> From<SubtreePathInner<'b, B>> for SubtreePath<'b, B> {
84 fn from(ref_variant: SubtreePathInner<'b, B>) -> Self {
85 Self { ref_variant }
86 }
87}
88
89impl<'b, B> From<&'b [B]> for SubtreePath<'b, B> {
90 fn from(value: &'b [B]) -> Self {
91 SubtreePathInner::Slice(value).into()
92 }
93}
94
95impl<'b, B, const N: usize> From<&'b [B; N]> for SubtreePath<'b, B> {
96 fn from(value: &'b [B; N]) -> Self {
97 SubtreePathInner::Slice(value).into()
98 }
99}
100
101impl<'s, 'b, B> From<&'s SubtreePathBuilder<'b, B>> for SubtreePath<'s, B> {
104 fn from(value: &'s SubtreePathBuilder<'b, B>) -> Self {
105 SubtreePathInner::SubtreePath(value).into()
106 }
107}
108
109impl<'b, B: AsRef<[u8]>> Hash for SubtreePath<'b, B> {
112 fn hash<H: Hasher>(&self, state: &mut H) {
113 match &self.ref_variant {
114 SubtreePathInner::Slice(slice) => slice
115 .iter()
116 .map(AsRef::as_ref)
117 .rev()
118 .for_each(|s| s.hash(state)),
119 SubtreePathInner::SubtreePath(path) => path.hash(state),
120 SubtreePathInner::SubtreePathIter(path_iter) => {
121 path_iter.clone().for_each(|s| s.hash(state))
122 }
123 }
124 }
125}
126
127impl<B> Clone for SubtreePath<'_, B> {
130 fn clone(&self) -> Self {
131 match &self.ref_variant {
132 SubtreePathInner::Slice(x) => SubtreePathInner::Slice(x),
133 SubtreePathInner::SubtreePath(x) => SubtreePathInner::SubtreePath(x),
134 SubtreePathInner::SubtreePathIter(x) => SubtreePathInner::SubtreePathIter(x.clone()),
135 }
136 .into()
137 }
138}
139
140impl SubtreePath<'static, [u8; 0]> {
141 pub const fn empty() -> Self {
143 SubtreePath {
144 ref_variant: SubtreePathInner::Slice(&[]),
145 }
146 }
147}
148
149impl<B> SubtreePath<'_, B> {
150 pub fn len(&self) -> usize {
152 match &self.ref_variant {
153 SubtreePathInner::Slice(s) => s.len(),
154 SubtreePathInner::SubtreePath(path) => path.len(),
155 SubtreePathInner::SubtreePathIter(path_iter) => path_iter.len(),
156 }
157 }
158
159 pub fn is_empty(&self) -> bool {
161 match &self.ref_variant {
162 SubtreePathInner::Slice(s) => s.is_empty(),
163 SubtreePathInner::SubtreePath(path) => path.is_empty(),
164 SubtreePathInner::SubtreePathIter(path_iter) => path_iter.is_empty(),
165 }
166 }
167}
168
169impl<'b, B: AsRef<[u8]>> SubtreePath<'b, B> {
170 pub fn derive_owned(&self) -> SubtreePathBuilder<'b, B> {
173 self.into()
174 }
175
176 pub fn derive_owned_with_child<'s, S>(&'b self, segment: S) -> SubtreePathBuilder<'b, B>
178 where
179 S: Into<CowLike<'s>>,
180 's: 'b,
181 {
182 SubtreePathBuilder {
183 base: self.clone(),
184 relative: SubtreePathRelative::Single(segment.into()),
185 }
186 }
187
188 pub fn derive_parent(&self) -> Option<(SubtreePath<'b, B>, &'b [u8])> {
195 match &self.ref_variant {
196 SubtreePathInner::Slice(path) => path
197 .split_last()
198 .map(|(tail, rest)| (SubtreePathInner::Slice(rest).into(), tail.as_ref())),
199 SubtreePathInner::SubtreePath(path) => path.derive_parent(),
200 SubtreePathInner::SubtreePathIter(iter) => {
201 let mut derived_iter = iter.clone();
202 derived_iter.next().map(|segment| {
203 (
204 SubtreePathInner::SubtreePathIter(derived_iter).into(),
205 segment,
206 )
207 })
208 }
209 }
210 }
211
212 pub fn into_reverse_iter(self) -> SubtreePathIter<'b, B> {
214 match self.ref_variant {
215 SubtreePathInner::Slice(slice) => SubtreePathIter::new(slice.iter()),
216 SubtreePathInner::SubtreePath(path) => path.reverse_iter(),
217 SubtreePathInner::SubtreePathIter(iter) => iter,
218 }
219 }
220
221 pub fn is_root(&self) -> bool {
224 match &self.ref_variant {
225 SubtreePathInner::Slice(s) => s.is_empty(),
226 SubtreePathInner::SubtreePath(path) => path.is_root(),
227 SubtreePathInner::SubtreePathIter(iter) => iter.is_empty(),
228 }
229 }
230
231 pub fn to_vec(&self) -> Vec<Vec<u8>> {
234 match &self.ref_variant {
235 SubtreePathInner::Slice(slice) => slice.iter().map(|x| x.as_ref().to_vec()).collect(),
236 SubtreePathInner::SubtreePath(path) => path.to_vec(),
237 SubtreePathInner::SubtreePathIter(iter) => {
238 let mut path = iter
239 .clone()
240 .map(|x| x.as_ref().to_vec())
241 .collect::<Vec<Vec<u8>>>();
242 path.reverse();
243 path
244 }
245 }
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252
253 #[test]
254 fn to_vec() {
255 let base: SubtreePath<_> = (&[b"one" as &[u8], b"two", b"three"]).into();
256 let mut builder = base.derive_owned_with_child(b"four");
257 builder.push_segment(b"five");
258 builder.push_segment(b"six");
259 builder.push_segment(b"seven");
260 builder.push_segment(b"eight");
261 let parent = builder.derive_parent().unwrap().0;
262
263 let as_vec = parent.to_vec();
264 let reference_vec = vec![
265 b"one".to_vec(),
266 b"two".to_vec(),
267 b"three".to_vec(),
268 b"four".to_vec(),
269 b"five".to_vec(),
270 b"six".to_vec(),
271 b"seven".to_vec(),
272 ];
273
274 assert_eq!(as_vec, reference_vec);
275 assert_eq!(parent.len(), reference_vec.len());
276 }
277}