Coverage Report

Created: 2023-04-25 07:07

/rust/registry/src/index.crates.io-6f17d22bba15001f/url-2.3.1/src/slicing.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2016 The rust-url developers.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
9
use crate::Url;
10
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
11
12
impl Index<RangeFull> for Url {
13
    type Output = str;
14
0
    fn index(&self, _: RangeFull) -> &str {
15
0
        &self.serialization
16
0
    }
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeFull>>::index
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeFull>>::index
17
}
18
19
impl Index<RangeFrom<Position>> for Url {
20
    type Output = str;
21
0
    fn index(&self, range: RangeFrom<Position>) -> &str {
22
0
        &self.serialization[self.index(range.start)..]
23
0
    }
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeFrom<url::slicing::Position>>>::index
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeFrom<url::slicing::Position>>>::index
24
}
25
26
impl Index<RangeTo<Position>> for Url {
27
    type Output = str;
28
0
    fn index(&self, range: RangeTo<Position>) -> &str {
29
0
        &self.serialization[..self.index(range.end)]
30
0
    }
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeTo<url::slicing::Position>>>::index
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::RangeTo<url::slicing::Position>>>::index
31
}
32
33
impl Index<Range<Position>> for Url {
34
    type Output = str;
35
0
    fn index(&self, range: Range<Position>) -> &str {
36
0
        &self.serialization[self.index(range.start)..self.index(range.end)]
37
0
    }
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::Range<url::slicing::Position>>>::index
Unexecuted instantiation: <url::Url as core::ops::index::Index<core::ops::range::Range<url::slicing::Position>>>::index
38
}
39
40
/// Indicates a position within a URL based on its components.
41
///
42
/// A range of positions can be used for slicing `Url`:
43
///
44
/// ```rust
45
/// # use url::{Url, Position};
46
/// # fn something(some_url: Url) {
47
/// let serialization: &str = &some_url[..];
48
/// let serialization_without_fragment: &str = &some_url[..Position::AfterQuery];
49
/// let authority: &str = &some_url[Position::BeforeUsername..Position::AfterPort];
50
/// let data_url_payload: &str = &some_url[Position::BeforePath..Position::AfterQuery];
51
/// let scheme_relative: &str = &some_url[Position::BeforeUsername..];
52
/// # }
53
/// ```
54
///
55
/// In a pseudo-grammar (where `[`…`]?` makes a sub-sequence optional),
56
/// URL components and delimiters that separate them are:
57
///
58
/// ```notrust
59
/// url =
60
///     scheme ":"
61
///     [ "//" [ username [ ":" password ]? "@" ]? host [ ":" port ]? ]?
62
///     path [ "?" query ]? [ "#" fragment ]?
63
/// ```
64
///
65
/// When a given component is not present,
66
/// its "before" and "after" position are the same
67
/// (so that `&some_url[BeforeFoo..AfterFoo]` is the empty string)
68
/// and component ordering is preserved
69
/// (so that a missing query "is between" a path and a fragment).
70
///
71
/// The end of a component and the start of the next are either the same or separate
72
/// by a delimiter.
73
/// (Not that the initial `/` of a path is considered part of the path here, not a delimiter.)
74
/// For example, `&url[..BeforeFragment]` would include a `#` delimiter (if present in `url`),
75
/// so `&url[..AfterQuery]` might be desired instead.
76
///
77
/// `BeforeScheme` and `AfterFragment` are always the start and end of the entire URL,
78
/// so `&url[BeforeScheme..X]` is the same as `&url[..X]`
79
/// and `&url[X..AfterFragment]` is the same as `&url[X..]`.
80
0
#[derive(Copy, Clone, Debug)]
Unexecuted instantiation: <url::slicing::Position as core::clone::Clone>::clone
Unexecuted instantiation: <url::slicing::Position as core::clone::Clone>::clone
Unexecuted instantiation: <url::slicing::Position as core::fmt::Debug>::fmt
Unexecuted instantiation: <url::slicing::Position as core::fmt::Debug>::fmt
81
pub enum Position {
82
    BeforeScheme,
83
    AfterScheme,
84
    BeforeUsername,
85
    AfterUsername,
86
    BeforePassword,
87
    AfterPassword,
88
    BeforeHost,
89
    AfterHost,
90
    BeforePort,
91
    AfterPort,
92
    BeforePath,
93
    AfterPath,
94
    BeforeQuery,
95
    AfterQuery,
96
    BeforeFragment,
97
    AfterFragment,
98
}
99
100
impl Url {
101
    #[inline]
102
0
    fn index(&self, position: Position) -> usize {
103
0
        match position {
104
0
            Position::BeforeScheme => 0,
105
106
0
            Position::AfterScheme => self.scheme_end as usize,
107
108
            Position::BeforeUsername => {
109
0
                if self.has_authority() {
110
0
                    self.scheme_end as usize + "://".len()
111
                } else {
112
0
                    debug_assert!(self.byte_at(self.scheme_end) == b':');
113
0
                    debug_assert!(self.scheme_end + ":".len() as u32 == self.username_end);
114
0
                    self.scheme_end as usize + ":".len()
115
                }
116
            }
117
118
0
            Position::AfterUsername => self.username_end as usize,
119
120
            Position::BeforePassword => {
121
0
                if self.has_authority() && self.byte_at(self.username_end) == b':' {
122
0
                    self.username_end as usize + ":".len()
123
                } else {
124
0
                    debug_assert!(self.username_end == self.host_start);
125
0
                    self.username_end as usize
126
                }
127
            }
128
129
            Position::AfterPassword => {
130
0
                if self.has_authority() && self.byte_at(self.username_end) == b':' {
131
0
                    debug_assert!(self.byte_at(self.host_start - "@".len() as u32) == b'@');
132
0
                    self.host_start as usize - "@".len()
133
                } else {
134
0
                    debug_assert!(self.username_end == self.host_start);
135
0
                    self.host_start as usize
136
                }
137
            }
138
139
0
            Position::BeforeHost => self.host_start as usize,
140
141
0
            Position::AfterHost => self.host_end as usize,
142
143
            Position::BeforePort => {
144
0
                if self.port.is_some() {
145
0
                    debug_assert!(self.byte_at(self.host_end) == b':');
146
0
                    self.host_end as usize + ":".len()
147
                } else {
148
0
                    self.host_end as usize
149
                }
150
            }
151
152
0
            Position::AfterPort => self.path_start as usize,
153
154
0
            Position::BeforePath => self.path_start as usize,
155
156
0
            Position::AfterPath => match (self.query_start, self.fragment_start) {
157
0
                (Some(q), _) => q as usize,
158
0
                (None, Some(f)) => f as usize,
159
0
                (None, None) => self.serialization.len(),
160
            },
161
162
0
            Position::BeforeQuery => match (self.query_start, self.fragment_start) {
163
0
                (Some(q), _) => {
164
0
                    debug_assert!(self.byte_at(q) == b'?');
165
0
                    q as usize + "?".len()
166
                }
167
0
                (None, Some(f)) => f as usize,
168
0
                (None, None) => self.serialization.len(),
169
            },
170
171
0
            Position::AfterQuery => match self.fragment_start {
172
0
                None => self.serialization.len(),
173
0
                Some(f) => f as usize,
174
            },
175
176
0
            Position::BeforeFragment => match self.fragment_start {
177
0
                Some(f) => {
178
0
                    debug_assert!(self.byte_at(f) == b'#');
179
0
                    f as usize + "#".len()
180
                }
181
0
                None => self.serialization.len(),
182
            },
183
184
0
            Position::AfterFragment => self.serialization.len(),
185
        }
186
0
    }
Unexecuted instantiation: <url::Url>::index
Unexecuted instantiation: <url::Url>::index
187
}