1use core::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
10
11use crate::Url;
12
13impl Index<RangeFull> for Url {
14 type Output = str;
15 fn index(&self, _: RangeFull) -> &str {
16 &self.serialization
17 }
18}
19
20impl Index<RangeFrom<Position>> for Url {
21 type Output = str;
22 fn index(&self, range: RangeFrom<Position>) -> &str {
23 &self.serialization[self.index(range.start)..]
24 }
25}
26
27impl Index<RangeTo<Position>> for Url {
28 type Output = str;
29 fn index(&self, range: RangeTo<Position>) -> &str {
30 &self.serialization[..self.index(range.end)]
31 }
32}
33
34impl Index<Range<Position>> for Url {
35 type Output = str;
36 fn index(&self, range: Range<Position>) -> &str {
37 &self.serialization[self.index(range.start)..self.index(range.end)]
38 }
39}
40
41fn count_digits(n: u16) -> usize {
43 match n {
44 0..=9 => 1,
45 10..=99 => 2,
46 100..=999 => 3,
47 1000..=9999 => 4,
48 10000..=65535 => 5,
49 }
50}
51
52#[test]
53fn test_count_digits() {
54 assert_eq!(count_digits(0), 1);
55 assert_eq!(count_digits(1), 1);
56 assert_eq!(count_digits(9), 1);
57 assert_eq!(count_digits(10), 2);
58 assert_eq!(count_digits(99), 2);
59 assert_eq!(count_digits(100), 3);
60 assert_eq!(count_digits(9999), 4);
61 assert_eq!(count_digits(65535), 5);
62}
63
64)]
105pub enum Position {
106 BeforeScheme,
107 AfterScheme,
108 BeforeUsername,
109 AfterUsername,
110 BeforePassword,
111 AfterPassword,
112 BeforeHost,
113 AfterHost,
114 BeforePort,
115 AfterPort,
116 BeforePath,
117 AfterPath,
118 BeforeQuery,
119 AfterQuery,
120 BeforeFragment,
121 AfterFragment,
122}
123
124impl Url {
125 #[inline]
126 fn index(&self, position: Position) -> usize {
127 match position {
128 Position::BeforeScheme => 0,
129
130 Position::AfterScheme => self.scheme_end as usize,
131
132 Position::BeforeUsername => {
133 if self.has_authority() {
134 self.scheme_end as usize + "://".len()
135 } else {
136 if true {
if !(self.byte_at(self.scheme_end) == b':') {
::core::panicking::panic("assertion failed: self.byte_at(self.scheme_end) == b\':\'")
};
};debug_assert!(self.byte_at(self.scheme_end) == b':');
137 if true {
if !(self.scheme_end + ":".len() as u32 == self.username_end) {
::core::panicking::panic("assertion failed: self.scheme_end + \":\".len() as u32 == self.username_end")
};
};debug_assert!(self.scheme_end + ":".len() as u32 == self.username_end);
138 self.scheme_end as usize + ":".len()
139 }
140 }
141
142 Position::AfterUsername => self.username_end as usize,
143
144 Position::BeforePassword => {
145 if self.has_authority() && self.byte_at(self.username_end) == b':' {
146 self.username_end as usize + ":".len()
147 } else {
148 if true {
if !(self.username_end == self.host_start) {
::core::panicking::panic("assertion failed: self.username_end == self.host_start")
};
};debug_assert!(self.username_end == self.host_start);
149 self.username_end as usize
150 }
151 }
152
153 Position::AfterPassword => {
154 if self.has_authority() && self.byte_at(self.username_end) == b':' {
155 if true {
if !(self.byte_at(self.host_start - "@".len() as u32) == b'@') {
::core::panicking::panic("assertion failed: self.byte_at(self.host_start - \"@\".len() as u32) == b\'@\'")
};
};debug_assert!(self.byte_at(self.host_start - "@".len() as u32) == b'@');
156 self.host_start as usize - "@".len()
157 } else {
158 if true {
if !(self.username_end == self.host_start) {
::core::panicking::panic("assertion failed: self.username_end == self.host_start")
};
};debug_assert!(self.username_end == self.host_start);
159 self.host_start as usize
160 }
161 }
162
163 Position::BeforeHost => self.host_start as usize,
164
165 Position::AfterHost => self.host_end as usize,
166
167 Position::BeforePort => {
168 if self.port.is_some() {
169 if true {
if !(self.byte_at(self.host_end) == b':') {
::core::panicking::panic("assertion failed: self.byte_at(self.host_end) == b\':\'")
};
};debug_assert!(self.byte_at(self.host_end) == b':');
170 self.host_end as usize + ":".len()
171 } else {
172 self.host_end as usize
173 }
174 }
175
176 Position::AfterPort => {
177 if let Some(port) = self.port {
178 if true {
if !(self.byte_at(self.host_end) == b':') {
::core::panicking::panic("assertion failed: self.byte_at(self.host_end) == b\':\'")
};
};debug_assert!(self.byte_at(self.host_end) == b':');
179 self.host_end as usize + ":".len() + count_digits(port)
180 } else {
181 self.host_end as usize
182 }
183 }
184
185 Position::BeforePath => self.path_start as usize,
186
187 Position::AfterPath => match (self.query_start, self.fragment_start) {
188 (Some(q), _) => q as usize,
189 (None, Some(f)) => f as usize,
190 (None, None) => self.serialization.len(),
191 },
192
193 Position::BeforeQuery => match (self.query_start, self.fragment_start) {
194 (Some(q), _) => {
195 if true {
if !(self.byte_at(q) == b'?') {
::core::panicking::panic("assertion failed: self.byte_at(q) == b\'?\'")
};
};debug_assert!(self.byte_at(q) == b'?');
196 q as usize + "?".len()
197 }
198 (None, Some(f)) => f as usize,
199 (None, None) => self.serialization.len(),
200 },
201
202 Position::AfterQuery => match self.fragment_start {
203 None => self.serialization.len(),
204 Some(f) => f as usize,
205 },
206
207 Position::BeforeFragment => match self.fragment_start {
208 Some(f) => {
209 if true {
if !(self.byte_at(f) == b'#') {
::core::panicking::panic("assertion failed: self.byte_at(f) == b\'#\'")
};
};debug_assert!(self.byte_at(f) == b'#');
210 f as usize + "#".len()
211 }
212 None => self.serialization.len(),
213 },
214
215 Position::AfterFragment => self.serialization.len(),
216 }
217 }
218}