keytree/
path.rs

1//! A namespace represents a position on a multi-leaf tree. There is only one root node. A
2//! namespace can look like `abc::def::ghi`, which implictly means `abc[0]::def[0]::ghi[..]`. The
3//! index `abc[0]`represents the first child leaf of a node. `ghi[..]` refers to all child leaves
4//! of a node.
5
6use core::cmp::Ordering;
7use core::fmt;
8use core::hash::{Hash, Hasher};
9
10#[derive(Debug, PartialEq)]
11pub enum PathError {
12    MultipleMatch,
13    NoMatch,
14    NoRemainder,
15    NotUnique,
16    OutOfBounds,
17    Parse(String, usize),
18    PathNotUnique,
19    Remove,
20    RootIndex,
21    SegmentImmut,
22}
23
24impl fmt::Display for PathError {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        match self {
27            PathError::MultipleMatch   => write!(f, "Multiple matches."),
28            PathError::NoMatch         => write!(f, "No match."),
29            PathError::NoRemainder     => write!(f, "No remainder."),
30            PathError::NotUnique       => write!(f, "Path not unique."),
31            PathError::OutOfBounds     => write!(f, "Index out of bounds."),
32            PathError::Parse(s, pos)   => write!(f, "Could not parse \"{}\" at position {}.", s, pos),
33            PathError::PathNotUnique   => write!(f, "Can't get last index of non-unique path."),
34            PathError::Remove          => write!(f, "Removed too many segments."),
35            PathError::RootIndex       => write!(f, "Root index is not zero."),
36            PathError::SegmentImmut    => write!(f, "Cannot mutate unique segment."),
37        }
38    }
39}
40
41// Parser state.
42enum PS {
43    Segment,
44    Separator,
45}
46
47// Represents a pointer into the Path String. Also represents a node in a tree. If the node
48// has one leaf it is Unique. If the node has multiple leaves it is Mult.
49#[derive(Clone)]
50pub struct Segment {
51    pub index:  usize,
52    start:      usize,
53    end:        usize,
54}
55
56impl Segment {
57
58    fn new(index: usize, start: usize, end: usize) -> Segment {
59        Segment {
60            index:  index,
61            start:  start,
62            end:    end,
63        }
64    }
65
66    // Shifts the pointer into the string to the right by n. Used by append functions. 
67    fn right_shift(&self, n: usize) -> Segment {
68        Segment {
69            start:  self.start + n,
70            end:    self.end + n,
71            index:  self.index,
72        }
73    }
74
75    // Shifts the pointer into the string to the left by n.
76    fn left_shift(&self, n: usize) -> Segment {
77        Segment {
78            start:  self.start - n,
79            end:    self.end - n,
80            index:  self.index,
81        }
82    }
83}
84
85impl fmt::Debug for Segment {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "({}, {})[{}]", self.start, self.end, self.index)
88    }
89}
90
91// Represents the name of a path in a tree with a single leaf node.
92#[derive(Clone)]
93pub struct UniquePath {
94    s:          String,
95    segments:   Vec<Segment>,
96}
97
98impl UniquePath {
99
100    pub fn new() -> Self {
101        UniquePath {
102            s:          String::new(),
103            segments:   Vec::new(),
104        }
105    }
106
107    pub fn from(s: &str) -> Result<Self, PathError> {
108        Ok(
109            NonUniquePath::from(s)?
110                .unique(0)
111        )
112    }
113
114    // Sets the path to non-unique.
115    pub fn non_unique(self) -> NonUniquePath {
116        NonUniquePath {
117            s:          self.s,
118            segments:   self.segments,
119        }
120    }
121
122    // Sets the last index to `index`.
123    pub fn set_last_index(&mut self, index: usize) {
124        let len = self.len() - 1;
125        self.segments[len].index = index;
126    }
127
128    pub fn index(&self, index: usize) -> usize {
129        if index > self.len() - 1 {
130            panic!("Out of bounds.")
131        } else {
132            self.segments[index].index
133        }
134    }
135
136    // Checks the equality of two UniquePaths as NonUniquePaths, i.e. ignoring the last index. 
137    pub fn eq_base(&self, other: &UniquePath) -> bool {
138        self.clone().non_unique() == other.clone().non_unique()
139    }
140
141    // Return the last index.
142    pub fn last_index(&self) -> usize {
143        self.segments[self.len() - 1].index
144    }
145
146    pub fn is_empty(&self) -> bool {
147        self.s.is_empty()
148    }
149    
150    pub fn segment_str(&self, n: usize) -> &str {
151        &self.s[self.segments[n].start..=self.segments[n].end]
152    }
153
154    /// Returns the number of segments in a namespace.
155    ///
156    pub fn len(&self) -> usize {
157        self.segments.len()
158    }
159
160    // Appends `other` to `self`, consuming `other`. Returns an error if `self` is not a unique
161    // path, or if the root of `other` does not have an index of 0.
162    pub fn append_unique(self, other: &UniquePath) -> UniquePath {
163
164        if self.is_empty()  { return other.clone() };
165        if other.is_empty() { return self };
166
167        // Handle segments.
168
169        let mut segments = self.segments;
170        let rshift = self.s.len() + 2;
171        for seg in other.segments.iter() {
172            segments.push(seg.right_shift(rshift));
173        }
174
175        // Handle s.
176
177        let mut s = self.s;
178        if s != "" { s.push_str("::") };
179        s.push_str(&other.s);
180
181        UniquePath {
182            s:          s,
183            segments:   segments,
184        }
185    }
186
187    // Consumes self and appends a NonUniquePath with other appended. If `other` is empty then the
188    // result will be unique which contradictions the return type, so the function fails if `other`
189    // is empty.
190    pub fn append_non_unique(self, other: &NonUniquePath) -> NonUniquePath {
191
192        if self.is_empty()  { return other.clone() };
193        if other.is_empty() { panic!("other must not be empty.") };
194
195        // Handle segments.
196        let mut segments = self.segments;
197        let rshift = self.s.len() + 2;
198        for seg in other.segments.iter() {
199            segments.push(seg.right_shift(rshift));
200        }
201
202        // Handle s.
203        let mut s = self.s;
204        if s != "" { s.push_str("::") };
205        s.push_str(&other.s);
206
207        // Return
208        NonUniquePath {
209            s:          s,
210            segments:   segments,
211        }
212    }
213
214    // Truncate's behaviour is a little unusual in that it returns a new value. This is because for
215    // both Self as UniquePath and Self as NonUnique path, this function should return a
216    // UniquePath. Also n has to be between 0 and length - 1, so that truncate can perform
217    // consistently on both UniquePath and NonUniquePath. Panics if bounds are exceeded.
218    pub fn truncate(self, n: usize) -> UniquePath {
219        if n == 0 {
220            UniquePath {
221                s:          String::new(),
222                segments:   Vec::new(),
223            }
224        } else if n <= self.len() {
225            let l = self.segments[0].start;
226            let r = self.segments[n - 1].end;
227            let mut segments = self.segments;
228            segments.truncate(n);
229            UniquePath {
230                s:          self.s[l..=r].to_string(),
231                segments:   segments,
232            }
233        } else {
234            panic!("Out of bounds.");
235        }
236    }
237
238    pub fn remove(self, n: usize) -> UniquePath {
239        if n > self.len() { panic!("remove() Out of bounds") };
240        let len = self.len();
241        self.truncate(len - n)
242    }
243
244    pub fn debug(&self) -> String {
245        format!("{:?}", self)
246    }
247}
248
249impl PartialEq for UniquePath {
250
251    fn eq(&self, other: &Self) -> bool {
252        if self.len()  != other.len()  { return false };
253        (0..self.len())
254            .all(|i| {
255                self.segment_str(i) == other.segment_str(i) &&
256                self.segments[i].index == other.segments[i].index
257            })
258    }
259}
260
261impl Hash for UniquePath {
262
263    fn hash<H: Hasher>(&self, state: &mut H) {
264        self
265            .segments
266            .iter()
267            .map(|seg| seg.index)
268            .for_each(|i| i.hash(state));
269    }
270}
271
272impl Eq for UniquePath {}
273
274impl Ord for UniquePath {
275
276    // Sort by
277    // 1. length
278    // 2. string section
279    // 3. index
280    //
281    fn cmp(&self, other: &Self) -> Ordering {
282        let min = self.len().min(other.len());
283        for n in 0..min {
284
285            // compare length
286            match self.len().cmp(&other.len()) {
287                Ordering::Less      => { return Ordering::Less      },
288                Ordering::Greater   => { return Ordering::Greater   },
289                Ordering::Equal     => {
290
291                    // compare name
292                    match self.segment_str(n).cmp(other.segment_str(n)) {
293                        Ordering::Less    => { return Ordering::Less    },
294                        Ordering::Greater => { return Ordering::Greater },
295                        Ordering::Equal   => {
296
297                            // compare index
298                            match (self.segments[n].index).cmp(&other.segments[n].index) {
299                                Ordering::Less      => { return Ordering::Less      },
300                                Ordering::Greater   => { return Ordering::Greater   },
301                                Ordering::Equal     => { continue                   },
302
303                            }
304                        },
305                    }
306                },
307            }
308        };
309        Ordering::Equal
310    }
311}
312
313impl PartialOrd for UniquePath {
314    fn partial_cmp(&self, other: &UniquePath) -> Option<Ordering> {
315        Some(self.cmp(other))
316    }
317}
318
319impl fmt::Display for UniquePath {
320    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
321        write!(f, "{}", self.s)
322    }
323}
324
325impl fmt::Debug for UniquePath {
326    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327        if self.is_empty() {
328            write!(f, "{}", "(empty)")
329        } else {
330            let mut s = String::new();
331            for i in 0..self.len() {
332                s.push_str(self.segment_str(i));
333                if i < self.len() {
334
335                    // all but last segment
336                    s.push_str(&format!("[{}]", self.index(i)));
337                    s.push_str("::");
338                }
339            };
340            s.pop();
341            s.pop();
342            write!(f, "{}", s)
343        }
344    }
345}
346
347// Represents the name of a path in a tree with potentially many leaf nodes.
348#[derive(Clone)]
349pub struct NonUniquePath {
350    s:          String,
351    segments:   Vec<Segment>,
352}
353
354impl NonUniquePath {
355
356    pub fn len(&self) -> usize {
357        self.segments.len()
358    }
359
360    // Returns Self as UniquePath.
361    pub fn unique(self, index: usize) -> UniquePath {
362        let mut segments = self.segments;
363        let len = segments.len() - 1;
364        segments[len].index = index;
365        UniquePath {
366            s:          self.s,
367            segments:   segments,
368        }
369    }
370
371    // Return the index at index.
372    pub fn index(&self, index: usize) -> usize {
373        if index <= self.len() - 2 {
374            self.segments[index].index
375        } else {
376            panic!("Out of bounds.");
377        }
378    }
379
380    pub fn is_empty(&self) -> bool {
381        self.s.is_empty()
382    }
383
384    pub fn segment_str(&self, n: usize) -> &str {
385        &self.s[self.segments[n].start..=self.segments[n].end]
386    }
387
388    // Parse a &str into a NonUniquePath
389    pub fn from(s: &str) -> Result<Self, PathError> {
390        let mut parser_state = PS::Segment;
391        let mut leftpos = 0usize;
392        let mut segments: Vec<Segment> = Vec::new();
393
394        if s == "" {
395            return Ok(
396                NonUniquePath {
397                    s:          String::new(),
398                    segments:   segments,
399                }
400            )
401        };
402
403        for (pos, ch) in s.char_indices() {
404            match (&parser_state, ch) {
405                (_, '\n') => {
406                    return Err(PathError::Parse(s.to_string(), pos))
407                },
408                
409                // If we are in a segment and arrive at a separator.
410                (PS::Segment, ':') => {
411                    if pos > leftpos {
412                        segments.push(Segment::new(0, leftpos, pos - 1));
413                        parser_state = PS::Separator;
414                    } else {
415                        return Err(PathError::Parse(s.to_string(), pos))
416                    }
417                },
418
419                // If we are in a segment and arrive at a char then check that the
420                // char is not whitespace;
421                (PS::Segment, ch) => {
422                    if ch.is_whitespace() {
423                        return Err(PathError::Parse(s.to_string(), pos));
424                    }
425                },
426
427                // If we are in a separator and we arrive at a ':' set leftpos.
428                (PS::Separator, ':') => {
429                    leftpos = pos + 1;
430                    parser_state = PS::Segment;
431                },
432
433                // If we are in a separator and we arrive at something other than ':'
434                (PS::Separator, _) => {
435                    return Err(PathError::Parse(s.to_string(), pos))
436                },
437            }
438        };
439
440        // Check that last segment exists.
441        if leftpos == s.len() {
442            return Err(PathError::Parse(s.to_string(), s.len()))
443        };
444
445        // Save last segment.
446        match parser_state {
447            PS::Segment => segments.push(Segment::new(0, leftpos, s.len() - 1)),
448            _           => return Err(PathError::Parse(s.to_string(), s.len())),
449        };
450
451        Ok(NonUniquePath {
452            s:          s.to_string(),
453            segments:   segments,
454        })
455    }
456
457    // Truncate's behaviour is a little unusual in that it returns a new value. This is because for
458    // both Self as UniquePath and Self as NonUnique path, this function should return a
459    // UniquePath.
460    pub fn truncate(&self, n: usize) -> Result<UniquePath, PathError> {
461        if n == 0 {
462            Ok(
463                UniquePath {
464                    s:          String::new(),
465                    segments:   Vec::new(),
466                }
467            )
468        } else if n > self.len() - 1 {
469            Err(PathError::OutOfBounds)
470        } else {
471            let s = self.s
472                .clone()[self.segments[0].start..=self.segments[n].end]
473                .to_string();
474            let mut segments = self.segments.clone();
475            segments.truncate(n);
476            Ok(
477                UniquePath {
478                    s:          s,
479                    segments:   segments,
480                }
481            )
482        }
483    }
484
485    // Returns a NonUniquePath with the first element. If self is empty, then returns empty.
486    pub fn tail(self) -> NonUniquePath {
487        if self.is_empty() {
488            self
489        } else if self.len() == 1 {
490            NonUniquePath {
491                s:          String::new(),
492                segments:   Vec::new(),
493            }
494        } else {
495            let len = self.segments.len();
496            let s = self.s[self.segments[1].start..=self.segments[len - 1].end]
497                .to_string();
498            let lshift = self.segments[0].end - self.segments[0].start + 3;
499            let segments = self.segments[1..]
500                .iter()
501                .map(|seg| {
502                    seg.left_shift(lshift)
503                })
504                .collect();
505            NonUniquePath {
506                s:          s,
507                segments:   segments,
508            }
509        }
510    }
511
512    pub fn debug(&self) -> String {
513        format!("{:?}", self)
514    }
515}
516
517impl Hash for NonUniquePath {
518    fn hash<H: Hasher>(&self, state: &mut H) {
519
520        &self.s.hash(state);
521
522        // Hash the indices if they exist.
523        if self.len() > 1 {
524
525            // Leave off last segment.
526            let len = self.segments.len() - 2;
527
528            self
529                .segments
530                .iter()
531                .take(len)
532                .map(|seg| seg.index)
533                .for_each(|i| i.hash(state));
534        };
535    }
536}
537
538impl PartialEq for NonUniquePath {
539    fn eq(&self, other: &Self) -> bool {
540        if self.len()  != other.len()  { return false };
541        (0..self.len() - 1)
542            .all(|i| {
543                self.segment_str(i) == other.segment_str(i) &&
544                self.segments[i].index == other.segments[i].index
545            })
546        &&
547        self.segment_str(self.len() - 1) == other.segment_str(self.len() - 1)
548    }
549}
550
551impl Eq for NonUniquePath {}
552
553impl Ord for NonUniquePath {
554
555    // Iterate over all but last segment. First compare the string value and then compare the
556    // index. Then compare the string value of the last segment. Then compare length.
557    fn cmp(&self, other: &Self) -> Ordering {
558        let min = self.len().min(other.len());
559        for n in 0..min - 1 {
560
561            // Compare name.
562            match self.segment_str(n).cmp(other.segment_str(n)) {
563                Ordering::Less    => { return Ordering::Less    },
564                Ordering::Greater => { return Ordering::Greater },
565                Ordering::Equal   => {
566
567                    // Compare index.
568                    match (self.segments[n].index).cmp(&other.segments[n].index) {
569                        Ordering::Less      => { return Ordering::Less },
570                        Ordering::Greater   => { return Ordering::Greater },
571                        Ordering::Equal     => continue,
572                    };
573                },
574            };
575        };
576        
577        // Last segment.
578        match self.segment_str(min - 1).cmp(other.segment_str(min - 1)) {
579            Ordering::Less      => { return Ordering::Less },
580            Ordering::Greater   => { return Ordering::Greater },
581            Ordering::Equal     => { return self.len().cmp(&other.len()) },
582        };
583    }
584}
585
586impl PartialOrd for NonUniquePath {
587    fn partial_cmp(&self, other: &NonUniquePath) -> Option<Ordering> {
588        Some(self.cmp(other))
589    }
590}
591
592impl fmt::Debug for NonUniquePath {
593    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594        let mut s = String::new();
595        if self.is_empty() {
596            write!(f, "{}", "(empty)")
597        } else {
598            for i in 0..self.len() - 1 {
599                s.push_str(&format!("{}[{}]::", self.segment_str(i), self.index(i)));
600            };
601            s.push_str(&format!("{}[..]", self.segment_str(self.len() - 1)));
602            write!(f, "{}", s)
603        }
604    }
605}