[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/psqlpy-python/rust-postgres-array/master/src/array.rs [Back]  [Original]

use std::fmt;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec;

use crate::Dimension;

/// A multi-dimensional array.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Array {
    dims: Vec,
    data: Vec,
}

impl fmt::Display for Array {
    fn fmt(&self, fmt: &mut fmt::Formatter(
    depth: usize,
    dims: &[Dimension],
    data: &mut I,
    fmt: &mut fmt::Formatter,
    T: 'a + fmt::Display,
{
    if dims.len() == 0 {
        return write!(fmt, "{{}}");
    }

    if depth == dims.len() {
        return write!(fmt, "{}", data.next().unwrap());
    }

    write!(fmt, "{{")?;
    for i in 0..dims[depth].len {
        if i != 0 {
            write!(fmt, ",")?;
        }
        fmt_helper(depth + 1, dims, data, fmt)?;
    }
    write!(fmt, "}}")
}

impl Array {
    /// Creates a new `Array` from its underlying components.
    ///
    /// The data array should be provided in the higher-dimensional equivalent
    /// of row-major order.
    ///
    /// # Panics
    ///
    /// Panics if the number of elements provided does not match the number of
    /// elements specified by the dimensions.
    pub fn from_parts(data: Vec, dimensions: Vec) -> Array {
        assert!(
            (data.is_empty() && dimensions.is_empty())
                || data.len() as i32 == dimensions.iter().fold(1, |acc, i| acc * i.len),
            "size mismatch"
        );
        Array {
            dims: dimensions,
            data,
        }
    }

    /// Creates a new one-dimensional array.
    pub fn from_vec(data: Vec, lower_bound: i32) -> Array {
        Array {
            dims: vec![Dimension {
                len: data.len() as i32,
                lower_bound,
            }],
            data,
        }
    }

    /// Wraps this array in a new dimension of size 1.
    ///
    /// For example, the one dimensional array `[1, 2]` would turn into the
    /// two-dimensional array `[[1, 2]]`.
    pub fn wrap(&mut self, lower_bound: i32) {
        self.dims.insert(
            0,
            Dimension {
                len: 1,
                lower_bound,
            },
        );
    }

    /// Consumes another array, appending it to the top level dimension of this
    /// array.
    ///
    /// The dimensions of the other array must be the same as the dimensions
    /// of this array with the first dimension removed. This includes lower
    /// bounds as well as lengths.
    ///
    /// For example, if `[3, 4]` is pushed onto `[[1, 2]]`, the result is
    /// `[[1, 2], [3, 4]]`.
    ///
    /// # Panics
    ///
    /// Panics if the dimensions of the two arrays do not match.
    pub fn push(&mut self, other: Array) {
        assert!(
            self.dims.len() - 1 == other.dims.len(),
            "cannot append differently shaped arrays"
        );
        for (dim1, dim2) in self.dims.iter().skip(1).zip(other.dims.iter()) {
            assert!(dim1 == dim2, "cannot append differently shaped arrays");
        }
        self.dims[0].len += 1;
        self.data.extend(other.data);
    }

    /// Returns the dimensions of this array.
    pub fn dimensions(&self) -> &[Dimension] {
        &self.dims
    }

    fn shift_idx(&self, indices: &[i32]) -> i32 {
        assert_eq!(self.dims.len(), indices.len());
        self.dims
            .iter()
            .zip(indices.iter().cloned())
            .rev()
            .fold((0, 1), |(acc, stride), (dim, idx)| {
                let shifted = dim.shift(idx);
                (acc + shifted * stride, dim.len * stride)
            })
            .0
    }

    /// Returns an iterator over references to the elements of the array in the
    /// higher-dimensional equivalent of row-major order.
    pub fn iter(&self) -> Iter {
        IterMut {
            inner: self.data.iter_mut(),
        }
    }

    /// Returns the underlying data vector for this Array in the
    /// higher-dimensional equivalent of row-major order.
    pub fn into_inner(self) -> Vec {
        self.data
    }
}

/// A trait implemented by types that can index into an `Array`.
pub trait ArrayIndex {
    /// Calculates the index into the `Array`'s underlying storage specified
    /// by the value of `self`.
    ///
    /// # Panics
    ///
    /// Panics if the value of `self` does not correspond to an in-bounds
    /// element of the `Array`.
    fn index(&self, array: &Array) -> i32;
}

impl i32 {
        array.shift_idx(*self)
    }
}

impl ArrayIndex for i32 {
    fn index(&self, array: &Array) -> i32 {
        let slice: &[i32] = &[*self];
        ArrayIndex::index(&slice, array)
    }
}

macro_rules! tuple_impl {
    ($($name:ident : $t:ty),+) => {
        impl ArrayIndex for ($($t,)+) {
            fn index(&self, array: &Array) -> i32 {
                let ($($name,)+) = *self;
                let slice: &[i32] = &[$($name),+];
                ArrayIndex::index(&slice, array)
            }
        }
    }
}

tuple_impl!(a: i32);
tuple_impl!(a: i32, b: i32);
tuple_impl!(a: i32, b: i32, c: i32);
tuple_impl!(a: i32, b: i32, c: i32, d: i32);
tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32);
tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32);
tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32);
tuple_impl!(
    a: i32,
    b: i32,
    c: i32,
    d: i32,
    e: i32,
    f: i32,
    g: i32,
    h: i32
);
tuple_impl!(
    a: i32,
    b: i32,
    c: i32,
    d: i32,
    e: i32,
    f: i32,
    g: i32,
    h: i32,
    i: i32
);

/// Indexes into the `Array`, retrieving a reference to the contained
/// value.
///
/// Since `Array`s can be multi-dimensional, the `Index` trait is
/// implemented for a variety of index types. In the most generic case, a
/// `&[i32]` can be used. In addition, a bare `i32` as well as tuples
/// of up to 10 `i32` values may be used for convenience.
///
/// # Panics
///
/// Panics if the index does not correspond to an in-bounds element of the
/// `Array`.
///
/// # Examples
///
/// ```rust
/// # use postgres_array::Array;
/// let mut array = Array::from_vec(vec![0i32, 1, 2, 3], 0);
/// assert_eq!(2, array[2]);
///
/// array.wrap(0);
/// array.push(Array::from_vec(vec![4, 5, 6, 7], 0));
///
/// assert_eq!(6, array[(1, 2)]);
/// ```
impl Index for Array {
    type Output = T;
    fn index(&self, idx: I) -> &T {
        let idx = idx.index(self);
        &self.data[idx as usize]
    }
}

impl IndexMut for Array {
    fn index_mut(&mut self, idx: I) -> &mut T {
        let idx = idx.index(self);
        &mut self.data[idx as usize]
    }
}

impl IntoIterator for &'a Array {
    type Item = &'a T;
    type IntoIter = Iter {
        self.iter()
    }
}

impl IntoIterator for &'a mut Array {
    type Item = &'a mut T;
    type IntoIter = IterMut {
        self.iter_mut()
    }
}

impl IntoIterator for Array {
    type Item = T;
    type IntoIter = IntoIter;

    fn into_iter(self) -> IntoIter {
        IntoIter {
            inner: self.data.into_iter(),
        }
    }
}

/// An iterator over references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct Iter,
}

impl Iterator for Iter Option {
    fn next_back(&mut self) -> Option {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

/// An iterator over mutable references to values of an `Array` in the
/// higher-dimensional equivalent of row-major order.
pub struct IterMut,
}

impl Iterator for IterMut Option {
    fn next_back(&mut self) -> Option {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

/// An iterator over values of an `Array` in the higher-dimensional
/// equivalent of row-major order.
pub struct IntoIter {
    inner: vec::IntoIter,
}

impl Iterator for IntoIter {
    type Item = T;

    fn next(&mut self) -> Option {
        self.inner.next()
    }

    fn size_hint(&self) -> (usize, Option) {
        self.inner.size_hint()
    }
}

impl DoubleEndedIterator for IntoIter {
    fn next_back(&mut self) -> Option {
        self.inner.next_back()
    }
}

impl ExactSizeIterator for IntoIter {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

Web Proxy Viewer  |  New URL  |  Original Page