1use static_regular_grammar::RegularGrammar;
2use std::{
3 borrow::{Borrow, Cow},
4 hash::{self, Hash},
5};
6
7mod authority;
8mod authority_mut;
9mod fragment;
10mod path;
11mod path_mut;
12mod query;
13mod reference;
14mod scheme;
15
16pub use authority::*;
17pub use authority_mut::*;
18pub use fragment::*;
19pub use path::*;
20pub use path_mut::*;
21pub use query::*;
22pub use reference::*;
23pub use scheme::*;
24
25use crate::{
26 common::{bytestr_eq, parse, RiBufImpl, RiImpl, RiRefBufImpl, RiRefImpl},
27 Iri, IriBuf, IriRef, IriRefBuf,
28};
29
30macro_rules! uri_error {
31 ($($(#[$meta:meta])* $variant:ident : $ident:ident),*) => {
32 #[derive(Debug, thiserror::Error)]
33 pub enum UriError<T> {
34 $(
35 $(#[$meta])*
36 $variant(#[from] $ident<T>)
37 ),*
38 }
39
40 $(
41 impl<'a> From<$ident<String>> for UriError<Cow<'a, str>> {
42 fn from($ident(value): $ident<String>) -> Self {
43 Self::$variant($ident(Cow::Owned(value)))
44 }
45 }
46
47 impl<'a> From<$ident<&'a str>> for UriError<Cow<'a, str>> {
48 fn from($ident(value): $ident<&'a str>) -> Self {
49 Self::$variant($ident(Cow::Borrowed(value)))
50 }
51 }
52
53 impl<'a> From<$ident<Vec<u8>>> for UriError<Cow<'a, [u8]>> {
54 fn from($ident(value): $ident<Vec<u8>>) -> Self {
55 Self::$variant($ident(Cow::Owned(value)))
56 }
57 }
58
59 impl<'a> From<$ident<&'a [u8]>> for UriError<Cow<'a, [u8]>> {
60 fn from($ident(value): $ident<&'a [u8]>) -> Self {
61 Self::$variant($ident(Cow::Borrowed(value)))
62 }
63 }
64 )*
65 };
66}
67
68uri_error! {
69 #[error("invalid URI: {0}")]
70 Uri: InvalidUri,
71
72 #[error("invalid URI reference: {0}")]
73 Reference: InvalidUriRef,
74
75 #[error("invalid URI scheme: {0}")]
76 Scheme: InvalidScheme,
77
78 #[error("invalid URI authority: {0}")]
79 Authority: InvalidAuthority,
80
81 #[error("invalid URI authority user info: {0}")]
82 UserInfo: InvalidUserInfo,
83
84 #[error("invalid URI authority host: {0}")]
85 Host: InvalidHost,
86
87 #[error("invalid URI authority port: {0}")]
88 Port: InvalidPort,
89
90 #[error("invalid URI path: {0}")]
91 Path: InvalidPath,
92
93 #[error("invalid URI path segment: {0}")]
94 PathSegment: InvalidSegment,
95
96 #[error("invalid URI query: {0}")]
97 Query: InvalidQuery,
98
99 #[error("invalid URI fragment: {0}")]
100 Fragment: InvalidFragment
101}
102
103#[derive(RegularGrammar)]
105#[grammar(
106 file = "src/uri/grammar.abnf",
107 entry_point = "URI",
108 ascii,
109 cache = "automata/uri.aut.cbor"
110)]
111#[grammar(sized(UriBuf, derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Hash)))]
112#[cfg_attr(feature = "serde", grammar(serde))]
113#[cfg_attr(feature = "ignore-grammars", grammar(disable))]
114pub struct Uri([u8]);
115
116impl RiRefImpl for Uri {
117 type Authority = Authority;
118 type Path = Path;
119 type Query = Query;
120 type Fragment = Fragment;
121
122 type RiRefBuf = UriRefBuf;
123
124 fn as_bytes(&self) -> &[u8] {
125 &self.0
126 }
127}
128
129impl RiImpl for Uri {}
130
131#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
132pub struct UriParts<'a> {
133 pub scheme: &'a Scheme,
134 pub authority: Option<&'a Authority>,
135 pub path: &'a Path,
136 pub query: Option<&'a Query>,
137 pub fragment: Option<&'a Fragment>,
138}
139
140impl Uri {
141 pub fn parts(&self) -> UriParts {
142 let bytes = self.as_bytes();
143 let ranges = parse::parts(bytes, 0);
144
145 UriParts {
146 scheme: unsafe { Scheme::new_unchecked(&bytes[ranges.scheme]) },
147 authority: ranges
148 .authority
149 .map(|r| unsafe { Authority::new_unchecked(&self.0[r]) }),
150 path: unsafe { Path::new_unchecked(&self.0[ranges.path]) },
151 query: ranges
152 .query
153 .map(|r| unsafe { Query::new_unchecked(&self.0[r]) }),
154 fragment: ranges
155 .fragment
156 .map(|r| unsafe { Fragment::new_unchecked(&self.0[r]) }),
157 }
158 }
159
160 pub fn as_uri_ref(&self) -> &UriRef {
164 unsafe { UriRef::new_unchecked(&self.0) }
165 }
166
167 pub fn as_iri(&self) -> &Iri {
168 unsafe { Iri::new_unchecked(std::str::from_utf8_unchecked(&self.0)) }
169 }
170
171 pub fn as_iri_ref(&self) -> &IriRef {
172 unsafe { IriRef::new_unchecked(std::str::from_utf8_unchecked(&self.0)) }
173 }
174
175 #[inline]
177 pub fn scheme(&self) -> &Scheme {
178 RiImpl::scheme(self)
179 }
180
181 pub fn authority(&self) -> Option<&Authority> {
183 RiRefImpl::authority(self)
184 }
185
186 pub fn path(&self) -> &Path {
188 RiRefImpl::path(self)
189 }
190
191 pub fn query(&self) -> Option<&Query> {
192 RiRefImpl::query(self)
193 }
194
195 pub fn fragment(&self) -> Option<&Fragment> {
196 RiRefImpl::fragment(self)
197 }
198
199 pub fn relative_to(&self, other: &(impl ?Sized + AsRef<UriRef>)) -> UriRefBuf {
213 self.as_uri_ref().relative_to(other)
214 }
215
216 #[inline]
225 pub fn suffix(
226 &self,
227 prefix: &(impl ?Sized + AsRef<Uri>),
228 ) -> Option<(PathBuf, Option<&Query>, Option<&Fragment>)> {
229 RiRefImpl::suffix(self, prefix.as_ref())
230 }
231
232 #[inline]
243 pub fn base(&self) -> &Self {
244 unsafe { Self::new_unchecked(RiRefImpl::base(self)) }
245 }
246}
247
248impl AsRef<UriRef> for Uri {
249 fn as_ref(&self) -> &UriRef {
250 self.as_uri_ref()
251 }
252}
253
254impl AsRef<Iri> for Uri {
255 fn as_ref(&self) -> &Iri {
256 self.as_iri()
257 }
258}
259
260impl AsRef<IriRef> for Uri {
261 fn as_ref(&self) -> &IriRef {
262 self.as_iri_ref()
263 }
264}
265
266impl Borrow<UriRef> for Uri {
267 fn borrow(&self) -> &UriRef {
268 self.as_uri_ref()
269 }
270}
271
272impl Borrow<Iri> for Uri {
273 fn borrow(&self) -> &Iri {
274 self.as_iri()
275 }
276}
277
278impl Borrow<IriRef> for Uri {
279 fn borrow(&self) -> &IriRef {
280 self.as_iri_ref()
281 }
282}
283
284bytestr_eq!(Uri);
285
286impl PartialEq for Uri {
287 fn eq(&self, other: &Self) -> bool {
288 self.parts() == other.parts()
289 }
290}
291
292impl<'a> PartialEq<&'a Uri> for Uri {
293 fn eq(&self, other: &&'a Self) -> bool {
294 *self == **other
295 }
296}
297
298impl PartialEq<UriBuf> for Uri {
299 fn eq(&self, other: &UriBuf) -> bool {
300 *self == *other.as_uri()
301 }
302}
303
304impl PartialEq<UriRef> for Uri {
305 fn eq(&self, other: &UriRef) -> bool {
306 *self.as_uri_ref() == *other
307 }
308}
309
310impl<'a> PartialEq<&'a UriRef> for Uri {
311 fn eq(&self, other: &&'a UriRef) -> bool {
312 *self.as_uri_ref() == **other
313 }
314}
315
316impl PartialEq<UriRefBuf> for Uri {
317 fn eq(&self, other: &UriRefBuf) -> bool {
318 *self.as_uri_ref() == *other.as_uri_ref()
319 }
320}
321
322impl Eq for Uri {}
323
324impl PartialOrd for Uri {
325 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
326 Some(self.cmp(other))
327 }
328}
329
330impl<'a> PartialOrd<&'a Uri> for Uri {
331 fn partial_cmp(&self, other: &&'a Self) -> Option<std::cmp::Ordering> {
332 self.partial_cmp(*other)
333 }
334}
335
336impl PartialOrd<UriBuf> for Uri {
337 fn partial_cmp(&self, other: &UriBuf) -> Option<std::cmp::Ordering> {
338 self.partial_cmp(other.as_uri())
339 }
340}
341
342impl PartialOrd<UriRef> for Uri {
343 fn partial_cmp(&self, other: &UriRef) -> Option<std::cmp::Ordering> {
344 self.as_uri_ref().partial_cmp(other)
345 }
346}
347
348impl<'a> PartialOrd<&'a UriRef> for Uri {
349 fn partial_cmp(&self, other: &&'a UriRef) -> Option<std::cmp::Ordering> {
350 self.as_uri_ref().partial_cmp(*other)
351 }
352}
353
354impl PartialOrd<UriRefBuf> for Uri {
355 fn partial_cmp(&self, other: &UriRefBuf) -> Option<std::cmp::Ordering> {
356 self.partial_cmp(other.as_uri_ref())
357 }
358}
359
360impl Ord for Uri {
361 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
362 self.parts().cmp(&other.parts())
363 }
364}
365
366impl Hash for Uri {
367 fn hash<H: hash::Hasher>(&self, state: &mut H) {
368 self.parts().hash(state)
369 }
370}
371
372impl RiRefImpl for UriBuf {
373 type Authority = Authority;
374 type Path = Path;
375 type Query = Query;
376 type Fragment = Fragment;
377
378 type RiRefBuf = UriRefBuf;
379
380 fn as_bytes(&self) -> &[u8] {
381 &self.0
382 }
383}
384
385impl RiImpl for UriBuf {}
386
387impl RiRefBufImpl for UriBuf {
388 type Ri = Uri;
389 type RiBuf = Self;
390
391 unsafe fn new_unchecked(bytes: Vec<u8>) -> Self {
392 Self::new_unchecked(bytes)
393 }
394
395 unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
396 &mut self.0
397 }
398
399 fn into_bytes(self) -> Vec<u8> {
400 self.0
401 }
402}
403
404impl RiBufImpl for UriBuf {}
405
406impl UriBuf {
407 pub fn from_scheme(scheme: SchemeBuf) -> Self {
408 RiBufImpl::from_scheme(scheme)
409 }
410
411 pub fn into_uri_ref(self) -> UriRefBuf {
412 unsafe { UriRefBuf::new_unchecked(self.0) }
413 }
414
415 pub fn into_iri(self) -> IriBuf {
416 unsafe { IriBuf::new_unchecked(String::from_utf8_unchecked(self.0)) }
417 }
418
419 pub fn into_iri_ref(self) -> IriRefBuf {
420 unsafe { IriRefBuf::new_unchecked(String::from_utf8_unchecked(self.0)) }
421 }
422
423 pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
431 &mut self.0
432 }
433
434 pub fn path_mut(&mut self) -> PathMut {
435 PathMut::from_impl(RiRefBufImpl::path_mut(self))
436 }
437
438 pub fn authority_mut(&mut self) -> Option<AuthorityMut> {
439 RiRefBufImpl::authority_mut(self).map(AuthorityMut::from_impl)
440 }
441
442 pub fn set_scheme(&mut self, new_scheme: &Scheme) {
455 RiBufImpl::set_scheme(self, new_scheme)
456 }
457
458 pub fn set_authority(&mut self, authority: Option<&Authority>) {
490 RiRefBufImpl::set_authority(self, authority)
491 }
492
493 pub fn set_path(&mut self, path: &Path) {
528 RiRefBufImpl::set_path(self, path)
529 }
530
531 pub fn set_query(&mut self, query: Option<&Query>) {
533 RiRefBufImpl::set_query(self, query)
534 }
535
536 pub fn set_fragment(&mut self, fragment: Option<&Fragment>) {
538 RiRefBufImpl::set_fragment(self, fragment)
539 }
540}
541
542impl AsRef<UriRef> for UriBuf {
543 fn as_ref(&self) -> &UriRef {
544 self.as_uri_ref()
545 }
546}
547
548impl AsRef<Iri> for UriBuf {
549 fn as_ref(&self) -> &Iri {
550 self.as_iri()
551 }
552}
553
554impl AsRef<IriRef> for UriBuf {
555 fn as_ref(&self) -> &IriRef {
556 self.as_iri_ref()
557 }
558}
559
560impl Borrow<UriRef> for UriBuf {
561 fn borrow(&self) -> &UriRef {
562 self.as_uri_ref()
563 }
564}
565
566impl Borrow<Iri> for UriBuf {
567 fn borrow(&self) -> &Iri {
568 self.as_iri()
569 }
570}
571
572impl Borrow<IriRef> for UriBuf {
573 fn borrow(&self) -> &IriRef {
574 self.as_iri_ref()
575 }
576}
577
578impl From<UriBuf> for UriRefBuf {
579 fn from(value: UriBuf) -> Self {
580 value.into_uri_ref()
581 }
582}
583
584bytestr_eq!(UriBuf);
585
586impl PartialEq<UriRef> for UriBuf {
587 fn eq(&self, other: &UriRef) -> bool {
588 *self.as_uri_ref() == *other
589 }
590}
591
592impl<'a> PartialEq<&'a UriRef> for UriBuf {
593 fn eq(&self, other: &&'a UriRef) -> bool {
594 *self.as_uri_ref() == **other
595 }
596}
597
598impl PartialEq<UriRefBuf> for UriBuf {
599 fn eq(&self, other: &UriRefBuf) -> bool {
600 *self.as_uri_ref() == *other.as_uri_ref()
601 }
602}
603
604impl PartialOrd<UriRef> for UriBuf {
605 fn partial_cmp(&self, other: &UriRef) -> Option<std::cmp::Ordering> {
606 self.as_uri_ref().partial_cmp(other)
607 }
608}
609
610impl<'a> PartialOrd<&'a UriRef> for UriBuf {
611 fn partial_cmp(&self, other: &&'a UriRef) -> Option<std::cmp::Ordering> {
612 self.as_uri_ref().partial_cmp(*other)
613 }
614}
615
616impl PartialOrd<UriRefBuf> for UriBuf {
617 fn partial_cmp(&self, other: &UriRefBuf) -> Option<std::cmp::Ordering> {
618 self.as_uri_ref().partial_cmp(other.as_uri_ref())
619 }
620}