1use static_regular_grammar::RegularGrammar;
2
3mod segment;
4
5pub use segment::*;
6
7use crate::common::path::{NormalizedSegmentsImpl, PathBufImpl, PathImpl, SegmentsImpl};
8
9use super::PathMut;
10
11#[derive(RegularGrammar)]
13#[grammar(
14 file = "src/iri/grammar.abnf",
15 entry_point = "ipath",
16 name = "IRI path",
17 cache = "automata/iri/path.aut.cbor"
18)]
19#[grammar(sized(PathBuf, derive(Debug, Display)))]
20#[cfg_attr(feature = "serde", grammar(serde))]
21#[cfg_attr(feature = "ignore-grammars", grammar(disable))]
22pub struct Path(str);
23
24impl PathImpl for Path {
25 const EMPTY: &'static Self = Self::EMPTY;
26
27 const EMPTY_ABSOLUTE: &'static Self = Self::EMPTY_ABSOLUTE;
28
29 type Segment = Segment;
30
31 type Owned = PathBuf;
32
33 unsafe fn new_unchecked(bytes: &[u8]) -> &Self {
34 Self::new_unchecked(std::str::from_utf8_unchecked(bytes))
35 }
36
37 #[inline(always)]
38 fn as_bytes(&self) -> &[u8] {
39 self.as_bytes()
40 }
41
42 fn to_path_buf(&self) -> Self::Owned {
43 unsafe { PathBuf::new_unchecked(self.to_string()) }
44 }
45}
46
47impl PathBufImpl for PathBuf {
48 type Borrowed = Path;
49
50 unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
51 self.0.as_mut_vec()
52 }
53
54 fn as_bytes(&self) -> &[u8] {
55 self.0.as_bytes()
56 }
57}
58
59impl Path {
60 pub const EMPTY_ABSOLUTE: &'static Self = unsafe { Self::new_unchecked("/") };
62
63 #[inline]
68 pub fn segment_count(&self) -> usize {
69 self.segments().count()
70 }
71
72 #[inline]
77 pub fn is_empty(&self) -> bool {
78 PathImpl::is_empty(self)
79 }
80
81 #[inline]
85 pub fn is_absolute(&self) -> bool {
86 PathImpl::is_absolute(self)
87 }
88
89 #[inline]
93 pub fn is_relative(&self) -> bool {
94 PathImpl::is_relative(self)
95 }
96
97 pub fn first(&self) -> Option<&Segment> {
98 PathImpl::first(self)
99 }
100
101 pub fn last(&self) -> Option<&Segment> {
102 PathImpl::last(self)
103 }
104
105 #[inline]
115 pub fn segments(&self) -> Segments {
116 Segments(PathImpl::segments(self))
117 }
118
119 #[inline]
125 pub fn normalized_segments(&self) -> NormalizedSegments {
126 NormalizedSegments(PathImpl::normalized_segments(self))
127 }
128
129 #[inline]
130 pub fn normalized(&self) -> PathBuf {
131 PathImpl::normalized(self)
132 }
133
134 #[inline]
140 pub fn file_name(&self) -> Option<&Segment> {
141 PathImpl::file_name(self)
142 }
143
144 pub fn directory(&self) -> &Self {
156 PathImpl::directory(self)
157 }
158
159 #[inline]
169 pub fn parent(&self) -> Option<&Self> {
170 PathImpl::parent(self)
171 }
172
173 #[inline]
184 pub fn parent_or_empty(&self) -> &Self {
185 PathImpl::parent_or_empty(self)
186 }
187
188 #[inline]
209 pub fn suffix(&self, prefix: &Self) -> Option<PathBuf> {
210 PathImpl::suffix(self, prefix)
211 }
212}
213
214impl<'a> IntoIterator for &'a Path {
215 type Item = &'a Segment;
216 type IntoIter = Segments<'a>;
217
218 #[inline]
219 fn into_iter(self) -> Segments<'a> {
220 self.segments()
221 }
222}
223
224impl PartialEq for Path {
225 #[inline]
226 fn eq(&self, other: &Path) -> bool {
227 if self.is_absolute() == other.is_absolute() {
228 let self_segments = self.normalized_segments();
229 let other_segments = other.normalized_segments();
230 self_segments.len() == other_segments.len()
231 && self_segments.zip(other_segments).all(|(a, b)| a == b)
232 } else {
233 false
234 }
235 }
236}
237
238impl PartialEq<str> for Path {
239 fn eq(&self, other: &str) -> bool {
240 self.as_str() == other
241 }
242}
243
244impl<'a> PartialEq<&'a str> for Path {
245 fn eq(&self, other: &&'a str) -> bool {
246 self.as_str() == *other
247 }
248}
249
250impl PartialEq<String> for Path {
251 fn eq(&self, other: &String) -> bool {
252 self.as_str() == other.as_str()
253 }
254}
255
256impl Eq for Path {}
257
258impl PartialOrd for Path {
259 #[inline]
260 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
261 Some(self.cmp(other))
262 }
263}
264
265impl Ord for Path {
266 #[inline]
267 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
268 use std::cmp::Ordering;
269 if self.is_absolute() == other.is_absolute() {
270 let mut self_segments = self.normalized_segments();
271 let mut other_segments = other.normalized_segments();
272
273 loop {
274 match (self_segments.next(), other_segments.next()) {
275 (None, None) => return Ordering::Equal,
276 (Some(_), None) => return Ordering::Greater,
277 (None, Some(_)) => return Ordering::Less,
278 (Some(a), Some(b)) => match a.cmp(b) {
279 Ordering::Greater => return Ordering::Greater,
280 Ordering::Less => return Ordering::Less,
281 Ordering::Equal => (),
282 },
283 }
284 }
285 } else if self.is_absolute() {
286 Ordering::Greater
287 } else {
288 Ordering::Less
289 }
290 }
291}
292
293impl std::hash::Hash for Path {
294 #[inline]
295 fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
296 self.is_absolute().hash(hasher);
297 self.normalized_segments().for_each(move |s| s.hash(hasher))
298 }
299}
300
301pub struct Segments<'a>(SegmentsImpl<'a, Path>);
302
303impl<'a> Iterator for Segments<'a> {
304 type Item = &'a Segment;
305
306 fn next(&mut self) -> Option<Self::Item> {
307 self.0.next()
308 }
309}
310
311impl<'a> DoubleEndedIterator for Segments<'a> {
312 fn next_back(&mut self) -> Option<Self::Item> {
313 self.0.next_back()
314 }
315}
316
317pub struct NormalizedSegments<'a>(NormalizedSegmentsImpl<'a, Path>);
318
319impl<'a> Iterator for NormalizedSegments<'a> {
320 type Item = &'a Segment;
321
322 fn size_hint(&self) -> (usize, Option<usize>) {
323 self.0.size_hint()
324 }
325
326 #[inline]
327 fn next(&mut self) -> Option<&'a Segment> {
328 self.0.next()
329 }
330}
331
332impl<'a> DoubleEndedIterator for NormalizedSegments<'a> {
333 #[inline]
334 fn next_back(&mut self) -> Option<Self::Item> {
335 self.0.next_back()
336 }
337}
338
339impl<'a> ExactSizeIterator for NormalizedSegments<'a> {}
340
341impl PathBuf {
342 pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
352 self.0.as_mut_vec()
353 }
354
355 pub fn as_path_mut(&mut self) -> PathMut {
356 PathMut::from_path(self)
357 }
358
359 pub fn push(&mut self, segment: &Segment) {
360 self.as_path_mut().push(segment)
361 }
362
363 pub fn pop(&mut self) {
368 self.as_path_mut().pop()
369 }
370
371 pub fn clear(&mut self) {
372 self.as_path_mut().clear()
373 }
374
375 #[inline]
377 pub fn symbolic_push(&mut self, segment: &Segment) {
378 self.as_path_mut().symbolic_push(segment)
379 }
380
381 #[inline]
387 pub fn symbolic_append<'s, P: IntoIterator<Item = &'s Segment>>(&mut self, path: P) {
388 self.as_path_mut().symbolic_append(path)
389 }
390
391 #[inline]
392 pub fn normalize(&mut self) {
393 self.as_path_mut().normalize()
394 }
395}
396
397impl PartialEq<str> for PathBuf {
398 fn eq(&self, other: &str) -> bool {
399 self.as_str() == other
400 }
401}
402
403impl<'a> PartialEq<&'a str> for PathBuf {
404 fn eq(&self, other: &&'a str) -> bool {
405 self.as_str() == *other
406 }
407}
408
409impl PartialEq<String> for PathBuf {
410 fn eq(&self, other: &String) -> bool {
411 self.as_str() == other.as_str()
412 }
413}
414
415#[cfg(test)]
416mod tests {
417 use super::*;
418
419 #[test]
420 fn empty() {
421 let path = Path::EMPTY;
422 assert!(path.is_empty());
423 assert!(!path.is_absolute());
424 assert!(path.segments().next().is_none());
425 }
426
427 #[test]
428 fn empty_absolute() {
429 let path = Path::EMPTY_ABSOLUTE;
430 assert!(path.is_empty());
431 assert!(path.is_absolute());
432 assert!(path.segments().next().is_none());
433 }
434
435 #[test]
436 fn non_empty() {
437 let path = Path::new("a/b").unwrap();
438
439 assert!(!path.is_empty());
440 assert!(!path.is_absolute());
441
442 let mut segments = path.segments();
443 assert!(segments.next().unwrap().as_str() == "a");
444 assert!(segments.next().unwrap().as_str() == "b");
445 assert!(segments.next().is_none());
446 }
447
448 #[test]
449 fn non_empty_absolute() {
450 let path = Path::new("/foo/bar").unwrap();
451 assert!(!path.is_empty());
452 assert!(path.is_absolute());
453
454 let mut segments = path.segments();
455 assert!(segments.next().unwrap().as_str() == "foo");
456 assert!(segments.next().unwrap().as_str() == "bar");
457 assert!(segments.next().is_none());
458 }
459
460 #[test]
461 fn next_segment() {
462 let vectors = [
463 ("foo/bar", 0, Some(("foo", 4))),
464 ("foo/bar", 4, Some(("bar", 8))),
465 ("foo/bar", 8, None),
466 ("foo/bar/", 8, Some(("", 9))),
467 ("foo/bar/", 9, None),
468 ("//foo", 1, Some(("", 2))),
469 ];
470
471 for (input, offset, expected) in vectors {
472 unsafe {
473 assert_eq!(
474 Path::new(input).unwrap().next_segment_from(offset),
475 expected.map(|(e, i)| (Segment::new(e).unwrap(), i))
476 )
477 }
478 }
479 }
480
481 #[test]
482 fn previous_segment() {
483 let vectors = [
484 ("/foo/bar", 1, None),
485 ("foo/bar", 0, None),
486 ("foo/bar", 4, Some(("foo", 0))),
487 ("foo/bar", 8, Some(("bar", 4))),
488 ("foo/bar/", 8, Some(("bar", 4))),
489 ("foo/bar/", 9, Some(("", 8))),
490 ("//a/b", 4, Some(("a", 2))),
491 ];
492
493 for (input, offset, expected) in vectors {
494 unsafe {
495 assert_eq!(
496 Path::new(input).unwrap().previous_segment_from(offset),
497 expected.map(|(e, i)| (Segment::new(e).unwrap(), i))
498 )
499 }
500 }
501 }
502
503 #[test]
504 fn first_segment() {
505 let vectors = [
506 ("", None),
507 ("/", None),
508 ("//", Some("")),
509 ("/foo/bar", Some("foo")),
510 ];
511
512 for (input, expected) in vectors {
513 assert_eq!(
514 Path::new(input).unwrap().first(),
515 expected.map(|e| Segment::new(e).unwrap())
516 )
517 }
518 }
519
520 #[test]
521 fn segments() {
522 let vectors: [(&str, &[&str]); 8] = [
523 ("", &[]),
524 ("foo", &["foo"]),
525 ("/foo", &["foo"]),
526 ("foo/", &["foo", ""]),
527 ("/foo/", &["foo", ""]),
528 ("a/b/c/d", &["a", "b", "c", "d"]),
529 ("a/b//c/d", &["a", "b", "", "c", "d"]),
530 ("//a/b/foo//bar/", &["", "a", "b", "foo", "", "bar", ""]),
531 ];
532
533 for (input, expected) in vectors {
534 let path = Path::new(input).unwrap();
535 let segments: Vec<_> = path.segments().collect();
536 assert_eq!(segments.len(), expected.len());
537 assert!(segments
538 .into_iter()
539 .zip(expected)
540 .all(|(a, b)| a.as_str() == *b))
541 }
542 }
543
544 #[test]
545 fn segments_rev() {
546 let vectors: [(&str, &[&str]); 8] = [
547 ("", &[]),
548 ("foo", &["foo"]),
549 ("/foo", &["foo"]),
550 ("foo/", &["foo", ""]),
551 ("/foo/", &["foo", ""]),
552 ("a/b/c/d", &["a", "b", "c", "d"]),
553 ("a/b//c/d", &["a", "b", "", "c", "d"]),
554 ("//a/b/foo//bar/", &["", "a", "b", "foo", "", "bar", ""]),
555 ];
556
557 for (input, expected) in vectors {
558 let path = Path::new(input).unwrap();
559 let segments: Vec<_> = path.segments().rev().collect();
560 assert_eq!(segments.len(), expected.len());
561 assert!(segments
562 .into_iter()
563 .zip(expected.into_iter().rev())
564 .all(|(a, b)| a.as_str() == *b))
565 }
566 }
567
568 #[test]
569 fn normalized() {
570 let vectors = [
571 ("", ""),
572 ("a/b/c", "a/b/c"),
573 ("a/..", ""),
574 ("a/b/..", "a/"),
575 ("a/b/../", "a/"),
576 ("a/b/c/..", "a/b/"),
577 ("a/b/c/.", "a/b/c/"),
578 ("a/../..", "../"),
579 ("/a/../..", "/"), ];
581
582 for (input, expected) in vectors {
583 let path = Path::new(input).unwrap();
585 let output = path.normalized();
586 assert_eq!(output.as_str(), expected);
587 }
588 }
589
590 #[test]
591 fn eq() {
592 let vectors = [
593 ("a/b/c", "a/b/c"),
594 ("a/b/c", "a/b/c/."),
595 ("a/b/c/", "a/b/c/./"),
596 ("a/b/c", "a/b/../b/c"),
597 ("a/b/c/..", "a/b"),
598 ("a/..", ""),
599 ("/a/..", "/"),
600 ("a/../..", ".."),
601 ("/a/../..", "/.."),
602 ("a/b/c/./", "a/b/c/"),
603 ("a/b/c/../", "a/b/"),
604 ];
605
606 for (a, b) in vectors {
607 let a = Path::new(a).unwrap();
608 let b = Path::new(b).unwrap();
609 assert_eq!(a, b)
610 }
611 }
612
613 #[test]
614 fn ne() {
615 let vectors = [
616 ("a/b/c", "a/b/c/"),
617 ("a/b/c/", "a/b/c/."),
618 ("a/b/c/../", "a/b"),
619 ];
620
621 for (a, b) in vectors {
622 let a = Path::new(a).unwrap();
623 let b = Path::new(b).unwrap();
624 assert_ne!(a, b)
625 }
626 }
627
628 #[test]
629 fn file_name() {
630 let vectors = [("//a/b/foo//bar/", None), ("//a/b/foo//bar", Some("bar"))];
631
632 for (input, expected) in vectors {
633 let input = Path::new(input).unwrap();
634 assert_eq!(input.file_name().map(Segment::as_str), expected)
635 }
636 }
637
638 #[test]
639 fn parent() {
640 let vectors = [
641 ("", None),
642 ("/", None),
643 (".", None),
644 ("//a/b/foo//bar", Some("//a/b/foo/")),
645 ("//a/b/foo//", Some("//a/b/foo/")),
646 ("//a/b/foo/", Some("//a/b/foo")),
647 ("//a/b/foo", Some("//a/b")),
648 ("//a/b", Some("//a")),
649 ("//a", Some("/./")),
650 ("/./", Some("/.")),
651 ("/.", Some("/")),
652 ];
653
654 for (input, expected) in vectors {
655 let input = Path::new(input).unwrap();
656 assert_eq!(input.parent().map(Path::as_str), expected)
657 }
658 }
659
660 #[test]
661 fn suffix() {
662 let vectors = [
663 ("/foo/bar/baz", "/foo/bar", Some("baz")),
664 ("//foo", "/", Some(".//foo")),
665 ("/a/b/baz", "/foo/bar", None),
666 ];
667
668 for (path, prefix, expected_suffix) in vectors {
669 let path = Path::new(path).unwrap();
671 let suffix = path.suffix(Path::new(prefix).unwrap());
672 assert_eq!(suffix.as_deref().map(Path::as_str), expected_suffix)
673 }
674 }
675}