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.
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.
11 //! A type representing either success or failure
13 #[allow(missing_doc)];
18 use iterator::Iterator;
19 use option::{None, Option, Some, OptionIterator};
21 use vec::{OwnedVector, ImmutableVector};
22 use container::Container;
26 /// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
28 /// In order to provide informative error messages, `E` is reqired to implement `ToStr`.
29 /// It is further recommended for `E` to be a descriptive error type, eg a `enum` for
30 /// all possible errors cases.
31 #[deriving(Clone, Eq)]
32 pub enum Result<T, E> {
33 /// Contains the successful result value
35 /// Contains the error value
39 impl<T, E: ToStr> Result<T, E> {
40 /// Convert to the `either` type
42 /// `Ok` result variants are converted to `either::Right` variants, `Err`
43 /// result variants are converted to `either::Left`.
45 pub fn to_either(self)-> either::Either<E, T>{
47 Ok(t) => either::Right(t),
48 Err(e) => either::Left(e),
52 /// Get a reference to the value out of a successful result
56 /// If the result is an error
58 pub fn get_ref<'a>(&'a self) -> &'a T {
61 Err(ref e) => fail!("called `Result::get_ref()` on `Err` value: %s", e.to_str()),
65 /// Returns true if the result is `Ok`
67 pub fn is_ok(&self) -> bool {
74 /// Returns true if the result is `Err`
76 pub fn is_err(&self) -> bool {
80 /// Call a method based on a previous result
82 /// If `self` is `Ok` then the value is extracted and passed to `op`
83 /// whereupon `op`s result is returned. if `self` is `Err` then it is
84 /// immediately returned. This function can be used to compose the results
89 /// for buf in read_file(file) {
93 pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
100 /// Call a method based on a previous result
102 /// If `self` is `Err` then the value is extracted and passed to `op`
103 /// whereupon `op`s result is returned. if `self` is `Ok` then it is
104 /// immediately returned. This function can be used to pass through a
105 /// successful result while handling an error.
107 pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
110 Err(ref t) => Some(t),
114 /// Unwraps a result, yielding the content of an `Ok`.
115 /// Fails if the value is a `Err` with an error message derived
116 /// from `E`'s `ToStr` implementation.
118 pub fn unwrap(self) -> T {
121 Err(e) => fail!("called `Result::unwrap()` on `Err` value: %s", e.to_str()),
125 /// Unwraps a result, yielding the content of an `Err`.
126 /// Fails if the value is a `Ok`.
128 pub fn unwrap_err(self) -> E {
129 self.expect_err("called `Result::unwrap_err()` on `Ok` value")
132 /// Unwraps a result, yielding the content of an `Ok`.
133 /// Fails if the value is a `Err` with a custom failure message.
135 pub fn expect(self, reason: &str) -> T {
138 Err(_) => fail!(reason.to_owned()),
142 /// Unwraps a result, yielding the content of an `Err`
143 /// Fails if the value is a `Ok` with a custom failure message.
145 pub fn expect_err(self, reason: &str) -> E {
148 Ok(_) => fail!(reason.to_owned()),
152 /// Call a method based on a previous result
154 /// If `self` is `Ok` then the value is extracted and passed to `op`
155 /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is
156 /// `Err` then it is immediately returned. This function can be used to
157 /// compose the results of two functions.
161 /// let res = do read_file(file).map_move |buf| {
165 pub fn map_move<U>(self, op: &fn(T) -> U) -> Result<U,E> {
172 /// Call a method based on a previous result
174 /// If `self` is `Err` then the value is extracted and passed to `op`
175 /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is
176 /// `Ok` then it is immediately returned. This function can be used to pass
177 /// through a successful result while handling an error.
179 pub fn map_err_move<F>(self, op: &fn(E) -> F) -> Result<T,F> {
186 /// Call a method based on a previous result
188 /// If `self` is `Ok` then the value is extracted and passed to `op`
189 /// whereupon `op`s result is returned. if `self` is `Err` then it is
190 /// immediately returned. This function can be used to compose the results
191 /// of two functions.
195 /// let res = do read_file(file) |buf| {
196 /// Ok(parse_bytes(buf))
199 pub fn chain<U>(self, op: &fn(T) -> Result<U, E>) -> Result<U, E> {
206 /// Call a function based on a previous result
208 /// If `self` is `Err` then the value is extracted and passed to `op`
209 /// whereupon `op`s result is returned. if `self` is `Ok` then it is
210 /// immediately returned. This function can be used to pass through a
211 /// successful result while handling an error.
213 pub fn chain_err<F>(self, op: &fn(E) -> Result<T, F>) -> Result<T, F> {
221 impl<T: Clone, E: ToStr> Result<T, E> {
222 /// Call a method based on a previous result
224 /// If `self` is `Err` then the value is extracted and passed to `op`
225 /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is
226 /// `Ok` then it is immediately returned. This function can be used to pass
227 /// through a successful result while handling an error.
229 pub fn map_err<F: Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> {
231 Ok(ref t) => Ok(t.clone()),
232 Err(ref e) => Err(op(e))
237 impl<T, E: Clone + ToStr> Result<T, E> {
238 /// Call a method based on a previous result
240 /// If `self` is `Ok` then the value is extracted and passed to `op`
241 /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is
242 /// `Err` then it is immediately returned. This function can be used to
243 /// compose the results of two functions.
247 /// let res = do read_file(file).map |buf| {
251 pub fn map<U>(&self, op: &fn(&T) -> U) -> Result<U,E> {
253 Ok(ref t) => Ok(op(t)),
254 Err(ref e) => Err(e.clone())
260 #[allow(missing_doc)]
261 pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
262 op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
265 Some(ref t) => match op(t) {
266 Ok(v) => Ok(Some(v)),
272 // FIXME: #8228 Replaceable by an external iterator?
273 /// Maps each element in the vector `ts` using the operation `op`. Should an
274 /// error occur, no further mappings are performed and the error is returned.
275 /// Should no error occur, a vector containing the result of each map is
278 /// Here is an example which increments every integer in a vector,
279 /// checking for overflow:
281 /// fn inc_conditionally(x: uint) -> result<uint,str> {
282 /// if x == uint::max_value { return Err("overflow"); }
283 /// else { return Ok(x+1u); }
285 /// map(~[1u, 2u, 3u], inc_conditionally).chain {|incd|
286 /// assert!(incd == ~[2u, 3u, 4u]);
289 pub fn map_vec<T,U,V>(ts: &[T], op: &fn(&T) -> Result<V,U>)
291 let mut vs: ~[V] = vec::with_capacity(ts.len());
295 Err(u) => return Err(u)
301 // FIXME: #8228 Replaceable by an external iterator?
302 /// Same as map, but it operates over two parallel vectors.
304 /// A precondition is used here to ensure that the vectors are the same
305 /// length. While we do not often use preconditions in the standard
306 /// library, a precondition is used here because result::t is generally
307 /// used in 'careful' code contexts where it is both appropriate and easy
308 /// to accommodate an error like the vectors being of different lengths.
310 pub fn map_vec2<S, T, U: ToStr, V>(ss: &[S], ts: &[T],
311 op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
312 assert!(vec::same_length(ss, ts));
314 let mut vs = vec::with_capacity(n);
317 match op(&ss[i],&ts[i]) {
319 Err(u) => return Err(u)
326 // FIXME: #8228 Replaceable by an external iterator?
327 /// Applies op to the pairwise elements from `ss` and `ts`, aborting on
328 /// error. This could be implemented using `map_zip()` but it is more efficient
329 /// on its own as no result vector is built.
331 pub fn iter_vec2<S, T, U: ToStr>(ss: &[S], ts: &[T],
332 op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
333 assert!(vec::same_length(ss, ts));
337 match op(&ss[i],&ts[i]) {
339 Err(u) => return Err(u)
353 pub fn op1() -> Result<int, ~str> { Ok(666) }
355 pub fn op2(i: int) -> Result<uint, ~str> {
359 pub fn op3() -> Result<int, ~str> { Err(~"sadface") }
362 pub fn chain_success() {
363 assert_eq!(op1().chain(op2).unwrap(), 667u);
367 pub fn chain_failure() {
368 assert_eq!(op3().chain( op2).unwrap_err(), ~"sadface");
372 pub fn test_impl_iter() {
373 let mut valid = false;
374 let okval = Ok::<~str, ~str>(~"a");
375 do okval.iter().next().map |_| { valid = true; };
378 let errval = Err::<~str, ~str>(~"b");
379 do errval.iter().next().map |_| { valid = false; };
384 pub fn test_impl_iter_err() {
385 let mut valid = true;
386 let okval = Ok::<~str, ~str>(~"a");
387 do okval.iter_err().next().map |_| { valid = false };
391 let errval = Err::<~str, ~str>(~"b");
392 do errval.iter_err().next().map |_| { valid = true };
397 pub fn test_impl_map() {
398 assert_eq!(Ok::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Ok(~"ba"));
399 assert_eq!(Err::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Err(~"a"));
403 pub fn test_impl_map_err() {
404 assert_eq!(Ok::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Ok(~"a"));
405 assert_eq!(Err::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Err(~"ba"));
409 pub fn test_impl_map_move() {
410 assert_eq!(Ok::<~str, ~str>(~"a").map_move(|x| x + ~"b"), Ok(~"ab"));
411 assert_eq!(Err::<~str, ~str>(~"a").map_move(|x| x + ~"b"), Err(~"a"));
415 pub fn test_impl_map_err_move() {
416 assert_eq!(Ok::<~str, ~str>(~"a").map_err_move(|x| x + ~"b"), Ok(~"a"));
417 assert_eq!(Err::<~str, ~str>(~"a").map_err_move(|x| x + ~"b"), Err(~"ab"));
421 pub fn test_get_ref_method() {
422 let foo: Result<int, ()> = Ok(100);
423 assert_eq!(*foo.get_ref(), 100);
427 pub fn test_to_either() {
428 let r: Result<int, ()> = Ok(100);
429 let err: Result<(), int> = Err(404);
431 assert_eq!(r.to_either(), either::Right(100));
432 assert_eq!(err.to_either(), either::Left(404));