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
//! Multi-dimensional arrays with per-dimension specifiable lower bounds
#![doc(html_root_url="https://sfackler.github.io/rust-postgres-array/doc/v0.5.0")]

#[macro_use(to_sql_checked)]
extern crate postgres;
extern crate byteorder;

#[doc(inline)]
pub use array::Array;

pub mod array;
mod impls;

/// Information about a dimension of an array.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Dimension {
    /// The length of the dimension.
    pub len: usize,
    /// The index of the first element of the dimension.
    pub lower_bound: isize,
}

impl Dimension {
    fn shift(&self, idx: isize) -> usize {
        let offset = self.lower_bound;
        assert!(idx >= offset, "out of bounds array access");
        assert!(offset >= 0 || idx <= 0 || usize::max_value() - (-offset) as usize >= idx as usize,
                "out of bounds array access");
        let shifted = idx.wrapping_sub(offset) as usize;
        assert!(shifted < self.len, "out of bounds array access");
        shifted
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_from_vec() {
        let a = Array::from_vec(vec!(0i32, 1, 2), -1);
        assert!(&[Dimension { len: 3, lower_bound: -1 }][..] ==
                a.dimensions());
        assert_eq!(0, a[-1]);
        assert_eq!(1, a[0]);
        assert_eq!(2, a[1]);
    }

    #[test]
    fn test_2d_slice_get() {
        let mut a = Array::from_vec(vec!(0i32, 1, 2), -1);
        a.wrap(1);
        assert_eq!(0, a[(1, -1)]);
        assert_eq!(1, a[(1, 0)]);
        assert_eq!(2, a[(1, 1)]);
    }

    #[test]
    #[should_panic]
    fn test_push_wrong_lower_bound() {
        let mut a = Array::from_vec(vec!(1i32), -1);
        a.push(Array::from_vec(vec!(2), 0));
    }

    #[test]
    #[should_panic]
    fn test_push_wrong_dims() {
        let mut a = Array::from_vec(vec!(1i32), -1);
        a.wrap(1);
        a.push(Array::from_vec(vec!(1, 2), -1));
    }

    #[test]
    #[should_panic]
    fn test_push_wrong_dim_count() {
        let mut a = Array::from_vec(vec!(1i32), -1);
        a.wrap(1);
        let mut b = Array::from_vec(vec!(2), -1);
        b.wrap(1);
        a.push(b);
    }

    #[test]
    fn test_push_ok() {
        let mut a = Array::from_vec(vec!(1i32, 2), 0);
        a.wrap(0);
        a.push(Array::from_vec(vec!(3, 4), 0));
        assert_eq!(1, a[(0, 0)]);
        assert_eq!(2, a[(0, 1)]);
        assert_eq!(3, a[(1, 0)]);
        assert_eq!(4, a[(1, 1)]);
    }

    #[test]
    fn test_3d() {
        let mut a = Array::from_vec(vec!(0i32, 1), 0);
        a.wrap(0);
        a.push(Array::from_vec(vec!(2, 3), 0));
        a.wrap(0);
        let mut b = Array::from_vec(vec!(4, 5), 0);
        b.wrap(0);
        b.push(Array::from_vec(vec!(6, 7), 0));
        a.push(b);
        assert_eq!(0, a[(0, 0, 0)]);
        assert_eq!(1, a[(0, 0, 1)]);
        assert_eq!(2, a[(0, 1, 0)]);
        assert_eq!(3, a[(0, 1, 1)]);
        assert_eq!(4, a[(1, 0, 0)]);
        assert_eq!(5, a[(1, 0, 1)]);
        assert_eq!(6, a[(1, 1, 0)]);
        assert_eq!(7, a[(1, 1, 1)]);
    }

    #[test]
    fn test_mut() {
        let mut a = Array::from_vec(vec!(1i32, 2), 0);
        a.wrap(0);
        a[(0, 0)] = 3;
        assert_eq!(3, a[(0, 0)]);
    }
}