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