bidivec 0.1.0

A crate offering bidimensional arrays, vectors and slices, with batteries included (such as pathfinding, flood-filling and more).
Documentation
use crate::bidiiter::{Iter, IterMut};
use std::cmp::{min, Ordering};
use std::default::Default;
use std::iter::Iterator;
use std::ops::{Index, IndexMut};

use crate::*;

/// A growable bidimensional array type with heap-allocated contents,
/// which trades off linear layout (and memory locality) for faster
/// performances when inserting and deleting items.
///
/// If you don't need to insert items (other than appending rows),
/// [`BidiGrowVec<T>`] offers better memory locality and a linear layout
/// which is friendly for unsafe code.
///
/// BidiGrowVecs have `O(1)` indexing, amortized `O(1)` push of rows (to the end) and
/// `O(row_length)` pops (from the end).
///
/// Most methods will not implicitly panic if out-of-bounds accesses are attempted,
/// but they will return a [`BidiError`] for graceful error handling.
///
/// # Examples
///
/// You can explicitly create a [`BidiGrowVec`] with [`BidiGrowVec::new`]:
///
/// ```
/// # use bidivec::BidiGrowVec;
/// let v: BidiGrowVec<i32> = BidiGrowVec::new();
/// ```
///
/// or by using the [`bidigrowvec!`] macro:
///
/// ```
/// # use bidivec::{BidiGrowVec, bidigrowvec};
/// // this creates an empty bidigrowvec
/// let v: BidiGrowVec<i32> = bidigrowvec![];
///
/// // this creates a 3x2 bidigrowvec, with all items equal to 1
/// let v = bidigrowvec![1; 3, 2];
///
/// // this creates a 3x2 bidigrowvec from items; the final '3' is the
/// // bidigrowvec's width
/// let v = bidigrowvec![1, 2, 3, 4, 5, 6; 3];
///
/// // this creates a 3x2 bidigrowvec, by listing the rows separately
/// let v = bidigrowvec!{
///     [1, 2, 3],
///     [4, 5, 6],
/// };
/// ```
///
/// You can push rows onto the end of a bidigrowvec (which will grow the bidigrowvec
/// as needed):
///
/// ```
/// # use bidivec::{BidiGrowVec, bidigrowvec};
/// let mut v = bidigrowvec![1, 2; 1];
///
/// v.push_row([3, 4]);
/// ```
///
/// Popping rows works in much the same way:
///
/// ```
/// # use bidivec::{BidiGrowVec, bidigrowvec};
/// let mut v = bidigrowvec![1, 2; 1];
///
/// let one_and_two = v.pop_row();
/// ```
///
/// BidiGrowVecs support indexing with cartesian coordinates (through the [`Index`] and [`IndexMut`] traits);
/// note that coordinates out of range will cause the code to panic.
/// The [`BidiGrowVec::get`] and [`BidiGrowVec::get_mut`] methods offer a safer way to access the bidigrowvec contents,
/// by returning an `Option`, in the same vein of `Vec<T>`.
///
/// ```
/// # use bidivec::{BidiGrowVec, bidigrowvec};
/// let mut v = bidigrowvec!{[1, 2, 3], [4, 5, 6]};
/// let four = v[(0, 1)];
/// v[(1, 1)] = v[(1, 0)] + v[(2, 0)];
/// ```
#[derive(Clone, Default, Debug, PartialEq)]
pub struct BidiGrowVec<T> {
    pub(crate) data: Vec<Vec<T>>,
}

impl<T> BidiGrowVec<T> {
    /// Constructs a new, empty [`BidiGrowVec<T>`].
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(unused_mut)]
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec: BidiGrowVec<i32> = BidiGrowVec::new();
    /// ```
    #[inline]
    pub fn new() -> Self {
        Self { data: Vec::new() }
    }

    /// Constructs a new [`BidiGrowVec<T>`] with the specified size,
    /// cloning the specified item in every position.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::with_elem(5, 3, 3);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 5);
    /// ```
    pub fn with_elem(value: T, width: usize, height: usize) -> Self
    where
        T: Clone,
    {
        let mut this = Self {
            data: Vec::with_capacity(height),
        };
        this.resize(width, height, value);
        this
    }

    /// Constructs a new [`BidiGrowVec<T>`] with the specified size,
    /// using the default value in every position.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::<i32>::with_size_default(3, 3);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 0);
    /// ```
    pub fn with_size_default(width: usize, height: usize) -> Self
    where
        T: Default,
    {
        Self::with_size_func(width, height, T::default)
    }

    /// Constructs a new [`BidiGrowVec<T>`] with the specified size,
    /// using the specified closure to produce values.
    /// The order the closure is called when producing a new value is
    /// not guaranteed. If the item produced is depending on the its
    /// coordinates, use the slower `BidiGrowVec<T>::with_size_func_xy`.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::with_size_func(3, 3, ||137);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 137);
    /// ```
    pub fn with_size_func<F>(width: usize, height: usize, f: F) -> Self
    where
        F: FnMut() -> T,
    {
        let mut this = Self {
            data: Vec::with_capacity(height),
        };
        this.resize_with(width, height, f);
        this
    }

    /// Constructs a new [`BidiGrowVec<T>`] with the specified size,
    /// using the specified closure to produce values.
    /// The order the closure is called when producing a new value is
    /// not guaranteed, but the closure will receive the item coordinates
    /// as an input. If the coordinates are not needed, `BidiGrowVec::with_size_func`
    /// is faster and uses less temporary memory (this method uses up
    /// to a row or column size of temporary memory).
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::with_size_func_xy(3, 3, |x,y| x+y);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 3);
    /// ```
    pub fn with_size_func_xy<F>(width: usize, height: usize, f: F) -> Self
    where
        F: FnMut(usize, usize) -> T,
    {
        let mut this = Self {
            data: Vec::with_capacity(height),
        };
        this.resize_with_xy(width, height, f);
        this
    }

    /// Creates a bidigrowvec from a draining iterator, using the specified
    /// `row_size`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
    /// let mut bvec = BidiGrowVec::from_iterator(vec.drain(..), 3).unwrap();
    ///
    /// let expected = bidigrowvec!{
    ///     [0, 1, 2],
    ///     [3, 4, 5],
    ///     [6, 7, 8],
    /// };
    ///
    /// assert_eq!(bvec, expected);
    /// ```
    pub fn from_iterator(
        iter: impl Iterator<Item = T>,
        row_size: usize,
    ) -> Result<Self, BidiError> {
        let vec = iter.collect::<Vec<T>>();
        Self::from_vec(vec, row_size)
    }

    /// Creates a bidigrowvec from another view iterator, using the specified
    /// mapping function to create and/or transform elements.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let from = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// let to = BidiGrowVec::from_view_map(&from, |n| n - 1);
    ///
    /// assert_eq!(to, bidigrowvec!{
    ///     [0, 1, 2],
    ///     [3, 4, 5],
    ///     [6, 7, 8],
    /// });
    /// ```
    pub fn from_view_map<V, F>(view: &V, mapper: F) -> Self
    where
        V: BidiView,
        F: Fn(&V::Output) -> T,
    {
        Self::with_size_func_xy(view.width(), view.height(), |x, y| mapper(&view[(x, y)]))
    }

    /// Creates a [`BidiGrowVec<T>`] from a `Vec<T>` and a specified row size.
    /// Note that, unlike [`BidiVec<T>`] where the operation is O(1), this
    /// constructor is O(n).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
    /// let mut bvec = BidiVec::from_vec(vec, 3).unwrap();
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 7);
    /// ```
    pub fn from_vec(vec: Vec<T>, row_size: usize) -> Result<Self, BidiError> {
        if vec.is_empty() && row_size == 0 {
            Ok(Self { data: Vec::new() })
        } else if row_size != 0 && (vec.len() % row_size) == 0 {
            let height = vec.len() / row_size;
            let mut this = Self {
                data: Vec::with_capacity(height),
            };
            let mut vec = vec;

            for _ in 0..height {
                let rest = vec.split_off(row_size);
                let row = vec;
                vec = rest;
                this.push_row(row)?;
            }

            Ok(this)
        } else {
            Err(BidiError::IncompatibleSize)
        }
    }

    /// Clears the bidigrowvec, removing all values.
    ///
    /// Note that this method has no effect on the allocated capacity
    /// of the bidigrowvec.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec![5; 3, 3];
    ///
    /// bvec.clear();
    ///
    /// assert!(bvec.is_empty());
    /// ```
    pub fn clear(&mut self) {
        self.data.clear();
    }

    /// Returns the number of items contained in the bidigrowvec.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec![5; 4, 3];
    ///
    /// assert_eq!(bvec.len(), 12);
    /// ```
    pub fn len(&self) -> usize {
        self.width() * self.height()
    }

    /// Returns the width (that is, the size of a row) in the bidigrowvec.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec![5; 4, 3];
    ///
    /// assert_eq!(bvec.width(), 4);
    /// ```
    pub fn width(&self) -> usize {
        if self.data.is_empty() {
            0
        } else {
            self.data[0].len()
        }
    }

    /// Returns the height (that is, the size of a column) in the bidigrowvec.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec![5; 4, 3];
    ///
    /// assert_eq!(bvec.height(), 3);
    /// ```
    pub fn height(&self) -> usize {
        self.data.len()
    }

    /// Returns true if the bidigrowvec contains no elements (that
    /// implies that its width, height and len are all zero).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::<i32>::new();
    ///
    /// assert!(bvec.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }

    /// Resizes the[`BidiGrowVec`] in-place so that it has new width and
    /// height.
    ///
    /// Any new item that has to be created is created by cloning the
    /// supplied value.
    /// If the new size is smaller than before in a dimension, the
    ///[`BidiGrowVec`] is truncated.
    ///
    /// This method requires `T` to implement [`Clone`],
    /// in order to be able to clone the passed value.
    /// If you need more flexibility (or want to rely on [`Default`] instead of
    /// [`Clone`]), use [`BidiGrowVec::resize_with`].
    /// If you only need to resize to a smaller size, use [`BidiGrowVec::truncate`].
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.resize(3, 3, 5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 5);
    /// ```
    pub fn resize(&mut self, new_width: usize, new_height: usize, value: T)
    where
        T: Clone,
    {
        if new_width == 0 || new_height == 0 {
            self.clear();
            return;
        }

        self.truncate(min(self.width(), new_width), min(self.height(), new_height))
            .unwrap();

        for _ in self.width()..new_width {
            self.push_col(std::iter::repeat(value.clone()).take(self.height()))
                .unwrap();
        }

        for _ in self.height()..new_height {
            self.push_row(std::iter::repeat(value.clone()).take(new_width))
                .unwrap();
        }
    }

    /// Resizes the[`BidiGrowVec`] in-place so that it has new width and
    /// height, using the specified closure to generate new values.
    /// The order the clousre is called when producing a new value is
    /// not guaranteed. If the item produced is depending on the its
    /// coordinates, use the slower `BidiGrowVec<T>::resize_with_xy`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.resize_with(3, 3, ||5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 5);
    /// ```
    pub fn resize_with<F>(&mut self, new_width: usize, new_height: usize, mut f: F)
    where
        F: FnMut() -> T,
    {
        if new_width == 0 || new_height == 0 {
            self.clear();
            return;
        }

        self.truncate(min(self.width(), new_width), min(self.height(), new_height))
            .unwrap();

        for _ in self.width()..new_width {
            // avoid https://github.com/rust-lang/rust-clippy/issues/8098
            #[allow(clippy::redundant_closure)]
            self.push_col(std::iter::repeat_with(|| f()).take(self.height()))
                .unwrap();
        }

        for _ in self.height()..new_height {
            // avoid https://github.com/rust-lang/rust-clippy/issues/8098
            #[allow(clippy::redundant_closure)]
            self.push_row(std::iter::repeat_with(|| f()).take(new_width))
                .unwrap();
        }
    }

    /// Resizes the[`BidiGrowVec`] (mostly) in-place so that it has new width and
    /// height, using the specified closure to generate new values.
    /// The order the closure is called when producing a new value is
    /// not guaranteed, but the closure will receive the item coordinates
    /// as an input. If the coordinates are not needed, `BidiGrowVec::resize_with`
    /// is faster and uses less temporary memory (this method uses up
    /// to a row or column size of temporary memory).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.resize_with(3, 3, ||5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 2)], 5);
    /// ```
    pub fn resize_with_xy<F>(&mut self, new_width: usize, new_height: usize, mut f: F)
    where
        F: FnMut(usize, usize) -> T,
    {
        if new_width == 0 || new_height == 0 {
            self.clear();
            return;
        }

        self.truncate(min(self.width(), new_width), min(self.height(), new_height))
            .unwrap();

        for x in self.width()..new_width {
            let mut tmp = Vec::with_capacity(self.height());

            for y in 0..self.height() {
                tmp.push(f(x, y));
            }

            self.push_col(tmp).unwrap();
        }

        for y in self.height()..new_height {
            let mut tmp = Vec::with_capacity(new_width);

            for x in 0..new_width {
                tmp.push(f(x, y));
            }

            self.push_row(tmp).unwrap();
        }
    }

    /// Truncates the[`BidiGrowVec`] so that it has new width and
    /// height that must be strictly lower or equal than the current.
    /// width and height, otherwise a [`BidiError::OutOfBounds`] error
    /// is produced.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec![5; 150, 18];
    /// bvec.truncate(3, 4).unwrap();
    ///
    /// assert_eq!(bvec.len(), 12);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 4);
    /// assert_eq!(bvec[(1, 2)], 5);
    /// ```
    pub fn truncate(&mut self, new_width: usize, new_height: usize) -> Result<(), BidiError> {
        if new_width > self.width() || new_height > self.height() {
            return Err(BidiError::OutOfBounds);
        }

        if new_width == self.width() && new_height == self.height() {
            return Ok(());
        }

        if new_width == 0 || new_height == 0 {
            self.clear();
        } else {
            self.data.truncate(new_height);

            for y in 0..new_height {
                self.data[y].truncate(new_width);
            }
        }

        Ok(())
    }

    /// Shrinks the capacity of the bidigrowvec as much as possible.
    pub fn shrink_to_fit(&mut self) {
        for v in self.data.iter_mut() {
            v.shrink_to_fit();
        }

        self.data.shrink_to_fit()
    }

    /// Converts the vector into a `Vec<T>` where items are linearly
    /// laid out by rows.
    /// This is an O(n) operation; if you need faster conversion to and
    /// from `Vec<T>` consider using [`BidiVec<T>`].
    pub fn into_vec(self) -> Vec<T> {
        let mut result = Vec::with_capacity(self.height() * self.width());
        let mut data = self.data;

        for mut row in data.drain(..) {
            result.append(&mut row);
        }

        result
    }

    /// Converts the vector into a `Vec<Vec<T>>` where items are arranged
    /// as in a vec of rows, where each row is itself a vec of items.
    /// This is O(1).
    pub fn into_vec_of_vec(self) -> Vec<Vec<T>> {
        self.data
    }

    /// Swaps two elements in the bidigrowvec. If any of the coordinates are out
    /// of range, [`BidiError::OutOfBounds`] is returned
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec[(2, 0)], 3);
    /// assert_eq!(bvec[(1, 2)], 8);
    ///
    /// bvec.swap((2, 0), (1, 2)).unwrap();
    ///
    /// assert_eq!(bvec[(2, 0)], 8);
    /// assert_eq!(bvec[(1, 2)], 3);
    /// ```
    #[inline(always)]
    pub fn swap(&mut self, a: (usize, usize), b: (usize, usize)) -> Result<(), BidiError> {
        if self.valid_coords(a.0, a.1) && self.valid_coords(b.0, b.1) {
            if a.1 == b.1 {
                self.data[a.1].swap(a.0, b.0);
            } else {
                let ptr1: *mut T = &mut self.data[a.1][a.0];
                let ptr2: *mut T = &mut self.data[b.1][b.0];
                unsafe {
                    std::ptr::swap(ptr1, ptr2);
                }
            }
            Ok(())
        } else {
            Err(BidiError::OutOfBounds)
        }
    }

    /// Appends a new column to the bidigrowvec.
    /// If the bidigrowvec is not empty, the column to be appended must contain
    /// exactly `height()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    /// If the bidigrowvec is not empty, this operation is also expensive
    /// as it requires O(column_size * bidigrowvec_size) time; use[`BidiGrowVec`] for
    /// faster column pushes (at the loss of linear layout).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.push_col([1, 2, 3]).unwrap();
    ///
    /// assert_eq!(bvec[(0, 0)], 1);
    /// assert_eq!(bvec[(0, 1)], 2);
    /// assert_eq!(bvec[(0, 2)], 3);
    /// ```
    pub fn push_col<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Result<(), BidiError> {
        if self.data.is_empty() {
            for val in iter.into_iter() {
                self.data.push(vec![val]);
            }
            Ok(())
        } else {
            let saved_width = self.width();
            let mut rollback = false;
            let mut rows_changed: usize = 0;

            for (row, val) in iter.into_iter().enumerate() {
                rows_changed += 1;
                if row < self.data.len() {
                    self.data[row].push(val);
                } else {
                    rollback = true;
                    break;
                }
            }

            if rollback || rows_changed != self.height() {
                for v in self.data.iter_mut() {
                    v.truncate(saved_width);
                }
                Err(BidiError::IncompatibleSize)
            } else {
                Ok(())
            }
        }
    }

    /// Appends a new row to the bidigrowvec.
    /// If the bidigrowvec is not empty, the row to be appended must contain
    /// exactly `width()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.push_row([1, 2, 3]).unwrap();
    ///
    /// assert_eq!(bvec[(0, 0)], 1);
    /// assert_eq!(bvec[(1, 0)], 2);
    /// assert_eq!(bvec[(2, 0)], 3);
    /// ```
    pub fn push_row<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Result<(), BidiError> {
        if self.data.is_empty() {
            self.data.push(iter.into_iter().collect::<Vec<T>>());
            Ok(())
        } else {
            let width = self.width();
            self.data.push(iter.into_iter().collect::<Vec<T>>());

            if self.data[self.data.len() - 1].len() != width {
                self.data.truncate(self.data.len() - 1);
                Err(BidiError::IncompatibleSize)
            } else {
                Ok(())
            }
        }
    }

    /// Inserts a new column in the middle of a bidigrowvec.
    /// If the bidigrowvec is not empty, the column to be inserted must contain
    /// exactly `height()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// If the bidigrowvec is not empty, this operation requires
    /// O(column_size * row_size) time.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.insert_col(1, [5, 5, 5]).unwrap();
    ///
    /// assert_eq!(bvec[(0, 0)], 1);
    /// assert_eq!(bvec[(1, 1)], 5);
    /// assert_eq!(bvec[(2, 2)], 1);
    /// ```
    pub fn insert_col<I: IntoIterator<Item = T>>(
        &mut self,
        col: usize,
        iter: I,
    ) -> Result<(), BidiError> {
        match col.cmp(&self.width()) {
            Ordering::Greater => Err(BidiError::OutOfBounds),
            Ordering::Equal => self.push_col(iter),
            Ordering::Less => {
                let saved_width = self.width();
                let mut rollback = false;
                let mut rows_changed: usize = 0;

                for (row, val) in iter.into_iter().enumerate() {
                    rows_changed += 1;
                    if row < self.data.len() {
                        self.data[row].insert(col, val);
                    } else {
                        rollback = true;
                        break;
                    }
                }

                if rollback || rows_changed != self.height() {
                    for v in self.data.iter_mut() {
                        if v.len() > saved_width {
                            v.remove(col);
                        }
                    }
                    Err(BidiError::IncompatibleSize)
                } else {
                    Ok(())
                }
            }
        }
    }

    /// Inserts a new row in the middle of a bidigrowvec.
    /// If the bidigrowvec is not empty, the row to be inserted must contain
    /// exactly `width()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// This operation is O(height).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiGrowVec;
    ///
    /// let mut bvec = BidiGrowVec::new();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.push_row([1, 1, 1]).unwrap();
    /// bvec.insert_row(1, [5, 5, 5]).unwrap();
    ///
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 4);
    /// assert_eq!(bvec[(1, 1)], 5);
    /// ```
    pub fn insert_row<I: IntoIterator<Item = T>>(
        &mut self,
        row: usize,
        iter: I,
    ) -> Result<(), BidiError> {
        match (row).cmp(&self.data.len()) {
            Ordering::Greater => Err(BidiError::OutOfBounds),
            Ordering::Equal => self.push_row(iter),
            Ordering::Less => {
                let row_data = iter.into_iter().collect::<Vec<T>>();

                if row_data.len() != self.width() {
                    Err(BidiError::IncompatibleSize)
                } else {
                    self.data.insert(row, row_data);
                    Ok(())
                }
            }
        }
    }

    /// Removes the specified column from the bidigrowvec. If the column is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If the deleted data is not needed, `BidiGrowVec::delete_col` provides
    /// better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec.remove_col(1).unwrap(), vec![2, 5, 8]);
    ///
    /// assert_eq!(bvec.width(), 2);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 1)], 6);
    /// ```
    pub fn remove_col(&mut self, col: usize) -> Result<Vec<T>, BidiError> {
        if col >= self.width() {
            Err(BidiError::OutOfBounds)
        } else {
            let mut result = Vec::with_capacity(self.height());

            for v in self.data.iter_mut() {
                result.push(v.remove(col));
            }

            self.collapse();

            Ok(result)
        }
    }

    /// Removes the specified row from the bidigrowvec. If the row is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec.remove_row(1).unwrap(), vec![4, 5, 6]);
    ///
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 2);
    /// assert_eq!(bvec[(1, 1)], 8);
    /// ```
    pub fn remove_row(&mut self, row: usize) -> Result<Vec<T>, BidiError> {
        if row >= self.height() {
            Err(BidiError::OutOfBounds)
        } else {
            Ok(self.data.remove(row))
        }
    }

    /// Deletes the specified column from the bidigrowvec. If the column is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiGrowVec::remove_col` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// bvec.delete_col(1).unwrap();
    ///
    /// assert_eq!(bvec.width(), 2);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec[(1, 1)], 6);
    /// ```
    pub fn delete_col(&mut self, col: usize) -> Result<(), BidiError> {
        if col >= self.width() {
            Err(BidiError::OutOfBounds)
        } else {
            for v in self.data.iter_mut() {
                v.remove(col);
            }
            self.collapse();
            Ok(())
        }
    }

    /// Deletes the specified row from the bidigrowvec. If the row is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// This method is no faster than `remove_row` and exists only
    /// for symmetry with `delete_col` and other data structures
    /// where `delete_row` offers a performance advantage.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// bvec.delete_row(1).unwrap();
    ///
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 2);
    /// assert_eq!(bvec[(1, 1)], 8);
    /// ```
    pub fn delete_row(&mut self, row: usize) -> Result<(), BidiError> {
        self.remove_row(row)?;
        Ok(())
    }

    /// Deletes the last column from the bidigrowvec.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiGrowVec::pop_col` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// bvec.delete_last_col();
    ///
    /// assert_eq!(bvec.width(), 2);
    /// assert_eq!(bvec.height(), 3);
    /// ```
    pub fn delete_last_col(&mut self) {
        if self.width() > 0 {
            self.delete_col(self.width() - 1).unwrap();
        }
    }

    /// Deletes the last row from the bidigrowvec.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiGrowVec::pop_row` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// bvec.delete_last_row();
    ///
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 2);
    /// ```
    pub fn delete_last_row(&mut self) {
        self.data.pop();
    }

    /// Removes the last column from the bidigrowvec, returning its data.
    ///
    /// If the removed data is not needed, `BidiGrowVec::delete_last_col`
    /// provides better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec.pop_col().unwrap(), vec![3, 6, 9]);
    ///
    /// assert_eq!(bvec.width(), 2);
    /// assert_eq!(bvec.height(), 3);
    /// ```
    #[must_use]
    pub fn pop_col(&mut self) -> Option<Vec<T>> {
        if self.is_empty() {
            None
        } else {
            Some(self.remove_col(self.width() - 1).unwrap())
        }
    }

    /// Removes the last row from the bidigrowvec, returning its data.
    ///
    /// If the removed data is not needed, `BidiGrowVec::delete_last_row`
    /// provides better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec.pop_row().unwrap(), vec![7, 8, 9]);
    ///
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 2);
    /// ```
    #[must_use]
    pub fn pop_row(&mut self) -> Option<Vec<T>> {
        self.data.pop()
    }

    /// Accesses an element in the BidiGrowVec, using its cartesian coordinates.
    /// If coordinates are outside of range, [`None`] is returned.
    ///
    /// If the error is not going to be handled, direct indexing is an easier
    /// way to achieve the same results.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(*bvec.get(1, 1).unwrap(), 5);
    /// assert_eq!(bvec[(1, 1)], 5);
    /// ```
    #[inline(always)]
    pub fn get(&self, x: usize, y: usize) -> Option<&T> {
        if self.valid_coords(x, y) {
            Some(&self.data[y][x])
        } else {
            None
        }
    }

    /// Mutably accesses an element in the BidiGrowVec, using its cartesian coordinates.
    /// If coordinates are outside of range, [`None`] is returned.
    ///
    /// If the error is not going to be handled, direct indexing is an easier
    /// way to achieve the same results.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// *bvec.get_mut(1, 1).unwrap() = 12;
    ///
    /// assert_eq!(*bvec.get(1, 1).unwrap(), 12);
    ///
    /// bvec[(1, 1)] = 13;
    ///
    /// assert_eq!(*bvec.get(1, 1).unwrap(), 13);
    /// ```
    #[inline(always)]
    pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
        if self.valid_coords(x, y) {
            Some(&mut self.data[y][x])
        } else {
            None
        }
    }

    /// Checks if the specified coordinates are inside the bidigrowvec bounds
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert!(bvec.valid_coords(1, 1));
    /// assert!(!bvec.valid_coords(3, 3));
    /// ```
    #[inline(always)]
    pub fn valid_coords(&self, x: usize, y: usize) -> bool {
        x < self.width() && y < self.height()
    }

    /// Reverses the order of the items in the specified row.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec[(2, 1)], 6);
    ///
    /// bvec.reverse_row(1).unwrap();
    ///
    /// assert_eq!(bvec[(2, 1)], 4);
    /// ```
    pub fn reverse_row(&mut self, row: usize) -> Result<(), BidiError> {
        if row >= self.height() {
            Err(BidiError::OutOfBounds)
        } else {
            self.data[row].reverse();
            Ok(())
        }
    }

    /// Reverses the order of the items in the specified column.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec[(1, 2)], 8);
    ///
    /// bvec.reverse_col(1).unwrap();
    ///
    /// assert_eq!(bvec[(1, 2)], 2);
    /// ```
    pub fn reverse_col(&mut self, col: usize) -> Result<(), BidiError> {
        if col >= self.width() {
            Err(BidiError::OutOfBounds)
        } else {
            let height = self.height();

            for y in 0..(height / 2) {
                self.swap((col, y), (col, height - 1 - y)).unwrap();
            }

            Ok(())
        }
    }

    /// Transposes the bidigrowvec, that is an operation that flips the bidigrowvec
    /// over its diagonal (or, more simply, switches the meaning of columns and
    /// rows). As such, the result of a transposition is as wide as the original
    /// was tall, and as tall as the original was wide.
    pub fn transpose(&mut self) {
        let width = self.width();
        let height = self.height();
        let min_dimension = std::cmp::min(width, height);

        for x in 0..min_dimension {
            for y in (x + 1)..min_dimension {
                self.swap((x, y), (y, x)).unwrap();
            }
        }

        if width > min_dimension {
            let mut excess_cols = Vec::new();

            while self.data[0].len() > min_dimension {
                let colv = self.remove_col(min_dimension).unwrap();
                excess_cols.push(colv);
            }

            for col in excess_cols.drain(..) {
                self.push_row(col).unwrap();
            }
        } else if height > min_dimension {
            let mut excess_rows = Vec::new();

            while self.data.len() > min_dimension {
                let rowv = self.remove_row(min_dimension).unwrap();
                excess_rows.push(rowv);
            }

            for row in excess_rows.drain(..) {
                self.push_col(row).unwrap();
            }
        }
    }

    /// Rotates the bidigrowvec 90°, counter-clockwise (or, 270° clockwise).
    /// The result of such a rotation is as wide as the original
    /// was tall, and as tall as the original was wide.
    ///
    /// While this is performed in-place, it still requires O(n) additional memory
    /// if the bidigrowvec width and height are different (i.e. it's not a square).
    pub fn rotate90ccw(&mut self) {
        self.transpose();
        self.reverse_columns();
    }

    /// Rotates the bidigrowvec 180°.
    pub fn rotate180(&mut self) {
        self.reverse_rows();
        self.reverse_columns();
    }

    /// Rotates the bidigrowvec 270°, counter-clockwise (or, 90° clockwise).
    /// The result of such a rotation is as wide as the original
    /// was tall, and as tall as the original was wide.
    ///
    /// While this is performed in-place, it still requires O(n) additional memory
    /// if the bidigrowvec width and height are different (i.e. it's not a square).
    pub fn rotate270ccw(&mut self) {
        self.transpose();
        self.reverse_rows();
    }

    /// Reverse the order of items in all columns. This is equivalent to flipping
    /// the data structure over its horizontal axis.
    pub fn reverse_columns(&mut self) {
        self.data.reverse();
    }

    /// Reverse the order of items in all rows. This is equivalent to flipping
    /// the data structure over its vertical axis.
    pub fn reverse_rows(&mut self) {
        for r in self.data.iter_mut() {
            r.reverse();
        }
    }

    /// Crops the data structure to its new bounds by moving the origin to
    /// a new location, reducing the width and height and dropping excess
    /// data.
    pub fn crop(&mut self, rect: &BidiRect) -> Result<(), BidiError> {
        if rect.width == 0 || rect.height == 0 {
            self.clear();
            Ok(())
        } else if (rect.max_x() > self.width()) || (rect.max_y() > self.height()) {
            Err(BidiError::OutOfBounds)
        } else {
            self.truncate(rect.max_x(), rect.max_y()).unwrap();
            for _ in 0..rect.x {
                self.remove_col(0).unwrap();
            }
            for _ in 0..rect.y {
                self.remove_row(0).unwrap();
            }
            Ok(())
        }
    }

    fn collapse(&mut self) {
        if !self.data.is_empty() && self.data[0].is_empty() {
            self.data.clear();
        }
    }

    /// Converts this instance into a [`BidiVec<T>`]
    /// This operation is `O(width*height)` in the worst case.
    pub fn into_bidivec(self) -> BidiVec<T> {
        BidiVec::<T>::from(self)
    }

    /// Converts this instance into a [`BidiArray<T>`]
    /// This operation is `O(width*height)` in the worst case.
    pub fn into_bidiarray(self) -> BidiArray<T> {
        BidiArray::<T>::from(self)
    }

    /// Converts this instance to an immutable [`BidiView`].
    pub fn as_bidiview(&self) -> &dyn BidiView<Output = T> {
        self
    }

    /// Converts this instance to a mutable [`BidiView`].
    pub fn as_bidiview_mut(&mut self) -> &dyn BidiViewMut<Output = T> {
        self
    }

    /// Returns an iterator over the items of the view
    pub fn iter(&self) -> Iter<T, Self> {
        Iter::new(self)
    }

    /// Returns a mutable iterator over the items of the view
    pub fn iter_mut(&mut self) -> IterMut<T, Self> {
        IterMut::new(self)
    }
}

impl<T> BidiFrom<&dyn BidiView<Output = T>> for BidiGrowVec<T>
where
    T: Clone,
{
    fn from_view(source: &dyn BidiView<Output = T>) -> Result<Self, BidiError> {
        Ok(BidiGrowVec::<T>::with_size_func_xy(
            source.width(),
            source.height(),
            |x, y| source[(x, y)].clone(),
        ))
    }

    fn from_view_cut(source: &dyn BidiView<Output = T>, cut: &BidiRect) -> Result<Self, BidiError> {
        if cut.max_x() > source.height() || cut.max_y() > source.width() {
            return Err(BidiError::OutOfBounds);
        }

        Ok(BidiGrowVec::<T>::with_size_func_xy(
            cut.width,
            cut.height,
            |x, y| source[(x + cut.x, y + cut.y)].clone(),
        ))
    }
}

impl<T> BidiFrom<BidiGrowVec<T>> for BidiGrowVec<T> {
    fn from_view(source: BidiGrowVec<T>) -> Result<Self, BidiError> {
        Ok(source)
    }

    fn from_view_cut(mut source: BidiGrowVec<T>, cut: &BidiRect) -> Result<Self, BidiError> {
        source.crop(cut)?;
        Ok(source)
    }
}

impl<T> BidiFrom<BidiVec<T>> for BidiGrowVec<T> {
    fn from_view(source: BidiVec<T>) -> Result<Self, BidiError> {
        Ok(Self::from(source))
    }

    fn from_view_cut(mut source: BidiVec<T>, cut: &BidiRect) -> Result<Self, BidiError> {
        source.crop(cut)?;
        Ok(Self::from(source))
    }
}

impl<T> BidiFrom<BidiArray<T>> for BidiGrowVec<T> {
    fn from_view(source: BidiArray<T>) -> Result<Self, BidiError> {
        Ok(Self::from(source))
    }

    fn from_view_cut(source: BidiArray<T>, cut: &BidiRect) -> Result<Self, BidiError> {
        let mut this = Self::from(source);
        this.crop(cut)?;
        Ok(this)
    }
}

impl<T> Index<(usize, usize)> for BidiGrowVec<T> {
    type Output = T;

    /// Accesses an element in the BidiGrowVec, using its cartesian coordinates.
    /// If coordinates are outside of range, it panics.
    ///
    /// If you want a more graceful error handling, see [`BidiGrowVec::get`].
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// assert_eq!(bvec[(1, 1)], 5);
    /// ```
    #[inline(always)]
    fn index(&self, index: (usize, usize)) -> &Self::Output {
        &self.data[index.1][index.0]
    }
}

impl<T> IndexMut<(usize, usize)> for BidiGrowVec<T> {
    /// Mutably accesses an element in the BidiGrowVec, using its cartesian coordinates.
    /// If coordinates are outside of range, it panics.
    ///
    /// If you want a more graceful error handling, see [`BidiGrowVec::get_mut`] and
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiGrowVec, bidigrowvec};
    ///
    /// let mut bvec = bidigrowvec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// bvec[(1, 1)] = 12;
    ///
    /// assert_eq!(bvec[(1, 1)], 12);
    /// ```
    #[inline(always)]
    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
        &mut self.data[index.1][index.0]
    }
}

impl<T> BidiView for BidiGrowVec<T> {
    fn width(&self) -> usize {
        BidiGrowVec::<T>::width(self)
    }
    fn height(&self) -> usize {
        BidiGrowVec::<T>::height(self)
    }

    fn get(&self, x: usize, y: usize) -> Option<&T> {
        self.get(x, y)
    }
}

impl<T> BidiViewMut for BidiGrowVec<T> {
    fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
        self.get_mut(x, y)
    }
}

unsafe impl<T> BidiViewMutIterable for BidiGrowVec<T> {}

impl<T> From<BidiVec<T>> for BidiGrowVec<T> {
    /// Creates a new instance of [`BidiGrowVec<T>`] from an existing [`BidiVec<T>`].
    /// This operation is `O(width*height)` in the worst case.
    fn from(other: BidiVec<T>) -> Self {
        let row_size = other.width();
        Self::from_vec(other.data, row_size).unwrap()
    }
}

impl<T> From<BidiArray<T>> for BidiGrowVec<T> {
    /// Creates a new instance of [`BidiGrowVec<T>`] from an existing [`BidiVec<T>`].
    /// This operation is `O(width*height)` in the worst case.
    fn from(other: BidiArray<T>) -> Self {
        let row_size = other.width();
        Self::from_vec(other.data.into_vec(), row_size).unwrap()
    }
}