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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
use rhai::plugin::*;
use rhai::{EvalAltResult, ImmutableString};
#[export_module]
pub mod url_module {
use url::Url;
/// Creates a new Url.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/")
/// ```
#[rhai_fn(name = "Url", return_raw)]
pub fn new(url: &str) -> Result<Url, Box<EvalAltResult>> {
Url::parse(url).map_err(|e| Box::<EvalAltResult>::from(e.to_string()))
}
/// Gets the full Url, same as to_string().
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/")
/// let fullUrl = url.href // 'http://test.dev/'
/// ```
#[rhai_fn(global, get = "href", pure)]
pub fn href(url: &mut Url) -> ImmutableString {
url.to_string().into()
}
/// Gets the Url scheme such as 'http' or 'https'.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/")
/// let scheme = url.scheme // 'http'
/// ```
#[rhai_fn(global, get = "scheme", pure)]
pub fn scheme(url: &mut Url) -> ImmutableString {
url.scheme().into()
}
/// Sets the Url scheme.
///
/// Be aware as this method will refuse to change the scheme under the following circumstances:
///
/// * If the new scheme is not in `[a-zA-Z][a-zA-Z0-9+.-]+`
/// * If this URL is cannot-be-a-base and the new scheme is one of
/// `http`, `https`, `ws`, `wss` or `ftp`
/// * If either the old or new scheme is `http`, `https`, `ws`,
/// `wss` or `ftp` and the other is not one of these
/// * If the new scheme is `file` and this URL includes credentials
/// or has a non-null port
/// * If this URL's scheme is `file` and its host is empty or null
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/")
/// url.scheme = "https"
///
/// let scheme = url.scheme // 'https'
/// let fullUrl = url.href // 'https://test.dev/'
/// ```
#[rhai_fn(global, set = "scheme", pure)]
pub fn set_scheme(url: &mut Url, value: &str) {
_ = url.set_scheme(value);
}
/// Gets the Url domain.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/")
/// let domain = url.domain // 'test.dev'
/// ```
#[rhai_fn(global, get = "domain", pure)]
pub fn domain(url: &mut Url) -> ImmutableString {
url.domain().unwrap_or("").into()
}
/// Gets the Url path.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/path")
/// let path = url.path // '/path'
/// ```
#[rhai_fn(global, get = "path", pure)]
pub fn path(url: &mut Url) -> ImmutableString {
url.path().into()
}
/// Sets the Url path.
#[rhai_fn(global, set = "path", pure)]
pub fn set_path(url: &mut Url, value: &str) {
url.set_path(value)
}
/// Gets the Url query string.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?page=2")
/// let query = url.query // 'page=2'
/// ```
#[rhai_fn(global, get = "query", pure)]
pub fn query(url: &mut Url) -> ImmutableString {
url.query().unwrap_or("").into()
}
/// Sets the Url query string.
#[rhai_fn(global, set = "query", pure)]
pub fn set_query(url: &mut Url, value: &str) {
if value.len() > 0 {
url.set_query(Some(value))
} else {
url.set_query(None)
}
}
/// Sets the Url query string.
#[rhai_fn(global, set = "query", pure)]
pub fn set_query_option(url: &mut Url, value: Option<&str>) {
match value {
Some(value) => url.set_query(Some(value)),
None => url.set_query(None),
}
}
/// Gets the Url fragment.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?#row=4")
/// let fragment = url.fragment // 'row=4'
/// ```
#[rhai_fn(global, get = "fragment", pure)]
pub fn fragment(url: &mut Url) -> ImmutableString {
url.fragment().unwrap_or("").into()
}
/// Sets the Url fragment.
#[rhai_fn(global, set = "fragment", pure)]
pub fn set_fragment(url: &mut Url, value: &str) {
if value.len() > 0 {
url.set_fragment(Some(value))
} else {
url.set_fragment(None)
}
}
/// Sets the Url fragment.
#[rhai_fn(global, set = "fragment", pure)]
pub fn set_fragment_option(url: &mut Url, value: Option<&str>) {
match value {
Some(value) => url.set_fragment(Some(value)),
None => url.set_query(None),
}
}
/// Gets the Url hash, alias of fragment.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?#row=4");
/// let hash = url.hash; // 'row=4'
/// ```
#[rhai_fn(global, get = "hash", pure)]
pub fn hash(url: &mut Url) -> ImmutableString {
url.fragment().unwrap_or("").into()
}
/// Sets the Url hash.
#[rhai_fn(global, set = "hash", pure)]
pub fn set_hash(url: &mut Url, value: &str) {
if value.len() > 0 {
url.set_fragment(Some(value))
} else {
url.set_fragment(None)
}
}
/// Sets the Url hash.
#[rhai_fn(global, set = "hash", pure)]
pub fn set_hash_option(url: &mut Url, value: Option<&str>) {
match value {
Some(value) => url.set_fragment(Some(value)),
None => url.set_query(None),
}
}
/*************************************************************
* Functions
************************************************************/
#[rhai_fn(
global,
name = "query_clear",
name = "query_delete",
name = "query_remove",
pure
)]
/// Clear the query string.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?q=query&b=1");
///
/// url.query_clear();
///
/// url == "http://test.dev/"
/// ```
pub fn query_clear(url: &mut Url) {
url.set_query(None)
}
/// Delete a key from the query
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?q=query&b=1");
///
/// url.query_delete("q"); // or
/// url.query_remove("q");
///
/// url == "http://test.dev/?b=1"
/// ```
#[rhai_fn(global, name = "query_delete", name = "query_remove", pure)]
pub fn query_delete(url: &mut Url, key: &str) {
let query: Vec<(String, String)> = url
.query_pairs()
.filter(|(name, _)| name != key)
.map(|(name, value)| (name.into_owned(), value.into_owned()))
.collect();
url.query_pairs_mut().clear().extend_pairs(&query);
// cleanup
if let Some(q) = url.query() {
if q.len() == 0 {
url.set_query(None)
}
}
}
#[rhai_fn(global, name = "query_append", pure)]
pub fn query_append(url: &mut Url, key: &str, value: &str) {
url.query_pairs_mut().append_pair(key, value);
}
/// Sets a query key
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?q=query&b=1");
///
/// url.query_set("q", "new-query"); // or
/// url.query_remove("q");
///
/// url == "http://test.dev/?q=new-query&b=1"
/// ```
#[rhai_fn(global, name = "query_set", pure)]
pub fn query_set(url: &mut Url, key: &str, value: &str) {
query_delete(url, key);
query_append(url, key, value);
}
/// Gets a query value for the specified key, it will return the first value found
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?q=query&b=1");
///
/// url.query_get("q"); // "query"
/// url.query_get("b"); // "1"
/// ```
#[rhai_fn(global, name = "query_get", pure)]
pub fn query_get(url: &mut Url, key: &str) -> ImmutableString {
match url.query_pairs().find(|(name, _)| name == key) {
Some((_, value)) => ImmutableString::from(value.as_ref()),
None => ImmutableString::from(""),
}
}
/// Gets a list of values for the specified key
///
/// Not available under `no_index`.
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/?q=query&q=second-query");
///
/// url.query_get("q"); // ["query", "second-query"]
/// ```
#[cfg(feature = "array")]
#[rhai_fn(global, name = "query_gets", name = "query_getAll", pure)]
pub fn query_gets(url: &mut Url, key: &str) -> rhai::Array {
url.query_pairs()
.filter(|(name, _)| name == key)
.map(|(_, value)| ImmutableString::from(value.as_ref()).into())
.collect()
}
/// Get the absolute url as a string
///
/// ### Example
///
/// ```js
/// let url = Url("http://test.dev/path");
///
/// url.to_string(); // "http://test.dev/path"
/// url.to_debug(); // "http://test.dev/path"
/// ```
#[rhai_fn(global, name = "to_string", name = "to_debug", pure)]
pub fn to_string(url: &mut Url) -> ImmutableString {
url.to_string().into()
}
}