bidivec 0.1.0

A crate offering bidimensional arrays, vectors and slices, with batteries included (such as pathfinding, flood-filling and more).
Documentation
use core::slice::SliceIndex;
use std::cmp::{min, Ordering};
#[rustversion::since(1.57)]
use std::collections::TryReserveError;
use std::default::Default;
use std::iter::Iterator;
#[rustversion::since(1.48)]
use std::ops::Range;
use std::ops::{Index, IndexMut};

use crate::bidiiter::{Iter, IterMut};
use crate::*;

#[cfg(debug_assertions)]
macro_rules! check_consistent {
    ($e:expr) => {{
        let this = $e;
        match this.row_size {
            None => if !this.data.is_empty() {
                panic!("BidiVec consistency failed: vec has {} elements, row_size is {:?}", this.data.len(), this.row_size);
            }
            Some(l) => if this.data.is_empty() || (this.data.len() % l) != 0 {
                panic!("BidiVec consistency failed: vec has {} elements, row_size is {:?}", this.data.len(), this.row_size);
            },
        };
    }};
}

#[cfg(not(debug_assertions))]
macro_rules! check_consistent {
    ($e:expr) => {};
}

/// A contiguous growable bidimensional array type with heap-allocated contents,
/// based on an underlying `Vec<T>`.
///
/// BidiVecs have `O(1)` indexing, amortized `O(1)` push of rows (to the end) and
/// `O(row_length)` pops (from the end).
///
/// This bidimensional data structure lays out its elements linearly in memory,
/// for better interoperability with native code and greater efficiency (due to
/// memory locality) when the data structure is not changing. This comes at a price
/// of higher cost for column based insertions and removals and mid-collection row
/// insertions and removals. For a more efficient type for these scenarios, see
/// [`BidiGrowVec`].
///
/// 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 [`BidiVec`] with [`BidiVec::new`]:
///
/// ```
/// # use bidivec::BidiVec;
/// let v: BidiVec<i32> = BidiVec::new();
/// ```
///
/// or by using the [`bidivec!`] macro:
///
/// ```
/// # use bidivec::{BidiVec, bidivec};
/// // this creates an empty bidivec
/// let v: BidiVec<i32> = bidivec![];
///
/// // this creates a 3x2 bidivec, with all items equal to 1
/// let v = bidivec![1; 3, 2];
///
/// // this creates a 3x2 bidivec from items; the final '3' is the
/// // bidivec's width
/// let v = bidivec![1, 2, 3, 4, 5, 6; 3];
///
/// // this creates a 3x2 bidivec, by listing the rows separately
/// let v = bidivec!{
///     [1, 2, 3],
///     [4, 5, 6],
/// };
/// ```
///
/// You can push rows onto the end of a bidivec (which will grow the bidivec
/// as needed):
///
/// ```
/// # use bidivec::{BidiVec, bidivec};
/// let mut v = bidivec![1, 2; 1];
///
/// v.push_row([3, 4]);
/// ```
///
/// Popping rows works in much the same way:
///
/// ```
/// # use bidivec::{BidiVec, bidivec};
/// let mut v = bidivec![1, 2; 1];
///
/// let one_and_two = v.pop_row();
/// ```
///
/// BidiVecs support indexing with cartesian coordinates (through the [`Index`] and [`IndexMut`] traits);
/// note that coordinates out of range will cause the code to panic.
/// The [`BidiVec::get`] and [`BidiVec::get_mut`] methods offer a safer way to access the bidivec contents,
/// by returning an `Option`, in the same vein of `Vec<T>`.
///
/// ```
/// # use bidivec::{BidiVec, bidivec};
/// let mut v = bidivec!{
///     [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 BidiVec<T> {
    pub(crate) data: Vec<T>,
    pub(crate) row_size: Option<usize>,
}

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

    /// Constructs a new, empty [`BidiVec<T>`] with the specified capacity.
    ///
    /// The bidivec will be able to hold exactly `capacity` elements without
    /// reallocating. If `capacity` is 0, the bidivec will not allocate.
    /// See the documentation of `Vec<T>` for further details.
    ///
    /// Note that the capacity is expressed in terms of elements, so to
    /// store, for example, a 3x3 bidivec, the capacity to request should be
    /// 9.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::with_capacity(9);
    ///
    /// // The bidivec contains no items, even though it has capacity for more
    /// assert_eq!(bvec.len(), 0);
    /// assert_eq!(bvec.capacity(), 9);
    ///
    /// // These are all done without reallocating...
    /// bvec.push_row([0, 1, 2]).unwrap();
    /// bvec.push_row([3, 4, 5]).unwrap();
    /// bvec.push_row([6, 7, 8]).unwrap();
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec.capacity(), 9);
    ///
    /// // ...but this may make the bidivec reallocate
    /// bvec.push_row([9, 10, 11]).unwrap();
    /// assert_eq!(bvec.len(), 12);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 4);
    /// assert!(bvec.capacity() >= 12);
    /// ```
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            data: Vec::with_capacity(capacity),
            row_size: None,
        }
    }

    /// Constructs a new, empty [`BidiVec<T>`] with the capacity to handle the
    /// specified size without reallocating.
    ///
    /// Note that the specified size doesn't put any constraint on the size
    /// that the bidivec will have.
    ///
    /// See the documentation of `Vec<T>` for further details.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::with_capacity_size(3, 3);
    ///
    /// // The bidivec contains no items, even though it has capacity for more
    /// assert_eq!(bvec.len(), 0);
    /// assert_eq!(bvec.capacity(), 9);
    ///
    /// // These are all done without reallocating...
    /// bvec.push_row([0, 1, 2]).unwrap();
    /// bvec.push_row([3, 4, 5]).unwrap();
    /// bvec.push_row([6, 7, 8]).unwrap();
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 3);
    /// assert_eq!(bvec.capacity(), 9);
    ///
    /// // ...but this may make the bidivec reallocate
    /// bvec.push_row([9, 10, 11]).unwrap();
    /// assert_eq!(bvec.len(), 12);
    /// assert_eq!(bvec.width(), 3);
    /// assert_eq!(bvec.height(), 4);
    /// assert!(bvec.capacity() >= 12);
    /// ```
    pub fn with_capacity_size(width: usize, height: usize) -> Self {
        Self {
            data: Vec::with_capacity(width * height),
            row_size: None,
        }
    }

    /// Constructs a new [`BidiVec<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::BidiVec;
    ///
    /// let mut bvec = BidiVec::with_elem(5, 3, 3);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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,
    {
        Self {
            data: vec![value; width * height],
            row_size: if width == 0 { None } else { Some(width) },
        }
    }

    /// Constructs a new [`BidiVec<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::BidiVec;
    ///
    /// let mut bvec = BidiVec::<i32>::with_size_default(3, 3);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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 [`BidiVec<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 `BidiVec<T>::with_size_func_xy`.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::with_size_func(3, 3, ||137);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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(width * height),
            row_size: None,
        };
        this.resize_with(width, height, f);
        this
    }

    /// Constructs a new [`BidiVec<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, `BidiVec::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::BidiVec;
    ///
    /// let mut bvec = BidiVec::with_size_func_xy(3, 3, |x,y| x+y);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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(width * height),
            row_size: None,
        };
        this.resize_with_xy(width, height, f);
        this
    }

    /// Creates a [`BidiVec<T>`] directly from the raw components of another vector.
    ///
    /// # Safety
    ///
    /// This is essentially the same to `Vec<T>::from_raw_parts`, so the same
    /// caveats apply.
    ///
    /// As this is highly unsafe, please check the documentation of `Vec<T>::from_raw_parts`
    /// before using this function.
    ///
    /// [`Vec<T>::from_raw_parts`]: crate::vec::Vec::from_raw_parts
    pub unsafe fn from_raw_parts(
        ptr: *mut T,
        length: usize,
        row_size: usize,
        capacity: usize,
    ) -> Result<Self, BidiError> {
        if length == 0 && row_size == 0 {
            Ok(Self {
                data: Vec::from_raw_parts(ptr, 0, capacity),
                row_size: None,
            })
        } else if row_size != 0 && (length % row_size) == 0 {
            Ok(Self {
                data: Vec::from_raw_parts(ptr, length, capacity),
                row_size: Some(row_size),
            })
        } else {
            Err(BidiError::IncompatibleSize)
        }
    }

    /// Creates a bidivec from a draining iterator, using the specified
    /// `row_size`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
    /// let mut bvec = BidiVec::from_iterator(vec.drain(..), 3).unwrap();
    ///
    /// let expected = bidivec!{
    ///     [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 bidivec from another view iterator, using the specified
    /// mapping function to create and/or transform elements.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let from = bidivec!{
    ///     [1, 2, 3],
    ///     [4, 5, 6],
    ///     [7, 8, 9],
    /// };
    ///
    /// let to = BidiVec::from_view_map(&from, |n| n - 1);
    ///
    /// assert_eq!(to, bidivec!{
    ///     [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 [`BidiVec<T>`] from a `Vec<T>` and a specified row size.
    ///
    /// # 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,
                row_size: None,
            })
        } else if row_size != 0 && (vec.len() % row_size) == 0 {
            Ok(Self {
                data: vec,
                row_size: Some(row_size),
            })
        } else {
            Err(BidiError::IncompatibleSize)
        }
    }

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

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

    /// Returns the width (that is, the size of a row) in the bidivec.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec![5; 4, 3];
    ///
    /// assert_eq!(bvec.width(), 4);
    /// ```
    pub fn width(&self) -> usize {
        check_consistent!(&self);
        self.row_size.unwrap_or(0)
    }

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

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

    /// Resizes the[`BidiVec`] 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
    ///[`BidiVec`] 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 [`BidiVec::resize_with`].
    /// If you only need to resize to a smaller size, use [`BidiVec::truncate`].
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::new();
    /// bvec.resize(3, 3, 5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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;
        }

        if self.row_size.is_some() {
            self.truncate(min(self.width(), new_width), min(self.height(), new_height))
                .unwrap();

            while self.width() < new_width {
                self.push_col(std::iter::repeat(value.clone()).take(self.height()))
                    .unwrap();
            }
        }

        self.data.resize(new_height * new_width, value);
        self.row_size = Some(new_width);
        check_consistent!(&self);
    }

    /// Resizes the[`BidiVec`] 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 `BidiVec<T>::resize_with_xy`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::new();
    /// bvec.resize_with(3, 3, ||5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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;
        }

        if self.row_size.is_some() {
            self.truncate(min(self.width(), new_width), min(self.height(), new_height))
                .unwrap();

            while 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();
            }
        }

        self.data.resize_with(new_height * new_width, f);
        self.row_size = Some(new_width);
        check_consistent!(&self);
    }

    /// Resizes the[`BidiVec`] (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, `BidiVec::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::BidiVec;
    ///
    /// let mut bvec = BidiVec::new();
    /// bvec.resize_with(3, 3, ||5);
    ///
    /// assert_eq!(bvec.len(), 9);
    /// assert_eq!(bvec.capacity(), 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;
        }

        if self.row_size.is_some() {
            self.truncate(min(self.width(), new_width), min(self.height(), new_height))
                .unwrap();

            while self.width() < new_width {
                let mut tmp = Vec::with_capacity(self.height());

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

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

            self.row_size = Some(new_width);
        }

        while self.height() < new_height {
            let y = self.height();
            for x in 0..new_width {
                self.data.push(f(x, y));
            }
            // if we just went from empty to filled, refresh row_size
            self.row_size = Some(new_width);
        }
        check_consistent!(&self);
    }

    /// Truncates the[`BidiVec`] 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::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec![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 {
            while self.width() > new_width {
                self.delete_last_col();
            }
            self.data.truncate(new_height * self.width());
        }

        check_consistent!(&self);
        Ok(())
    }

    /// Returns the number of elements the bidivec can hold without
    /// reallocating.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let bvec: BidiVec<i32> = BidiVec::with_capacity(10);
    /// assert_eq!(bvec.capacity(), 10);
    /// ```
    pub fn capacity(&self) -> usize {
        self.data.capacity()
    }

    /// Reserves capacity for at least `additional` more elements to be inserted
    /// in the given [`BidiVec<T>`]. The collection may reserve more space to avoid
    /// frequent reallocations. After calling [`BidiVec::reserve`], capacity will be
    /// greater than or equal to `self.len() + additional`. Does nothing if
    /// capacity is already sufficient.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec![111i32; 2, 2];
    /// bvec.reserve(10);
    /// assert!(bvec.capacity() >= 14);
    /// ```
    pub fn reserve(&mut self, additional: usize) {
        self.data.reserve(additional)
    }

    /// Reserves capacity for exactly `additional` more elements to be inserted
    /// in the given [`BidiVec<T>`]. The collection may reserve more space to avoid
    /// frequent reallocations. After calling [`BidiVec::reserve`], capacity will be
    /// greater than or equal to `self.len() + additional`. Does nothing if
    /// capacity is already sufficient.
    ///
    /// Note that the allocator may give the collection more space than it
    /// requests. Therefore, capacity can not be relied upon to be precisely
    /// minimal. Prefer [`BidiVec::reserve`] if future insertions are expected.
    ///
    /// # Panics
    ///
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec![111i32; 2, 2];
    /// bvec.reserve_exact(10);
    /// assert!(bvec.capacity() >= 14);
    /// ```
    pub fn reserve_exact(&mut self, additional: usize) {
        self.data.reserve_exact(additional)
    }

    /// Tries to reserve capacity for at least `additional` more elements to be inserted
    /// in the given [`BidiVec<T>`]. The collection may reserve more space to avoid
    /// frequent reallocations. After calling `try_reserve`, capacity will be
    /// greater than or equal to `self.len() + additional`. Does nothing if
    /// capacity is already sufficient.
    ///
    /// Requires rustc 1.57 or later.
    #[rustversion::since(1.57)]
    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
        self.data.try_reserve(additional)
    }

    /// Tries to reserve the minimum capacity for exactly `additional`
    /// elements to be inserted in the given `Vec<T>`. After calling
    /// `try_reserve_exact`, capacity will be greater than or equal to
    /// `self.len() + additional` if it returns `Ok(())`.
    /// Does nothing if the capacity is already sufficient.
    ///
    /// Requires rustc 1.57 or later.
    #[rustversion::since(1.57)]
    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
        self.data.try_reserve_exact(additional)
    }

    /// Shrinks the capacity of the bidivec as much as possible.
    ///
    /// See `Vec::shrink_to_fit` for more details
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::<i32>::with_capacity(10);
    /// bvec.push_row([1, 2, 3]).unwrap();
    /// assert_eq!(bvec.capacity(), 10);
    /// bvec.shrink_to_fit();
    /// assert!(bvec.capacity() >= 3);
    /// ```
    pub fn shrink_to_fit(&mut self) {
        self.data.shrink_to_fit()
    }

    /// Shrinks the capacity of the bidivec with a lower bound.
    ///
    /// The capacity will remain at least as large as both the length
    /// and the supplied value.
    ///
    /// If the current capacity is less than the lower limit, this is a no-op.
    ///
    /// Requires rustc 1.56 or later.
    #[rustversion::since(1.56)]
    pub fn shrink_to(&mut self, min_capacity: usize) {
        self.data.shrink_to(min_capacity)
    }

    /// Extracts a slice containing the specified range of bidivec contents,
    /// laid out linearly, by rows.
    pub fn as_slice<R: SliceIndex<[T]>>(&self, range: R) -> &R::Output {
        &self.data[range]
    }

    /// Extracts a slice containing the specified range of bidivec contents,
    /// laid out linearly, by rows.
    pub fn as_mut_slice<R: SliceIndex<[T]>>(&mut self, range: R) -> &mut R::Output {
        &mut self.data[range]
    }

    /// Returns a raw pointer to the bidivec's buffer.
    ///
    /// The caller must ensure that the bidivec outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    /// Modifying the bidivec may cause its buffer to be reallocated,
    /// which would also make any pointers to it invalid.
    ///
    /// The caller must also ensure that the memory the pointer (non-transitively) points to
    /// is never written to (except inside an [`UnsafeCell`][std::cell::UnsafeCell]) using this pointer or any pointer
    /// derived from it. If you need to mutate the contents of the slice, use [`Vec::as_mut_ptr`].
    pub fn as_ptr(&self) -> *const T {
        self.data.as_ptr()
    }

    /// Returns an unsafe mutable pointer to the vector's buffer.
    ///
    /// The caller must ensure that the vector outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    /// Modifying the vector may cause its buffer to be reallocated,
    /// which would also make any pointers to it invalid.
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self.data.as_mut_ptr()
    }

    /// Returns the two raw pointers spanning the slice.
    ///
    /// The returned range is half-open, which means that the end pointer
    /// points *one past* the last element of the slice. This way, an empty
    /// slice is represented by two equal pointers, and the difference between
    /// the two pointers represents the size of the slice.
    ///
    /// See [`Vec::as_ptr`] for warnings on using these pointers. The end pointer
    /// requires extra caution, as it does not point to a valid element in the
    /// slice.
    ///
    /// This function is useful for interacting with foreign interfaces which
    /// use two pointers to refer to a range of elements in memory, as is
    /// common in C++.
    ///
    /// Requires rustc 1.48 or later.
    #[rustversion::since(1.48)]
    pub fn as_ptr_range(&self) -> Range<*const T> {
        self.data.as_ptr_range()
    }

    /// Returns the two mutable raw pointers spanning the slice.
    ///
    /// The returned range is half-open, which means that the end pointer
    /// points *one past* the last element of the slice. This way, an empty
    /// slice is represented by two equal pointers, and the difference between
    /// the two pointers represents the size of the slice.
    ///
    /// See [`Vec::as_mut_ptr`] and [`Vec::as_ptr`] for warnings on using these pointers.
    /// The end pointer requires extra caution, as it does not point to a valid
    /// element in the slice.
    ///
    /// This function is useful for interacting with foreign interfaces which
    /// use two pointers to refer to a range of elements in memory, as is
    /// common in C++.
    ///
    /// Requires rustc 1.48 or later.
    #[rustversion::since(1.48)]
    pub fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
        self.data.as_mut_ptr_range()
    }

    /// Converts the vector into a `Box<[T]>` where items are linearly
    /// laid out by rows.
    pub fn into_boxed_slice(self) -> Box<[T]> {
        self.data.into_boxed_slice()
    }

    /// Converts the vector into a `Vec<T>` where items are linearly
    /// laid out by rows.
    pub fn into_vec(self) -> Vec<T> {
        self.data
    }

    /// Swaps two elements in the bidivec. If any of the coordinates are out
    /// of range, [`BidiError::OutOfBounds`] is returned
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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> {
        let idx_a = self.calc_index(a.0, a.1)?;
        let idx_b = self.calc_index(b.0, b.1)?;

        self.data.swap(idx_a, idx_b);
        Ok(())
    }

    /// Appends a new column to the bidivec.
    /// If the bidivec is not empty, the column to be appended must contain
    /// exactly `height()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    /// If the bidivec is not empty, this operation is also expensive
    /// as it requires O(column_size * bidivec_size) time; use[`BidiGrowVec`] for
    /// faster column pushes (at the loss of linear layout).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::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> {
        match self.row_size {
            None => {
                self.data.extend(iter);
                self.row_size = Some(1);
                check_consistent!(self);
                Ok(())
            }
            Some(row_size) => {
                let mut rows_changed: usize = 0;
                let mut force_rollback: bool = false;

                for (row, val) in iter.into_iter().enumerate() {
                    let insertion_point = (row + 1) * row_size + row;

                    match insertion_point.cmp(&self.data.len()) {
                        Ordering::Less => self.data.insert(insertion_point, val),
                        Ordering::Equal => self.data.push(val),
                        Ordering::Greater => {
                            force_rollback = true;
                            break;
                        }
                    }

                    rows_changed += 1;
                }

                if force_rollback
                    || ((self.data.len() % (row_size + 1)) != 0)
                    || (rows_changed == 0)
                {
                    for row in (0..rows_changed).rev() {
                        self.data.remove((row + 1) * row_size + row);
                    }
                    check_consistent!(self);
                    Err(BidiError::IncompatibleSize)
                } else {
                    self.row_size = Some(row_size + 1);
                    check_consistent!(self);
                    Ok(())
                }
            }
        }
    }

    /// Appends a new row to the bidivec.
    /// If the bidivec is not empty, the row to be appended must contain
    /// exactly `width()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::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> {
        match self.row_size {
            None => {
                self.data.extend(iter);
                self.row_size = Some(self.data.len());
                check_consistent!(self);
                Ok(())
            }
            Some(row_size) => {
                let rollback_len = self.data.len();

                self.data.extend(iter);

                if self.data.len() != (row_size + rollback_len) {
                    self.data.truncate(rollback_len);
                    check_consistent!(self);
                    Err(BidiError::IncompatibleSize)
                } else {
                    check_consistent!(self);
                    Ok(())
                }
            }
        }
    }

    /// Inserts a new column in the middle of a bidivec.
    /// If the bidivec is not empty, the column to be inserted must contain
    /// exactly `height()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// If the bidivec is not empty, this operation is also expensive
    /// as it requires O(column_size * bidivec_size) time; use[`BidiGrowVec`] for
    /// faster column pushes (at the loss of linear layout).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::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 self.row_size {
            None if col == 0 => self.push_col(iter),
            None => Err(BidiError::OutOfBounds),
            Some(row_size) => match col.cmp(&row_size) {
                Ordering::Greater => Err(BidiError::OutOfBounds),
                Ordering::Equal => self.push_col(iter),
                Ordering::Less => {
                    let expected_len = self.data.len() + self.height();
                    let expected_count = self.height();
                    let mut insertion_count = 0;
                    let mut overflowed = false;

                    for v in iter.into_iter() {
                        let new_index = col + insertion_count * (row_size + 1);
                        insertion_count += 1;

                        if new_index >= self.data.len() {
                            overflowed = true;
                            break;
                        }

                        self.data.insert(new_index, v);

                        if insertion_count > expected_count {
                            break;
                        }
                    }

                    if overflowed || self.data.len() != expected_len {
                        for i in 0..insertion_count {
                            let del_index = col + i * row_size;

                            if del_index >= self.data.len() {
                                break;
                            }

                            self.data.remove(del_index);
                        }
                        //check_consistent!(self);
                        Err(BidiError::IncompatibleSize)
                    } else {
                        self.row_size = Some(row_size + 1);
                        check_consistent!(self);
                        Ok(())
                    }
                }
            },
        }
    }

    /// Inserts a new row in the middle of a bidivec.
    /// If the bidivec is not empty, the row to be inserted must contain
    /// exactly `width()` elements, or [`BidiError::IncompatibleSize`] is
    /// returned.
    ///
    /// This operation is O(bidivec_size).
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::BidiVec;
    ///
    /// let mut bvec = BidiVec::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 self.row_size {
            None if row == 0 => self.push_row(iter),
            None => Err(BidiError::OutOfBounds),
            Some(row_size) => match (row * row_size).cmp(&self.data.len()) {
                Ordering::Greater => Err(BidiError::OutOfBounds),
                Ordering::Equal => self.push_row(iter),
                Ordering::Less => {
                    let expected_len = self.data.len() + row_size;
                    let insertion_base = row * row_size;
                    let mut insertion_count = 0;

                    for v in iter.into_iter() {
                        self.data.insert(insertion_base + insertion_count, v);
                        insertion_count += 1;

                        if insertion_count > row_size {
                            break;
                        }
                    }

                    if self.data.len() != expected_len {
                        for _ in 0..insertion_count {
                            self.data.remove(insertion_base);
                        }
                        check_consistent!(self);
                        Err(BidiError::IncompatibleSize)
                    } else {
                        check_consistent!(self);
                        Ok(())
                    }
                }
            },
        }
    }

    /// Removes the specified column from the bidivec. If the column is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If the deleted data is not needed, `BidiVec::delete_col` provides
    /// better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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() {
            return Err(BidiError::OutOfBounds);
        }

        let row_size = self.row_size.unwrap();
        let mut result = Vec::with_capacity(self.height());

        for i in (0..self.height()).rev() {
            result.push(self.data.remove(i * row_size + col));
        }

        if self.data.is_empty() {
            self.row_size = None;
        } else {
            self.row_size = Some(row_size - 1);
        }

        result.reverse();

        Ok(result)
    }

    /// Removes the specified row from the bidivec. If the row is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If the deleted data is not needed, `BidiVec::delete_row` provides
    /// better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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() {
            return Err(BidiError::OutOfBounds);
        }

        let row_size = self.row_size.unwrap();
        let mut result = Vec::with_capacity(self.width());

        for _ in 0..self.width() {
            result.push(self.data.remove(row * row_size));
        }

        if self.data.is_empty() {
            self.row_size = None;
        }

        Ok(result)
    }

    /// Deletes the specified column from the bidivec. If the column is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiVec::remove_col` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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() {
            return Err(BidiError::OutOfBounds);
        }

        if let Some(row_size) = self.row_size {
            for i in (0..self.height()).rev() {
                self.data.remove(i * row_size + col);
            }

            if self.data.is_empty() {
                self.row_size = None;
            } else {
                self.row_size = Some(row_size - 1);
            }
        }

        Ok(())
    }

    /// Deletes the specified row from the bidivec. If the row is
    /// outside of range, [`BidiError::OutOfBounds`] is returned.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiVec::remove_row` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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> {
        if row >= self.height() {
            return Err(BidiError::OutOfBounds);
        }

        if let Some(row_size) = self.row_size {
            for _ in 0..self.width() {
                self.data.remove(row * row_size);
            }

            if self.data.is_empty() {
                self.row_size = None;
            }
        }

        Ok(())
    }

    /// Deletes the last column from the bidivec.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiVec::pop_col` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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 let Some(row_size) = self.row_size {
            for i in (0..self.height()).rev() {
                self.data.remove((i + 1) * row_size - 1);
            }

            if self.data.is_empty() {
                self.row_size = None;
            } else {
                self.row_size = Some(row_size - 1);
            }

            check_consistent!(self);
        }
    }

    /// Deletes the last row from the bidivec.
    ///
    /// If you need to access the deleted data is not needed,
    /// `BidiVec::pop_row` provides that data, at a performance cost.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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) {
        if let Some(row_size) = self.row_size {
            self.data.truncate(self.data.len().saturating_sub(row_size));

            if self.data.is_empty() {
                self.row_size = None;
            }

            check_consistent!(self);
        }
    }

    /// Removes the last column from the bidivec, returning its data.
    ///
    /// If the removed data is not needed, `BidiVec::delete_last_col`
    /// provides better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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 let Some(row_size) = self.row_size {
            let mut result = Vec::with_capacity(self.height());

            for i in (0..self.height()).rev() {
                result.push(self.data.remove((i + 1) * row_size - 1));
            }

            if self.data.is_empty() {
                self.row_size = None;
            } else {
                self.row_size = Some(row_size - 1);
            }

            result.reverse();

            check_consistent!(self);
            Some(result)
        } else {
            None
        }
    }

    /// Removes the last row from the bidivec, returning its data.
    ///
    /// If the removed data is not needed, `BidiVec::delete_last_row`
    /// provides better performances.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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>> {
        if let Some(row_size) = self.row_size {
            let result = self
                .data
                .split_off(self.data.len().saturating_sub(row_size));

            if self.data.is_empty() {
                self.row_size = None;
            }

            check_consistent!(self);
            Some(result)
        } else {
            None
        }
    }

    /// Accesses an element in the BidiVec, 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::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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> {
        match self.calc_index(x, y) {
            Ok(idx) => Some(unsafe { self.data.get_unchecked(idx) }),
            Err(_) => None,
        }
    }

    /// Mutably accesses an element in the BidiVec, 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::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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> {
        match self.calc_index(x, y) {
            Ok(idx) => Some(unsafe { self.data.get_unchecked_mut(idx) }),
            Err(_) => None,
        }
    }

    /// Checks if the specified coordinates are inside the bidivec bounds
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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 {
        self.calc_index(x, y).is_ok()
    }

    #[inline(always)]
    fn calc_index(&self, x: usize, y: usize) -> Result<usize, BidiError> {
        check_consistent!(&self);

        match self.row_size {
            Some(w) => {
                let idx = y * w + x;
                if x >= w || idx >= self.data.len() {
                    Err(BidiError::OutOfBounds)
                } else {
                    Ok(idx)
                }
            }
            None => Err(BidiError::OutOfBounds),
        }
    }

    /// Reverses the order of the items in the specified row.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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() {
            return Err(BidiError::OutOfBounds);
        }

        let width = self.width();

        for x in 0..(width / 2) {
            self.swap((x, row), (width - 1 - x, row)).unwrap();
        }

        Ok(())
    }

    /// Reverses the order of the items in the specified column.
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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() {
            return Err(BidiError::OutOfBounds);
        }

        let height = self.height();

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

        Ok(())
    }

    /// Transposes the bidivec, that is an operation that flips the bidivec
    /// 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.
    ///
    /// While this is performed in-place, it still requires O(n) additional memory
    /// if the bidivec width and height are different (i.e. it's not a square).
    pub fn transpose(&mut self) {
        if let Some(row_size) = self.row_size {
            let mut slice = BidiMutSlice::new(&mut self.data, row_size).unwrap();
            slice.transpose();
            self.row_size = Some(self.height());
        }
    }

    /// Rotates the bidivec 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 bidivec width and height are different (i.e. it's not a square).
    pub fn rotate90ccw(&mut self) {
        self.transpose();
        self.reverse_columns();
    }

    /// Rotates the bidivec 180°.
    pub fn rotate180(&mut self) {
        self.data.reverse();
    }

    /// Rotates the bidivec 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 bidivec 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) {
        for col in 0..self.width() {
            self.reverse_col(col).unwrap();
        }
    }

    /// 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 row in 0..self.height() {
            self.reverse_row(row).unwrap();
        }
    }

    /// 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(())
        }
    }

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

    /// Converts this instance into a [`BidiArray<T>`]
    /// This operation is `O(1)` 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 BidiVec<T>
where
    T: Clone,
{
    fn from_view(source: &dyn BidiView<Output = T>) -> Result<Self, BidiError> {
        Ok(BidiVec::<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(BidiVec::<T>::with_size_func_xy(
            cut.width,
            cut.height,
            |x, y| source[(x + cut.x, y + cut.y)].clone(),
        ))
    }
}

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

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

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

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

impl<T> BidiFrom<BidiArray<T>> for BidiVec<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 BidiVec<T> {
    type Output = T;

    /// Accesses an element in the BidiVec, using its cartesian coordinates.
    /// If coordinates are outside of range, it panics.
    ///
    /// If you want a more graceful error handling, see [`BidiVec::get`].
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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 {
        let idx = self.calc_index(index.0, index.1).unwrap_or_else(|_| {
            panic!(
                "Indexes out of bidivec bounds: ({},{}) out of {}x{}",
                index.0,
                index.1,
                self.width(),
                self.height()
            )
        });
        unsafe { self.data.get_unchecked(idx) }
    }
}

impl<T> IndexMut<(usize, usize)> for BidiVec<T> {
    /// Mutably accesses an element in the BidiVec, using its cartesian coordinates.
    /// If coordinates are outside of range, it panics.
    ///
    /// If you want a more graceful error handling, see [`BidiVec::get_mut`] and
    ///
    /// # Examples
    ///
    /// ```
    /// use bidivec::{BidiVec, bidivec};
    ///
    /// let mut bvec = bidivec!{
    ///     [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 {
        let idx = self.calc_index(index.0, index.1).unwrap_or_else(|_| {
            panic!(
                "Indexes out of bidivec bounds: ({},{}) out of {}x{}",
                index.0,
                index.1,
                self.width(),
                self.height()
            )
        });
        unsafe { self.data.get_unchecked_mut(idx) }
    }
}

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

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

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

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

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

impl<T> From<BidiArray<T>> for BidiVec<T> {
    /// Creates a new instance of [`BidiVec<T>`] from an existing [`BidiVec<T>`].
    /// This operation is `O(1)` in the worst case.
    fn from(other: BidiArray<T>) -> Self {
        Self {
            data: other.data.into_vec(),
            row_size: if other.row_size == 0 {
                None
            } else {
                Some(other.row_size)
            },
        }
    }
}