postgres_array/
array.rs

1use std::fmt;
2use std::ops::{Index, IndexMut};
3use std::slice;
4use std::vec;
5
6use crate::Dimension;
7
8/// A multi-dimensional array.
9#[derive(Debug, PartialEq, Eq, Clone)]
10pub struct Array<T> {
11    dims: Vec<Dimension>,
12    data: Vec<T>,
13}
14
15impl<T: fmt::Display> fmt::Display for Array<T> {
16    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
17        if self.dims.iter().any(|dim| dim.lower_bound != 1) {
18            for dim in &self.dims {
19                write!(
20                    fmt,
21                    "[{}:{}]",
22                    dim.lower_bound,
23                    dim.lower_bound + dim.len - 1
24                )?;
25            }
26            write!(fmt, "=")?;
27        }
28        fmt_helper(0, &self.dims, &mut self.data.iter(), fmt)
29    }
30}
31
32fn fmt_helper<'a, T, I>(
33    depth: usize,
34    dims: &[Dimension],
35    data: &mut I,
36    fmt: &mut fmt::Formatter<'_>,
37) -> fmt::Result
38where
39    I: Iterator<Item = &'a T>,
40    T: 'a + fmt::Display,
41{
42    if dims.len() == 0 {
43        return write!(fmt, "{{}}");
44    }
45
46    if depth == dims.len() {
47        return write!(fmt, "{}", data.next().unwrap());
48    }
49
50    write!(fmt, "{{")?;
51    for i in 0..dims[depth].len {
52        if i != 0 {
53            write!(fmt, ",")?;
54        }
55        fmt_helper(depth + 1, dims, data, fmt)?;
56    }
57    write!(fmt, "}}")
58}
59
60impl<T> Array<T> {
61    /// Creates a new `Array` from its underlying components.
62    ///
63    /// The data array should be provided in the higher-dimensional equivalent
64    /// of row-major order.
65    ///
66    /// # Panics
67    ///
68    /// Panics if the number of elements provided does not match the number of
69    /// elements specified by the dimensions.
70    pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
71        assert!(
72            (data.is_empty() && dimensions.is_empty())
73                || data.len() as i32 == dimensions.iter().fold(1, |acc, i| acc * i.len),
74            "size mismatch"
75        );
76        Array {
77            dims: dimensions,
78            data,
79        }
80    }
81
82    /// Creates a new one-dimensional array.
83    pub fn from_vec(data: Vec<T>, lower_bound: i32) -> Array<T> {
84        Array {
85            dims: vec![Dimension {
86                len: data.len() as i32,
87                lower_bound,
88            }],
89            data,
90        }
91    }
92
93    /// Wraps this array in a new dimension of size 1.
94    ///
95    /// For example, the one dimensional array `[1, 2]` would turn into the
96    /// two-dimensional array `[[1, 2]]`.
97    pub fn wrap(&mut self, lower_bound: i32) {
98        self.dims.insert(
99            0,
100            Dimension {
101                len: 1,
102                lower_bound,
103            },
104        );
105    }
106
107    /// Consumes another array, appending it to the top level dimension of this
108    /// array.
109    ///
110    /// The dimensions of the other array must be the same as the dimensions
111    /// of this array with the first dimension removed. This includes lower
112    /// bounds as well as lengths.
113    ///
114    /// For example, if `[3, 4]` is pushed onto `[[1, 2]]`, the result is
115    /// `[[1, 2], [3, 4]]`.
116    ///
117    /// # Panics
118    ///
119    /// Panics if the dimensions of the two arrays do not match.
120    pub fn push(&mut self, other: Array<T>) {
121        assert!(
122            self.dims.len() - 1 == other.dims.len(),
123            "cannot append differently shaped arrays"
124        );
125        for (dim1, dim2) in self.dims.iter().skip(1).zip(other.dims.iter()) {
126            assert!(dim1 == dim2, "cannot append differently shaped arrays");
127        }
128        self.dims[0].len += 1;
129        self.data.extend(other.data);
130    }
131
132    /// Returns the dimensions of this array.
133    pub fn dimensions(&self) -> &[Dimension] {
134        &self.dims
135    }
136
137    fn shift_idx(&self, indices: &[i32]) -> i32 {
138        assert_eq!(self.dims.len(), indices.len());
139        self.dims
140            .iter()
141            .zip(indices.iter().cloned())
142            .rev()
143            .fold((0, 1), |(acc, stride), (dim, idx)| {
144                let shifted = dim.shift(idx);
145                (acc + shifted * stride, dim.len * stride)
146            })
147            .0
148    }
149
150    /// Returns an iterator over references to the elements of the array in the
151    /// higher-dimensional equivalent of row-major order.
152    pub fn iter(&self) -> Iter<'_, T> {
153        Iter {
154            inner: self.data.iter(),
155        }
156    }
157
158    /// Returns an iterator over mutable references to the elements of the
159    /// array in the higher-dimensional equivalent of row-major order.
160    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
161        IterMut {
162            inner: self.data.iter_mut(),
163        }
164    }
165
166    /// Returns the underlying data vector for this Array in the
167    /// higher-dimensional equivalent of row-major order.
168    pub fn into_inner(self) -> Vec<T> {
169        self.data
170    }
171}
172
173/// A trait implemented by types that can index into an `Array`.
174pub trait ArrayIndex {
175    /// Calculates the index into the `Array`'s underlying storage specified
176    /// by the value of `self`.
177    ///
178    /// # Panics
179    ///
180    /// Panics if the value of `self` does not correspond to an in-bounds
181    /// element of the `Array`.
182    fn index<T>(&self, array: &Array<T>) -> i32;
183}
184
185impl<'a> ArrayIndex for &'a [i32] {
186    fn index<T>(&self, array: &Array<T>) -> i32 {
187        array.shift_idx(*self)
188    }
189}
190
191impl ArrayIndex for i32 {
192    fn index<T>(&self, array: &Array<T>) -> i32 {
193        let slice: &[i32] = &[*self];
194        ArrayIndex::index(&slice, array)
195    }
196}
197
198macro_rules! tuple_impl {
199    ($($name:ident : $t:ty),+) => {
200        impl ArrayIndex for ($($t,)+) {
201            fn index<T>(&self, array: &Array<T>) -> i32 {
202                let ($($name,)+) = *self;
203                let slice: &[i32] = &[$($name),+];
204                ArrayIndex::index(&slice, array)
205            }
206        }
207    }
208}
209
210tuple_impl!(a: i32);
211tuple_impl!(a: i32, b: i32);
212tuple_impl!(a: i32, b: i32, c: i32);
213tuple_impl!(a: i32, b: i32, c: i32, d: i32);
214tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32);
215tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32);
216tuple_impl!(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32);
217tuple_impl!(
218    a: i32,
219    b: i32,
220    c: i32,
221    d: i32,
222    e: i32,
223    f: i32,
224    g: i32,
225    h: i32
226);
227tuple_impl!(
228    a: i32,
229    b: i32,
230    c: i32,
231    d: i32,
232    e: i32,
233    f: i32,
234    g: i32,
235    h: i32,
236    i: i32
237);
238
239/// Indexes into the `Array`, retrieving a reference to the contained
240/// value.
241///
242/// Since `Array`s can be multi-dimensional, the `Index` trait is
243/// implemented for a variety of index types. In the most generic case, a
244/// `&[i32]` can be used. In addition, a bare `i32` as well as tuples
245/// of up to 10 `i32` values may be used for convenience.
246///
247/// # Panics
248///
249/// Panics if the index does not correspond to an in-bounds element of the
250/// `Array`.
251///
252/// # Examples
253///
254/// ```rust
255/// # use postgres_array::Array;
256/// let mut array = Array::from_vec(vec![0i32, 1, 2, 3], 0);
257/// assert_eq!(2, array[2]);
258///
259/// array.wrap(0);
260/// array.push(Array::from_vec(vec![4, 5, 6, 7], 0));
261///
262/// assert_eq!(6, array[(1, 2)]);
263/// ```
264impl<T, I: ArrayIndex> Index<I> for Array<T> {
265    type Output = T;
266    fn index(&self, idx: I) -> &T {
267        let idx = idx.index(self);
268        &self.data[idx as usize]
269    }
270}
271
272impl<T, I: ArrayIndex> IndexMut<I> for Array<T> {
273    fn index_mut(&mut self, idx: I) -> &mut T {
274        let idx = idx.index(self);
275        &mut self.data[idx as usize]
276    }
277}
278
279impl<'a, T: 'a> IntoIterator for &'a Array<T> {
280    type Item = &'a T;
281    type IntoIter = Iter<'a, T>;
282
283    fn into_iter(self) -> Iter<'a, T> {
284        self.iter()
285    }
286}
287
288impl<'a, T: 'a> IntoIterator for &'a mut Array<T> {
289    type Item = &'a mut T;
290    type IntoIter = IterMut<'a, T>;
291
292    fn into_iter(self) -> IterMut<'a, T> {
293        self.iter_mut()
294    }
295}
296
297impl<T> IntoIterator for Array<T> {
298    type Item = T;
299    type IntoIter = IntoIter<T>;
300
301    fn into_iter(self) -> IntoIter<T> {
302        IntoIter {
303            inner: self.data.into_iter(),
304        }
305    }
306}
307
308/// An iterator over references to values of an `Array` in the
309/// higher-dimensional equivalent of row-major order.
310pub struct Iter<'a, T> {
311    inner: slice::Iter<'a, T>,
312}
313
314impl<'a, T: 'a> Iterator for Iter<'a, T> {
315    type Item = &'a T;
316
317    fn next(&mut self) -> Option<&'a T> {
318        self.inner.next()
319    }
320
321    fn size_hint(&self) -> (usize, Option<usize>) {
322        self.inner.size_hint()
323    }
324}
325
326impl<'a, T: 'a> DoubleEndedIterator for Iter<'a, T> {
327    fn next_back(&mut self) -> Option<&'a T> {
328        self.inner.next_back()
329    }
330}
331
332impl<'a, T: 'a> ExactSizeIterator for Iter<'a, T> {
333    fn len(&self) -> usize {
334        self.inner.len()
335    }
336}
337
338/// An iterator over mutable references to values of an `Array` in the
339/// higher-dimensional equivalent of row-major order.
340pub struct IterMut<'a, T> {
341    inner: slice::IterMut<'a, T>,
342}
343
344impl<'a, T: 'a> Iterator for IterMut<'a, T> {
345    type Item = &'a mut T;
346
347    fn next(&mut self) -> Option<&'a mut T> {
348        self.inner.next()
349    }
350
351    fn size_hint(&self) -> (usize, Option<usize>) {
352        self.inner.size_hint()
353    }
354}
355
356impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
357    fn next_back(&mut self) -> Option<&'a mut T> {
358        self.inner.next_back()
359    }
360}
361
362impl<'a, T: 'a> ExactSizeIterator for IterMut<'a, T> {
363    fn len(&self) -> usize {
364        self.inner.len()
365    }
366}
367
368/// An iterator over values of an `Array` in the higher-dimensional
369/// equivalent of row-major order.
370pub struct IntoIter<T> {
371    inner: vec::IntoIter<T>,
372}
373
374impl<T> Iterator for IntoIter<T> {
375    type Item = T;
376
377    fn next(&mut self) -> Option<T> {
378        self.inner.next()
379    }
380
381    fn size_hint(&self) -> (usize, Option<usize>) {
382        self.inner.size_hint()
383    }
384}
385
386impl<T> DoubleEndedIterator for IntoIter<T> {
387    fn next_back(&mut self) -> Option<T> {
388        self.inner.next_back()
389    }
390}
391
392impl<T> ExactSizeIterator for IntoIter<T> {
393    fn len(&self) -> usize {
394        self.inner.len()
395    }
396}