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
//! Implementation of [`At`](../trait.At.html) for core datatypes.
//!
//! The following traits are implemented:
//! * `At<usize, View=T> for [T]`: simple indexing
//! * `At<range, View=[T]> for [T]`: subslice (of fixed size)
//! * `At<(), View=T> for Option<T>`: the only meaningful sort of access
//! * `At<(), View=R> for Result<R,E>`: access to the `Ok` value
//!
//! All implementations never panic: `None` is returned instead if the 
//! index doesn't make sense. If you want panicking behaviour simply 
//! add `.unwrap()` to your access:
//!
//! ``` should_panic
//! # use smart_access::Cps;
//! let mut foo = [0,1,2];
//!
//! (&mut foo[..]).at(3).access(|x| { *x += 1; }).unwrap();
//! ```
//!
//! is the same as
//!
//! ``` should_panic
//! # use smart_access::Cps;
//! # let mut foo = [0,1,2];
//! (&mut foo[..])[3].access(|x| { *x += 1; });
//! ```

mod slice;

#[test]#[cfg(feature="alloc")]
fn test_slice() {
    use crate::Cps;
    use alloc::vec;

    let mut foo = vec![1,2,3,4,5];

    let update = |i| move |slice: &mut [i32]| {
        let old_value = slice[0];
        
        slice[0] = i;

        old_value
    };
    
    assert!((&mut foo[..]).at(1..3).access(update(6)) == Some(2));
    assert!(foo == vec![1,6,3,4,5]);
    
    assert!((&mut foo[..]).at(2..).access(update(7)) == Some(3));
    assert!(foo == vec![1,6,7,4,5]);
    
    assert!((&mut foo[..]).at(..4).access(update(8)) == Some(1));
    assert!(foo == vec![8,6,7,4,5]);
    
    assert!((&mut foo[..]).at(..).access(update(9)) == Some(8));
    assert!(foo == vec![9,6,7,4,5]);
    
    assert!((&mut foo[..]).at(..=6).access(update(1)) == None);
    assert!(foo == vec![9,6,7,4,5]);
    
    assert!((&mut foo[..]).at(3..=4).access(update(0)) == Some(4));
    assert!(foo == vec![9,6,7,0,5]);

    assert!((&mut foo[..]).at(4).replace(1) == Some(5));
    assert!(foo == vec![9,6,7,0,1]);
}


// Other implementations

use crate::At;

impl<T> At<()> for Option<T> {
    type View = T;

    fn access_at<R, F>(&mut self, _: (), f: F) -> Option<R> where
        F: FnOnce(&mut T) -> R
    {
        match self {
            Some(x) => Some(f(x)),
            None    => None,
        }
    }
}

impl<T,S> At<()> for Result<T,S> {
    type View = T;

    fn access_at<R, F>(&mut self, _: (), f: F) -> Option<R> where
        F: FnOnce(&mut T) -> R
    {
        match self {
            Ok(x)  => Some(f(x)),
            Err(_) => None,
        }
    }
}


#[test]
fn test_optional() {
    use crate::Cps;

    let mut foo: Option<i32> = Some(0);
    let mut bar: Option<i32> = None;

    assert!(foo.at(()).replace(1) == Some(0));
    assert!(foo == Some(1));
    assert!(bar.at(()).replace(2) == None);
    assert!(bar == None);

    let mut foo: Result<i32,i32> = Ok(0);
    let mut bar: Result<i32,i32> = Err(1);
    
    assert!(foo.at(()).replace(1) == Some(0));
    assert!(foo == Ok(1));
    assert!(bar.at(()).replace(2) == None);
    assert!(bar == Err(1));
}