1use std::{
38 cmp,
39 fmt::{self, Display},
40 hash::{Hash, Hasher},
41};
42
43use crate::{
44 subtree_path_builder::{SubtreePathBuilder, SubtreePathRelative},
45 util::CowLike,
46 SubtreePathIter,
47};
48
49#[derive(Debug)]
51pub struct SubtreePath<'b, B> {
52 pub(crate) ref_variant: SubtreePathInner<'b, B>,
53}
54
55impl<B: AsRef<[u8]>> Display for SubtreePath<'_, B> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
57 fn bytes_to_hex_or_ascii(bytes: &[u8]) -> String {
58 const ALLOWED_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
60 abcdefghijklmnopqrstuvwxyz\
61 0123456789_-/\\[]@";
62
63 if bytes.iter().all(|&c| ALLOWED_CHARS.contains(&c)) {
65 String::from_utf8(bytes.to_vec())
67 .unwrap_or_else(|_| format!("0x{}", hex::encode(bytes)))
68 } else {
69 format!("0x{}", hex::encode(bytes))
71 }
72 }
73
74 match &self.ref_variant {
75 SubtreePathInner::Slice(slice) => {
76 let ascii_path = slice
77 .iter()
78 .map(|e| bytes_to_hex_or_ascii(e.as_ref()))
79 .collect::<Vec<_>>()
80 .join("/");
81 write!(f, "{}", ascii_path)
82 }
83 SubtreePathInner::SubtreePath(subtree_path) => {
84 let ascii_path = subtree_path
85 .to_vec()
86 .into_iter()
87 .map(|a| bytes_to_hex_or_ascii(a.as_slice()))
88 .collect::<Vec<_>>()
89 .join("/");
90 write!(f, "{}", ascii_path)
91 }
92 SubtreePathInner::SubtreePathIter(iter) => {
93 let ascii_path = iter
94 .clone()
95 .map(bytes_to_hex_or_ascii)
96 .collect::<Vec<_>>()
97 .join("/");
98 write!(f, "{}", ascii_path)
99 }
100 }
101 }
102}
103
104#[derive(Debug)]
106pub(crate) enum SubtreePathInner<'b, B> {
107 Slice(&'b [B]),
110 SubtreePath(&'b SubtreePathBuilder<'b, B>),
112 SubtreePathIter(SubtreePathIter<'b, B>),
120}
121
122impl<'br, BL, BR> PartialEq<SubtreePath<'br, BR>> for SubtreePath<'_, BL>
123where
124 BL: AsRef<[u8]>,
125 BR: AsRef<[u8]>,
126{
127 fn eq(&self, other: &SubtreePath<'br, BR>) -> bool {
128 self.clone()
129 .into_reverse_iter()
130 .eq(other.clone().into_reverse_iter())
131 }
132}
133
134impl<'br, BL, BR> PartialOrd<SubtreePath<'br, BR>> for SubtreePath<'_, BL>
140where
141 BL: AsRef<[u8]>,
142 BR: AsRef<[u8]>,
143{
144 fn partial_cmp(&self, other: &SubtreePath<'br, BR>) -> Option<cmp::Ordering> {
145 let iter_a = self.clone().into_reverse_iter();
146 let iter_b = other.clone().into_reverse_iter();
147
148 Some(
149 iter_a
150 .len()
151 .cmp(&iter_b.len())
152 .reverse()
153 .then_with(|| iter_a.cmp(iter_b)),
154 )
155 }
156}
157
158impl<'br, BL, BR> PartialOrd<SubtreePathBuilder<'br, BR>> for SubtreePathBuilder<'_, BL>
159where
160 BL: AsRef<[u8]>,
161 BR: AsRef<[u8]>,
162{
163 fn partial_cmp(&self, other: &SubtreePathBuilder<'br, BR>) -> Option<cmp::Ordering> {
164 let iter_a = self.reverse_iter();
165 let iter_b = other.reverse_iter();
166
167 Some(
168 iter_a
169 .len()
170 .cmp(&iter_b.len())
171 .reverse()
172 .then_with(|| iter_a.cmp(iter_b)),
173 )
174 }
175}
176
177impl<'br, BL, BR> PartialOrd<SubtreePathBuilder<'br, BR>> for SubtreePath<'_, BL>
178where
179 BL: AsRef<[u8]>,
180 BR: AsRef<[u8]>,
181{
182 fn partial_cmp(&self, other: &SubtreePathBuilder<'br, BR>) -> Option<cmp::Ordering> {
183 self.partial_cmp(&SubtreePath::from(other))
184 }
185}
186
187impl<BL> Ord for SubtreePath<'_, BL>
188where
189 BL: AsRef<[u8]>,
190{
191 fn cmp(&self, other: &Self) -> cmp::Ordering {
192 self.partial_cmp(other).expect("order is totally defined")
193 }
194}
195
196impl<BL> Ord for SubtreePathBuilder<'_, BL>
197where
198 BL: AsRef<[u8]>,
199{
200 fn cmp(&self, other: &Self) -> cmp::Ordering {
201 self.partial_cmp(other).expect("order is totally defined")
202 }
203}
204
205impl<B: AsRef<[u8]>> Eq for SubtreePath<'_, B> {}
206
207impl<'b, B> From<SubtreePathInner<'b, B>> for SubtreePath<'b, B> {
208 fn from(ref_variant: SubtreePathInner<'b, B>) -> Self {
209 Self { ref_variant }
210 }
211}
212
213impl<'b, B> From<&'b [B]> for SubtreePath<'b, B> {
214 fn from(value: &'b [B]) -> Self {
215 SubtreePathInner::Slice(value).into()
216 }
217}
218
219impl<'b, B, const N: usize> From<&'b [B; N]> for SubtreePath<'b, B> {
220 fn from(value: &'b [B; N]) -> Self {
221 SubtreePathInner::Slice(value).into()
222 }
223}
224
225impl<'s, 'b, B> From<&'s SubtreePathBuilder<'b, B>> for SubtreePath<'s, B> {
228 fn from(value: &'s SubtreePathBuilder<'b, B>) -> Self {
229 SubtreePathInner::SubtreePath(value).into()
230 }
231}
232
233impl<B: AsRef<[u8]>> Hash for SubtreePath<'_, B> {
236 fn hash<H: Hasher>(&self, state: &mut H) {
237 match &self.ref_variant {
238 SubtreePathInner::Slice(slice) => slice
239 .iter()
240 .map(AsRef::as_ref)
241 .rev()
242 .for_each(|s| s.hash(state)),
243 SubtreePathInner::SubtreePath(path) => path.hash(state),
244 SubtreePathInner::SubtreePathIter(path_iter) => {
245 path_iter.clone().for_each(|s| s.hash(state))
246 }
247 }
248 }
249}
250
251impl<B> Clone for SubtreePath<'_, B> {
254 fn clone(&self) -> Self {
255 match &self.ref_variant {
256 SubtreePathInner::Slice(x) => SubtreePathInner::Slice(x),
257 SubtreePathInner::SubtreePath(x) => SubtreePathInner::SubtreePath(x),
258 SubtreePathInner::SubtreePathIter(x) => SubtreePathInner::SubtreePathIter(x.clone()),
259 }
260 .into()
261 }
262}
263
264impl SubtreePath<'static, [u8; 0]> {
265 pub const fn empty() -> Self {
267 SubtreePath {
268 ref_variant: SubtreePathInner::Slice(&[]),
269 }
270 }
271}
272
273impl<B> SubtreePath<'_, B> {
274 pub fn len(&self) -> usize {
276 match &self.ref_variant {
277 SubtreePathInner::Slice(s) => s.len(),
278 SubtreePathInner::SubtreePath(path) => path.len(),
279 SubtreePathInner::SubtreePathIter(path_iter) => path_iter.len(),
280 }
281 }
282
283 pub fn is_empty(&self) -> bool {
285 match &self.ref_variant {
286 SubtreePathInner::Slice(s) => s.is_empty(),
287 SubtreePathInner::SubtreePath(path) => path.is_empty(),
288 SubtreePathInner::SubtreePathIter(path_iter) => path_iter.is_empty(),
289 }
290 }
291}
292
293impl<'b, B: AsRef<[u8]>> SubtreePath<'b, B> {
294 pub fn derive_owned(&self) -> SubtreePathBuilder<'b, B> {
297 self.into()
298 }
299
300 pub fn derive_owned_with_child<'s, S>(&self, segment: S) -> SubtreePathBuilder<'b, B>
302 where
303 S: Into<CowLike<'s>>,
304 's: 'b,
305 {
306 SubtreePathBuilder {
307 base: self.clone(),
308 relative: SubtreePathRelative::Single(segment.into()),
309 }
310 }
311
312 pub fn derive_parent(&self) -> Option<(SubtreePath<'b, B>, &'b [u8])> {
319 match &self.ref_variant {
320 SubtreePathInner::Slice(path) => path
321 .split_last()
322 .map(|(tail, rest)| (SubtreePathInner::Slice(rest).into(), tail.as_ref())),
323 SubtreePathInner::SubtreePath(path) => path.derive_parent(),
324 SubtreePathInner::SubtreePathIter(iter) => {
325 let mut derived_iter = iter.clone();
326 derived_iter.next().map(|segment| {
327 (
328 SubtreePathInner::SubtreePathIter(derived_iter).into(),
329 segment,
330 )
331 })
332 }
333 }
334 }
335
336 pub fn into_reverse_iter(self) -> SubtreePathIter<'b, B> {
338 match self.ref_variant {
339 SubtreePathInner::Slice(slice) => SubtreePathIter::new(slice.iter()),
340 SubtreePathInner::SubtreePath(path) => path.reverse_iter(),
341 SubtreePathInner::SubtreePathIter(iter) => iter,
342 }
343 }
344
345 pub fn is_root(&self) -> bool {
348 match &self.ref_variant {
349 SubtreePathInner::Slice(s) => s.is_empty(),
350 SubtreePathInner::SubtreePath(path) => path.is_root(),
351 SubtreePathInner::SubtreePathIter(iter) => iter.is_empty(),
352 }
353 }
354
355 pub fn to_vec(&self) -> Vec<Vec<u8>> {
358 match &self.ref_variant {
359 SubtreePathInner::Slice(slice) => slice.iter().map(|x| x.as_ref().to_vec()).collect(),
360 SubtreePathInner::SubtreePath(path) => path.to_vec(),
361 SubtreePathInner::SubtreePathIter(iter) => {
362 let mut path = iter
363 .clone()
364 .map(|x| x.as_ref().to_vec())
365 .collect::<Vec<Vec<u8>>>();
366 path.reverse();
367 path
368 }
369 }
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 use super::*;
376
377 #[test]
378 fn to_vec() {
379 let base: SubtreePath<_> = (&[b"one" as &[u8], b"two", b"three"]).into();
380 let mut builder = base.derive_owned_with_child(b"four");
381 builder.push_segment(b"five");
382 builder.push_segment(b"six");
383 builder.push_segment(b"seven");
384 builder.push_segment(b"eight");
385 let parent = builder.derive_parent().unwrap().0;
386
387 let as_vec = parent.to_vec();
388 let reference_vec = vec![
389 b"one".to_vec(),
390 b"two".to_vec(),
391 b"three".to_vec(),
392 b"four".to_vec(),
393 b"five".to_vec(),
394 b"six".to_vec(),
395 b"seven".to_vec(),
396 ];
397
398 assert_eq!(as_vec, reference_vec);
399 assert_eq!(parent.len(), reference_vec.len());
400 }
401
402 #[test]
403 fn ordering() {
404 let path_a: SubtreePath<_> = (&[b"one" as &[u8], b"two", b"three"]).into();
405 let path_b = path_a.derive_owned_with_child(b"four");
406 let path_c = path_a.derive_owned_with_child(b"notfour");
407 let (path_d_parent, _) = path_a.derive_parent().unwrap();
408 let path_d = path_d_parent.derive_owned_with_child(b"three");
409
410 assert!(!matches!(
412 SubtreePath::from(&path_b).cmp(&SubtreePath::from(&path_c)),
413 cmp::Ordering::Equal
414 ));
415
416 assert!(matches!(
418 path_a.cmp(&SubtreePath::from(&path_d)),
419 cmp::Ordering::Equal
420 ));
421
422 assert!(path_a > path_b);
424 assert!(path_a > path_c);
425 }
426}