http_req/
uri.rs

1//! uri operations
2use crate::error::{Error, ParseErr};
3use std::{
4    convert::TryFrom,
5    fmt,
6    ops::{Index, Range},
7    str,
8    string::ToString,
9};
10
11const HTTP_PORT: u16 = 80;
12const HTTPS_PORT: u16 = 443;
13
14///A (half-open) range bounded inclusively below and exclusively above (start..end) with `Copy`.
15#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
16pub struct RangeC {
17    pub start: usize,
18    pub end: usize,
19}
20
21impl RangeC {
22    ///Creates new `RangeC` with `start` and `end`.
23    ///
24    ///# Exmaples
25    ///```
26    ///use http_req::uri::RangeC;
27    ///
28    ///const range: RangeC = RangeC::new(0, 20);
29    ///```
30    pub const fn new(start: usize, end: usize) -> RangeC {
31        RangeC { start, end }
32    }
33}
34
35impl From<RangeC> for Range<usize> {
36    fn from(range: RangeC) -> Range<usize> {
37        Range {
38            start: range.start,
39            end: range.end,
40        }
41    }
42}
43
44impl Index<RangeC> for str {
45    type Output = str;
46
47    #[inline]
48    fn index(&self, index: RangeC) -> &str {
49        &self[..][Range::from(index)]
50    }
51}
52
53impl Index<RangeC> for String {
54    type Output = str;
55
56    #[inline]
57    fn index(&self, index: RangeC) -> &str {
58        &self[..][Range::from(index)]
59    }
60}
61
62///Representation of Uniform Resource Identifier
63///
64///# Example
65///```
66///use http_req::uri::Uri;
67///use std::convert::TryFrom;
68///
69///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
70///assert_eq!(uri.host(), Some("foo.com"));
71///```
72#[derive(Clone, Debug, PartialEq)]
73pub struct Uri<'a> {
74    inner: &'a str,
75    scheme: RangeC,
76    authority: Option<Authority<'a>>,
77    path: Option<RangeC>,
78    query: Option<RangeC>,
79    fragment: Option<RangeC>,
80}
81
82impl<'a> Uri<'a> {
83    ///Returns scheme of this `Uri`.
84    ///
85    ///# Example
86    ///```
87    ///use http_req::uri::Uri;
88    ///use std::convert::TryFrom;
89    ///
90    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
91    ///assert_eq!(uri.scheme(), "https");
92    ///```
93    pub fn scheme(&self) -> &str {
94        &self.inner[self.scheme]
95    }
96
97    ///Returns information about the user included in this `Uri`.
98    ///     
99    ///# Example
100    ///```
101    ///use http_req::uri::Uri;
102    ///use std::convert::TryFrom;
103    ///
104    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
105    ///assert_eq!(uri.user_info(), Some("user:info"));
106    ///```
107    pub fn user_info(&self) -> Option<&str> {
108        self.authority.as_ref().and_then(|a| a.user_info())
109    }
110
111    ///Returns host of this `Uri`.
112    ///     
113    ///# Example
114    ///```
115    ///use http_req::uri::Uri;
116    ///use std::convert::TryFrom;
117    ///
118    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
119    ///assert_eq!(uri.host(), Some("foo.com"));
120    ///```
121    pub fn host(&self) -> Option<&str> {
122        self.authority.as_ref().map(|a| a.host())
123    }
124
125    ///Returns host of this `Uri` to use in a header.
126    ///     
127    ///# Example
128    ///```
129    ///use http_req::uri::Uri;
130    ///use std::convert::TryFrom;
131    ///
132    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
133    ///assert_eq!(uri.host_header(), Some("foo.com:12".to_string()));
134    ///```
135    pub fn host_header(&self) -> Option<String> {
136        self.host().map(|h| match self.corr_port() {
137            HTTP_PORT | HTTPS_PORT => h.to_string(),
138            p => format!("{}:{}", h, p),
139        })
140    }
141
142    ///Returns port of this `Uri`
143    ///     
144    ///# Example
145    ///```
146    ///use http_req::uri::Uri;
147    ///use std::convert::TryFrom;
148    ///
149    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
150    ///assert_eq!(uri.port(), Some(12));
151    ///```
152    pub fn port(&self) -> Option<u16> {
153        self.authority.as_ref().and_then(|a| a.port())
154    }
155
156    ///Returns port corresponding to this `Uri`.
157    ///Returns default port if it hasn't been set in the uri.
158    ///  
159    ///# Example
160    ///```
161    ///use http_req::uri::Uri;
162    ///use std::convert::TryFrom;
163    ///
164    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
165    ///assert_eq!(uri.corr_port(), 12);
166    ///```
167    pub fn corr_port(&self) -> u16 {
168        let default_port = match self.scheme() {
169            "https" => HTTPS_PORT,
170            _ => HTTP_PORT,
171        };
172
173        match self.authority {
174            Some(ref a) => a.port().unwrap_or(default_port),
175            None => default_port,
176        }
177    }
178
179    ///Returns path of this `Uri`.
180    ///  
181    ///# Example
182    ///```
183    ///use http_req::uri::Uri;
184    ///use std::convert::TryFrom;
185    ///
186    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
187    ///assert_eq!(uri.path(), Some("/bar/baz"));
188    ///```
189    pub fn path(&self) -> Option<&str> {
190        self.path.map(|r| &self.inner[r])
191    }
192
193    ///Returns query of this `Uri`.
194    ///  
195    ///# Example
196    ///```
197    ///use http_req::uri::Uri;
198    ///use std::convert::TryFrom;
199    ///
200    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
201    ///assert_eq!(uri.query(), Some("query"));
202    ///```
203    pub fn query(&self) -> Option<&str> {
204        self.query.map(|r| &self.inner[r])
205    }
206
207    ///Returns fragment of this `Uri`.
208    ///  
209    ///# Example
210    ///```
211    ///use http_req::uri::Uri;
212    ///use std::convert::TryFrom;
213    ///
214    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
215    ///assert_eq!(uri.fragment(), Some("fragment"));
216    ///```
217    pub fn fragment(&self) -> Option<&str> {
218        self.fragment.map(|r| &self.inner[r])
219    }
220
221    ///Returns resource `Uri` points to.
222    ///  
223    ///# Example
224    ///```
225    ///use http_req::uri::Uri;
226    ///use std::convert::TryFrom;
227    ///
228    ///let uri: Uri = Uri::try_from("https://user:info@foo.com:12/bar/baz?query#fragment").unwrap();;
229    ///assert_eq!(uri.resource(), "/bar/baz?query#fragment");
230    ///```
231    pub fn resource(&self) -> &str {
232        let mut result = "/";
233
234        for v in &[self.path, self.query, self.fragment] {
235            if let Some(r) = v {
236                result = &self.inner[r.start..];
237                break;
238            }
239        }
240
241        result
242    }
243}
244
245impl<'a> fmt::Display for Uri<'a> {
246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247        let uri = if let Some(auth) = &self.authority {
248            let mut uri = self.inner.to_string();
249            let auth = auth.to_string();
250            let start = self.scheme.end + 3;
251
252            uri.replace_range(start..(start + auth.len()), &auth);
253            uri
254        } else {
255            self.inner.to_string()
256        };
257
258        write!(f, "{}", uri)
259    }
260}
261
262impl<'a> TryFrom<&'a str> for Uri<'a> {
263    type Error = Error;
264
265    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
266        let (scheme, mut uri_part) = get_chunks(&s, Some(RangeC::new(0, s.len())), ":");
267        let scheme = scheme.ok_or(ParseErr::UriErr)?;
268
269        let mut authority = None;
270
271        if let Some(u) = &uri_part {
272            if s[*u].contains("//") {
273                let (auth, part) = get_chunks(&s, Some(RangeC::new(u.start + 2, u.end)), "/");
274
275                authority = if let Some(a) = auth {
276                    Some(Authority::try_from(&s[a])?)
277                } else {
278                    None
279                };
280
281                uri_part = part;
282            }
283        }
284
285        let (mut path, uri_part) = get_chunks(&s, uri_part, "?");
286
287        if authority.is_some() || &s[scheme] == "file" {
288            path = path.map(|p| RangeC::new(p.start - 1, p.end));
289        }
290
291        let (query, fragment) = get_chunks(&s, uri_part, "#");
292
293        Ok(Uri {
294            inner: s,
295            scheme,
296            authority,
297            path,
298            query,
299            fragment,
300        })
301    }
302}
303
304///Authority of Uri
305///
306///# Example
307///```
308///use http_req::uri::Authority;
309///use std::convert::TryFrom;
310///
311///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
312///assert_eq!(auth.host(), "foo.com");
313///```
314#[derive(Clone, Debug, PartialEq)]
315pub struct Authority<'a> {
316    inner: &'a str,
317    username: Option<RangeC>,
318    password: Option<RangeC>,
319    host: RangeC,
320    port: Option<RangeC>,
321}
322
323impl<'a> Authority<'a> {
324    ///Returns username of this `Authority`
325    ///
326    ///# Example
327    ///```
328    ///use http_req::uri::Authority;
329    ///use std::convert::TryFrom;
330    ///
331    ///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
332    ///assert_eq!(auth.username(), Some("user"));
333    ///```
334    pub fn username(&self) -> Option<&'a str> {
335        self.username.map(|r| &self.inner[r])
336    }
337
338    ///Returns password of this `Authority`
339    ///
340    ///# Example
341    ///```
342    ///use http_req::uri::Authority;
343    ///use std::convert::TryFrom;
344    ///
345    ///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
346    ///assert_eq!(auth.password(), Some("info"));
347    ///```
348    pub fn password(&self) -> Option<&str> {
349        self.password.map(|r| &self.inner[r])
350    }
351
352    ///Returns information about the user
353    ///
354    ///# Example
355    ///```
356    ///use http_req::uri::Authority;
357    ///use std::convert::TryFrom;
358    ///
359    ///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
360    ///assert_eq!(auth.user_info(), Some("user:info"));
361    ///```
362    pub fn user_info(&self) -> Option<&str> {
363        match (&self.username, &self.password) {
364            (Some(u), Some(p)) => Some(&self.inner[u.start..p.end]),
365            (Some(u), None) => Some(&self.inner[*u]),
366            _ => None,
367        }
368    }
369
370    ///Returns host of this `Authority`
371    ///
372    ///# Example
373    ///```
374    ///use http_req::uri::Authority;
375    ///use std::convert::TryFrom;
376    ///
377    ///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
378    ///assert_eq!(auth.host(), "foo.com");
379    ///```
380    pub fn host(&self) -> &str {
381        &self.inner[self.host]
382    }
383
384    ///Returns port of this `Authority`
385    ///
386    ///# Example
387    ///```
388    ///use http_req::uri::Authority;
389    ///use std::convert::TryFrom;
390    ///
391    ///let auth: Authority = Authority::try_from("user:info@foo.com:443").unwrap();
392    ///assert_eq!(auth.port(), Some(443));
393    ///```
394    pub fn port(&self) -> Option<u16> {
395        self.port.as_ref().map(|p| self.inner[*p].parse().unwrap())
396    }
397}
398
399impl<'a> TryFrom<&'a str> for Authority<'a> {
400    type Error = ParseErr;
401
402    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
403        let mut username = None;
404        let mut password = None;
405
406        let uri_part = if s.contains('@') {
407            let (info, part) = get_chunks(&s, Some(RangeC::new(0, s.len())), "@");
408            let (name, pass) = get_chunks(&s, info, ":");
409
410            username = name;
411            password = pass;
412
413            part
414        } else {
415            Some(RangeC::new(0, s.len()))
416        };
417
418        let split_by = if s.contains(']') && s.contains('[') {
419            "]:"
420        } else {
421            ":"
422        };
423        let (host, port) = get_chunks(&s, uri_part, split_by);
424        let host = host.ok_or(ParseErr::UriErr)?;
425
426        if let Some(p) = port {
427            if s[p].parse::<u16>().is_err() {
428                return Err(ParseErr::UriErr);
429            }
430        }
431
432        Ok(Authority {
433            inner: s,
434            username,
435            password,
436            host,
437            port,
438        })
439    }
440}
441
442impl<'a> fmt::Display for Authority<'a> {
443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444        let auth = if let Some(pass) = self.password {
445            let range = Range::from(pass);
446
447            let hidden_pass = "*".repeat(range.len());
448            let mut auth = self.inner.to_string();
449            auth.replace_range(range, &hidden_pass);
450
451            auth
452        } else {
453            self.inner.to_string()
454        };
455
456        write!(f, "{}", auth)
457    }
458}
459
460//Removes whitespace from `text`
461pub fn remove_spaces(text: &mut String) {
462    text.retain(|c| !c.is_whitespace());
463}
464
465//Splits `s` by `separator`. If `separator` is found inside `s`, it will return two `Some` values
466//consisting `RangeC` of each `&str`. If `separator` is at the end of `s` or it's not found,
467//it will return tuple consisting `Some` with `RangeC` of entire `s` inside and None.
468fn get_chunks<'a>(
469    s: &'a str,
470    range: Option<RangeC>,
471    separator: &'a str,
472) -> (Option<RangeC>, Option<RangeC>) {
473    if let Some(r) = range {
474        let range = Range::from(r);
475
476        match s[range.clone()].find(separator) {
477            Some(i) => {
478                let mid = r.start + i + separator.len();
479                let before = Some(RangeC::new(r.start, mid - 1)).filter(|r| r.start != r.end);
480                let after = Some(RangeC::new(mid, r.end)).filter(|r| r.start != r.end);
481
482                (before, after)
483            }
484            None => {
485                if !s[range].is_empty() {
486                    (Some(r), None)
487                } else {
488                    (None, None)
489                }
490            }
491        }
492    } else {
493        (None, None)
494    }
495}
496
497#[cfg(test)]
498mod tests {
499    use super::*;
500
501    const TEST_URIS: [&str; 5] = [
502        "https://user:info@foo.com:12/bar/baz?query#fragment",
503        "file:///C:/Users/User/Pictures/screenshot.png",
504        "https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol",
505        "mailto:John.Doe@example.com",
506        "https://[4b10:bbb0:0:d0::ba7:8001]:443/",
507    ];
508
509    const TEST_AUTH: [&str; 4] = [
510        "user:info@foo.com:12",
511        "en.wikipedia.org",
512        "John.Doe@example.com",
513        "[4b10:bbb0:0:d0::ba7:8001]:443",
514    ];
515
516    #[test]
517    fn remove_space() {
518        let mut text = String::from("Hello World     !");
519        let expect = String::from("HelloWorld!");
520
521        remove_spaces(&mut text);
522        assert_eq!(text, expect);
523    }
524
525    #[test]
526    fn uri_full_parse() {
527        let uri = Uri::try_from(
528            "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1",
529        )
530        .unwrap();
531        assert_eq!(uri.scheme(), "abc");
532
533        assert_eq!(uri.user_info(), Some("username:password"));
534        assert_eq!(uri.host(), Some("example.com"));
535        assert_eq!(uri.port(), Some(123));
536
537        assert_eq!(uri.path(), Some("/path/data"));
538        assert_eq!(uri.query(), Some("key=value&key2=value2"));
539        assert_eq!(uri.fragment(), Some("fragid1"));
540    }
541
542    #[test]
543    fn uri_parse() {
544        for uri in TEST_URIS.iter() {
545            Uri::try_from(*uri).unwrap();
546        }
547    }
548
549    #[test]
550    fn uri_scheme() {
551        let uris: Vec<_> = TEST_URIS
552            .iter()
553            .map(|uri| Uri::try_from(*uri).unwrap())
554            .collect();
555
556        assert_eq!(uris[0].scheme(), "https");
557        assert_eq!(uris[1].scheme(), "file");
558        assert_eq!(uris[2].scheme(), "https");
559        assert_eq!(uris[3].scheme(), "mailto");
560        assert_eq!(uris[4].scheme(), "https");
561    }
562
563    #[test]
564    fn uri_uesr_info() {
565        let uris: Vec<_> = TEST_URIS
566            .iter()
567            .map(|uri| Uri::try_from(*uri).unwrap())
568            .collect();
569
570        assert_eq!(uris[0].user_info(), Some("user:info"));
571        assert_eq!(uris[1].user_info(), None);
572        assert_eq!(uris[2].user_info(), None);
573        assert_eq!(uris[3].user_info(), None);
574        assert_eq!(uris[4].user_info(), None);
575    }
576
577    #[test]
578    fn uri_host() {
579        let uris: Vec<_> = TEST_URIS
580            .iter()
581            .map(|uri| Uri::try_from(*uri).unwrap())
582            .collect();
583
584        assert_eq!(uris[0].host(), Some("foo.com"));
585        assert_eq!(uris[1].host(), None);
586        assert_eq!(uris[2].host(), Some("en.wikipedia.org"));
587        assert_eq!(uris[3].host(), None);
588        assert_eq!(uris[4].host(), Some("[4b10:bbb0:0:d0::ba7:8001]"));
589    }
590
591    #[test]
592    fn uri_host_header() {
593        let uri_def: Uri =
594            Uri::try_from("https://en.wikipedia.org:443/wiki/Hypertext_Transfer_Protocol").unwrap();
595        let uris: Vec<_> = TEST_URIS
596            .iter()
597            .map(|uri| Uri::try_from(*uri).unwrap())
598            .collect();
599
600        assert_eq!(uris[0].host_header(), Some("foo.com:12".to_string()));
601        assert_eq!(uris[2].host_header(), Some("en.wikipedia.org".to_string()));
602        assert_eq!(uri_def.host_header(), Some("en.wikipedia.org".to_string()));
603    }
604
605    #[test]
606    fn uri_port() {
607        let uris: Vec<_> = TEST_URIS
608            .iter()
609            .map(|uri| Uri::try_from(*uri).unwrap())
610            .collect();
611
612        assert_eq!(uris[0].port(), Some(12));
613        assert_eq!(uris[4].port(), Some(443));
614
615        for i in 1..3 {
616            assert_eq!(uris[i].port(), None);
617        }
618    }
619
620    #[test]
621    fn uri_corr_port() {
622        let uris: Vec<_> = TEST_URIS
623            .iter()
624            .map(|uri| Uri::try_from(*uri).unwrap())
625            .collect();
626
627        assert_eq!(uris[0].corr_port(), 12);
628        assert_eq!(uris[1].corr_port(), HTTP_PORT);
629        assert_eq!(uris[2].corr_port(), HTTPS_PORT);
630        assert_eq!(uris[3].corr_port(), HTTP_PORT);
631        assert_eq!(uris[4].corr_port(), HTTPS_PORT);
632    }
633
634    #[test]
635    fn uri_path() {
636        let uris: Vec<_> = TEST_URIS
637            .iter()
638            .map(|uri| Uri::try_from(*uri).unwrap())
639            .collect();
640
641        assert_eq!(uris[0].path(), Some("/bar/baz"));
642        assert_eq!(
643            uris[1].path(),
644            Some("/C:/Users/User/Pictures/screenshot.png")
645        );
646        assert_eq!(uris[2].path(), Some("/wiki/Hypertext_Transfer_Protocol"));
647        assert_eq!(uris[3].path(), Some("John.Doe@example.com"));
648        assert_eq!(uris[4].path(), None);
649    }
650
651    #[test]
652    fn uri_query() {
653        let uris: Vec<_> = TEST_URIS
654            .iter()
655            .map(|uri| Uri::try_from(*uri).unwrap())
656            .collect();
657
658        assert_eq!(uris[0].query(), Some("query"));
659
660        for i in 1..4 {
661            assert_eq!(uris[i].query(), None);
662        }
663    }
664
665    #[test]
666    fn uri_fragment() {
667        let uris: Vec<_> = TEST_URIS
668            .iter()
669            .map(|uri| Uri::try_from(*uri).unwrap())
670            .collect();
671
672        assert_eq!(uris[0].fragment(), Some("fragment"));
673
674        for i in 1..4 {
675            assert_eq!(uris[i].fragment(), None);
676        }
677    }
678
679    #[test]
680    fn uri_resource() {
681        let uris: Vec<_> = TEST_URIS
682            .iter()
683            .map(|uri| Uri::try_from(*uri).unwrap())
684            .collect();
685
686        assert_eq!(uris[0].resource(), "/bar/baz?query#fragment");
687        assert_eq!(uris[1].resource(), "/C:/Users/User/Pictures/screenshot.png");
688        assert_eq!(uris[2].resource(), "/wiki/Hypertext_Transfer_Protocol");
689        assert_eq!(uris[3].resource(), "John.Doe@example.com");
690        assert_eq!(uris[4].resource(), "/");
691    }
692
693    #[test]
694    fn uri_display() {
695        let uris: Vec<_> = TEST_URIS
696            .iter()
697            .map(|uri| Uri::try_from(*uri).unwrap())
698            .collect();
699
700        assert_eq!(
701            uris[0].to_string(),
702            "https://user:****@foo.com:12/bar/baz?query#fragment"
703        );
704
705        for i in 1..uris.len() {
706            let s = uris[i].to_string();
707            assert_eq!(s, TEST_URIS[i]);
708        }
709    }
710
711    #[test]
712    fn authority_username() {
713        let auths: Vec<_> = TEST_AUTH
714            .iter()
715            .map(|auth| Authority::try_from(*auth).unwrap())
716            .collect();
717
718        assert_eq!(auths[0].username(), Some("user"));
719        assert_eq!(auths[1].username(), None);
720        assert_eq!(auths[2].username(), Some("John.Doe"));
721        assert_eq!(auths[3].username(), None);
722    }
723
724    #[test]
725    fn authority_password() {
726        let auths: Vec<_> = TEST_AUTH
727            .iter()
728            .map(|auth| Authority::try_from(*auth).unwrap())
729            .collect();
730
731        assert_eq!(auths[0].password(), Some("info"));
732        assert_eq!(auths[1].password(), None);
733        assert_eq!(auths[2].password(), None);
734        assert_eq!(auths[3].password(), None);
735    }
736
737    #[test]
738    fn authority_host() {
739        let auths: Vec<_> = TEST_AUTH
740            .iter()
741            .map(|auth| Authority::try_from(*auth).unwrap())
742            .collect();
743
744        assert_eq!(auths[0].host(), "foo.com");
745        assert_eq!(auths[1].host(), "en.wikipedia.org");
746        assert_eq!(auths[2].host(), "example.com");
747        assert_eq!(auths[3].host(), "[4b10:bbb0:0:d0::ba7:8001]");
748    }
749
750    #[test]
751    fn authority_port() {
752        let auths: Vec<_> = TEST_AUTH
753            .iter()
754            .map(|auth| Authority::try_from(*auth).unwrap())
755            .collect();
756
757        assert_eq!(auths[0].port(), Some(12));
758        assert_eq!(auths[1].port(), None);
759        assert_eq!(auths[2].port(), None);
760        assert_eq!(auths[3].port(), Some(443));
761    }
762
763    #[test]
764    fn authority_from_str() {
765        for auth in TEST_AUTH.iter() {
766            Authority::try_from(*auth).unwrap();
767        }
768    }
769
770    #[test]
771    fn authority_display() {
772        let auths: Vec<_> = TEST_AUTH
773            .iter()
774            .map(|auth| Authority::try_from(*auth).unwrap())
775            .collect();
776
777        assert_eq!("user:****@foo.com:12", auths[0].to_string());
778
779        for i in 1..auths.len() {
780            let s = auths[i].to_string();
781            assert_eq!(s, TEST_AUTH[i]);
782        }
783    }
784
785    #[test]
786    fn range_c_new() {
787        assert_eq!(
788            RangeC::new(22, 343),
789            RangeC {
790                start: 22,
791                end: 343,
792            }
793        )
794    }
795
796    #[test]
797    fn range_from_range_c() {
798        assert_eq!(
799            Range::from(RangeC::new(222, 43)),
800            Range {
801                start: 222,
802                end: 43,
803            }
804        )
805    }
806
807    #[test]
808    fn range_c_index() {
809        const RANGE: RangeC = RangeC::new(0, 4);
810        let text = TEST_AUTH[0].to_string();
811
812        assert_eq!(text[..4], text[RANGE])
813    }
814}