1use crate::Url;
10use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
11
12impl Index<RangeFull> for Url {
13 type Output = str;
14 fn index(&self, _: RangeFull) -> &str {
15 &self.serialization
16 }
17}
18
19impl Index<RangeFrom<Position>> for Url {
20 type Output = str;
21 fn index(&self, range: RangeFrom<Position>) -> &str {
22 &self.serialization[self.index(range.start)..]
23 }
24}
25
26impl Index<RangeTo<Position>> for Url {
27 type Output = str;
28 fn index(&self, range: RangeTo<Position>) -> &str {
29 &self.serialization[..self.index(range.end)]
30 }
31}
32
33impl Index<Range<Position>> for Url {
34 type Output = str;
35 fn index(&self, range: Range<Position>) -> &str {
36 &self.serialization[self.index(range.start)..self.index(range.end)]
37 }
38}
39
40#[derive(Copy, Clone, Debug)]
81pub 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
100impl Url {
101 #[inline]
102 fn index(&self, position: Position) -> usize {
103 match position {
104 Position::BeforeScheme => 0,
105
106 Position::AfterScheme => self.scheme_end as usize,
107
108 Position::BeforeUsername => {
109 if self.has_authority() {
110 self.scheme_end as usize + "://".len()
111 } else {
112 debug_assert!(self.byte_at(self.scheme_end) == b':');
113 debug_assert!(self.scheme_end + ":".len() as u32 == self.username_end);
114 self.scheme_end as usize + ":".len()
115 }
116 }
117
118 Position::AfterUsername => self.username_end as usize,
119
120 Position::BeforePassword => {
121 if self.has_authority() && self.byte_at(self.username_end) == b':' {
122 self.username_end as usize + ":".len()
123 } else {
124 debug_assert!(self.username_end == self.host_start);
125 self.username_end as usize
126 }
127 }
128
129 Position::AfterPassword => {
130 if self.has_authority() && self.byte_at(self.username_end) == b':' {
131 debug_assert!(self.byte_at(self.host_start - "@".len() as u32) == b'@');
132 self.host_start as usize - "@".len()
133 } else {
134 debug_assert!(self.username_end == self.host_start);
135 self.host_start as usize
136 }
137 }
138
139 Position::BeforeHost => self.host_start as usize,
140
141 Position::AfterHost => self.host_end as usize,
142
143 Position::BeforePort => {
144 if self.port.is_some() {
145 debug_assert!(self.byte_at(self.host_end) == b':');
146 self.host_end as usize + ":".len()
147 } else {
148 self.host_end as usize
149 }
150 }
151
152 Position::AfterPort => self.path_start as usize,
153
154 Position::BeforePath => self.path_start as usize,
155
156 Position::AfterPath => match (self.query_start, self.fragment_start) {
157 (Some(q), _) => q as usize,
158 (None, Some(f)) => f as usize,
159 (None, None) => self.serialization.len(),
160 },
161
162 Position::BeforeQuery => match (self.query_start, self.fragment_start) {
163 (Some(q), _) => {
164 debug_assert!(self.byte_at(q) == b'?');
165 q as usize + "?".len()
166 }
167 (None, Some(f)) => f as usize,
168 (None, None) => self.serialization.len(),
169 },
170
171 Position::AfterQuery => match self.fragment_start {
172 None => self.serialization.len(),
173 Some(f) => f as usize,
174 },
175
176 Position::BeforeFragment => match self.fragment_start {
177 Some(f) => {
178 debug_assert!(self.byte_at(f) == b'#');
179 f as usize + "#".len()
180 }
181 None => self.serialization.len(),
182 },
183
184 Position::AfterFragment => self.serialization.len(),
185 }
186 }
187}