]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
1 | // Copyright 2012 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use fmt; | |
12 | ||
13 | /// An unbounded range. Use `..` (two dots) for its shorthand. | |
14 | /// | |
15 | /// Its primary use case is slicing index. It cannot serve as an iterator | |
16 | /// because it doesn't have a starting point. | |
17 | /// | |
18 | /// # Examples | |
19 | /// | |
20 | /// The `..` syntax is a `RangeFull`: | |
21 | /// | |
22 | /// ``` | |
23 | /// assert_eq!((..), std::ops::RangeFull); | |
24 | /// ``` | |
25 | /// | |
26 | /// It does not have an `IntoIterator` implementation, so you can't use it in a | |
27 | /// `for` loop directly. This won't compile: | |
28 | /// | |
29 | /// ```compile_fail,E0277 | |
30 | /// for i in .. { | |
31 | /// // ... | |
32 | /// } | |
33 | /// ``` | |
34 | /// | |
35 | /// Used as a slicing index, `RangeFull` produces the full array as a slice. | |
36 | /// | |
37 | /// ``` | |
38 | /// let arr = [0, 1, 2, 3]; | |
39 | /// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull | |
40 | /// assert_eq!(arr[ ..3], [0,1,2 ]); | |
41 | /// assert_eq!(arr[1.. ], [ 1,2,3]); | |
42 | /// assert_eq!(arr[1..3], [ 1,2 ]); | |
43 | /// ``` | |
44 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
45 | #[stable(feature = "rust1", since = "1.0.0")] | |
46 | pub struct RangeFull; | |
47 | ||
48 | #[stable(feature = "rust1", since = "1.0.0")] | |
49 | impl fmt::Debug for RangeFull { | |
50 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
51 | write!(fmt, "..") | |
52 | } | |
53 | } | |
54 | ||
55 | /// A (half-open) range which is bounded at both ends: { x | start <= x < end }. | |
56 | /// Use `start..end` (two dots) for its shorthand. | |
57 | /// | |
58 | /// See the [`contains`](#method.contains) method for its characterization. | |
59 | /// | |
60 | /// # Examples | |
61 | /// | |
62 | /// ``` | |
63 | /// fn main() { | |
64 | /// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); | |
65 | /// assert_eq!(3+4+5, (3..6).sum()); | |
66 | /// | |
67 | /// let arr = [0, 1, 2, 3]; | |
68 | /// assert_eq!(arr[ .. ], [0,1,2,3]); | |
69 | /// assert_eq!(arr[ ..3], [0,1,2 ]); | |
70 | /// assert_eq!(arr[1.. ], [ 1,2,3]); | |
71 | /// assert_eq!(arr[1..3], [ 1,2 ]); // Range | |
72 | /// } | |
73 | /// ``` | |
74 | #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 | |
75 | #[stable(feature = "rust1", since = "1.0.0")] | |
76 | pub struct Range<Idx> { | |
77 | /// The lower bound of the range (inclusive). | |
78 | #[stable(feature = "rust1", since = "1.0.0")] | |
79 | pub start: Idx, | |
80 | /// The upper bound of the range (exclusive). | |
81 | #[stable(feature = "rust1", since = "1.0.0")] | |
82 | pub end: Idx, | |
83 | } | |
84 | ||
85 | #[stable(feature = "rust1", since = "1.0.0")] | |
86 | impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> { | |
87 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
88 | write!(fmt, "{:?}..{:?}", self.start, self.end) | |
89 | } | |
90 | } | |
91 | ||
92 | #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] | |
93 | impl<Idx: PartialOrd<Idx>> Range<Idx> { | |
94 | /// # Examples | |
95 | /// | |
96 | /// ``` | |
97 | /// #![feature(range_contains)] | |
98 | /// fn main() { | |
99 | /// assert!( ! (3..5).contains(2)); | |
100 | /// assert!( (3..5).contains(3)); | |
101 | /// assert!( (3..5).contains(4)); | |
102 | /// assert!( ! (3..5).contains(5)); | |
103 | /// | |
104 | /// assert!( ! (3..3).contains(3)); | |
105 | /// assert!( ! (3..2).contains(3)); | |
106 | /// } | |
107 | /// ``` | |
108 | pub fn contains(&self, item: Idx) -> bool { | |
109 | (self.start <= item) && (item < self.end) | |
110 | } | |
111 | } | |
112 | ||
113 | /// A range which is only bounded below: { x | start <= x }. | |
114 | /// Use `start..` for its shorthand. | |
115 | /// | |
116 | /// See the [`contains`](#method.contains) method for its characterization. | |
117 | /// | |
118 | /// Note: Currently, no overflow checking is done for the iterator | |
119 | /// implementation; if you use an integer range and the integer overflows, it | |
120 | /// might panic in debug mode or create an endless loop in release mode. This | |
121 | /// overflow behavior might change in the future. | |
122 | /// | |
123 | /// # Examples | |
124 | /// | |
125 | /// ``` | |
126 | /// fn main() { | |
127 | /// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); | |
128 | /// assert_eq!(2+3+4, (2..).take(3).sum()); | |
129 | /// | |
130 | /// let arr = [0, 1, 2, 3]; | |
131 | /// assert_eq!(arr[ .. ], [0,1,2,3]); | |
132 | /// assert_eq!(arr[ ..3], [0,1,2 ]); | |
133 | /// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom | |
134 | /// assert_eq!(arr[1..3], [ 1,2 ]); | |
135 | /// } | |
136 | /// ``` | |
137 | #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 | |
138 | #[stable(feature = "rust1", since = "1.0.0")] | |
139 | pub struct RangeFrom<Idx> { | |
140 | /// The lower bound of the range (inclusive). | |
141 | #[stable(feature = "rust1", since = "1.0.0")] | |
142 | pub start: Idx, | |
143 | } | |
144 | ||
145 | #[stable(feature = "rust1", since = "1.0.0")] | |
146 | impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> { | |
147 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
148 | write!(fmt, "{:?}..", self.start) | |
149 | } | |
150 | } | |
151 | ||
152 | #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] | |
153 | impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> { | |
154 | /// # Examples | |
155 | /// | |
156 | /// ``` | |
157 | /// #![feature(range_contains)] | |
158 | /// fn main() { | |
159 | /// assert!( ! (3..).contains(2)); | |
160 | /// assert!( (3..).contains(3)); | |
161 | /// assert!( (3..).contains(1_000_000_000)); | |
162 | /// } | |
163 | /// ``` | |
164 | pub fn contains(&self, item: Idx) -> bool { | |
165 | (self.start <= item) | |
166 | } | |
167 | } | |
168 | ||
169 | /// A range which is only bounded above: { x | x < end }. | |
170 | /// Use `..end` (two dots) for its shorthand. | |
171 | /// | |
172 | /// See the [`contains`](#method.contains) method for its characterization. | |
173 | /// | |
174 | /// It cannot serve as an iterator because it doesn't have a starting point. | |
175 | /// | |
176 | /// # Examples | |
177 | /// | |
178 | /// The `..{integer}` syntax is a `RangeTo`: | |
179 | /// | |
180 | /// ``` | |
181 | /// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); | |
182 | /// ``` | |
183 | /// | |
184 | /// It does not have an `IntoIterator` implementation, so you can't use it in a | |
185 | /// `for` loop directly. This won't compile: | |
186 | /// | |
187 | /// ```compile_fail,E0277 | |
188 | /// for i in ..5 { | |
189 | /// // ... | |
190 | /// } | |
191 | /// ``` | |
192 | /// | |
193 | /// When used as a slicing index, `RangeTo` produces a slice of all array | |
194 | /// elements before the index indicated by `end`. | |
195 | /// | |
196 | /// ``` | |
197 | /// let arr = [0, 1, 2, 3]; | |
198 | /// assert_eq!(arr[ .. ], [0,1,2,3]); | |
199 | /// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo | |
200 | /// assert_eq!(arr[1.. ], [ 1,2,3]); | |
201 | /// assert_eq!(arr[1..3], [ 1,2 ]); | |
202 | /// ``` | |
203 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
204 | #[stable(feature = "rust1", since = "1.0.0")] | |
205 | pub struct RangeTo<Idx> { | |
206 | /// The upper bound of the range (exclusive). | |
207 | #[stable(feature = "rust1", since = "1.0.0")] | |
208 | pub end: Idx, | |
209 | } | |
210 | ||
211 | #[stable(feature = "rust1", since = "1.0.0")] | |
212 | impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> { | |
213 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
214 | write!(fmt, "..{:?}", self.end) | |
215 | } | |
216 | } | |
217 | ||
218 | #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] | |
219 | impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { | |
220 | /// # Examples | |
221 | /// | |
222 | /// ``` | |
223 | /// #![feature(range_contains)] | |
224 | /// fn main() { | |
225 | /// assert!( (..5).contains(-1_000_000_000)); | |
226 | /// assert!( (..5).contains(4)); | |
227 | /// assert!( ! (..5).contains(5)); | |
228 | /// } | |
229 | /// ``` | |
230 | pub fn contains(&self, item: Idx) -> bool { | |
231 | (item < self.end) | |
232 | } | |
233 | } | |
234 | ||
235 | /// An inclusive range which is bounded at both ends: { x | start <= x <= end }. | |
236 | /// Use `start...end` (three dots) for its shorthand. | |
237 | /// | |
238 | /// See the [`contains`](#method.contains) method for its characterization. | |
239 | /// | |
240 | /// # Examples | |
241 | /// | |
242 | /// ``` | |
243 | /// #![feature(inclusive_range,inclusive_range_syntax)] | |
244 | /// fn main() { | |
245 | /// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 }); | |
246 | /// assert_eq!(3+4+5, (3...5).sum()); | |
247 | /// | |
248 | /// let arr = [0, 1, 2, 3]; | |
249 | /// assert_eq!(arr[ ...2], [0,1,2 ]); | |
250 | /// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive | |
251 | /// } | |
252 | /// ``` | |
253 | #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 | |
254 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] | |
255 | pub struct RangeInclusive<Idx> { | |
256 | /// The lower bound of the range (inclusive). | |
257 | #[unstable(feature = "inclusive_range", | |
258 | reason = "recently added, follows RFC", | |
259 | issue = "28237")] | |
260 | pub start: Idx, | |
261 | /// The upper bound of the range (inclusive). | |
262 | #[unstable(feature = "inclusive_range", | |
263 | reason = "recently added, follows RFC", | |
264 | issue = "28237")] | |
265 | pub end: Idx, | |
266 | } | |
267 | ||
268 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] | |
269 | impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> { | |
270 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
271 | write!(fmt, "{:?}...{:?}", self.start, self.end) | |
272 | } | |
273 | } | |
274 | ||
275 | #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] | |
276 | impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { | |
277 | /// # Examples | |
278 | /// | |
279 | /// ``` | |
280 | /// #![feature(range_contains,inclusive_range_syntax)] | |
281 | /// fn main() { | |
282 | /// assert!( ! (3...5).contains(2)); | |
283 | /// assert!( (3...5).contains(3)); | |
284 | /// assert!( (3...5).contains(4)); | |
285 | /// assert!( (3...5).contains(5)); | |
286 | /// assert!( ! (3...5).contains(6)); | |
287 | /// | |
288 | /// assert!( (3...3).contains(3)); | |
289 | /// assert!( ! (3...2).contains(3)); | |
290 | /// } | |
291 | /// ``` | |
292 | pub fn contains(&self, item: Idx) -> bool { | |
293 | self.start <= item && item <= self.end | |
294 | } | |
295 | } | |
296 | ||
297 | /// An inclusive range which is only bounded above: { x | x <= end }. | |
298 | /// Use `...end` (three dots) for its shorthand. | |
299 | /// | |
300 | /// See the [`contains`](#method.contains) method for its characterization. | |
301 | /// | |
302 | /// It cannot serve as an iterator because it doesn't have a starting point. | |
303 | /// | |
304 | /// # Examples | |
305 | /// | |
306 | /// The `...{integer}` syntax is a `RangeToInclusive`: | |
307 | /// | |
308 | /// ``` | |
309 | /// #![feature(inclusive_range,inclusive_range_syntax)] | |
310 | /// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); | |
311 | /// ``` | |
312 | /// | |
313 | /// It does not have an `IntoIterator` implementation, so you can't use it in a | |
314 | /// `for` loop directly. This won't compile: | |
315 | /// | |
316 | /// ```compile_fail,E0277 | |
317 | /// #![feature(inclusive_range_syntax)] | |
318 | /// for i in ...5 { | |
319 | /// // ... | |
320 | /// } | |
321 | /// ``` | |
322 | /// | |
323 | /// When used as a slicing index, `RangeToInclusive` produces a slice of all | |
324 | /// array elements up to and including the index indicated by `end`. | |
325 | /// | |
326 | /// ``` | |
327 | /// #![feature(inclusive_range_syntax)] | |
328 | /// let arr = [0, 1, 2, 3]; | |
329 | /// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive | |
330 | /// assert_eq!(arr[1...2], [ 1,2 ]); | |
331 | /// ``` | |
332 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
333 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] | |
334 | pub struct RangeToInclusive<Idx> { | |
335 | /// The upper bound of the range (inclusive) | |
336 | #[unstable(feature = "inclusive_range", | |
337 | reason = "recently added, follows RFC", | |
338 | issue = "28237")] | |
339 | pub end: Idx, | |
340 | } | |
341 | ||
342 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] | |
343 | impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> { | |
344 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
345 | write!(fmt, "...{:?}", self.end) | |
346 | } | |
347 | } | |
348 | ||
349 | #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] | |
350 | impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> { | |
351 | /// # Examples | |
352 | /// | |
353 | /// ``` | |
354 | /// #![feature(range_contains,inclusive_range_syntax)] | |
355 | /// fn main() { | |
356 | /// assert!( (...5).contains(-1_000_000_000)); | |
357 | /// assert!( (...5).contains(5)); | |
358 | /// assert!( ! (...5).contains(6)); | |
359 | /// } | |
360 | /// ``` | |
361 | pub fn contains(&self, item: Idx) -> bool { | |
362 | (item <= self.end) | |
363 | } | |
364 | } | |
365 | ||
366 | // RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>> | |
367 | // because underflow would be possible with (..0).into() |