async_coap_uri/lib.rs
1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16//! # Safe, In-place URI Abstraction
17//!
18//! This crate provides safe, efficient, full-featured support for using and manipulating
19//! [Uniform Resource Identifiers][IETF-RFC3986].
20//!
21//! What makes this crate unique is that it provides URI-specific types that have the same
22//! unsized/sized[^1] type duality that is used for [`&str`]/[`String`], except with specific
23//! guarantees on the content, as well as convenient domain-specific methods to access the
24//! URI components. The API was designed to be easy-to-use while making as few
25//! heap allocations as possible. Most common operations require no allocations at all,
26//! and those that do are provided as a convenience rather than a fundamental requirement.
27//! For example, you can parse and fully percent-decode a URI without doing a single allocation.
28//!
29//! Similar to how you can specify a [`&'static str`](str) inline as a *string literal*,
30//! you can specify in-line "URI literals" that are checked for well-formedness at compile
31//! time.
32//!
33//! ## Important Types
34//!
35//! This crate provides three fundamental types named after their [IETF-RFC3986] counterparts:
36//!
37//! [**URI-references**][URI-reference] are contained in the unsized string slice
38//! subtype [`&UriRef`] ,with [`UriRefBuf`] being the sized, heap-allocated version. This
39//! is the most flexible and commonly used type, since it can contain either a [URI]
40//! (like "`http://example.com/`") or a [relative-reference] (Like "`/a/b/c?q=foo`").
41//! URI-reference literals for this type can be created using the [`uri_ref!`] macro.
42//!
43//! Actual full [**URIs**][URI] (like "`http://example.com/`") can be contained in the unsized
44//! string slice subtype [`&Uri`] ,with [`UriBuf`] being the sized, heap-allocated version.
45//! This type is less flexible than [`UriRef`] because it cannot hold a [relative-reference]:
46//! if you have a `&Uri`, you are guaranteed that it does not contain a [relative-reference].
47//! URI literals for this type can be created using the [`uri!`] macro.
48//!
49//! [**Relative-references**][relative-reference] (Like "`/a/b/c?q=foo`") are contained in the
50//! unsized string slice
51//! subtype [`&RelRef`] ,with [`RelRefBuf`] being the sized, heap-allocated version.
52//! This type is less flexible than [`UriRef`] because it cannot hold a full [URI].
53//! If you have a `&RelRef`, you are guaranteed that it can only contain a *path*, *query*,
54//! and/or *fragment*.
55//! Relative-reference literals for this type can be created using the [`rel_ref!`] macro.
56//!
57//! Each type above provides methods for accessing the individual URI components in both
58//! raw and percent-decoded form. Additionally, they also provide iterator accessors for
59//! parsing path segments and query items—again both in raw and percent-decoded forms.
60//!
61//! In some cases it can be more efficient to pre-compute the offsets of all of the URI components
62//! rather than recalculate them individually, as the methods on the above types do.
63//! For such cases, [`UriRawComponents`] pre-computes each component of the URI internally,
64//! allowing for more efficient repeated access. The type uses no memory allocations and is
65//! scoped to the lifetime of the type that was used to create it.
66//!
67//! A common trait—[`AnyUriRef`]—for all of these types (Including [`UriRawComponents`]) is
68//! provided to make usage in generic contexts easier by allowing you to pass a borrowed reference
69//! to of the above types as an argument.
70//!
71//! ## Network Path Support
72//!
73//! This crate aims for complete [IETF-RFC3986] compliance while still being fast and efficient,
74//! but there is one part where it deviates very slightly: *network paths*.
75//!
76//! A network path is essentially a full URI without a **scheme**, *but with an* **authority**.
77//! For example, `//example.com/a/b/c?q=123#body` is a *network path*.
78//!
79//! According to [IETF-RFC3986] section 4.2, network paths are *relative-references*.
80//! However, this crate considers them to belong to
81//! [`&Uri`]/[`UriBuf`], not [`&RelRef`]/[`RelRefBuf`] as IETF-RFC3986 would imply.
82//! This was done to simplify typical usage patterns by guaranteeing that a
83//! [`&RelRef`]/[`RelRefBuf`] will never have a scheme or an authority component.
84//!
85//! ## Casting and Deref
86//!
87//! [`UriRef`] implements [`Deref<Target=str>`], allowing you to use all of the
88//! non-mutating methods from [`str`], like [`len()`]. as well as create new string slices using
89//! the `[begin..end]` syntax. A [`&UriRef`] can be cast to a [`&str`] for free via the method
90//! [`UriRef.as_str()`].
91//!
92//! [`Uri`] implements [`Deref<Target=UriRef>`], allowing you to use a [`&Uri`]
93//! anywhere a [`&UriRef`] is called for, and since [`UriRef`] implements [`Deref<Target=str>`],
94//! you can also use all of the [`str`] methods, too. A [`&Uri`] can be cast to a [`&UriRef`] for
95//! free via the method [`Uri.as_uri_ref()`], and likewise to a [`&str`] via the method [`Uri.as_str()`].
96//!
97//! You might think that [`RelRef`] would implement [`Deref<Target=UriRef>`], too, but this actually
98//! isn't safe. So while there is a [`RelRef.as_uri_ref()`], it returns a `Cow<UriRef>` instead of
99//! a [`&UriRef`]. For more information, see [this section](struct.RelRef.html#relref-and-deref).
100//!
101//! ## URI "Literals"
102//!
103//! For cases where you need a URI "literal", you can use the [`uri_ref!`], [`rel_ref!`],
104//! and/or [`uri!`] macros:
105//!
106//! ```
107//! use async_coap_uri::prelude::*;
108//!
109//! let uri: &Uri = uri!("http://example.com/foo/bar/");
110//! let (abs_part, rel_part) = uri.split();
111//!
112//! assert_eq!(uri!("http://example.com"), abs_part);
113//! assert_eq!(rel_ref!("/foo/bar/"), rel_part);
114//! ```
115//!
116//! These "literals" are checked for correctness at compile time:
117//!
118//! ```compile_fail
119//! # use async_coap_uri::prelude::*;
120//! // This will not compile.
121//! let x = uri!("%00 invalid %ff");
122//! ```
123//!
124//! [^1]: This unsized/sized pattern is useful because there are often cases where you would want to have
125//! a method or function take a URI as an argument. If you just passed a `&str` or a [`String`],
126//! you would need to verify that the URI was well-formed each time the method or function was
127//! called. You could fix this by creating a wrapper struct (something like `UriRef(String)`,
128//! which is similar to [rust-url](https://docs.rs/url/2.0.0/src/url/lib.rs.html#162) does it),
129//! but this requires the use of alloc and is inefficient in many cases, so this crate uses the
130//! unsized/sized pattern.
131//!
132//! [IETF-RFC3986]: https://tools.ietf.org/html/rfc3986
133//! [URI-reference]: https://tools.ietf.org/html/rfc3986#section-4.1
134//! [relative-reference]: https://tools.ietf.org/html/rfc3986#section-4.2
135//! [URI]: https://tools.ietf.org/html/rfc3986#section-3
136//! [`UriRef.as_str()`]: struct.UriRef.html#method.as_str
137//! [`RelRef.as_uri_ref()`]: struct.RelRef.html#method.as_uri
138//! [`Uri.as_uri_ref()`]: struct.Uri.html#method.as_uri
139//! [`Uri.as_str()`]: struct.Uri.html#method.as_str
140//! [`&Uri`]: Uri
141//! [`&RelRef`]: RelRef
142//! [`&UriRef`]: UriRef
143//! [`&str`]: str
144//! [`Deref<Target=str>`]: core::ops::Deref
145//! [`Deref<Target=UriRef>`]: core::ops::Deref
146//! [`len()`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.len
147//! [`&Path`]: std::path::Path
148//! [`PathBuf`]: std::path::PathBuf
149//! [`&OsStr`]: std::ffi::OsStr
150//! [`OsString`]: std::ffi::OsString
151//!
152
153#![warn(missing_docs)]
154#![warn(missing_debug_implementations)]
155#![warn(rust_2018_idioms)]
156#![warn(clippy::all)]
157#![cfg_attr(not(feature = "std"), no_std)]
158
159#[cfg(feature = "std")]
160#[macro_use]
161extern crate lazy_static;
162
163pub mod escape;
164use escape::*;
165
166mod uri_ref;
167pub use uri_ref::UriRef;
168
169#[cfg(feature = "std")]
170mod uri_ref_buf;
171#[cfg(feature = "std")]
172pub use uri_ref_buf::UriRefBuf;
173
174mod uri_raw_components;
175pub use uri_raw_components::UriRawComponents;
176
177mod rel_ref;
178pub use rel_ref::RelRef;
179
180mod uri;
181pub use uri::Uri;
182
183mod uri_type;
184pub use uri_type::UriType;
185
186mod any_uri_ref;
187pub use any_uri_ref::AnyUriRef;
188pub use any_uri_ref::UriDisplay;
189
190mod error;
191pub use error::{ParseError, ResolveError};
192
193#[cfg(feature = "std")]
194mod rel_ref_buf;
195#[cfg(feature = "std")]
196pub use rel_ref_buf::RelRefBuf;
197
198#[cfg(feature = "std")]
199mod uri_buf;
200#[cfg(feature = "std")]
201pub use uri_buf::UriBuf;
202
203#[cfg(feature = "std")]
204mod uri_unescape_buf;
205#[cfg(feature = "std")]
206pub use uri_unescape_buf::UriUnescapeBuf;
207
208#[cfg(feature = "std")]
209mod regexes;
210#[cfg(feature = "std")]
211pub(crate) use regexes::*;
212
213#[cfg(test)]
214mod test;
215
216#[doc(hidden)]
217pub mod macros;
218
219#[cfg(feature = "std")]
220use std::borrow::Cow;
221
222/// Convenience type for `Cow<'a, Uri>`.
223#[cfg(feature = "std")]
224pub type UriCow<'a> = Cow<'a, Uri>;
225
226/// Convenience type for `Cow<'a, UriRef>`.
227#[cfg(feature = "std")]
228pub type UriRefCow<'a> = Cow<'a, UriRef>;
229
230/// Convenience type for `Cow<'a, RelRef>`.
231#[cfg(feature = "std")]
232pub type RelRefCow<'a> = Cow<'a, RelRef>;
233
234use proc_macro_hack::proc_macro_hack;
235
236/// Used by the `uri` macro to verify correctness at compile-time.
237#[doc(hidden)]
238#[proc_macro_hack]
239pub use async_coap_uri_macros::assert_uri_literal;
240
241/// Used by the `uri_ref` macro to verify correctness at compile-time.
242#[doc(hidden)]
243#[proc_macro_hack]
244pub use async_coap_uri_macros::assert_uri_ref_literal;
245
246/// Used by the `rel_ref` macro to verify correctness at compile-time.
247#[doc(hidden)]
248#[proc_macro_hack]
249pub use async_coap_uri_macros::assert_rel_ref_literal;
250
251#[doc(hidden)]
252pub mod prelude {
253 pub use super::escape::StrExt;
254 pub use super::AnyUriRef;
255 pub use super::UriRawComponents;
256 pub use super::{rel_ref, uri, uri_ref};
257 pub use super::{RelRef, Uri, UriRef};
258
259 pub use {assert_rel_ref_literal, assert_uri_literal, assert_uri_ref_literal};
260
261 #[cfg(feature = "std")]
262 pub use super::{RelRefBuf, UriBuf, UriRefBuf};
263
264 #[cfg(feature = "std")]
265 pub use super::{RelRefCow, UriCow, UriRefCow};
266
267 #[cfg(feature = "std")]
268 pub use super::{rel_ref_format, uri_format, uri_ref_format};
269}