]> git.lizzy.rs Git - rust.git/blob - src/libstd/either.rs
auto merge of #10519 : nikomatsakis/rust/issue-8624-borrowck-overly-permissive, r...
[rust.git] / src / libstd / either.rs
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 //! A type that represents one of two alternatives
12
13 #[allow(missing_doc)];
14
15 use option::{Some, None};
16 use option;
17 use clone::Clone;
18 use container::Container;
19 use cmp::Eq;
20 use iter::{Iterator, FilterMap};
21 use result::Result;
22 use result;
23 use str::StrSlice;
24 use vec;
25 use vec::{OwnedVector, ImmutableVector};
26
27 /// `Either` is a type that represents one of two alternatives
28 #[deriving(Clone, Eq, IterBytes)]
29 pub enum Either<L, R> {
30     Left(L),
31     Right(R)
32 }
33
34 impl<L, R> Either<L, R> {
35     /// Applies a function based on the given either value
36     ///
37     /// If `value` is `Left(L)` then `f_left` is applied to its contents, if
38     /// `value` is `Right(R)` then `f_right` is applied to its contents, and the
39     /// result is returned.
40     #[inline]
41     pub fn either<T>(&self, f_left: |&L| -> T, f_right: |&R| -> T) -> T {
42         match *self {
43             Left(ref l) => f_left(l),
44             Right(ref r) => f_right(r)
45         }
46     }
47
48     /// Flips between left and right of a given `Either`
49     #[inline]
50     pub fn flip(self) -> Either<R, L> {
51         match self {
52             Right(r) => Left(r),
53             Left(l) => Right(l)
54         }
55     }
56
57     /// Checks whether the given value is a `Left`
58     #[inline]
59     pub fn is_left(&self) -> bool {
60         match *self {
61             Left(_) => true,
62             _ => false
63         }
64     }
65
66     /// Checks whether the given value is a `Right`
67     #[inline]
68     pub fn is_right(&self) -> bool {
69         match *self {
70             Right(_) => true,
71             _ => false
72         }
73     }
74
75     /// Retrieves the value from a `Left`.
76     /// Fails with a specified reason if the `Either` is `Right`.
77     #[inline]
78     pub fn expect_left(self, reason: &str) -> L {
79         match self {
80             Left(x) => x,
81             Right(_) => fail!("{}", reason.to_owned())
82         }
83     }
84
85     /// Retrieves the value from a `Left`. Fails if the `Either` is `Right`.
86     #[inline]
87     pub fn unwrap_left(self) -> L {
88         self.expect_left("called Either::unwrap_left()` on `Right` value")
89     }
90
91     /// Retrieves the value from a `Right`.
92     /// Fails with a specified reason if the `Either` is `Left`.
93     #[inline]
94     pub fn expect_right(self, reason: &str) -> R {
95         match self {
96             Right(x) => x,
97             Left(_) => fail!("{}", reason.to_owned())
98         }
99     }
100
101     /// Retrieves the value from a `Right`. Fails if the `Either` is `Left`.
102     #[inline]
103     pub fn unwrap_right(self) -> R {
104         self.expect_right("called Either::unwrap_right()` on `Left` value")
105     }
106 }
107
108 /// A generic trait for converting a value to a `Either`
109 pub trait ToEither<L, R> {
110     /// Convert to the `either` type
111     fn to_either(&self) -> Either<L, R>;
112 }
113
114 /// A generic trait for converting a value to a `Either`
115 pub trait IntoEither<L, R> {
116     /// Convert to the `either` type
117     fn into_either(self) -> Either<L, R>;
118 }
119
120 /// A generic trait for converting a value to a `Either`
121 pub trait AsEither<L, R> {
122     /// Convert to the `either` type
123     fn as_either<'a>(&'a self) -> Either<&'a L, &'a R>;
124 }
125
126 impl<L, R: Clone> option::ToOption<R> for Either<L, R> {
127     #[inline]
128     fn to_option(&self)-> option::Option<R> {
129         match *self {
130             Left(_) => None,
131             Right(ref r) => Some(r.clone()),
132         }
133     }
134 }
135
136 impl<L, R> option::IntoOption<R> for Either<L, R> {
137     #[inline]
138     fn into_option(self)-> option::Option<R> {
139         match self {
140             Left(_) => None,
141             Right(r) => Some(r),
142         }
143     }
144 }
145
146 impl<L, R> option::AsOption<R> for Either<L, R> {
147     #[inline]
148     fn as_option<'a>(&'a self) -> option::Option<&'a R> {
149         match *self {
150             Left(_) => None,
151             Right(ref r) => Some(r),
152         }
153     }
154 }
155
156 impl<L: Clone, R: Clone> result::ToResult<R, L> for Either<L, R> {
157     #[inline]
158     fn to_result(&self)-> result::Result<R, L> {
159         match *self {
160             Left(ref l) => result::Err(l.clone()),
161             Right(ref r) => result::Ok(r.clone()),
162         }
163     }
164 }
165
166 impl<L, R> result::IntoResult<R, L> for Either<L, R> {
167     #[inline]
168     fn into_result(self)-> result::Result<R, L> {
169         match self {
170             Left(l) => result::Err(l),
171             Right(r) => result::Ok(r),
172         }
173     }
174 }
175
176 impl<L, R> result::AsResult<R, L> for Either<L, R> {
177     #[inline]
178     fn as_result<'a>(&'a self) -> result::Result<&'a R, &'a L> {
179         match *self {
180             Left(ref l) => result::Err(l),
181             Right(ref r) => result::Ok(r),
182         }
183     }
184 }
185
186 impl<L: Clone, R: Clone> ToEither<L, R> for Either<L, R> {
187     fn to_either(&self) -> Either<L, R> { self.clone() }
188 }
189
190 impl<L, R> IntoEither<L, R> for Either<L, R> {
191     fn into_either(self) -> Either<L, R> { self }
192 }
193
194 impl<L, R> AsEither<L, R> for Either<L, R> {
195     fn as_either<'a>(&'a self) -> Either<&'a L, &'a R> {
196         match *self {
197             Left(ref l) => Left(l),
198             Right(ref r) => Right(r),
199         }
200     }
201 }
202
203 /// An iterator yielding the `Left` values of its source
204 pub type Lefts<L, R, Iter> = FilterMap<'static, Either<L, R>, L, Iter>;
205
206 /// An iterator yielding the `Right` values of its source
207 pub type Rights<L, R, Iter> = FilterMap<'static, Either<L, R>, R, Iter>;
208
209 /// Extracts all the left values
210 pub fn lefts<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
211     -> Lefts<L, R, Iter> {
212     eithers.filter_map(|elt| {
213         match elt {
214             Left(x) => Some(x),
215             _ => None,
216         }
217     })
218 }
219
220 /// Extracts all the right values
221 pub fn rights<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
222     -> Rights<L, R, Iter> {
223     eithers.filter_map(|elt| {
224         match elt {
225             Right(x) => Some(x),
226             _ => None,
227         }
228     })
229 }
230
231
232 // FIXME: #8228 Replaceable by an external iterator?
233 /// Extracts from a vector of either all the left values and right values
234 ///
235 /// Returns a structure containing a vector of left values and a vector of
236 /// right values.
237 pub fn partition<L, R>(eithers: ~[Either<L, R>]) -> (~[L], ~[R]) {
238     let n_lefts = eithers.iter().count(|elt| elt.is_left());
239     let mut lefts = vec::with_capacity(n_lefts);
240     let mut rights = vec::with_capacity(eithers.len() - n_lefts);
241     for elt in eithers.move_iter() {
242         match elt {
243             Left(l) => lefts.push(l),
244             Right(r) => rights.push(r)
245         }
246     }
247     return (lefts, rights);
248 }
249
250 #[cfg(test)]
251 mod tests {
252     use super::*;
253
254     use option::{IntoOption, ToOption, AsOption};
255     use option;
256     use result::{IntoResult, ToResult, AsResult};
257     use result;
258
259     #[test]
260     fn test_either_left() {
261         let val = Left(10);
262         fn f_left(x: &int) -> bool { *x == 10 }
263         fn f_right(_x: &uint) -> bool { false }
264         assert!(val.either(f_left, f_right));
265     }
266
267     #[test]
268     fn test_either_right() {
269         let val = Right(10u);
270         fn f_left(_x: &int) -> bool { false }
271         fn f_right(x: &uint) -> bool { *x == 10u }
272         assert!(val.either(f_left, f_right));
273     }
274
275     #[test]
276     fn test_lefts() {
277         let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
278         let result = lefts(input.move_iter()).to_owned_vec();
279         assert_eq!(result, ~[10, 12, 14]);
280     }
281
282     #[test]
283     fn test_lefts_none() {
284         let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
285         let result = lefts(input.move_iter()).to_owned_vec();
286         assert_eq!(result.len(), 0u);
287     }
288
289     #[test]
290     fn test_lefts_empty() {
291         let input: ~[Either<int, int>] = ~[];
292         let result = lefts(input.move_iter()).to_owned_vec();
293         assert_eq!(result.len(), 0u);
294     }
295
296     #[test]
297     fn test_rights() {
298         let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
299         let result = rights(input.move_iter()).to_owned_vec();
300         assert_eq!(result, ~[11, 13]);
301     }
302
303     #[test]
304     fn test_rights_none() {
305         let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
306         let result = rights(input.move_iter()).to_owned_vec();
307         assert_eq!(result.len(), 0u);
308     }
309
310     #[test]
311     fn test_rights_empty() {
312         let input: ~[Either<int, int>] = ~[];
313         let result = rights(input.move_iter()).to_owned_vec();
314         assert_eq!(result.len(), 0u);
315     }
316
317     #[test]
318     fn test_partition() {
319         let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
320         let (lefts, rights) = partition(input);
321         assert_eq!(lefts[0], 10);
322         assert_eq!(lefts[1], 12);
323         assert_eq!(lefts[2], 14);
324         assert_eq!(rights[0], 11);
325         assert_eq!(rights[1], 13);
326     }
327
328     #[test]
329     fn test_partition_no_lefts() {
330         let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
331         let (lefts, rights) = partition(input);
332         assert_eq!(lefts.len(), 0u);
333         assert_eq!(rights.len(), 2u);
334     }
335
336     #[test]
337     fn test_partition_no_rights() {
338         let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
339         let (lefts, rights) = partition(input);
340         assert_eq!(lefts.len(), 2u);
341         assert_eq!(rights.len(), 0u);
342     }
343
344     #[test]
345     fn test_partition_empty() {
346         let input: ~[Either<int, int>] = ~[];
347         let (lefts, rights) = partition(input);
348         assert_eq!(lefts.len(), 0u);
349         assert_eq!(rights.len(), 0u);
350     }
351
352     #[test]
353     pub fn test_to_option() {
354         let right: Either<int, int> = Right(100);
355         let left: Either<int, int> = Left(404);
356
357         assert_eq!(right.to_option(), option::Some(100));
358         assert_eq!(left.to_option(), option::None);
359     }
360
361     #[test]
362     pub fn test_into_option() {
363         let right: Either<int, int> = Right(100);
364         let left: Either<int, int> = Left(404);
365
366         assert_eq!(right.into_option(), option::Some(100));
367         assert_eq!(left.into_option(), option::None);
368     }
369
370     #[test]
371     pub fn test_as_option() {
372         let right: Either<int, int> = Right(100);
373         let left: Either<int, int> = Left(404);
374
375         assert_eq!(right.as_option().unwrap(), &100);
376         assert_eq!(left.as_option(), option::None);
377     }
378
379     #[test]
380     pub fn test_to_result() {
381         let right: Either<int, int> = Right(100);
382         let left: Either<int, int> = Left(404);
383
384         assert_eq!(right.to_result(), result::Ok(100));
385         assert_eq!(left.to_result(), result::Err(404));
386     }
387
388     #[test]
389     pub fn test_into_result() {
390         let right: Either<int, int> = Right(100);
391         let left: Either<int, int> = Left(404);
392
393         assert_eq!(right.into_result(), result::Ok(100));
394         assert_eq!(left.into_result(), result::Err(404));
395     }
396
397     #[test]
398     pub fn test_as_result() {
399         let right: Either<int, int> = Right(100);
400         let left: Either<int, int> = Left(404);
401
402         let x = 100;
403         assert_eq!(right.as_result(), result::Ok(&x));
404
405         let x = 404;
406         assert_eq!(left.as_result(), result::Err(&x));
407     }
408
409     #[test]
410     pub fn test_to_either() {
411         let right: Either<int, int> = Right(100);
412         let left: Either<int, int> = Left(404);
413
414         assert_eq!(right.to_either(), Right(100));
415         assert_eq!(left.to_either(), Left(404));
416     }
417
418     #[test]
419     pub fn test_into_either() {
420         let right: Either<int, int> = Right(100);
421         let left: Either<int, int> = Left(404);
422
423         assert_eq!(right.into_either(), Right(100));
424         assert_eq!(left.into_either(), Left(404));
425     }
426
427     #[test]
428     pub fn test_as_either() {
429         let right: Either<int, int> = Right(100);
430         let left: Either<int, int> = Left(404);
431
432         assert_eq!(right.as_either().unwrap_right(), &100);
433         assert_eq!(left.as_either().unwrap_left(), &404);
434     }
435 }