iri_string/types.rs
1//! URI and IRI types.
2//!
3//! # URI and IRI
4//!
5//! IRIs (Internationalized Resource Identifiers) are defined in [RFC 3987],
6//! and URIs (Uniform Resource Identifiers) are defined in [RFC 3986].
7//!
8//! URI consists of only ASCII characters, and is a subset of IRI.
9//!
10//! IRIs are defined as below:
11//!
12//! ```text
13//! IRI = scheme ":" ihier-part [ "?" iquery ] [ "#" ifragment ]
14//! IRI-reference = IRI / irelative-ref
15//! absolute-IRI = scheme ":" ihier-part [ "?" iquery ]
16//! irelative-ref = irelative-part [ "?" iquery ] [ "#" ifragment ]
17//! (`irelative-part` is roughly same as `ihier-part`.)
18//! ```
19//!
20//! Definitions for URIs are almost same, but they cannot have non-ASCII characters.
21//!
22//! # Types
23//!
24//! Types can be categorized by:
25//!
26//! * syntax,
27//! * spec, and
28//! * ownership.
29//!
30//! ## Syntax
31//!
32//! Since URIs and IRIs have almost same syntax and share algorithms, they are implemented by
33//! generic types.
34//!
35//! * [`RiStr`] and [`RiString`]
36//! + String types for `IRI` and `URI` rules.
37//! * [`RiAbsoluteStr`] and [`RiAbsoluteString`]
38//! + String types for `absolute-IRI` and `absolute-URI` rules.
39//! * [`RiReferenceStr`] and [`RiReferenceString`]
40//! + String types for `IRI-reference` and `URI-reference` rules.
41//! * [`RiRelativeStr`] and [`RiRelativeString`]
42//! + String types for `irelative-ref` and `relative-ref` rules.
43//! * [`RiFragmentStr`] and [`RiFragmentString`]
44//! + String types for `ifragment` and `fragment` rules.
45//! + Note that these types represents a substring of an IRI / URI references.
46//! They are not intended to used directly as an IRI / URI references.
47//!
48//! "Ri" stands for "Resource Identifier".
49//!
50//! ## Spec
51//!
52//! These types have a type parameter, which represents RFC specification.
53//! [`IriSpec`] represents [RFC 3987] spec, and [`UriSpec`] represents [RFC 3986] spec.
54//! For example, `RiAbsoluteStr<IriSpec>` can have `absolute-IRI` string value,
55//! and `RiReferenceStr<UriSpec>` can have `URI-reference` string value.
56//!
57//! ## Ownership
58//!
59//! String-like types have usually two variations, borrowed and owned.
60//!
61//! Borrowed types (such as `str`, `Path`, `OsStr`) are unsized, and used by reference style.
62//! Owned types (such as `String`, `PathBuf`, `OsString`) are sized, and requires heap allocation.
63//! Owned types can be coerced to a borrowed type (for example, `&String` is automatically coerced
64//! to `&str` in many context).
65//!
66//! IRI / URI types have same variations, `RiFooStr` and `RiFooString`
67//! (`Foo` part represents syntax).
68//! They are very similar to `&str` and `String`.
69//! `Deref` is implemented, `RiFooStr::len()` is available, `&RiFooString` can be coerced to
70//! `&RiFooStr`, `Cow<'_, RiFooStr>` and `Box<RiFooStr>` is available, and so on.
71//!
72//! # Hierarchy and safe conversion
73//!
74//! IRI syntaxes have the hierarchy below.
75//!
76//! ```text
77//! RiReferenceStr
78//! |-- RiStr
79//! | `-- RiAbsoluteStr
80//! `-- RiRelativeStr
81//! ```
82//!
83//! Therefore, the conversions below are safe and cheap:
84//!
85//! * `RiStr -> RiReferenceStr`
86//! * `RiAbsoluteStr -> RiStr`
87//! * `RiAbsoluteStr -> RiReferenceStr`
88//! * `RiRelativeStr -> RiReferenceStr`
89//!
90//! For safely convertible types (consider `FooStr -> BarStr` is safe), traits
91//! below are implemented:
92//!
93//! * `AsRef<BarStr> for FooStr`
94//! * `AsRef<BarStr> for FooString`
95//! * `From<FooString> for BarString`
96//! * `PartialEq<FooStr> for BarStr`, and lots of impls like that
97//! + `PartialEq` and `ParitalOrd`.
98//! + Slice, owned, `Cow`, reference, etc...
99//!
100//! ## Fallible conversions
101//!
102//! Fallible conversions are implemented from plain string into IRI strings.
103//!
104//! * `TryFrom<&str> for &FooStr`
105//! * `TryFrom<&str> for FooString`
106//! * `TryFrom<String> for FooString`
107//! * `FromStr for FooString`
108//!
109//! Some IRI string types provide more convenient methods to convert between IRI types.
110//! For example, [`RiReferenceString::into_iri()`] tries to convert an IRI reference into an IRI,
111//! and returns `Result<IriString, IriRelativeString>`.
112//! This is because an IRI reference is valid as an IRI or a relative IRI reference.
113//! Such methods are usually more efficient than using `TryFrom` for plain strings, because they
114//! prevents you from losing ownership of a string, and does a conversion without extra memory
115//! allocation.
116//!
117//! # Aliases
118//!
119//! This module contains type aliases for RFC 3986 URI types and RFC 3987 IRI types.
120//!
121//! `IriFooStr{,ing}` are aliases of `RiFooStr{,ing}<IriSpec>`, and `UriFooStr{,ing}` are aliases
122//! of `RiFooStr{,ing}<UriSpec>`.
123//!
124//! # Wrapped string types
125//!
126//! Similar to string types in std (such as `str`, `std::path::Path`, and `std::ffi::OsStr`),
127//! IRI string types in this crate provides convenient conversions to:
128//!
129//! * `std::box::Box`,
130//! * `std::borrow::Cow`,
131//! * `std::rc::Rc`, and
132//! * `std::sync::Arc`.
133//!
134//! ```
135//! # use iri_string::validate::Error;
136//! # #[cfg(feature = "std")] {
137//! use std::borrow::Cow;
138//! use std::rc::Rc;
139//! use std::sync::Arc;
140//!
141//! use iri_string::types::IriStr;
142//!
143//! let iri = IriStr::new("http://example.com/")?;
144//! let iri_owned = iri.to_owned();
145//!
146//! // From slice.
147//! let cow_1_1: Cow<'_, IriStr> = iri.into();
148//! let cow_1_2 = Cow::<'_, IriStr>::from(iri);
149//! assert!(matches!(cow_1_1, Cow::Borrowed(_)));
150//! assert!(matches!(cow_1_2, Cow::Borrowed(_)));
151//! // From owned.
152//! let cow_2_1: Cow<'_, IriStr> = iri_owned.clone().into();
153//! let cow_2_2 = Cow::<'_, IriStr>::from(iri_owned.clone());
154//! assert!(matches!(cow_2_1, Cow::Owned(_)));
155//! assert!(matches!(cow_2_2, Cow::Owned(_)));
156//!
157//! // From slice.
158//! let box_1_1: Box<IriStr> = iri.into();
159//! let box_1_2 = Box::<IriStr>::from(iri);
160//! // From owned.
161//! let box_2_1: Box<IriStr> = iri_owned.clone().into();
162//! let box_2_2 = Box::<IriStr>::from(iri_owned.clone());
163//!
164//! // From slice.
165//! let rc_1_1: Rc<IriStr> = iri.into();
166//! let rc_1_2 = Rc::<IriStr>::from(iri);
167//! // From owned.
168//! // Note that `From<owned> for Rc<borrowed>` is not implemented for now.
169//! // Get borrowed string by `.as_slice()` and convert it.
170//! let rc_2_1: Rc<IriStr> = iri_owned.clone().as_slice().into();
171//! let rc_2_2 = Rc::<IriStr>::from(iri_owned.clone().as_slice());
172//!
173//! // From slice.
174//! let arc_1_1: Arc<IriStr> = iri.into();
175//! let arc_1_2 = Arc::<IriStr>::from(iri);
176//! // From owned.
177//! // Note that `From<owned> for Arc<borrowed>` is not implemented for now.
178//! // Get borrowed string by `.as_slice()` and convert it.
179//! let arc_2_1: Arc<IriStr> = iri_owned.clone().as_slice().into();
180//! let arc_2_2 = Arc::<IriStr>::from(iri_owned.clone().as_slice());
181//! # }
182//! # Ok::<_, Error>(())
183//! ```
184//!
185//! [RFC 3986]: https://tools.ietf.org/html/rfc3986
186//! [RFC 3987]: https://tools.ietf.org/html/rfc3987
187//! [`RiStr`]: struct.RiStr.html
188//! [`RiString`]: struct.RiString.html
189//! [`RiAbsoluteStr`]: struct.RiAbsoluteStr.html
190//! [`RiAbsoluteString`]: struct.RiAbsoluteString.html
191//! [`RiFragmentStr`]: struct.RiFragmentStr.html
192//! [`RiFragmentString`]: struct.RiFragmentString.html
193//! [`RiReferenceStr`]: struct.RiReferenceStr.html
194//! [`RiReferenceString`]: struct.RiReferenceString.html
195//! [`RiReferenceString::into_iri()`]: struct.RiReferenceString.html#method.into_iri
196//! [`RiRelativeStr`]: struct.RiRelativeStr.html
197//! [`RiRelativeString`]: struct.RiRelativeString.html
198//! [`IriSpec`]: ../spec/enum.IriSpec.html
199//! [`UriSpec`]: ../spec/enum.UriSpec.html
200
201#[cfg(feature = "alloc")]
202pub use self::{
203 generic::{
204 CreationError, RiAbsoluteString, RiFragmentString, RiQueryString, RiReferenceString,
205 RiRelativeString, RiString,
206 },
207 iri::{
208 IriAbsoluteString, IriFragmentString, IriQueryString, IriReferenceString,
209 IriRelativeString, IriString,
210 },
211 uri::{
212 UriAbsoluteString, UriFragmentString, UriQueryString, UriReferenceString,
213 UriRelativeString, UriString,
214 },
215};
216pub use self::{
217 generic::{RiAbsoluteStr, RiFragmentStr, RiQueryStr, RiReferenceStr, RiRelativeStr, RiStr},
218 iri::{IriAbsoluteStr, IriFragmentStr, IriQueryStr, IriReferenceStr, IriRelativeStr, IriStr},
219 uri::{UriAbsoluteStr, UriFragmentStr, UriQueryStr, UriReferenceStr, UriRelativeStr, UriStr},
220};
221
222pub(crate) mod generic;
223mod iri;
224mod uri;