1use std::hash::{self, Hash};
2
3use static_regular_grammar::RegularGrammar;
4
5use crate::{
6 common::{parse, RiRefBufImpl, RiRefImpl},
7 InvalidIri, InvalidUri, Iri, IriBuf, IriRef, IriRefBuf, Uri, UriBuf,
8};
9
10use super::{bytestr_eq, Authority, AuthorityMut, Fragment, Path, PathBuf, PathMut, Query, Scheme};
11
12#[derive(RegularGrammar)]
14#[grammar(
15 file = "src/uri/grammar.abnf",
16 entry_point = "URI-reference",
17 name = "URI reference",
18 cache = "automata/uri/reference.aut.cbor",
19 ascii
20)]
21#[grammar(sized(
22 UriRefBuf,
23 derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Hash)
24))]
25#[cfg_attr(feature = "serde", grammar(serde))]
26#[cfg_attr(feature = "ignore-grammars", grammar(disable))]
27pub struct UriRef([u8]);
28
29impl RiRefImpl for UriRef {
30 type Authority = Authority;
31 type Path = Path;
32 type Query = Query;
33 type Fragment = Fragment;
34
35 type RiRefBuf = UriRefBuf;
36
37 fn as_bytes(&self) -> &[u8] {
38 &self.0
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub struct UriRefParts<'a> {
44 pub scheme: Option<&'a Scheme>,
45 pub authority: Option<&'a Authority>,
46 pub path: &'a Path,
47 pub query: Option<&'a Query>,
48 pub fragment: Option<&'a Fragment>,
49}
50
51impl UriRef {
52 pub fn parts(&self) -> UriRefParts {
53 let bytes = self.as_bytes();
54 let ranges = parse::reference_parts(bytes, 0);
55
56 UriRefParts {
57 scheme: ranges
58 .scheme
59 .map(|r| unsafe { Scheme::new_unchecked(&bytes[r]) }),
60 authority: ranges
61 .authority
62 .map(|r| unsafe { Authority::new_unchecked(&self.0[r]) }),
63 path: unsafe { Path::new_unchecked(&self.0[ranges.path]) },
64 query: ranges
65 .query
66 .map(|r| unsafe { Query::new_unchecked(&self.0[r]) }),
67 fragment: ranges
68 .fragment
69 .map(|r| unsafe { Fragment::new_unchecked(&self.0[r]) }),
70 }
71 }
72
73 #[inline]
74 pub fn as_uri(&self) -> Option<&Uri> {
75 if self.scheme().is_some() {
76 Some(unsafe { Uri::new_unchecked(&self.0) })
77 } else {
78 None
79 }
80 }
81
82 #[inline]
83 pub fn as_iri(&self) -> Option<&Iri> {
84 if self.scheme().is_some() {
85 Some(unsafe { Iri::new_unchecked(std::str::from_utf8_unchecked(&self.0)) })
86 } else {
87 None
88 }
89 }
90
91 #[inline]
92 pub fn as_iri_ref(&self) -> &IriRef {
93 unsafe { IriRef::new_unchecked(std::str::from_utf8_unchecked(&self.0)) }
94 }
95
96 #[inline]
98 pub fn scheme(&self) -> Option<&Scheme> {
99 RiRefImpl::scheme_opt(self)
100 }
101
102 pub fn authority(&self) -> Option<&Authority> {
104 RiRefImpl::authority(self)
105 }
106
107 pub fn path(&self) -> &Path {
109 RiRefImpl::path(self)
110 }
111
112 pub fn query(&self) -> Option<&Query> {
113 RiRefImpl::query(self)
114 }
115
116 pub fn fragment(&self) -> Option<&Fragment> {
117 RiRefImpl::fragment(self)
118 }
119
120 #[inline]
125 pub fn resolved(&self, base_iri: &(impl ?Sized + AsRef<Uri>)) -> UriBuf {
126 let iri_ref = self.to_owned();
127 iri_ref.into_resolved(base_iri)
128 }
129
130 pub fn relative_to(&self, other: &(impl ?Sized + AsRef<UriRef>)) -> UriRefBuf {
144 RiRefImpl::relative_to(self, other.as_ref())
145 }
146
147 #[inline]
156 pub fn suffix(
157 &self,
158 prefix: &(impl ?Sized + AsRef<UriRef>),
159 ) -> Option<(PathBuf, Option<&Query>, Option<&Fragment>)> {
160 RiRefImpl::suffix(self, prefix.as_ref())
161 }
162
163 #[inline]
174 pub fn base(&self) -> &Self {
175 unsafe { Self::new_unchecked(RiRefImpl::base(self)) }
176 }
177}
178
179impl AsRef<IriRef> for UriRef {
180 fn as_ref(&self) -> &IriRef {
181 self.as_iri_ref()
182 }
183}
184
185impl<'a> From<&'a UriRef> for &'a IriRef {
186 fn from(value: &'a UriRef) -> Self {
187 value.as_iri_ref()
188 }
189}
190
191impl<'a> TryFrom<&'a UriRef> for &'a Uri {
192 type Error = InvalidUri<&'a UriRef>;
193
194 fn try_from(value: &'a UriRef) -> Result<Self, Self::Error> {
195 value.as_uri().ok_or(InvalidUri(value))
196 }
197}
198
199impl<'a> TryFrom<&'a UriRef> for &'a Iri {
200 type Error = InvalidIri<&'a UriRef>;
201
202 fn try_from(value: &'a UriRef) -> Result<Self, Self::Error> {
203 value.as_iri().ok_or(InvalidIri(value))
204 }
205}
206
207bytestr_eq!(UriRef);
208
209impl PartialEq for UriRef {
210 fn eq(&self, other: &Self) -> bool {
211 self.parts() == other.parts()
212 }
213}
214
215impl<'a> PartialEq<&'a UriRef> for UriRef {
216 fn eq(&self, other: &&'a Self) -> bool {
217 *self == **other
218 }
219}
220
221impl PartialEq<UriRefBuf> for UriRef {
222 fn eq(&self, other: &UriRefBuf) -> bool {
223 *self == *other.as_uri_ref()
224 }
225}
226
227impl PartialEq<Uri> for UriRef {
228 fn eq(&self, other: &Uri) -> bool {
229 *self == *other.as_uri_ref()
230 }
231}
232
233impl<'a> PartialEq<&'a Uri> for UriRef {
234 fn eq(&self, other: &&'a Uri) -> bool {
235 *self == *other.as_uri_ref()
236 }
237}
238
239impl PartialEq<UriBuf> for UriRef {
240 fn eq(&self, other: &UriBuf) -> bool {
241 *self == *other.as_uri_ref()
242 }
243}
244
245impl Eq for UriRef {}
246
247impl PartialOrd for UriRef {
248 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
249 Some(self.cmp(other))
250 }
251}
252
253impl<'a> PartialOrd<&'a UriRef> for UriRef {
254 fn partial_cmp(&self, other: &&'a Self) -> Option<std::cmp::Ordering> {
255 self.partial_cmp(*other)
256 }
257}
258
259impl PartialOrd<UriRefBuf> for UriRef {
260 fn partial_cmp(&self, other: &UriRefBuf) -> Option<std::cmp::Ordering> {
261 self.partial_cmp(other.as_uri_ref())
262 }
263}
264
265impl PartialOrd<Uri> for UriRef {
266 fn partial_cmp(&self, other: &Uri) -> Option<std::cmp::Ordering> {
267 self.partial_cmp(other.as_uri_ref())
268 }
269}
270
271impl<'a> PartialOrd<&'a Uri> for UriRef {
272 fn partial_cmp(&self, other: &&'a Uri) -> Option<std::cmp::Ordering> {
273 self.partial_cmp(other.as_uri_ref())
274 }
275}
276
277impl PartialOrd<UriBuf> for UriRef {
278 fn partial_cmp(&self, other: &UriBuf) -> Option<std::cmp::Ordering> {
279 self.partial_cmp(other.as_uri_ref())
280 }
281}
282
283impl Ord for UriRef {
284 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
285 self.parts().cmp(&other.parts())
286 }
287}
288
289impl Hash for UriRef {
290 fn hash<H: hash::Hasher>(&self, state: &mut H) {
291 self.parts().hash(state)
292 }
293}
294
295impl RiRefImpl for UriRefBuf {
296 type Authority = Authority;
297 type Path = Path;
298 type Query = Query;
299 type Fragment = Fragment;
300
301 type RiRefBuf = Self;
302
303 fn as_bytes(&self) -> &[u8] {
304 &self.0
305 }
306}
307
308impl RiRefBufImpl for UriRefBuf {
309 type Ri = Uri;
310 type RiBuf = UriBuf;
311
312 unsafe fn new_unchecked(bytes: Vec<u8>) -> Self {
313 Self::new_unchecked(bytes)
314 }
315
316 unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
317 &mut self.0
318 }
319
320 fn into_bytes(self) -> Vec<u8> {
321 self.0
322 }
323}
324
325impl UriRefBuf {
326 pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
334 &mut self.0
335 }
336
337 pub fn into_iri_ref(self) -> IriRefBuf {
338 unsafe { IriRefBuf::new_unchecked(String::from_utf8_unchecked(self.0)) }
339 }
340
341 pub fn try_into_uri(self) -> Result<UriBuf, InvalidUri<Self>> {
342 if self.scheme().is_some() {
343 unsafe { Ok(UriBuf::new_unchecked(self.0)) }
344 } else {
345 Err(InvalidUri(self))
346 }
347 }
348
349 pub fn try_into_iri(self) -> Result<IriBuf, InvalidIri<Self>> {
350 if self.scheme().is_some() {
351 unsafe { Ok(IriBuf::new_unchecked(String::from_utf8_unchecked(self.0))) }
352 } else {
353 Err(InvalidIri(self))
354 }
355 }
356
357 pub fn path_mut(&mut self) -> PathMut {
358 PathMut::from_impl(RiRefBufImpl::path_mut(self))
359 }
360
361 pub fn authority_mut(&mut self) -> Option<AuthorityMut> {
362 RiRefBufImpl::authority_mut(self).map(AuthorityMut::from_impl)
363 }
364
365 pub fn set_scheme(&mut self, scheme: Option<&Scheme>) {
390 RiRefBufImpl::set_scheme(self, scheme)
391 }
392
393 pub fn set_authority(&mut self, authority: Option<&Authority>) {
425 RiRefBufImpl::set_authority(self, authority)
426 }
427
428 pub fn set_path(&mut self, path: &Path) {
470 RiRefBufImpl::set_path(self, path)
471 }
472
473 pub fn set_query(&mut self, query: Option<&Query>) {
475 RiRefBufImpl::set_query(self, query)
476 }
477
478 pub fn set_fragment(&mut self, fragment: Option<&Fragment>) {
480 RiRefBufImpl::set_fragment(self, fragment)
481 }
482
483 pub fn resolve(&mut self, base_iri: &(impl ?Sized + AsRef<Uri>)) {
489 RiRefBufImpl::resolve(self, base_iri.as_ref())
490 }
491
492 pub fn into_resolved(self, base_iri: &(impl ?Sized + AsRef<Uri>)) -> UriBuf {
493 RiRefBufImpl::into_resolved(self, base_iri.as_ref())
494 }
495}
496
497impl AsRef<IriRef> for UriRefBuf {
498 fn as_ref(&self) -> &IriRef {
499 self.as_iri_ref()
500 }
501}
502
503impl From<UriRefBuf> for IriRefBuf {
504 fn from(value: UriRefBuf) -> Self {
505 value.into_iri_ref()
506 }
507}
508
509impl TryFrom<UriRefBuf> for UriBuf {
510 type Error = InvalidUri<UriRefBuf>;
511
512 fn try_from(value: UriRefBuf) -> Result<Self, Self::Error> {
513 value.try_into_uri()
514 }
515}
516
517impl TryFrom<UriRefBuf> for IriBuf {
518 type Error = InvalidIri<UriRefBuf>;
519
520 fn try_from(value: UriRefBuf) -> Result<Self, Self::Error> {
521 value.try_into_iri()
522 }
523}
524
525bytestr_eq!(UriRefBuf);
526
527impl PartialEq<Uri> for UriRefBuf {
528 fn eq(&self, other: &Uri) -> bool {
529 *self.as_uri_ref() == *other.as_uri_ref()
530 }
531}
532
533impl<'a> PartialEq<&'a Uri> for UriRefBuf {
534 fn eq(&self, other: &&'a Uri) -> bool {
535 *self.as_uri_ref() == *other.as_uri_ref()
536 }
537}
538
539impl PartialEq<UriBuf> for UriRefBuf {
540 fn eq(&self, other: &UriBuf) -> bool {
541 *self.as_uri_ref() == *other.as_uri_ref()
542 }
543}
544
545impl PartialOrd<Uri> for UriRefBuf {
546 fn partial_cmp(&self, other: &Uri) -> Option<std::cmp::Ordering> {
547 self.as_uri_ref().partial_cmp(other.as_uri_ref())
548 }
549}
550
551impl<'a> PartialOrd<&'a Uri> for UriRefBuf {
552 fn partial_cmp(&self, other: &&'a Uri) -> Option<std::cmp::Ordering> {
553 self.as_uri_ref().partial_cmp(other.as_uri_ref())
554 }
555}
556
557impl PartialOrd<UriBuf> for UriRefBuf {
558 fn partial_cmp(&self, other: &UriBuf) -> Option<std::cmp::Ordering> {
559 self.as_uri_ref().partial_cmp(other.as_uri_ref())
560 }
561}
562
563#[cfg(test)]
564mod tests {
565 use super::*;
566
567 const PARTS: [(
568 &[u8],
569 (
570 Option<&[u8]>,
571 Option<&[u8]>,
572 &[u8],
573 Option<&[u8]>,
574 Option<&[u8]>,
575 ),
576 ); 36] = [
577 (b"", (None, None, b"", None, None)),
579 (b"scheme:", (Some(b"scheme"), None, b"", None, None)),
581 (b"//authority", (None, Some(b"authority"), b"", None, None)),
582 (b"path", (None, None, b"path", None, None)),
583 (b"/path", (None, None, b"/path", None, None)),
584 (b"/", (None, None, b"/", None, None)),
585 (b"foo//bar", (None, None, b"foo//bar", None, None)),
586 (b"?query", (None, None, b"", Some(b"query"), None)),
587 (b"#fragment", (None, None, b"", None, Some(b"fragment"))),
588 (
589 b"scheme:?query",
590 (Some(b"scheme"), None, b"", Some(b"query"), None),
591 ),
592 (
594 b"scheme://authority",
595 (Some(b"scheme"), Some(b"authority"), b"", None, None),
596 ),
597 (b"scheme:path", (Some(b"scheme"), None, b"path", None, None)),
598 (
599 b"scheme:/path",
600 (Some(b"scheme"), None, b"/path", None, None),
601 ),
602 (
603 b"scheme:?query",
604 (Some(b"scheme"), None, b"", Some(b"query"), None),
605 ),
606 (
607 b"scheme:#fragment",
608 (Some(b"scheme"), None, b"", None, Some(b"fragment")),
609 ),
610 (
611 b"//authority/path",
612 (None, Some(b"authority"), b"/path", None, None),
613 ),
614 (
615 b"//authority?query",
616 (None, Some(b"authority"), b"", Some(b"query"), None),
617 ),
618 (
619 b"//authority#fragment",
620 (None, Some(b"authority"), b"", None, Some(b"fragment")),
621 ),
622 (b"path?query", (None, None, b"path", Some(b"query"), None)),
623 (b"/path?query", (None, None, b"/path", Some(b"query"), None)),
624 (
625 b"path#fragment",
626 (None, None, b"path", None, Some(b"fragment")),
627 ),
628 (
629 b"?query#fragment",
630 (None, None, b"", Some(b"query"), Some(b"fragment")),
631 ),
632 (
634 b"scheme://authority/path",
635 (Some(b"scheme"), Some(b"authority"), b"/path", None, None),
636 ),
637 (
638 b"scheme://authority?query",
639 (
640 Some(b"scheme"),
641 Some(b"authority"),
642 b"",
643 Some(b"query"),
644 None,
645 ),
646 ),
647 (
648 b"scheme://authority#fragment",
649 (
650 Some(b"scheme"),
651 Some(b"authority"),
652 b"",
653 None,
654 Some(b"fragment"),
655 ),
656 ),
657 (
658 b"scheme:path?query",
659 (Some(b"scheme"), None, b"path", Some(b"query"), None),
660 ),
661 (
662 b"scheme:path#fragment",
663 (Some(b"scheme"), None, b"path", None, Some(b"fragment")),
664 ),
665 (
666 b"//authority/path?query",
667 (None, Some(b"authority"), b"/path", Some(b"query"), None),
668 ),
669 (
670 b"//authority/path#fragment",
671 (None, Some(b"authority"), b"/path", None, Some(b"fragment")),
672 ),
673 (
674 b"//authority?query#fragment",
675 (
676 None,
677 Some(b"authority"),
678 b"",
679 Some(b"query"),
680 Some(b"fragment"),
681 ),
682 ),
683 (
684 b"path?query#fragment",
685 (None, None, b"path", Some(b"query"), Some(b"fragment")),
686 ),
687 (
689 b"scheme://authority/path?query",
690 (
691 Some(b"scheme"),
692 Some(b"authority"),
693 b"/path",
694 Some(b"query"),
695 None,
696 ),
697 ),
698 (
699 b"scheme://authority/path#fragment",
700 (
701 Some(b"scheme"),
702 Some(b"authority"),
703 b"/path",
704 None,
705 Some(b"fragment"),
706 ),
707 ),
708 (
709 b"scheme://authority?query#fragment",
710 (
711 Some(b"scheme"),
712 Some(b"authority"),
713 b"",
714 Some(b"query"),
715 Some(b"fragment"),
716 ),
717 ),
718 (
719 b"scheme:path?query#fragment",
720 (
721 Some(b"scheme"),
722 None,
723 b"path",
724 Some(b"query"),
725 Some(b"fragment"),
726 ),
727 ),
728 (
730 b"scheme://authority/path?query#fragment",
731 (
732 Some(b"scheme"),
733 Some(b"authority"),
734 b"/path",
735 Some(b"query"),
736 Some(b"fragment"),
737 ),
738 ),
739 ];
740
741 #[test]
742 fn parts() {
743 for (input, expected) in PARTS {
744 let input = UriRef::new(input).unwrap();
745 let parts = input.parts();
746
747 assert_eq!(parts.scheme.map(Scheme::as_bytes), expected.0);
748 assert_eq!(parts.authority.map(Authority::as_bytes), expected.1);
749 assert_eq!(parts.path.as_bytes(), expected.2);
750 assert_eq!(parts.query.map(Query::as_bytes), expected.3);
751 assert_eq!(parts.fragment.map(Fragment::as_bytes), expected.4)
752 }
753 }
754
755 #[test]
756 fn scheme() {
757 for (input, expected) in PARTS {
758 let input = UriRef::new(input).unwrap();
759 assert_eq!(input.scheme().map(Scheme::as_bytes), expected.0)
760 }
761 }
762
763 #[test]
764 fn authority() {
765 for (input, expected) in PARTS {
766 let input = UriRef::new(input).unwrap();
767 assert_eq!(input.authority().map(Authority::as_bytes), expected.1)
769 }
770 }
771
772 #[test]
773 fn set_authority() {
774 let vectors: [(&[u8], Option<&[u8]>, &[u8]); 3] = [
775 (
776 b"scheme:/path",
777 Some(b"authority"),
778 b"scheme://authority/path",
779 ),
780 (
781 b"scheme:path",
782 Some(b"authority"),
783 b"scheme://authority/path",
784 ),
785 (b"scheme://authority//path", None, b"scheme:/.//path"),
786 ];
787
788 for (input, authority, expected) in vectors {
789 let mut buffer = UriRefBuf::new(input.to_vec()).unwrap();
790 let authority = authority.map(Authority::new).transpose().unwrap();
791 buffer.set_authority(authority);
792 assert_eq!(buffer.as_bytes(), expected)
794 }
795 }
796
797 #[test]
798 fn path() {
799 for (input, expected) in PARTS {
800 let input = UriRef::new(input).unwrap();
801 assert_eq!(input.path().as_bytes(), expected.2)
803 }
804 }
805
806 #[test]
807 fn query() {
808 for (input, expected) in PARTS {
809 let input = UriRef::new(input).unwrap();
810 assert_eq!(input.query().map(Query::as_bytes), expected.3)
812 }
813 }
814
815 #[test]
816 fn fragment() {
817 for (input, expected) in PARTS {
818 let input = UriRef::new(input).unwrap();
819 assert_eq!(input.fragment().map(Fragment::as_bytes), expected.4)
821 }
822 }
823}