1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

/// Extension trait for doing `Result<Option<T>, E>  ->  Result<T, E>`
pub trait ResultOptionExt<T, E, F>
    where T: Sized,
          E: Sized,
          F: FnOnce() -> E
{
    fn inner_ok_or_else(self, f: F) -> Result<T, E>;
}

impl<T, E, F> ResultOptionExt<T, E, F> for Result<Option<T>, E>
    where T: Sized,
          E: Sized,
          F: FnOnce() -> E
{
    fn inner_ok_or_else(self, f: F) -> Result<T, E> {
        self.and_then(|opt| opt.ok_or_else(f))
    }
}



/// Extension trait for doing
///
/// ```ignore
///     Iterator<Item = Result<Option<T>, E>>  ->  Iterator<Item = Result<T, E>>
/// ```
///
pub trait IterInnerOkOrElse<T, E, F>
    where T: Sized,
          E: Sized,
          Self: Iterator<Item = Result<Option<T>, E>> + Sized,
          F: Fn() -> E,
{
    fn map_inner_ok_or_else(self, f: F) -> IterInnerOkOrElseImpl<Self, T, E, F>;
}

pub struct IterInnerOkOrElseImpl<I, T, E, F>(I, F)
    where I: Iterator<Item = Result<Option<T>, E>> + Sized,
          T: Sized,
          E: Sized,
          F: Fn() -> E;

impl<I, T, E, F> IterInnerOkOrElse<T, E, F> for I
    where I: Iterator<Item = Result<Option<T>, E>> + Sized,
          T: Sized,
          E: Sized,
          F: Fn() -> E,
{
    fn map_inner_ok_or_else(self, f: F) -> IterInnerOkOrElseImpl<I, T, E, F> {
        IterInnerOkOrElseImpl(self, f)
    }
}

impl<I, T, E, F> Iterator for IterInnerOkOrElseImpl<I, T, E, F>
    where I: Iterator<Item = Result<Option<T>, E>> + Sized,
          T: Sized,
          E: Sized,
          F: Fn() -> E,
{
    type Item = Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|e| e.and_then(|opt| opt.ok_or_else(|| (self.1)())))
    }
}


#[test]
fn compile_test_1() {
    let v : Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
    let _ : Result<Vec<i32>, &'static str> = v
        .into_iter()
        .map(Some)
        .map(Ok)
        .map_inner_ok_or_else(|| "error message")
        .collect();
}

#[test]
fn compile_test_2() {
    let v : Vec<Option<i32>> = vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(0)];
    let _ : Result<Vec<i32>, &'static str> = v
        .into_iter()
        .map(Ok)
        .map_inner_ok_or_else(|| "error message")
        .collect();
}

#[test]
fn compile_test_3() {
    let v : Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
    let r : Result<Vec<i32>, &'static str> = v
        .into_iter()
        .map(|i| if i < 5 { Some(i) } else { None })
        .map(Ok)
        .map_inner_ok_or_else(|| "less than 5 in list")
        .collect();

    assert!(r.is_err());
    assert_eq!(r.unwrap_err(), "less than 5 in list");
}

#[test]
fn compile_test_4() {
    use std::collections::HashMap;

    let v : Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
    let mut h = HashMap::new();
    (0..10).into_iter().for_each(|e| {
        h.insert(e, e);
    });

    let r : Result<Vec<_>, &'static str> = v
        .into_iter()
        .chain(::std::iter::once(10))
        .map(|e| Ok(h.get(&e)))
        .map_inner_ok_or_else(|| "at least one key missing")
        .collect();

    assert!(r.is_err());
    assert_eq!(r.unwrap_err(), "at least one key missing");
}