1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! Generic resource identifier types.
//!
//! ```text
//! IRI = scheme ":" ihier-part [ "?" iquery ] [ "#" ifragment ]
//! IRI-reference = IRI / irelative-ref
//! absolute-IRI = scheme ":" ihier-part [ "?" iquery ]
//! irelative-ref = irelative-part [ "?" iquery ] [ "#" ifragment ]
//! (`irelative-part` is roughly same as `ihier-part`.)
//! ```
//!
//! Hierarchy:
//!
//! ```text
//! RiReferenceStr
//! |-- RiStr
//! | `-- RiAbsoluteStr
//! `-- RiRelativeStr
//! ```
//!
//! Therefore, the conversions below are safe and cheap:
//!
//! * `RiStr -> RiReferenceStr`
//! * `RiAbsoluteStr -> RiStr`
//! * `RiAbsoluteStr -> RiReferenceStr`
//! * `RiRelativeStr -> RiReferenceStr`
//!
//! For safely convertible types (consider `FooStr -> BarStr` is safe), traits
//! below are implemented:
//!
//! * `AsRef<BarStr> for FooStr`
//! * `AsRef<BarStr> for FooString`
//! * `From<FooString> for BarString`
//! * `PartialEq<FooStr> for BarStr` and lots of impls like that
//! + `PartialEq` and `ParitalOrd`.
//! + Slice, owned, `Cow`, reference, etc...
//!
//! # IDNA encoding
//!
//! This crate does not have built-in IDNA converter, but the user can provide
//! such conversion function and replace the domain part of IRIs.
//!
//! ## Slice IRI types
//!
//! 1. Get host by `authority_components()?.host()`.
//! 2. Process the name.
//! 3. Create a builder by `Builder::from(&...)`.
//! 4. Overwrite the domain by `.host(...)`.
//! 5. Build the new IRI by `.build()`.
//!
//! ```
//! # #[cfg(feature = "alloc")] extern crate alloc;
//! # #[cfg(feature = "alloc")] use alloc::string::ToString;
//! use iri_string::build::Builder;
//! use iri_string::types::{IriStr, UriStr};
//!
//! struct IdnaEncodedDomain<'a> {
//! /* ... */
//! # raw: &'a str,
//! }
//! impl IdnaEncodedDomain<'_> {
//! pub fn as_str(&self) -> &str {
//! /* ... */
//! # match self.raw {
//! # "alpha.\u{03B1}.example.com" => "alpha.xn--mxa.example.com",
//! # _ => unimplemented!(),
//! # }
//! }
//! }
//! // Usually IDNA conversion requires dynamic memory allocation, but
//! // `iri-string` itself does not require or assume that. It is enough if the
//! // conversion result can be retrieved as `&str`, so users can do whatever
//! // such as limiting the possible input and/or using statically allocated buffer.
//! fn apply_idna(s: &str) -> IdnaEncodedDomain<'_> {
//! /* ... */
//! # IdnaEncodedDomain { raw: s }
//! }
//!
//! let orig_iri = IriStr::new("https://alpha.\u{03B1}.example.com").unwrap();
//!
//! // 1. Get the host.
//! let orig_host = orig_iri.authority_components()
//! .expect("orig_iri has a host")
//! .host();
//! debug_assert_eq!(orig_host, "alpha.\u{03B1}.example.com");
//!
//! // 2. Process the name.
//! let new_domain = apply_idna(orig_host);
//!
//! // 3. Create a builder.
//! let mut builder = Builder::from(orig_iri);
//!
//! // 4. Overwrite the domain.
//! builder.host(new_domain.as_str());
//!
//! // 5. Build the new IRI.
//! let new_iri = builder.build::<UriStr>()
//! .expect("the new host is a valid domain and now they are US-ASCII only");
//!
//! // Note that `ToString::to_string()` requires `alloc` feature.
//! #[cfg(feature = "alloc")]
//! debug_assert_eq!(new_iri.to_string(), "https://alpha.xn--mxa.example.com");
//! ```
//!
//! ## Allocated IRI types
//!
//! For allocated types such as `IriString`, you can use
//! `{,try_}replace_host{,_reg_name}` methods.
//!
//! 1. Get host by `authority_components()?.host()`.
//! 2. Process the name.
//! 3. Replace the host by the new result.
//!
//! ```
//! # #[cfg(feature = "alloc")] {
//! # extern crate alloc;
//! # use alloc::string::String;
//! use iri_string::types::IriString;
//!
//! fn apply_idna(s: &str) -> String {
//! /* ... */
//! # match s {
//! # "alpha.\u{03B1}.example.com" => "alpha.xn--mxa.example.com".to_owned(),
//! # _ => unimplemented!(),
//! # }
//! }
//!
//! let mut iri =
//! IriString::try_from("https://alpha.\u{03B1}.example.com")
//! .unwrap();
//!
//! // 1. Get the host.
//! let orig_host = iri.authority_components()
//! .expect("orig_iri has a host")
//! .host();
//! debug_assert_eq!(orig_host, "alpha.\u{03B1}.example.com");
//!
//! // 2. Process the name.
//! let new_domain = apply_idna(orig_host);
//!
//! // 3. Replace the host.
//! iri.replace_host(&new_domain);
//! debug_assert_eq!(iri, "https://alpha.xn--mxa.example.com");
//! # }
//! ```
pub use ;
pub use ;
/// Replaces the host in-place and returns the range of the new host, if authority is not empty.
///
/// If the IRI has no authority, returns `None` without doing nothing. Note
/// that an empty host is distinguished from the absence of an authority.
///
/// If the new host is invalid (i.e., [`validate::validate_host`][`crate::validate::host`]
/// returns `Err(_)`), also returns `None` without doing anything.