1use 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
41enum PS {
43 Segment,
44 Separator,
45}
46
47#[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 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 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#[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 pub fn non_unique(self) -> NonUniquePath {
116 NonUniquePath {
117 s: self.s,
118 segments: self.segments,
119 }
120 }
121
122 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 pub fn eq_base(&self, other: &UniquePath) -> bool {
138 self.clone().non_unique() == other.clone().non_unique()
139 }
140
141 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 pub fn len(&self) -> usize {
157 self.segments.len()
158 }
159
160 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 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 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 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 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 let mut s = self.s;
204 if s != "" { s.push_str("::") };
205 s.push_str(&other.s);
206
207 NonUniquePath {
209 s: s,
210 segments: segments,
211 }
212 }
213
214 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 fn cmp(&self, other: &Self) -> Ordering {
282 let min = self.len().min(other.len());
283 for n in 0..min {
284
285 match self.len().cmp(&other.len()) {
287 Ordering::Less => { return Ordering::Less },
288 Ordering::Greater => { return Ordering::Greater },
289 Ordering::Equal => {
290
291 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 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 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#[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 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 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 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 (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 (PS::Segment, ch) => {
422 if ch.is_whitespace() {
423 return Err(PathError::Parse(s.to_string(), pos));
424 }
425 },
426
427 (PS::Separator, ':') => {
429 leftpos = pos + 1;
430 parser_state = PS::Segment;
431 },
432
433 (PS::Separator, _) => {
435 return Err(PathError::Parse(s.to_string(), pos))
436 },
437 }
438 };
439
440 if leftpos == s.len() {
442 return Err(PathError::Parse(s.to_string(), s.len()))
443 };
444
445 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 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 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 if self.len() > 1 {
524
525 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 fn cmp(&self, other: &Self) -> Ordering {
558 let min = self.len().min(other.len());
559 for n in 0..min - 1 {
560
561 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 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 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}