├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml ├── README.md ├── examples ├── random │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── tic-tac-toe │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── src └── lib.rs └── tests └── array2d.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "array2d" 3 | version = "0.3.2" 4 | authors = ["Harrison McCullough "] 5 | edition = "2018" 6 | description = "A fixed sized two-dimensional array" 7 | readme = "README.md" 8 | license = "MIT" 9 | repository = "https://github.com/HarrisonMc555/array2d" 10 | 11 | [dependencies] 12 | serde = { version = "1.0", features = ["derive"], optional = true } 13 | bevy_reflect = { version = "0.14.2", optional = true } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # array2d 2 | 3 | Array2D provides a fixed sized two-dimensional array. It is more efficient 4 | and is easier to use than a vector of vectors, i.e. `Vec>`. 5 | 6 | This is beneficial when using a grid-like structure, which is common in 7 | image processing, game boards, and other situations. Array2D cannot be used 8 | when rows or columns might have different lengths⁠—all rows and columns must 9 | be the same length. 10 | 11 | ## How to use [`Array2D`] 12 | 13 | ### Creating an [`Array2D`] 14 | 15 | An [`Array2D`] can be created in many different ways. These include: 16 | - Providing the rows or the columns, which must all be the same size (see 17 | [`from_rows`] and [`from_columns`]). 18 | - Providing a "flat" slice of elements in either [row major or column 19 | major order] along with the dimensions, which must match the number of 20 | elements in the slice (see [`from_row_major`] and 21 | [`from_column_major`]). 22 | - Providing a value to repeatedly put in every location (see 23 | [`filled_with`]). 24 | - Providing a generator function that is repeatedly called to produce 25 | values to fill the array (see [`filled_by_row_major`] and 26 | [`filled_by_column_major`]). 27 | - Providing an iterator that is used to produce values to fill the array 28 | (see [`from_iter_row_major`] and [`from_iter_column_major`]). 29 | 30 | ### Accessing data from an [`Array2D`] 31 | 32 | [`Array2D`] supports several forms of indexing: 33 | - Using the indexing syntax (square brackets) with a tuple of [`(usize, 34 | usize)`], which panics on out-of-bounds accesses. 35 | - Using the [`get`], [`get_mut`], and [`set`] methods, which return an 36 | [`Option`] or a [`Result`] on out-of-bounds accesses. 37 | - Using the row major or column major version of these methods, 38 | i.e. [`get_row_major`], [`get_mut_row_major`], [`set_row_major`], 39 | [`get_column_major`], [`get_mut_column_major`], 40 | [`set_column_major`]. These perform the same tasks as the non row/column 41 | major methods, but take one index instead of two. 42 | 43 | [`Array2D`] also supports several forms of iteration. You can iterate 44 | through: 45 | - All of the elements, in either [row major or column major order] (see 46 | [`elements_row_major_iter`] and [`elements_column_major_iter`]). 47 | - Individual rows or columns (see [`row_iter`] and [`column_iter`]). 48 | - All rows or all columns (see [`rows_iter`] and [`columns_iter`]). 49 | 50 | ### Extracting all data from an [`Array2D`] 51 | 52 | An [`Array2D`] can be converted back into a [`Vec`] through several 53 | methods. You can extract the data as: 54 | - A [`Vec`] of rows or columns (see [`as_rows`] and [`as_columns`]). 55 | - A "flat" [`Vec`] of elements in either [row major or column major order] 56 | (see [`as_row_major`] and [`as_column_major`]). 57 | 58 | ## Examples 59 | 60 | ```rust 61 | use array2d::{Array2D, Error}; 62 | 63 | pub fn main() -> Result<(), Error> { 64 | // Create an array filled with the same element. 65 | let prefilled = Array2D::filled_with(42, 2, 3); 66 | assert_eq!(prefilled.num_rows(), 2); 67 | assert_eq!(prefilled.num_columns(), 3); 68 | assert_eq!(prefilled[(0, 0)], 42); 69 | 70 | // Create an array from the given rows. You can also use columns 71 | // with the `columns` function 72 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 73 | let from_rows = Array2D::from_rows(&rows)?; 74 | assert_eq!(from_rows.num_rows(), 2); 75 | assert_eq!(from_rows.num_columns(), 3); 76 | assert_eq!(from_rows[(1, 1)], 5); 77 | 78 | // Create an array from a flat Vec of elements in row major or 79 | // column major order. 80 | let column_major = vec![1, 4, 2, 5, 3, 6]; 81 | let from_column_major = 82 | Array2D::from_column_major(&column_major, 2, 3)?; 83 | assert_eq!(from_column_major.num_rows(), 2); 84 | assert_eq!(from_column_major.num_columns(), 3); 85 | assert_eq!(from_column_major[(1, 1)], 5); 86 | 87 | // Implements `Eq` if the element type does. 88 | assert_eq!(from_rows, from_column_major); 89 | 90 | // Index into an array using a tuple of usize to access or alter 91 | // the array. 92 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 93 | let mut array = Array2D::from_rows(&rows)?; 94 | array[(1, 1)] = 100; 95 | 96 | // Convert the array back into a nested Vec using `as_rows` or 97 | // `as_columns`. 98 | let array_rows = array.as_rows(); 99 | assert_eq!(array_rows, vec![vec![1, 2, 3], vec![4, 100, 6]]); 100 | 101 | // Convert the array back into a flat Vec using `as_row_major` or 102 | // `as_column_major`. 103 | let array_column_major = array.as_column_major(); 104 | assert_eq!(array_column_major, vec![1, 4, 2, 100, 3, 6]); 105 | 106 | // Iterate over a single row or column 107 | println!("First column:"); 108 | for element in array.column_iter(0)? { 109 | println!("{}", element); 110 | } 111 | 112 | // Iterate over all rows or columns. 113 | println!("All elements:"); 114 | for row_iter in array.rows_iter() { 115 | for element in row_iter { 116 | print!("{} ", element); 117 | } 118 | println!(); 119 | } 120 | 121 | Ok(()) 122 | } 123 | ``` 124 | 125 | [`Array2D`]: struct.Array2D.html 126 | [`from_rows`]: struct.Array2D.html#method.from_rows 127 | [`from_columns`]: struct.Array2D.html#method.from_columns 128 | [`from_row_major`]: struct.Array2D.html#method.from_row_major 129 | [`from_column_major`]: struct.Array2D.html#method.from_column_major 130 | [`filled_with`]: struct.Array2D.html#method.filled_with 131 | [`filled_by_row_major`]: struct.Array2D.html#method.filled_by_row_major 132 | [`filled_by_column_major`]: struct.Array2D.html#method.filled_by_column_major 133 | [`from_iter_row_major`]: struct.Array2D.html#method.from_iter_row_major 134 | [`from_iter_column_major`]: struct.Array2D.html#method.from_iter_column_major 135 | [`get`]: struct.Array2D.html#method.get 136 | [`get_mut`]: struct.Array2D.html#method.get_mut 137 | [`set`]: struct.Array2D.html#method.set 138 | [`get_row_major`]: struct.Array2D.html#method.get_row_major 139 | [`get_mut_row_major`]: struct.Array2D.html#method.get_mut_row_major 140 | [`set_row_major`]: struct.Array2D.html#method.set_row_major 141 | [`get_column_major`]: struct.Array2D.html#method.get_column_major 142 | [`get_mut_column_major`]: struct.Array2D.html#method.get_mut_column_major 143 | [`set_column_major`]: struct.Array2D.html#method.set_column_major 144 | [`elements_row_major_iter`]: struct.Array2D.html#method.elements_row_major_iter 145 | [`elements_column_major_iter`]: struct.Array2D.html#method.elements_column_major_iter 146 | [`row_iter`]: struct.Array2D.html#method.row_iter 147 | [`column_iter`]: struct.Array2D.html#method.column_iter 148 | [`rows_iter`]: struct.Array2D.html#method.rows_iter 149 | [`columns_iter`]: struct.Array2D.html#method.columns_iter 150 | [`as_rows`]: struct.Array2D.html#method.as_rows 151 | [`as_columns`]: struct.Array2D.html#method.as_columns 152 | [`as_row_major`]: struct.Array2D.html#method.as_row_major 153 | [`as_column_major`]: struct.Array2D.html#method.as_column_major 154 | [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 155 | [`Option`]: https://doc.rust-lang.org/std/option/ 156 | [`Result`]: https://doc.rust-lang.org/std/result/ 157 | [`(usize, usize)`]: https://doc.rust-lang.org/std/primitive.usize.html 158 | [row major or column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 159 | 160 | License: MIT 161 | -------------------------------------------------------------------------------- /examples/random/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /examples/random/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "random" 3 | version = "0.1.0" 4 | authors = ["Harrison McCullough "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | array2d = { path = "../.." } 9 | rand = "0.6.5" 10 | -------------------------------------------------------------------------------- /examples/random/src/main.rs: -------------------------------------------------------------------------------- 1 | use array2d::Array2D; 2 | use rand::prelude::*; 3 | 4 | fn main() { 5 | let mut rng = rand::thread_rng(); 6 | let board = Array2D::filled_by_row_major(|| rng.gen_range(0, 10), 3, 2); 7 | println!("{:?}", board); 8 | 9 | let mut counter = 1; 10 | let f = || { 11 | let tmp = counter; 12 | counter += 1; 13 | tmp 14 | }; 15 | let board2 = Array2D::filled_by_column_major(f, 2, 3); 16 | println!("{:?}", board2); 17 | } 18 | -------------------------------------------------------------------------------- /examples/tic-tac-toe/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /examples/tic-tac-toe/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tic-tac-toe" 3 | version = "0.1.0" 4 | authors = ["Harrison McCullough "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | array2d = { path = "../.." } 9 | -------------------------------------------------------------------------------- /examples/tic-tac-toe/src/main.rs: -------------------------------------------------------------------------------- 1 | use array2d::Array2D; 2 | 3 | fn format_board(board: &Array2D) -> String { 4 | board 5 | .rows_iter() 6 | .map(|row_iter| row_iter.cloned().collect::>().join("|")) 7 | .collect::>() 8 | .join("\n-----\n") 9 | } 10 | 11 | fn main() { 12 | let mut board = Array2D::filled_with(" ".to_string(), 3, 3); 13 | println!("{}\n", format_board(&board)); 14 | board[(0, 2)] = "X".to_string(); 15 | println!("{}\n", format_board(&board)); 16 | } 17 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Array2D provides a fixed sized two-dimensional array. It is more efficient 2 | //! and is easier to use than a vector of vectors, i.e. `Vec>`. 3 | //! 4 | //! This is beneficial when using a grid-like structure, which is common in 5 | //! image processing, game boards, and other situations. Array2D cannot be used 6 | //! when rows or columns might have different lengths⁠—all rows and columns must 7 | //! be the same length. 8 | //! 9 | //! # How to use [`Array2D`] 10 | //! 11 | //! ## Creating an [`Array2D`] 12 | //! 13 | //! An [`Array2D`] can be created in many different ways. These include: 14 | //! - Providing the rows or the columns, which must all be the same size (see 15 | //! [`from_rows`] and [`from_columns`]). 16 | //! - Providing a "flat" slice of elements in either [row major or column 17 | //! major order] along with the dimensions, which must match the number of 18 | //! elements in the slice (see [`from_row_major`] and 19 | //! [`from_column_major`]). 20 | //! - Providing a value to repeatedly put in every location (see 21 | //! [`filled_with`]). 22 | //! - Providing a generator function that is repeatedly called to produce 23 | //! values to fill the array (see [`filled_by_row_major`] and 24 | //! [`filled_by_column_major`]). 25 | //! - Providing an iterator that is used to produce values to fill the array 26 | //! (see [`from_iter_row_major`] and [`from_iter_column_major`]). 27 | //! 28 | //! ## Accessing data from an [`Array2D`] 29 | //! 30 | //! [`Array2D`] supports several forms of indexing: 31 | //! - Using the indexing syntax (square brackets) with a tuple of [`(usize, 32 | //! usize)`], which panics on out-of-bounds accesses. 33 | //! - Using the [`get`], [`get_mut`], and [`set`] methods, which return an 34 | //! [`Option`] or a [`Result`] on out-of-bounds accesses. 35 | //! - Using the row major or column major version of these methods, 36 | //! i.e. [`get_row_major`], [`get_mut_row_major`], [`set_row_major`], 37 | //! [`get_column_major`], [`get_mut_column_major`], 38 | //! [`set_column_major`]. These perform the same tasks as the non row/column 39 | //! major methods, but take one index instead of two. 40 | //! 41 | //! [`Array2D`] also supports several forms of iteration. You can iterate 42 | //! through: 43 | //! - All the elements, in either [row major or column major order] (see 44 | //! [`elements_row_major_iter`] and [`elements_column_major_iter`]). 45 | //! - Individual rows or columns (see [`row_iter`] and [`column_iter`]). 46 | //! - All rows or all columns (see [`rows_iter`] and [`columns_iter`]). 47 | //! 48 | //! ## Extracting all data from an [`Array2D`] 49 | //! 50 | //! An [`Array2D`] can be converted back into a [`Vec`] through several 51 | //! methods. You can extract the data as: 52 | //! - A [`Vec`] of rows or columns (see [`as_rows`] and [`as_columns`]). 53 | //! - A "flat" [`Vec`] of elements in either [row major or column major order] 54 | //! (see [`as_row_major`] and [`as_column_major`]). 55 | //! 56 | //! # Examples 57 | //! 58 | //! ```rust 59 | //! use array2d::{Array2D, Error}; 60 | //! 61 | //! pub fn main() -> Result<(), Error> { 62 | //! // Create an array filled with the same element. 63 | //! let prefilled = Array2D::filled_with( 2, 3,42); 64 | //! assert_eq!(prefilled.num_rows(), 2); 65 | //! assert_eq!(prefilled.num_columns(), 3); 66 | //! assert_eq!(prefilled[(0, 0)], 42); 67 | //! 68 | //! // Create an array from the given rows. You can also use columns 69 | //! // with the `columns` function 70 | //! let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 71 | //! let from_rows = Array2D::from_rows(&rows)?; 72 | //! assert_eq!(from_rows.num_rows(), 2); 73 | //! assert_eq!(from_rows.num_columns(), 3); 74 | //! assert_eq!(from_rows[(1, 1)], 5); 75 | //! 76 | //! // Create an array from a flat Vec of elements in row major or 77 | //! // column major order. 78 | //! let column_major = vec![1, 4, 2, 5, 3, 6]; 79 | //! let from_column_major = 80 | //! Array2D::from_column_major( 2, 3,&column_major)?; 81 | //! assert_eq!(from_column_major.num_rows(), 2); 82 | //! assert_eq!(from_column_major.num_columns(), 3); 83 | //! assert_eq!(from_column_major[(1, 1)], 5); 84 | //! 85 | //! // Implements `Eq` if the element type does. 86 | //! assert_eq!(from_rows, from_column_major); 87 | //! 88 | //! // Index into an array using a tuple of usize to access or alter 89 | //! // the array. 90 | //! let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 91 | //! let mut array = Array2D::from_rows(&rows)?; 92 | //! array[(1, 1)] = 100; 93 | //! 94 | //! // Convert the array back into a nested Vec using `as_rows` or 95 | //! // `as_columns`. 96 | //! let array_rows = array.as_rows(); 97 | //! assert_eq!(array_rows, vec![vec![1, 2, 3], vec![4, 100, 6]]); 98 | //! 99 | //! // Convert the array back into a flat Vec using `as_row_major` or 100 | //! // `as_column_major`. 101 | //! let array_column_major = array.as_column_major(); 102 | //! assert_eq!(array_column_major, vec![1, 4, 2, 100, 3, 6]); 103 | //! 104 | //! // Iterate over a single row or column 105 | //! println!("First column:"); 106 | //! for element in array.column_iter(0)? { 107 | //! println!("{}", element); 108 | //! } 109 | //! 110 | //! // Iterate over all rows or columns. 111 | //! println!("All elements:"); 112 | //! for row_iter in array.rows_iter() { 113 | //! for element in row_iter { 114 | //! print!("{} ", element); 115 | //! } 116 | //! println!(); 117 | //! } 118 | //! 119 | //! Ok(()) 120 | //! } 121 | //! ``` 122 | //! 123 | //! [`Array2D`]: struct.Array2D.html 124 | //! [`from_rows`]: struct.Array2D.html#method.from_rows 125 | //! [`from_columns`]: struct.Array2D.html#method.from_columns 126 | //! [`from_row_major`]: struct.Array2D.html#method.from_row_major 127 | //! [`from_column_major`]: struct.Array2D.html#method.from_column_major 128 | //! [`filled_with`]: struct.Array2D.html#method.filled_with 129 | //! [`filled_by_row_major`]: struct.Array2D.html#method.filled_by_row_major 130 | //! [`filled_by_column_major`]: struct.Array2D.html#method.filled_by_column_major 131 | //! [`from_iter_row_major`]: struct.Array2D.html#method.from_iter_row_major 132 | //! [`from_iter_column_major`]: struct.Array2D.html#method.from_iter_column_major 133 | //! [`get`]: struct.Array2D.html#method.get 134 | //! [`get_mut`]: struct.Array2D.html#method.get_mut 135 | //! [`set`]: struct.Array2D.html#method.set 136 | //! [`get_row_major`]: struct.Array2D.html#method.get_row_major 137 | //! [`get_mut_row_major`]: struct.Array2D.html#method.get_mut_row_major 138 | //! [`set_row_major`]: struct.Array2D.html#method.set_row_major 139 | //! [`get_column_major`]: struct.Array2D.html#method.get_column_major 140 | //! [`get_mut_column_major`]: struct.Array2D.html#method.get_mut_column_major 141 | //! [`set_column_major`]: struct.Array2D.html#method.set_column_major 142 | //! [`elements_row_major_iter`]: struct.Array2D.html#method.elements_row_major_iter 143 | //! [`elements_column_major_iter`]: struct.Array2D.html#method.elements_column_major_iter 144 | //! [`row_iter`]: struct.Array2D.html#method.row_iter 145 | //! [`column_iter`]: struct.Array2D.html#method.column_iter 146 | //! [`rows_iter`]: struct.Array2D.html#method.rows_iter 147 | //! [`columns_iter`]: struct.Array2D.html#method.columns_iter 148 | //! [`as_rows`]: struct.Array2D.html#method.as_rows 149 | //! [`as_columns`]: struct.Array2D.html#method.as_columns 150 | //! [`as_row_major`]: struct.Array2D.html#method.as_row_major 151 | //! [`as_column_major`]: struct.Array2D.html#method.as_column_major 152 | //! [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 153 | //! [`Option`]: https://doc.rust-lang.org/std/option/ 154 | //! [`Result`]: https://doc.rust-lang.org/std/result/ 155 | //! [`(usize, usize)`]: https://doc.rust-lang.org/std/primitive.usize.html 156 | //! [row major or column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 157 | 158 | #![deny(missing_docs)] 159 | 160 | use std::fmt::{Display, Formatter}; 161 | use std::ops::{Index, IndexMut}; 162 | 163 | #[cfg(feature = "bevy_reflect")] 164 | use bevy_reflect::Reflect; 165 | #[cfg(feature = "serde")] 166 | use serde::{Deserialize, Serialize}; 167 | 168 | /// A fixed sized two-dimensional array. 169 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 170 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 171 | #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] 172 | pub struct Array2D { 173 | array: Vec, 174 | num_rows: usize, 175 | num_columns: usize, 176 | } 177 | 178 | /// An error that can arise during the use of an [`Array2D`]. 179 | /// 180 | /// [`Array2D`]: struct.Array2D.html 181 | #[derive(Debug, Eq, PartialEq)] 182 | pub enum Error { 183 | /// The given indices were out of bounds. 184 | IndicesOutOfBounds(usize, usize), 185 | /// The given index in row or column major order was out of bounds. 186 | IndexOutOfBounds(usize), 187 | /// The dimensions given did not match the elements provided 188 | DimensionMismatch, 189 | /// There were not enough elements to fill the array. 190 | NotEnoughElements, 191 | } 192 | 193 | impl Display for Error { 194 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 195 | match self { 196 | Error::IndicesOutOfBounds(row, column) => { 197 | write!(f, "indices ({row}, {column}) out of bounds") 198 | } 199 | Error::IndexOutOfBounds(index) => write!(f, "index {index} out of bounds"), 200 | Error::DimensionMismatch => write!(f, "dimension mismatch"), 201 | Error::NotEnoughElements => write!(f, "not enough elements"), 202 | } 203 | } 204 | } 205 | 206 | impl std::error::Error for Error {} 207 | 208 | impl Array2D { 209 | /// Creates a new [`Array2D`] from a slice of rows, each of which is a 210 | /// [`Vec`] of elements. 211 | /// 212 | /// Returns an error if the rows are not all the same size. 213 | /// 214 | /// # Examples 215 | /// 216 | /// ``` 217 | /// # use array2d::{Array2D, Error}; 218 | /// # fn main() -> Result<(), Error> { 219 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 220 | /// let array = Array2D::from_rows(&rows)?; 221 | /// assert_eq!(array[(1, 2)], 6); 222 | /// assert_eq!(array.as_rows(), rows); 223 | /// # Ok(()) 224 | /// # } 225 | /// ``` 226 | /// 227 | /// [`Array2D`]: struct.Array2D.html 228 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 229 | pub fn from_rows(elements: &[Vec]) -> Result 230 | where 231 | T: Clone, 232 | { 233 | let row_len = elements.first().map(Vec::len).unwrap_or(0); 234 | if !elements.iter().all(|row| row.len() == row_len) { 235 | return Err(Error::DimensionMismatch); 236 | } 237 | Ok(Array2D { 238 | array: flatten(elements), 239 | num_rows: elements.len(), 240 | num_columns: row_len, 241 | }) 242 | } 243 | 244 | /// Creates a new [`Array2D`] from a slice of columns, each of which 245 | /// contains a [`Vec`] of elements. 246 | /// 247 | /// Returns an error if the columns are not all the same size. 248 | /// 249 | /// # Examples 250 | /// 251 | /// ``` 252 | /// # use array2d::{Array2D, Error}; 253 | /// # fn main() -> Result<(), Error> { 254 | /// let columns = vec![vec![1, 4], vec![2, 5], vec![3, 6]]; 255 | /// let array = Array2D::from_columns(&columns)?; 256 | /// assert_eq!(array[(1, 2)], 6); 257 | /// assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 258 | /// # Ok(()) 259 | /// # } 260 | /// ``` 261 | /// 262 | /// [`Array2D`]: struct.Array2D.html 263 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 264 | pub fn from_columns(elements: &[Vec]) -> Result 265 | where 266 | T: Clone, 267 | { 268 | let column_len = elements.first().map(Vec::len).unwrap_or(0); 269 | if !elements.iter().all(|column| column.len() == column_len) { 270 | return Err(Error::DimensionMismatch); 271 | } 272 | let num_rows = column_len; 273 | let num_columns = elements.len(); 274 | let array = indices_row_major(num_rows, num_columns) 275 | .map(|(row, column)| elements[column][row].clone()) 276 | .collect(); 277 | Ok(Array2D { 278 | array, 279 | num_rows, 280 | num_columns, 281 | }) 282 | } 283 | 284 | /// Creates a new [`Array2D`] from the given flat slice in [row major 285 | /// order]. 286 | /// 287 | /// Returns an error if the number of elements in `elements` is not the 288 | /// product of `num_rows` and `num_columns`, i.e. the dimensions do not 289 | /// match. 290 | /// 291 | /// # Examples 292 | /// 293 | /// ``` 294 | /// # use array2d::{Array2D, Error}; 295 | /// # fn main() -> Result<(), Error> { 296 | /// let row_major = vec![1, 2, 3, 4, 5, 6]; 297 | /// let array = Array2D::from_row_major( 2, 3,&row_major)?; 298 | /// assert_eq!(array[(1, 2)], 6); 299 | /// assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 300 | /// # Ok(()) 301 | /// # } 302 | /// ``` 303 | /// 304 | /// [`Array2D`]: struct.Array2D.html 305 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 306 | pub fn from_row_major( 307 | num_rows: usize, 308 | num_columns: usize, 309 | elements: &[T], 310 | ) -> Result 311 | where 312 | T: Clone, 313 | { 314 | let total_len = num_rows * num_columns; 315 | if total_len != elements.len() { 316 | return Err(Error::DimensionMismatch); 317 | } 318 | Ok(Array2D { 319 | array: elements.to_vec(), 320 | num_rows, 321 | num_columns, 322 | }) 323 | } 324 | 325 | /// Creates a new [`Array2D`] from the given flat slice in [column major 326 | /// order]. 327 | /// 328 | /// Return an error if the number of elements in `elements` is not the 329 | /// product of `num_rows` and `num_columns`, i.e. the dimensions do not 330 | /// match. 331 | /// 332 | /// # Examples 333 | /// 334 | /// ``` 335 | /// # use array2d::{Array2D, Error}; 336 | /// # fn main() -> Result<(), Error> { 337 | /// let column_major = vec![1, 4, 2, 5, 3, 6]; 338 | /// let array = Array2D::from_column_major( 2, 3,&column_major)?; 339 | /// assert_eq!(array[(1, 2)], 6); 340 | /// assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 341 | /// # Ok(()) 342 | /// # } 343 | /// ``` 344 | /// 345 | /// [`Array2D`]: struct.Array2D.html 346 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 347 | pub fn from_column_major( 348 | num_rows: usize, 349 | num_columns: usize, 350 | elements: &[T], 351 | ) -> Result 352 | where 353 | T: Clone, 354 | { 355 | let total_len = num_rows * num_columns; 356 | if total_len != elements.len() { 357 | return Err(Error::DimensionMismatch); 358 | } 359 | let indices_row_major = 360 | (0..num_rows).flat_map(move |row| (0..num_columns).map(move |column| (row, column))); 361 | let array = indices_row_major 362 | .map(|(row, column)| { 363 | let index = column * num_rows + row; 364 | elements[index].clone() 365 | }) 366 | .collect(); 367 | Ok(Array2D { 368 | array, 369 | num_rows, 370 | num_columns, 371 | }) 372 | } 373 | 374 | /// Creates a new [`Array2D`] with the specified number of rows and columns 375 | /// that contains `element` in every location. 376 | /// 377 | /// # Examples 378 | /// 379 | /// ``` 380 | /// # use array2d::{Array2D, Error}; 381 | /// let array = Array2D::filled_with( 2, 3,42); 382 | /// assert_eq!(array.as_rows(), vec![vec![42, 42, 42], vec![42, 42, 42]]); 383 | /// ``` 384 | /// 385 | /// [`Array2D`]: struct.Array2D.html 386 | pub fn filled_with(num_rows: usize, num_columns: usize, element: T) -> Self 387 | where 388 | T: Clone, 389 | { 390 | let total_len = num_rows * num_columns; 391 | let array = vec![element; total_len]; 392 | Array2D { 393 | array, 394 | num_rows, 395 | num_columns, 396 | } 397 | } 398 | 399 | /// Creates a new [`Array2D`] with the specified number of rows and columns 400 | /// and fills each element with the result of calling the given 401 | /// function. The function is called once for every location going in 402 | /// row major order. 403 | /// 404 | /// # Examples 405 | /// 406 | /// ``` 407 | /// # use array2d::{Array2D, Error}; 408 | /// let mut counter = 1; 409 | /// let increment = || { 410 | /// let tmp = counter; 411 | /// counter += 1; 412 | /// tmp 413 | /// }; 414 | /// let array = Array2D::filled_by_row_major( 2, 3,increment); 415 | /// assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 416 | /// ``` 417 | /// 418 | /// [`Array2D`]: struct.Array2D.html 419 | pub fn filled_by_row_major(num_rows: usize, num_columns: usize, mut generator: F) -> Self 420 | where 421 | F: FnMut() -> T, 422 | { 423 | let total_len = num_rows * num_columns; 424 | let array = (0..total_len).map(|_| generator()).collect(); 425 | Array2D { 426 | array, 427 | num_rows, 428 | num_columns, 429 | } 430 | } 431 | 432 | /// Creates a new [`Array2D`] with the specified number of rows and columns 433 | /// and fills each element with the result of calling the given 434 | /// function. The function is called once for every location going in 435 | /// column major order. 436 | /// 437 | /// # Examples 438 | /// 439 | /// ``` 440 | /// # use array2d::{Array2D, Error}; 441 | /// let mut counter = 1; 442 | /// let increment = || { 443 | /// let tmp = counter; 444 | /// counter += 1; 445 | /// tmp 446 | /// }; 447 | /// let array = Array2D::filled_by_column_major( 2, 3,increment); 448 | /// assert_eq!(array.as_columns(), vec![vec![1, 2], vec![3, 4], vec![5, 6]]); 449 | /// ``` 450 | /// 451 | /// [`Array2D`]: struct.Array2D.html 452 | pub fn filled_by_column_major(num_rows: usize, num_columns: usize, mut generator: F) -> Self 453 | where 454 | F: FnMut() -> T, 455 | T: Clone, 456 | { 457 | let total_len = num_rows * num_columns; 458 | let array_column_major = (0..total_len).map(|_| generator()).collect::>(); 459 | Array2D::from_column_major(num_rows, num_columns, &array_column_major) 460 | .expect("Filled by should never fail") 461 | } 462 | 463 | /// Creates a new [`Array2D`] with the specified number of rows and columns 464 | /// and fills each element with the elements produced from the provided 465 | /// iterator. If the iterator produces more than enough elements, the 466 | /// remaining are unused. Returns an error if the iterator does not produce 467 | /// enough elements. 468 | /// 469 | /// The elements are inserted into the array in [row major order]. 470 | /// 471 | /// # Examples 472 | /// 473 | /// ``` 474 | /// # use array2d::{Array2D, Error}; 475 | /// # fn main() -> Result<(), Error> { 476 | /// let iterator = 1..; 477 | /// let array = Array2D::from_iter_row_major( 2, 3,iterator)?; 478 | /// assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 479 | /// # Ok(()) 480 | /// # } 481 | /// ``` 482 | /// 483 | /// [`Array2D`]: struct.Array2D.html 484 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 485 | pub fn from_iter_row_major( 486 | num_rows: usize, 487 | num_columns: usize, 488 | iterator: I, 489 | ) -> Result 490 | where 491 | I: Iterator, 492 | { 493 | let total_len = num_rows * num_columns; 494 | let array = iterator.take(total_len).collect::>(); 495 | if array.len() != total_len { 496 | return Err(Error::NotEnoughElements); 497 | } 498 | Ok(Array2D { 499 | array, 500 | num_rows, 501 | num_columns, 502 | }) 503 | } 504 | 505 | /// Creates a new [`Array2D`] with the specified number of rows and columns 506 | /// and fills each element with the elements produced from the provided 507 | /// iterator. If the iterator produces more than enough elements, the 508 | /// remaining are unused. Returns an error if the iterator does not produce 509 | /// enough elements. 510 | /// 511 | /// The elements are inserted into the array in [column major order]. 512 | /// 513 | /// # Examples 514 | /// 515 | /// ``` 516 | /// # use array2d::{Array2D, Error}; 517 | /// # fn main() -> Result<(), Error> { 518 | /// let iterator = 1..; 519 | /// let array = Array2D::from_iter_column_major( 2, 3,iterator)?; 520 | /// assert_eq!(array.as_rows(), vec![vec![1, 3, 5], vec![2, 4, 6]]); 521 | /// # Ok(()) 522 | /// # } 523 | /// ``` 524 | /// 525 | /// [`Array2D`]: struct.Array2D.html 526 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 527 | pub fn from_iter_column_major( 528 | num_rows: usize, 529 | num_columns: usize, 530 | iterator: I, 531 | ) -> Result 532 | where 533 | I: Iterator, 534 | T: Clone, 535 | { 536 | let total_len = num_rows * num_columns; 537 | let array_column_major = iterator.take(total_len).collect::>(); 538 | Array2D::from_column_major(num_rows, num_columns, &array_column_major) 539 | .map_err(|_| Error::NotEnoughElements) 540 | } 541 | 542 | /// Creates a new [`Array2D`] from an existing [`Array2D`]. Each element is traversed in [row major order]. The 543 | /// element is passed to `mapper`, which produces the new element to use in the new array. 544 | /// 545 | /// # Examples 546 | /// 547 | /// ``` 548 | /// # use array2d::{Array2D, Error}; 549 | /// # fn main() -> Result<(), Error> { 550 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 551 | /// let array = Array2D::from_rows(&rows)?; 552 | /// let new_array = array.map_row_major(|x| x * 10); 553 | /// let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 554 | /// assert_eq!(new_array.as_rows(), expected); 555 | /// # Ok(()) 556 | /// # } 557 | /// ``` 558 | /// 559 | /// [`Array2D`]: struct.Array2D.html 560 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 561 | pub fn map_row_major(&self, mapper: F) -> Array2D 562 | where 563 | F: FnMut(&T) -> U, 564 | { 565 | let mut mapper = mapper; 566 | Array2D::from_iter_row_major( 567 | self.num_rows, 568 | self.num_columns, 569 | self.enumerate_row_major().map(|(_, element)| mapper(element)), 570 | ) 571 | .expect("Source Array2D should have compatible values for num_rows, num_columns, and enumerate_row_major") 572 | } 573 | 574 | /// Creates a new [`Array2D`] from an existing [`Array2D`]. Each element is traversed in [colum major order]. The 575 | /// element is passed to `mapper`, which produces the new element to use in the new array. 576 | /// 577 | /// # Examples 578 | /// 579 | /// ``` 580 | /// # use array2d::{Array2D, Error}; 581 | /// # fn main() -> Result<(), Error> { 582 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 583 | /// let array = Array2D::from_rows(&rows)?; 584 | /// let new_array = array.map_column_major(|x| x * 10); 585 | /// let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 586 | /// assert_eq!(new_array.as_rows(), expected); 587 | /// # Ok(()) 588 | /// # } 589 | /// ``` 590 | /// 591 | /// [`Array2D`]: struct.Array2D.html 592 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 593 | pub fn map_column_major(&self, mapper: F) -> Array2D 594 | where 595 | F: FnMut(&T) -> U, 596 | U: Clone, 597 | { 598 | let mut mapper = mapper; 599 | Array2D::from_iter_column_major( 600 | self.num_rows, 601 | self.num_columns, 602 | self.enumerate_column_major().map(|(_, element)| mapper(element)), 603 | ) 604 | .expect("Source Array2D should have compatible values for num_rows, num_columns, and enumerate_column_major") 605 | } 606 | 607 | /// Creates a new [`Array2D`] from an existing [`Array2D`]. Each element is traversed in [row major order]. The 608 | /// index and element are passed to `mapper`, which produces the new element to use in the new array. 609 | /// 610 | /// # Examples 611 | /// 612 | /// ``` 613 | /// # use array2d::{Array2D, Error}; 614 | /// # fn main() -> Result<(), Error> { 615 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 616 | /// let array = Array2D::from_rows(&rows)?; 617 | /// let new_array = array.map_with_index_row_major(|_, x| x * 10); 618 | /// let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 619 | /// assert_eq!(new_array.as_rows(), expected); 620 | /// # Ok(()) 621 | /// # } 622 | /// ``` 623 | /// 624 | /// [`Array2D`]: struct.Array2D.html 625 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 626 | pub fn map_with_index_row_major(&self, mapper: F) -> Array2D 627 | where 628 | F: FnMut((usize, usize), &T) -> U, 629 | { 630 | let mut mapper = mapper; 631 | Array2D::from_iter_row_major( 632 | self.num_rows, 633 | self.num_columns, 634 | self.enumerate_row_major().map(|(index, element)| mapper(index, element)), 635 | ) 636 | .expect("Source Array2D should have compatible values for num_rows, num_columns, and enumerate_row_major") 637 | } 638 | 639 | /// Creates a new [`Array2D`] from an existing [`Array2D`]. Each element is traversed in [colum major order]. The 640 | /// index and element are passed to `mapper`, which produces the new element to use in the new array. 641 | /// 642 | /// # Examples 643 | /// 644 | /// ``` 645 | /// # use array2d::{Array2D, Error}; 646 | /// # fn main() -> Result<(), Error> { 647 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 648 | /// let array = Array2D::from_rows(&rows)?; 649 | /// let new_array = array.map_with_index_column_major(|_, x| x * 10); 650 | /// let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 651 | /// assert_eq!(new_array.as_rows(), expected); 652 | /// # Ok(()) 653 | /// # } 654 | /// ``` 655 | /// 656 | /// [`Array2D`]: struct.Array2D.html 657 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 658 | pub fn map_with_index_column_major(&self, mapper: F) -> Array2D 659 | where 660 | F: FnMut((usize, usize), &T) -> U, 661 | U: Clone, 662 | { 663 | let mut mapper = mapper; 664 | Array2D::from_iter_column_major( 665 | self.num_rows, 666 | self.num_columns, 667 | self.enumerate_column_major().map(|(index, element)| mapper(index, element)), 668 | ) 669 | .expect("Source Array2D should have compatible values for num_rows, num_columns, and enumerate_column_major") 670 | } 671 | 672 | /// The number of rows. 673 | pub fn num_rows(&self) -> usize { 674 | self.num_rows 675 | } 676 | 677 | /// The number of columns. 678 | pub fn num_columns(&self) -> usize { 679 | self.num_columns 680 | } 681 | 682 | /// The total number of elements, i.e. the product of `num_rows` and 683 | /// `num_columns`. 684 | pub fn num_elements(&self) -> usize { 685 | self.num_rows * self.num_columns 686 | } 687 | 688 | /// The number of elements in each row, i.e. the number of columns. 689 | pub fn row_len(&self) -> usize { 690 | self.num_columns 691 | } 692 | 693 | /// The number of elements in each column, i.e. the number of rows. 694 | pub fn column_len(&self) -> usize { 695 | self.num_rows 696 | } 697 | 698 | /// Returns a reference to the element at the given `row` and `column` if the 699 | /// index is in bounds (wrapped in [`Some`]). Returns [`None`] if the index 700 | /// is out of bounds. 701 | /// 702 | /// # Examples 703 | /// 704 | /// ``` 705 | /// # use array2d::{Array2D, Error}; 706 | /// let array = Array2D::filled_with( 2, 3,42); 707 | /// assert_eq!(array.get(0, 0), Some(&42)); 708 | /// assert_eq!(array.get(10, 10), None); 709 | /// ``` 710 | /// 711 | /// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some 712 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 713 | pub fn get(&self, row: usize, column: usize) -> Option<&T> { 714 | self.get_index(row, column).map(|index| &self.array[index]) 715 | } 716 | 717 | /// Returns a reference to the element at the given index in row major 718 | /// order. Returns [`None`] if the index is out of bounds. 719 | /// 720 | /// # Examples 721 | /// 722 | /// ``` 723 | /// # use array2d::{Array2D, Error}; 724 | /// # fn main() -> Result<(), Error> { 725 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 726 | /// let array = Array2D::from_rows(&rows)?; 727 | /// assert_eq!(array.get_row_major(2), Some(&3)); 728 | /// assert_eq!(array.get_row_major(4), Some(&5)); 729 | /// assert_eq!(array.get_row_major(10), None); 730 | /// # Ok(()) 731 | /// # } 732 | /// ``` 733 | /// 734 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 735 | pub fn get_row_major(&self, index: usize) -> Option<&T> { 736 | self.array.get(index) 737 | } 738 | 739 | /// Returns a reference to the element at the given index in column major 740 | /// order. Returns [`None`] if the index is out of bounds. 741 | /// 742 | /// # Examples 743 | /// 744 | /// ``` 745 | /// # use array2d::{Array2D, Error}; 746 | /// # fn main() -> Result<(), Error> { 747 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 748 | /// let array = Array2D::from_rows(&rows)?; 749 | /// assert_eq!(array.get_column_major(2), Some(&2)); 750 | /// assert_eq!(array.get_column_major(4), Some(&3)); 751 | /// assert_eq!(array.get_column_major(10), None); 752 | /// # Ok(()) 753 | /// # } 754 | /// ``` 755 | /// 756 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 757 | pub fn get_column_major(&self, index: usize) -> Option<&T> { 758 | let column = dbg!(dbg!(index) / self.num_rows); 759 | let row = dbg!(index % self.num_rows); 760 | self.get(row, column) 761 | } 762 | 763 | /// Returns a mutable reference to the element at the given `row` and 764 | /// `column` if the index is in bounds (wrapped in [`Some`]). Returns 765 | /// [`None`] if the index is out of bounds. 766 | /// 767 | /// # Examples 768 | /// 769 | /// ``` 770 | /// # use array2d::{Array2D, Error}; 771 | /// let mut array = Array2D::filled_with( 2, 3,42); 772 | /// 773 | /// assert_eq!(array.get_mut(0, 0), Some(&mut 42)); 774 | /// assert_eq!(array.get_mut(10, 10), None); 775 | /// 776 | /// array.get_mut(0, 0).map(|x| *x = 100); 777 | /// assert_eq!(array.get(0, 0), Some(&100)); 778 | /// 779 | /// array.get_mut(10, 10).map(|x| *x = 200); 780 | /// assert_eq!(array.get(10, 10), None); 781 | /// ``` 782 | /// 783 | /// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some 784 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 785 | pub fn get_mut(&mut self, row: usize, column: usize) -> Option<&mut T> { 786 | self.get_index(row, column) 787 | .map(move |index| &mut self.array[index]) 788 | } 789 | 790 | /// Returns a mutable reference to the element at the given index in row 791 | /// major order. Returns [`None`] if the index is out of bounds. 792 | /// 793 | /// # Examples 794 | /// 795 | /// ``` 796 | /// # use array2d::{Array2D, Error}; 797 | /// # fn main() -> Result<(), Error> { 798 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 799 | /// let mut array = Array2D::from_rows(&rows)?; 800 | /// 801 | /// assert_eq!(array.get_mut_row_major(1), Some(&mut 2)); 802 | /// assert_eq!(array.get_mut_row_major(10), None); 803 | /// 804 | /// array.get_mut_row_major(3).map(|x| *x = 100); 805 | /// assert_eq!(array.get(1, 0), Some(&100)); 806 | /// 807 | /// array.get_mut_row_major(10).map(|x| *x = 200); 808 | /// assert_eq!(array.get(10, 10), None); 809 | /// # Ok(()) 810 | /// # } 811 | /// ``` 812 | /// 813 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 814 | pub fn get_mut_row_major(&mut self, index: usize) -> Option<&mut T> { 815 | self.array.get_mut(index) 816 | } 817 | 818 | /// Returns a mutable reference to the element at the given index in row 819 | /// major order. Returns [`None`] if the index is out of bounds. 820 | /// 821 | /// # Examples 822 | /// 823 | /// ``` 824 | /// # use array2d::{Array2D, Error}; 825 | /// # fn main() -> Result<(), Error> { 826 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 827 | /// let mut array = Array2D::from_rows(&rows)?; 828 | /// 829 | /// assert_eq!(array.get_mut_column_major(1), Some(&mut 4)); 830 | /// assert_eq!(array.get_mut_column_major(10), None); 831 | /// 832 | /// array.get_mut_column_major(4).map(|x| *x = 100); 833 | /// assert_eq!(array.get(0, 2), Some(&100)); 834 | /// 835 | /// array.get_mut_column_major(10).map(|x| *x = 200); 836 | /// assert_eq!(array.get(10, 10), None); 837 | /// # Ok(()) 838 | /// # } 839 | /// ``` 840 | /// 841 | /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None 842 | pub fn get_mut_column_major(&mut self, index: usize) -> Option<&mut T> { 843 | let column = index / self.num_rows; 844 | let row = index % self.num_rows; 845 | self.get_mut(row, column) 846 | } 847 | 848 | /// Changes the element at given `row` and `column` to `element`. Returns 849 | /// [`Ok(())`] if the indices were in bounds and returns an [`Err`] 850 | /// otherwise. 851 | /// 852 | /// # Examples 853 | /// 854 | /// ``` 855 | /// # use array2d::{Array2D, Error}; 856 | /// let mut array = Array2D::filled_with( 2, 3,42); 857 | /// 858 | /// let result = array.set(0, 0, 100); 859 | /// assert_eq!(result, Ok(())); 860 | /// assert_eq!(array.get(0, 0), Some(&100)); 861 | /// 862 | /// let result = array.set(10, 20, 200); 863 | /// assert_eq!(result, Err(Error::IndicesOutOfBounds(10, 20))); 864 | /// ``` 865 | /// 866 | /// [`Ok(())`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok 867 | /// [array2d::Error]: enum.Error.html 868 | /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err 869 | /// [`array2d::Error`]: enum.Error.html 870 | pub fn set(&mut self, row: usize, column: usize, element: T) -> Result<(), Error> { 871 | self.get_mut(row, column) 872 | .map(|location| { 873 | *location = element; 874 | }) 875 | .ok_or(Error::IndicesOutOfBounds(row, column)) 876 | } 877 | 878 | /// Changes the element at the given `index` to `element`, in row major 879 | /// order. Returns [`Ok(())`] if the index is in bounds and returns an 880 | /// [`Err`] otherwise. 881 | /// 882 | /// # Examples 883 | /// 884 | /// ``` 885 | /// # use array2d::{Array2D, Error}; 886 | /// let mut array = Array2D::filled_with( 2, 3,42); 887 | /// 888 | /// let result = array.set_row_major(4, 100); 889 | /// assert_eq!(result, Ok(())); 890 | /// assert_eq!(array.get(1, 1), Some(&100)); 891 | /// 892 | /// let result = array.set_row_major(10, 200); 893 | /// assert_eq!(result, Err(Error::IndexOutOfBounds(10))); 894 | /// ``` 895 | /// 896 | /// [`Ok(())`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok 897 | /// [array2d::Error]: enum.Error.html 898 | /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err 899 | /// [`array2d::Error`]: enum.Error.html 900 | pub fn set_row_major(&mut self, index: usize, element: T) -> Result<(), Error> { 901 | self.get_mut_row_major(index) 902 | .map(|location| { 903 | *location = element; 904 | }) 905 | .ok_or(Error::IndexOutOfBounds(index)) 906 | } 907 | 908 | /// Changes the element at the given `index` to `element`, in column major 909 | /// order. Returns [`Ok(())`] if the index is in bounds and returns an 910 | /// [`Err`] otherwise. 911 | /// 912 | /// # Examples 913 | /// 914 | /// ``` 915 | /// # use array2d::{Array2D, Error}; 916 | /// let mut array = Array2D::filled_with( 2, 3,42); 917 | /// 918 | /// let result = array.set_column_major(4, 100); 919 | /// assert_eq!(result, Ok(())); 920 | /// assert_eq!(array.get(0, 2), Some(&100)); 921 | /// 922 | /// let result = array.set_column_major(10, 200); 923 | /// assert_eq!(result, Err(Error::IndexOutOfBounds(10))); 924 | /// ``` 925 | /// 926 | /// [`Ok(())`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok 927 | /// [array2d::Error]: enum.Error.html 928 | /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err 929 | /// [`array2d::Error`]: enum.Error.html 930 | pub fn set_column_major(&mut self, index: usize, element: T) -> Result<(), Error> { 931 | self.get_mut_column_major(index) 932 | .map(|location| { 933 | *location = element; 934 | }) 935 | .ok_or(Error::IndexOutOfBounds(index)) 936 | } 937 | 938 | /// Returns an [`Iterator`] over references to all elements in [row major 939 | /// order]. 940 | /// 941 | /// # Examples 942 | /// 943 | /// ``` 944 | /// # use array2d::{Array2D, Error}; 945 | /// # fn main() -> Result<(), Error> { 946 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 947 | /// let elements = vec![1, 2, 3, 4, 5, 6]; 948 | /// let array = Array2D::from_rows(&rows)?; 949 | /// let row_major = array.elements_row_major_iter(); 950 | /// assert_eq!(row_major.cloned().collect::>(), elements); 951 | /// # Ok(()) 952 | /// # } 953 | /// ``` 954 | /// 955 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 956 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 957 | pub fn elements_row_major_iter(&self) -> impl DoubleEndedIterator + Clone { 958 | self.array.iter() 959 | } 960 | 961 | /// Returns an [`Iterator`] over references to all elements in [column major 962 | /// order]. 963 | /// 964 | /// # Examples 965 | /// 966 | /// ``` 967 | /// # use array2d::{Array2D, Error}; 968 | /// # fn main() -> Result<(), Error> { 969 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 970 | /// let elements = vec![1, 4, 2, 5, 3, 6]; 971 | /// let array = Array2D::from_rows(&rows)?; 972 | /// let column_major = array.elements_column_major_iter(); 973 | /// assert_eq!(column_major.cloned().collect::>(), elements); 974 | /// # Ok(()) 975 | /// # } 976 | /// ``` 977 | /// 978 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 979 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 980 | pub fn elements_column_major_iter(&self) -> impl DoubleEndedIterator + Clone { 981 | self.indices_column_major().map(move |i| &self[i]) 982 | } 983 | 984 | /// Returns an [`Iterator`] over references to all elements in the given 985 | /// row. Returns an error if the index is out of bounds. 986 | /// 987 | /// # Examples 988 | /// 989 | /// ``` 990 | /// # use array2d::{Array2D, Error}; 991 | /// # fn main() -> Result<(), Error> { 992 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 993 | /// let array = Array2D::from_rows(&rows)?; 994 | /// let mut row_iter = array.row_iter(1)?; 995 | /// assert_eq!(row_iter.next(), Some(&4)); 996 | /// assert_eq!(row_iter.next(), Some(&5)); 997 | /// assert_eq!(row_iter.next(), Some(&6)); 998 | /// assert_eq!(row_iter.next(), None); 999 | /// # Ok(()) 1000 | /// # } 1001 | /// ``` 1002 | /// 1003 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 1004 | pub fn row_iter( 1005 | &self, 1006 | row_index: usize, 1007 | ) -> Result + Clone, Error> { 1008 | let start = self 1009 | .get_index(row_index, 0) 1010 | .ok_or(Error::IndicesOutOfBounds(row_index, 0))?; 1011 | let end = start + self.row_len(); 1012 | Ok(self.array[start..end].iter()) 1013 | } 1014 | 1015 | /// Returns an [`Iterator`] over references to all elements in the given 1016 | /// column. Returns an error if the index is out of bounds. 1017 | /// 1018 | /// # Examples 1019 | /// 1020 | /// ``` 1021 | /// # use array2d::{Array2D, Error}; 1022 | /// # fn main() -> Result<(), Error> { 1023 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1024 | /// let array = Array2D::from_rows(&rows)?; 1025 | /// let mut column_iter = array.column_iter(1)?; 1026 | /// assert_eq!(column_iter.next(), Some(&2)); 1027 | /// assert_eq!(column_iter.next(), Some(&5)); 1028 | /// assert_eq!(column_iter.next(), None); 1029 | /// # Ok(()) 1030 | /// # } 1031 | /// ``` 1032 | /// 1033 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 1034 | pub fn column_iter( 1035 | &self, 1036 | column_index: usize, 1037 | ) -> Result + Clone, Error> { 1038 | if column_index >= self.num_columns { 1039 | return Err(Error::IndicesOutOfBounds(0, column_index)); 1040 | } 1041 | Ok((0..self.column_len()).map(move |row_index| &self[(row_index, column_index)])) 1042 | } 1043 | 1044 | /// Returns an [`Iterator`] over all rows. Each [`Item`] is itself another 1045 | /// [`Iterator`] over references to the elements in that row. 1046 | /// 1047 | /// # Examples 1048 | /// 1049 | /// ``` 1050 | /// # use array2d::{Array2D, Error}; 1051 | /// # fn main() -> Result<(), Error> { 1052 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1053 | /// let array = Array2D::from_rows(&rows)?; 1054 | /// for row_iter in array.rows_iter() { 1055 | /// for element in row_iter { 1056 | /// print!("{} ", element); 1057 | /// } 1058 | /// println!(); 1059 | /// } 1060 | /// 1061 | /// let mut rows_iter = array.rows_iter(); 1062 | /// 1063 | /// let mut first_row_iter = rows_iter.next().unwrap(); 1064 | /// assert_eq!(first_row_iter.next(), Some(&1)); 1065 | /// assert_eq!(first_row_iter.next(), Some(&2)); 1066 | /// assert_eq!(first_row_iter.next(), Some(&3)); 1067 | /// assert_eq!(first_row_iter.next(), None); 1068 | /// 1069 | /// let mut second_row_iter = rows_iter.next().unwrap(); 1070 | /// assert_eq!(second_row_iter.next(), Some(&4)); 1071 | /// assert_eq!(second_row_iter.next(), Some(&5)); 1072 | /// assert_eq!(second_row_iter.next(), Some(&6)); 1073 | /// assert_eq!(second_row_iter.next(), None); 1074 | /// 1075 | /// assert!(rows_iter.next().is_none()); 1076 | /// # Ok(()) 1077 | /// # } 1078 | /// ``` 1079 | /// 1080 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 1081 | /// [`Item`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#associatedtype.Item 1082 | pub fn rows_iter( 1083 | &self, 1084 | ) -> impl DoubleEndedIterator + Clone> + Clone { 1085 | (0..self.num_rows()).map(move |row_index| { 1086 | self.row_iter(row_index) 1087 | .expect("rows_iter should never fail") 1088 | }) 1089 | } 1090 | 1091 | /// Returns an [`Iterator`] over all columns. Each [`Item`] is itself 1092 | /// another [`Iterator`] over references to the elements in that column. 1093 | /// 1094 | /// # Examples 1095 | /// 1096 | /// ``` 1097 | /// # use array2d::{Array2D, Error}; 1098 | /// # fn main() -> Result<(), Error> { 1099 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1100 | /// let array = Array2D::from_rows(&rows)?; 1101 | /// for column_iter in array.columns_iter() { 1102 | /// for element in column_iter { 1103 | /// print!("{} ", element); 1104 | /// } 1105 | /// println!(); 1106 | /// } 1107 | /// 1108 | /// let mut columns_iter = array.columns_iter(); 1109 | /// 1110 | /// let mut first_column_iter = columns_iter.next().unwrap(); 1111 | /// assert_eq!(first_column_iter.next(), Some(&1)); 1112 | /// assert_eq!(first_column_iter.next(), Some(&4)); 1113 | /// assert_eq!(first_column_iter.next(), None); 1114 | /// 1115 | /// let mut second_column_iter = columns_iter.next().unwrap(); 1116 | /// assert_eq!(second_column_iter.next(), Some(&2)); 1117 | /// assert_eq!(second_column_iter.next(), Some(&5)); 1118 | /// assert_eq!(second_column_iter.next(), None); 1119 | /// 1120 | /// let mut third_column_iter = columns_iter.next().unwrap(); 1121 | /// assert_eq!(third_column_iter.next(), Some(&3)); 1122 | /// assert_eq!(third_column_iter.next(), Some(&6)); 1123 | /// assert_eq!(third_column_iter.next(), None); 1124 | /// 1125 | /// assert!(columns_iter.next().is_none()); 1126 | /// # Ok(()) 1127 | /// # } 1128 | /// ``` 1129 | /// 1130 | /// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html 1131 | /// [`Item`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#associatedtype.Item 1132 | pub fn columns_iter( 1133 | &self, 1134 | ) -> impl DoubleEndedIterator + Clone> + Clone { 1135 | (0..self.num_columns).map(move |column_index| { 1136 | self.column_iter(column_index) 1137 | .expect("columns_iter should never fail") 1138 | }) 1139 | } 1140 | 1141 | /// Collects the [`Array2D`] into a [`Vec`] of rows, each of which contains 1142 | /// a [`Vec`] of elements. 1143 | /// 1144 | /// # Examples 1145 | /// 1146 | /// ``` 1147 | /// # use array2d::{Array2D, Error}; 1148 | /// # fn main() -> Result<(), Error> { 1149 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1150 | /// let array = Array2D::from_rows(&rows)?; 1151 | /// assert_eq!(array.as_rows(), rows); 1152 | /// # Ok(()) 1153 | /// # } 1154 | /// ``` 1155 | /// 1156 | /// [`Array2D`]: struct.Array2D.html 1157 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 1158 | pub fn as_rows(&self) -> Vec> 1159 | where 1160 | T: Clone, 1161 | { 1162 | self.rows_iter() 1163 | .map(|row_iter| row_iter.cloned().collect()) 1164 | .collect() 1165 | } 1166 | 1167 | /// Collects the [`Array2D`] into a [`Vec`] of columns, each of which 1168 | /// contains a [`Vec`] of elements. 1169 | /// 1170 | /// # Examples 1171 | /// 1172 | /// ``` 1173 | /// # use array2d::{Array2D, Error}; 1174 | /// # fn main() -> Result<(), Error> { 1175 | /// let columns = vec![vec![1, 4], vec![2, 5], vec![3, 6]]; 1176 | /// let array = Array2D::from_columns(&columns)?; 1177 | /// assert_eq!(array.as_columns(), columns); 1178 | /// # Ok(()) 1179 | /// # } 1180 | /// ``` 1181 | /// 1182 | /// [`Array2D`]: struct.Array2D.html 1183 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 1184 | pub fn as_columns(&self) -> Vec> 1185 | where 1186 | T: Clone, 1187 | { 1188 | self.columns_iter() 1189 | .map(|column_iter| column_iter.cloned().collect()) 1190 | .collect() 1191 | } 1192 | 1193 | /// Collects the [`Array2D`] into a [`Vec`] of elements in [row major 1194 | /// order]. 1195 | /// 1196 | /// # Examples 1197 | /// 1198 | /// ``` 1199 | /// # use array2d::{Array2D, Error}; 1200 | /// # fn main() -> Result<(), Error> { 1201 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1202 | /// let array = Array2D::from_rows(&rows)?; 1203 | /// assert_eq!(array.as_row_major(), vec![1, 2, 3, 4, 5, 6]); 1204 | /// # Ok(()) 1205 | /// # } 1206 | /// ``` 1207 | /// 1208 | /// [`Array2D`]: struct.Array2D.html 1209 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 1210 | /// [row major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 1211 | pub fn as_row_major(&self) -> Vec 1212 | where 1213 | T: Clone, 1214 | { 1215 | self.elements_row_major_iter().cloned().collect() 1216 | } 1217 | 1218 | /// Collects the [`Array2D`] into a [`Vec`] of elements in [column major 1219 | /// order]. 1220 | /// 1221 | /// # Examples 1222 | /// 1223 | /// ``` 1224 | /// # use array2d::{Array2D, Error}; 1225 | /// # fn main() -> Result<(), Error> { 1226 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1227 | /// let array = Array2D::from_rows(&rows)?; 1228 | /// assert_eq!(array.as_column_major(), vec![1, 4, 2, 5, 3, 6]); 1229 | /// # Ok(()) 1230 | /// # } 1231 | /// ``` 1232 | /// 1233 | /// [`Array2D`]: struct.Array2D.html 1234 | /// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html 1235 | /// [column major order]: https://en.wikipedia.org/wiki/Row-_and_column-major_order 1236 | pub fn as_column_major(&self) -> Vec 1237 | where 1238 | T: Clone, 1239 | { 1240 | self.elements_column_major_iter().cloned().collect() 1241 | } 1242 | 1243 | /// Returns the indices of the array in row major order. Each index is a tuple of [`usize`]. 1244 | /// 1245 | /// # Examples 1246 | /// 1247 | /// ``` 1248 | /// # use array2d::{Array2D, Error}; 1249 | /// # fn main() -> Result<(), Error> { 1250 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1251 | /// let array = Array2D::from_rows(&rows)?; 1252 | /// let indices_row_major = array.indices_row_major().collect::>(); 1253 | /// assert_eq!( 1254 | /// indices_row_major, 1255 | /// vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)] 1256 | /// ); 1257 | /// # Ok(()) 1258 | /// # } 1259 | /// ``` 1260 | /// 1261 | /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html 1262 | pub fn indices_row_major(&self) -> impl DoubleEndedIterator + Clone { 1263 | indices_row_major(self.num_rows, self.num_columns) 1264 | } 1265 | 1266 | /// Returns the indices of the array in column major order. Each index is a tuple of [`usize`]. 1267 | /// 1268 | /// # Examples 1269 | /// 1270 | /// ``` 1271 | /// # use array2d::{Array2D, Error}; 1272 | /// # fn main() -> Result<(), Error> { 1273 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1274 | /// let array = Array2D::from_rows(&rows)?; 1275 | /// let indices_column_major = array.indices_column_major().collect::>(); 1276 | /// assert_eq!( 1277 | /// indices_column_major, 1278 | /// vec![(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2)] 1279 | /// ); 1280 | /// # Ok(()) 1281 | /// # } 1282 | /// ``` 1283 | /// 1284 | /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html 1285 | pub fn indices_column_major(&self) -> impl DoubleEndedIterator + Clone { 1286 | indices_column_major(self.num_rows, self.num_columns) 1287 | } 1288 | 1289 | /// Iterate through the array in row major order along with the corresponding indices. Each 1290 | /// index is a tuple of [`usize`]. 1291 | /// 1292 | /// # Examples 1293 | /// 1294 | /// ``` 1295 | /// # use array2d::{Array2D, Error}; 1296 | /// # fn main() -> Result<(), Error> { 1297 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1298 | /// let array = Array2D::from_rows(&rows)?; 1299 | /// let enumerate_row_major = array.enumerate_row_major().collect::>(); 1300 | /// assert_eq!( 1301 | /// enumerate_row_major, 1302 | /// vec![ 1303 | /// ((0, 0), &1), 1304 | /// ((0, 1), &2), 1305 | /// ((0, 2), &3), 1306 | /// ((1, 0), &4), 1307 | /// ((1, 1), &5), 1308 | /// ((1, 2), &6) 1309 | /// ] 1310 | /// ); 1311 | /// # Ok(()) 1312 | /// # } 1313 | /// ``` 1314 | /// 1315 | /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html 1316 | pub fn enumerate_row_major( 1317 | &self, 1318 | ) -> impl DoubleEndedIterator + Clone { 1319 | self.indices_row_major().map(move |i| (i, &self[i])) 1320 | } 1321 | 1322 | /// Iterate through the array in column major order along with the corresponding indices. Each 1323 | /// index is a tuple of [`usize`]. 1324 | /// 1325 | /// # Examples 1326 | /// 1327 | /// ``` 1328 | /// # use array2d::{Array2D, Error}; 1329 | /// # fn main() -> Result<(), Error> { 1330 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1331 | /// let array = Array2D::from_rows(&rows)?; 1332 | /// let enumerate_column_major = array.enumerate_column_major().collect::>(); 1333 | /// assert_eq!( 1334 | /// enumerate_column_major, 1335 | /// vec![ 1336 | /// ((0, 0), &1), 1337 | /// ((1, 0), &4), 1338 | /// ((0, 1), &2), 1339 | /// ((1, 1), &5), 1340 | /// ((0, 2), &3), 1341 | /// ((1, 2), &6) 1342 | /// ] 1343 | /// ); 1344 | /// # Ok(()) 1345 | /// # } 1346 | /// ``` 1347 | /// 1348 | /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html 1349 | pub fn enumerate_column_major( 1350 | &self, 1351 | ) -> impl DoubleEndedIterator + Clone { 1352 | self.indices_column_major().map(move |i| (i, &self[i])) 1353 | } 1354 | 1355 | /// Swaps two elements in the [`Array2D`]. Returns an empty [`Ok`] value if both indices are in bounds and the 1356 | /// values were successfully swapped (if the indices were different). If either index was out of bounds, an 1357 | /// [`Err`] is returned with the out-of-bounds index. 1358 | /// 1359 | /// If `row1` equals to `row2` and `column1` equals to `column2`, it's guaranteed that elements won't change value. 1360 | /// 1361 | /// # Examples 1362 | /// 1363 | /// ``` 1364 | /// # use array2d::{Array2D, Error}; 1365 | /// # fn main() -> Result<(), Error> { 1366 | /// let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 1367 | /// let mut array = Array2D::from_rows(&rows)?; 1368 | /// assert!(array.swap((0, 1), (1, 0)).is_ok()); 1369 | /// let expected_rows = vec![vec![1, 4, 3], vec![2, 5, 6]]; 1370 | /// assert_eq!(array.as_rows(), expected_rows); 1371 | /// # Ok(()) 1372 | /// # } 1373 | /// ``` 1374 | pub fn swap( 1375 | &mut self, 1376 | (row1, column1): (usize, usize), 1377 | (row2, column2): (usize, usize), 1378 | ) -> Result<(), Error> { 1379 | let index1 = self 1380 | .get_index(row1, column1) 1381 | .ok_or(Error::IndicesOutOfBounds(row1, column1))?; 1382 | let index2 = self 1383 | .get_index(row2, column2) 1384 | .ok_or(Error::IndicesOutOfBounds(row2, column2))?; 1385 | self.array.swap(index1, index2); 1386 | Ok(()) 1387 | } 1388 | 1389 | fn get_index(&self, row: usize, column: usize) -> Option { 1390 | if row < self.num_rows && column < self.num_columns { 1391 | Some(row * self.row_len() + column) 1392 | } else { 1393 | None 1394 | } 1395 | } 1396 | } 1397 | 1398 | impl Index<(usize, usize)> for Array2D { 1399 | type Output = T; 1400 | 1401 | /// Returns the element at the given indices, given as `(row, column)`. 1402 | /// 1403 | /// # Examples 1404 | /// 1405 | /// ``` 1406 | /// # use array2d::{Array2D, Error}; 1407 | /// let array = Array2D::filled_with( 2, 3,42); 1408 | /// assert_eq!(array[(0, 0)], 42); 1409 | /// ``` 1410 | /// 1411 | /// # Panics 1412 | /// 1413 | /// Panics if the indices are out of bounds. 1414 | /// 1415 | /// ```rust,should_panic 1416 | /// # use array2d::Array2D; 1417 | /// let array = Array2D::filled_with( 2, 3,42); 1418 | /// let element = array[(10, 10)]; 1419 | /// ``` 1420 | fn index(&self, (row, column): (usize, usize)) -> &Self::Output { 1421 | self.get(row, column) 1422 | .unwrap_or_else(|| panic!("Index indices {}, {} out of bounds", row, column)) 1423 | } 1424 | } 1425 | 1426 | impl IndexMut<(usize, usize)> for Array2D { 1427 | /// Returns a mutable version of the element at the given indices, given as 1428 | /// `(row, column)`. 1429 | /// 1430 | /// # Examples 1431 | /// 1432 | /// ``` 1433 | /// # use array2d::{Array2D, Error}; 1434 | /// let mut array = Array2D::filled_with( 2, 3,42); 1435 | /// array[(0, 0)] = 100; 1436 | /// assert_eq!(array[(0, 0)], 100); 1437 | /// ``` 1438 | /// 1439 | /// # Panics 1440 | /// 1441 | /// Panics if the indices are out of bounds. 1442 | /// 1443 | /// ```rust,should_panic 1444 | /// # use array2d::Array2D; 1445 | /// let mut array = Array2D::filled_with( 2, 3,42); 1446 | /// array[(10, 10)] = 7; 1447 | /// ``` 1448 | fn index_mut(&mut self, (row, column): (usize, usize)) -> &mut Self::Output { 1449 | self.get_mut(row, column) 1450 | .unwrap_or_else(|| panic!("Index mut indices {}, {} out of bounds", row, column)) 1451 | } 1452 | } 1453 | 1454 | fn flatten(nested: &[Vec]) -> Vec { 1455 | nested.iter().flat_map(|row| row.clone()).collect() 1456 | } 1457 | 1458 | fn indices_row_major( 1459 | num_rows: usize, 1460 | num_columns: usize, 1461 | ) -> impl DoubleEndedIterator + Clone { 1462 | (0..num_rows).flat_map(move |row| (0..num_columns).map(move |column| (row, column))) 1463 | } 1464 | 1465 | fn indices_column_major( 1466 | num_rows: usize, 1467 | num_columns: usize, 1468 | ) -> impl DoubleEndedIterator + Clone { 1469 | (0..num_columns).flat_map(move |column| (0..num_rows).map(move |row| (row, column))) 1470 | } 1471 | -------------------------------------------------------------------------------- /tests/array2d.rs: -------------------------------------------------------------------------------- 1 | use array2d::{Array2D, Error}; 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Normal Operation //////////////////////////////////////////////////////////// 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | #[test] 8 | fn test_from_rows() -> Result<(), Error> { 9 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 10 | let array = Array2D::from_rows(&rows)?; 11 | assert_eq!(array.as_rows(), rows); 12 | Ok(()) 13 | } 14 | 15 | #[test] 16 | fn test_from_columns() -> Result<(), Error> { 17 | let columns = vec![vec![1, 4], vec![2, 5], vec![3, 6]]; 18 | let array = Array2D::from_columns(&columns)?; 19 | assert_eq!(array.as_columns(), columns); 20 | Ok(()) 21 | } 22 | 23 | #[test] 24 | fn test_from_row_major() -> Result<(), Error> { 25 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 26 | let row_major = vec![1, 2, 3, 4, 5, 6]; 27 | let num_rows = 2; 28 | let num_columns = 3; 29 | let array = Array2D::from_row_major(num_rows, num_columns, &row_major)?; 30 | for (row_index, row) in rows.iter().enumerate() { 31 | for (column_index, element) in row.iter().enumerate() { 32 | assert_eq!(array.get(row_index, column_index), Some(element)); 33 | } 34 | } 35 | Ok(()) 36 | } 37 | 38 | #[test] 39 | fn test_from_column_major() -> Result<(), Error> { 40 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 41 | let column_major = vec![1, 4, 2, 5, 3, 6]; 42 | let num_rows = 2; 43 | let num_columns = 3; 44 | let array = Array2D::from_column_major(num_rows, num_columns, &column_major)?; 45 | for (row_index, row) in rows.iter().enumerate() { 46 | for (column_index, element) in row.iter().enumerate() { 47 | assert_eq!(array.get(row_index, column_index), Some(element)); 48 | } 49 | } 50 | Ok(()) 51 | } 52 | 53 | #[test] 54 | fn test_filled_with() -> Result<(), Error> { 55 | let element = 7; 56 | let array = Array2D::filled_with(4, 5, element); 57 | assert_eq!(array.num_rows(), 4); 58 | assert_eq!(array.num_columns(), 5); 59 | assert_eq!(array.num_elements(), 20); 60 | for element in array.elements_row_major_iter() { 61 | assert_eq!(element, &7); 62 | } 63 | for element in array.elements_column_major_iter() { 64 | assert_eq!(element, &7); 65 | } 66 | Ok(()) 67 | } 68 | 69 | #[test] 70 | fn test_filled_by_row_major() -> Result<(), Error> { 71 | let mut counter = 1; 72 | let increment = || { 73 | let tmp = counter; 74 | counter += 1; 75 | tmp 76 | }; 77 | let array = Array2D::filled_by_row_major(2, 3, increment); 78 | assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 79 | Ok(()) 80 | } 81 | 82 | #[test] 83 | fn test_filled_by_column_major() -> Result<(), Error> { 84 | let mut counter = 1; 85 | let increment = || { 86 | let tmp = counter; 87 | counter += 1; 88 | tmp 89 | }; 90 | let array = Array2D::filled_by_column_major(2, 3, increment); 91 | assert_eq!(array.as_columns(), vec![vec![1, 2], vec![3, 4], vec![5, 6]]); 92 | Ok(()) 93 | } 94 | 95 | #[test] 96 | fn test_from_iter_row_major() -> Result<(), Error> { 97 | let array = Array2D::from_iter_row_major(2, 3, 1..)?; 98 | assert_eq!(array.as_rows(), vec![vec![1, 2, 3], vec![4, 5, 6]]); 99 | Ok(()) 100 | } 101 | 102 | #[test] 103 | fn test_from_iter_column_major() -> Result<(), Error> { 104 | let array = Array2D::from_iter_column_major(2, 3, 1..)?; 105 | assert_eq!(array.as_columns(), vec![vec![1, 2], vec![3, 4], vec![5, 6]]); 106 | Ok(()) 107 | } 108 | 109 | #[test] 110 | fn test_map_row_major() -> Result<(), Error> { 111 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 112 | let array = Array2D::from_rows(&rows)?; 113 | 114 | let new_array = array.map_row_major(|x| x * 10); 115 | let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 116 | assert_eq!(expected, new_array.as_rows()); 117 | 118 | let mut mutable_counter = 100; 119 | let new_array = array.map_row_major(|_| { 120 | mutable_counter += 1; 121 | mutable_counter 122 | }); 123 | let expected = vec![vec![101, 102, 103], vec![104, 105, 106]]; 124 | assert_eq!(expected, new_array.as_rows()); 125 | 126 | Ok(()) 127 | } 128 | 129 | #[test] 130 | fn test_map_column_major() -> Result<(), Error> { 131 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 132 | let array = Array2D::from_rows(&rows)?; 133 | 134 | let new_array = array.map_column_major(|x| x * 10); 135 | let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 136 | assert_eq!(expected, new_array.as_rows()); 137 | 138 | let mut mutable_counter = 100; 139 | let new_array = array.map_column_major(|_| { 140 | mutable_counter += 1; 141 | mutable_counter 142 | }); 143 | let expected = vec![vec![101, 103, 105], vec![102, 104, 106]]; 144 | assert_eq!(expected, new_array.as_rows()); 145 | 146 | Ok(()) 147 | } 148 | 149 | #[test] 150 | fn test_map_with_index_row_major() -> Result<(), Error> { 151 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 152 | let array = Array2D::from_rows(&rows)?; 153 | 154 | let new_array = array.map_with_index_row_major(|_, x| x * 10); 155 | let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 156 | assert_eq!(expected, new_array.as_rows()); 157 | 158 | let new_array = array.map_with_index_row_major(|i, _| i); 159 | let expected = vec![vec![(0, 0), (0, 1), (0, 2)], vec![(1, 0), (1, 1), (1, 2)]]; 160 | assert_eq!(expected, new_array.as_rows()); 161 | 162 | let new_array = array.map_with_index_row_major(|i, e| format!("{} {:?}", e, i)); 163 | let expected = vec![ 164 | vec!["1 (0, 0)", "2 (0, 1)", "3 (0, 2)"], 165 | vec!["4 (1, 0)", "5 (1, 1)", "6 (1, 2)"], 166 | ]; 167 | assert_eq!(expected, new_array.as_rows()); 168 | 169 | let mut mutable_counter = 100; 170 | let new_array = array.map_with_index_row_major(|_, _| { 171 | mutable_counter += 1; 172 | mutable_counter 173 | }); 174 | let expected = vec![vec![101, 102, 103], vec![104, 105, 106]]; 175 | assert_eq!(expected, new_array.as_rows()); 176 | 177 | Ok(()) 178 | } 179 | 180 | #[test] 181 | fn test_map_with_index_column_major() -> Result<(), Error> { 182 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 183 | let array = Array2D::from_rows(&rows)?; 184 | 185 | let new_array = array.map_with_index_column_major(|_, x| x * 10); 186 | let expected = vec![vec![10, 20, 30], vec![40, 50, 60]]; 187 | assert_eq!(expected, new_array.as_rows()); 188 | 189 | let new_array = array.map_with_index_column_major(|i, _| i); 190 | let expected = vec![vec![(0, 0), (0, 1), (0, 2)], vec![(1, 0), (1, 1), (1, 2)]]; 191 | assert_eq!(expected, new_array.as_rows()); 192 | 193 | let new_array = array.map_with_index_column_major(|i, e| format!("{} {:?}", e, i)); 194 | let expected = vec![ 195 | vec!["1 (0, 0)", "2 (0, 1)", "3 (0, 2)"], 196 | vec!["4 (1, 0)", "5 (1, 1)", "6 (1, 2)"], 197 | ]; 198 | assert_eq!(expected, new_array.as_rows()); 199 | 200 | let mut mutable_counter = 100; 201 | let new_array = array.map_with_index_column_major(|_, _| { 202 | mutable_counter += 1; 203 | mutable_counter 204 | }); 205 | let expected = vec![vec![101, 103, 105], vec![102, 104, 106]]; 206 | assert_eq!(expected, new_array.as_rows()); 207 | 208 | Ok(()) 209 | } 210 | 211 | #[test] 212 | fn test_dimensions() -> Result<(), Error> { 213 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 214 | let array = Array2D::from_rows(&rows)?; 215 | assert_eq!(array.num_rows(), 2); 216 | assert_eq!(array.num_columns(), 3); 217 | assert_eq!(array.row_len(), 3); 218 | assert_eq!(array.column_len(), 2); 219 | Ok(()) 220 | } 221 | 222 | #[test] 223 | fn test_get() -> Result<(), Error> { 224 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 225 | let array = Array2D::from_rows(&rows)?; 226 | for row in 0..rows.len() { 227 | for column in 0..rows[0].len() { 228 | assert_eq!(array.get(row, column), Some(&rows[row][column])); 229 | } 230 | } 231 | Ok(()) 232 | } 233 | 234 | #[test] 235 | fn test_get_row_major() -> Result<(), Error> { 236 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 237 | let array = Array2D::from_rows(&rows)?; 238 | assert_eq!(array.get_row_major(0), Some(&1)); 239 | assert_eq!(array.get_row_major(1), Some(&2)); 240 | assert_eq!(array.get_row_major(2), Some(&3)); 241 | assert_eq!(array.get_row_major(3), Some(&4)); 242 | assert_eq!(array.get_row_major(4), Some(&5)); 243 | assert_eq!(array.get_row_major(5), Some(&6)); 244 | assert_eq!(array.get_row_major(6), None); 245 | Ok(()) 246 | } 247 | 248 | #[test] 249 | fn test_get_column_major() -> Result<(), Error> { 250 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 251 | let array = Array2D::from_rows(&rows)?; 252 | assert_eq!(array.get_column_major(0), Some(&1)); 253 | assert_eq!(array.get_column_major(1), Some(&4)); 254 | assert_eq!(array.get_column_major(2), Some(&2)); 255 | assert_eq!(array.get_column_major(3), Some(&5)); 256 | assert_eq!(array.get_column_major(4), Some(&3)); 257 | assert_eq!(array.get_column_major(5), Some(&6)); 258 | assert_eq!(array.get_column_major(6), None); 259 | Ok(()) 260 | } 261 | 262 | #[test] 263 | fn test_get_mut() -> Result<(), Error> { 264 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 265 | let mut array = Array2D::from_rows(&rows)?; 266 | let (set_row, set_column) = (0, 2); 267 | let element = 53; 268 | let element_ref_option = array.get_mut(set_row, set_column); 269 | assert!(element_ref_option.is_some()); 270 | let element_ref = element_ref_option.unwrap(); 271 | assert_eq!(element_ref, &rows[set_row][set_column]); 272 | *element_ref = element; 273 | assert_eq!(element_ref, &element); 274 | for row in 0..rows.len() { 275 | for column in 0..rows[0].len() { 276 | let actual = array.get(row, column); 277 | if (row, column) == (set_row, set_column) { 278 | assert_eq!(actual, Some(&element)); 279 | } else { 280 | assert_eq!(actual, Some(&rows[row][column])); 281 | } 282 | } 283 | } 284 | Ok(()) 285 | } 286 | 287 | #[test] 288 | fn test_get_mut_row_major() -> Result<(), Error> { 289 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 290 | let mut array = Array2D::from_rows(&rows)?; 291 | assert_eq!(array.get_mut_row_major(0), Some(&mut 1)); 292 | assert_eq!(array.get_mut_row_major(1), Some(&mut 2)); 293 | assert_eq!(array.get_mut_row_major(2), Some(&mut 3)); 294 | assert_eq!(array.get_mut_row_major(3), Some(&mut 4)); 295 | assert_eq!(array.get_mut_row_major(4), Some(&mut 5)); 296 | assert_eq!(array.get_mut_row_major(5), Some(&mut 6)); 297 | assert_eq!(array.get_mut_row_major(6), None); 298 | Ok(()) 299 | } 300 | 301 | #[test] 302 | fn test_get_mut_column_major() -> Result<(), Error> { 303 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 304 | let mut array = Array2D::from_rows(&rows)?; 305 | assert_eq!(array.get_mut_column_major(0), Some(&mut 1)); 306 | assert_eq!(array.get_mut_column_major(1), Some(&mut 4)); 307 | assert_eq!(array.get_mut_column_major(2), Some(&mut 2)); 308 | assert_eq!(array.get_mut_column_major(3), Some(&mut 5)); 309 | assert_eq!(array.get_mut_column_major(4), Some(&mut 3)); 310 | assert_eq!(array.get_mut_column_major(5), Some(&mut 6)); 311 | assert_eq!(array.get_mut_column_major(6), None); 312 | Ok(()) 313 | } 314 | 315 | #[test] 316 | fn test_set() -> Result<(), Error> { 317 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 318 | let mut array = Array2D::from_rows(&rows)?; 319 | let (set_row, set_column) = (1, 0); 320 | let element = 42; 321 | array.set(set_row, set_column, element).unwrap(); 322 | for row in 0..rows.len() { 323 | for column in 0..rows[0].len() { 324 | let actual = array.get(row, column); 325 | if (row, column) == (set_row, set_column) { 326 | assert_eq!(actual, Some(&element)); 327 | } else { 328 | assert_eq!(actual, Some(&rows[row][column])); 329 | } 330 | } 331 | } 332 | Ok(()) 333 | } 334 | 335 | #[test] 336 | fn test_set_row_major() -> Result<(), Error> { 337 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 338 | let mut array = Array2D::from_rows(&rows)?; 339 | let set_index = 4; 340 | let set_row = 1; 341 | let set_column = 1; 342 | let element = 42; 343 | array.set_row_major(set_index, element).unwrap(); 344 | for row in 0..rows.len() { 345 | for column in 0..rows[0].len() { 346 | let actual = array.get(row, column); 347 | if (row, column) == (set_row, set_column) { 348 | assert_eq!(actual, Some(&element)); 349 | } else { 350 | assert_eq!(actual, Some(&rows[row][column])); 351 | } 352 | } 353 | } 354 | Ok(()) 355 | } 356 | 357 | #[test] 358 | fn test_set_column_major() -> Result<(), Error> { 359 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 360 | let mut array = Array2D::from_rows(&rows)?; 361 | let set_index = 4; 362 | let set_row = 0; 363 | let set_column = 2; 364 | let element = 42; 365 | array.set_column_major(set_index, element).unwrap(); 366 | for row in 0..rows.len() { 367 | for column in 0..rows[0].len() { 368 | let actual = array.get(row, column); 369 | if (row, column) == (set_row, set_column) { 370 | assert_eq!(actual, Some(&element)); 371 | } else { 372 | assert_eq!(actual, Some(&rows[row][column])); 373 | } 374 | } 375 | } 376 | Ok(()) 377 | } 378 | 379 | #[test] 380 | fn test_elements_row_major_iter() -> Result<(), Error> { 381 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 382 | let row_major = vec![1, 2, 3, 4, 5, 6]; 383 | let array = Array2D::from_rows(&rows)?; 384 | let row_len = rows[0].len(); 385 | for (index, element) in array.elements_row_major_iter().enumerate() { 386 | let row_index = index / row_len; 387 | let column_index = index % row_len; 388 | // Do it both ways to make sure we're doing this right 389 | assert_eq!(element, &rows[row_index][column_index]); 390 | assert_eq!(element, &row_major[index]); 391 | } 392 | Ok(()) 393 | } 394 | 395 | #[test] 396 | fn test_elements_column_major_iter() -> Result<(), Error> { 397 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 398 | let column_major = vec![1, 4, 2, 5, 3, 6]; 399 | let array = Array2D::from_rows(&rows)?; 400 | let column_len = rows.len(); 401 | for (index, element) in array.elements_column_major_iter().enumerate() { 402 | let column_index = index / column_len; 403 | let row_index = index % column_len; 404 | // Do it both ways to make sure we're doing this right 405 | assert_eq!(element, &rows[row_index][column_index]); 406 | assert_eq!(element, &column_major[index]); 407 | } 408 | Ok(()) 409 | } 410 | 411 | #[test] 412 | fn test_row_iter() -> Result<(), Error> { 413 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 414 | let array = Array2D::from_rows(&rows)?; 415 | let first_row_iter = array.row_iter(0)?; 416 | for (index, element) in first_row_iter.enumerate() { 417 | assert_eq!(element, &rows[0][index]); 418 | } 419 | let second_row_iter = array.row_iter(1)?; 420 | for (index, element) in second_row_iter.enumerate() { 421 | assert_eq!(element, &rows[1][index]); 422 | } 423 | Ok(()) 424 | } 425 | 426 | #[test] 427 | fn test_column_iter() -> Result<(), Error> { 428 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 429 | let array = Array2D::from_rows(&rows)?; 430 | let first_column_iter = array.column_iter(0)?; 431 | for (index, element) in first_column_iter.enumerate() { 432 | assert_eq!(element, &rows[index][0]); 433 | } 434 | let second_column_iter = array.column_iter(1)?; 435 | for (index, element) in second_column_iter.enumerate() { 436 | assert_eq!(element, &rows[index][1]); 437 | } 438 | Ok(()) 439 | } 440 | 441 | #[test] 442 | fn test_rows_iter() -> Result<(), Error> { 443 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 444 | let array = Array2D::from_rows(&rows)?; 445 | for (row_index, row_iter) in array.rows_iter().enumerate() { 446 | for (column_index, element) in row_iter.enumerate() { 447 | assert_eq!(element, &rows[row_index][column_index]); 448 | } 449 | } 450 | Ok(()) 451 | } 452 | 453 | #[test] 454 | fn test_columns_iter() -> Result<(), Error> { 455 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 456 | let array = Array2D::from_rows(&rows)?; 457 | for (column_index, column_iter) in array.columns_iter().enumerate() { 458 | for (row_index, element) in column_iter.enumerate() { 459 | assert_eq!(element, &rows[row_index][column_index]); 460 | } 461 | } 462 | Ok(()) 463 | } 464 | 465 | #[test] 466 | fn test_op_index() -> Result<(), Error> { 467 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 468 | let array = Array2D::from_rows(&rows)?; 469 | for row in 0..rows.len() { 470 | for column in 0..rows[0].len() { 471 | assert_eq!(array[(row, column)], rows[row][column]); 472 | } 473 | } 474 | Ok(()) 475 | } 476 | 477 | #[test] 478 | fn test_op_index_mut() -> Result<(), Error> { 479 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 480 | let mut array = Array2D::from_rows(&rows)?; 481 | for row in 0..rows.len() { 482 | for column in 0..rows[0].len() { 483 | array[(row, column)] += 1; 484 | assert_eq!(array[(row, column)], rows[row][column] + 1); 485 | } 486 | } 487 | Ok(()) 488 | } 489 | 490 | #[test] 491 | fn test_swap() -> Result<(), Error> { 492 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 493 | let mut array = Array2D::from_rows(&rows)?; 494 | 495 | assert!(array.swap((0, 1), (1, 0)).is_ok()); 496 | let expected_rows = vec![vec![1, 4, 3], vec![2, 5, 6]]; 497 | assert_eq!(array.as_rows(), expected_rows); 498 | 499 | let expected_err = Error::IndicesOutOfBounds(2, 0); 500 | assert_eq!(array.swap((0, 1), (2, 0)).unwrap_err(), expected_err); 501 | // The failed swap should not have modified the array. 502 | assert_eq!(array.as_rows(), expected_rows); 503 | 504 | Ok(()) 505 | } 506 | 507 | //////////////////////////////////////////////////////////////////////////////// 508 | // Error Handling ////////////////////////////////////////////////////////////// 509 | //////////////////////////////////////////////////////////////////////////////// 510 | 511 | #[test] 512 | fn test_from_rows_not_all_same_size() { 513 | let rows = vec![vec![1, 2, 3], vec![4, 5]]; 514 | let result = Array2D::from_rows(&rows); 515 | assert_eq!(result, Err(Error::DimensionMismatch)); 516 | } 517 | 518 | #[test] 519 | fn test_from_columns_not_all_same_size() { 520 | let columns = vec![vec![1, 4], vec![2, 3], vec![4]]; 521 | let result = Array2D::from_columns(&columns); 522 | assert_eq!(result, Err(Error::DimensionMismatch)); 523 | } 524 | 525 | #[test] 526 | fn test_from_row_major_dimensions_do_not_match_size() { 527 | let row_major = vec![1, 2, 3, 4, 5, 6, 7]; 528 | let num_rows = 2; 529 | let num_columns = 3; 530 | let result = Array2D::from_row_major(num_rows, num_columns, &row_major); 531 | assert_eq!(result, Err(Error::DimensionMismatch)); 532 | } 533 | 534 | #[test] 535 | fn test_from_column_major_dimensions_do_not_match_size() { 536 | let column_major = vec![1, 4, 2, 5, 3]; 537 | let num_rows = 2; 538 | let num_columns = 3; 539 | let result = Array2D::from_column_major(num_rows, num_columns, &column_major); 540 | assert_eq!(result, Err(Error::DimensionMismatch)); 541 | } 542 | 543 | #[test] 544 | fn test_from_iter_row_major_not_enough() { 545 | let iter = 1..5; 546 | let num_rows = 2; 547 | let num_columns = 3; 548 | let result = Array2D::from_iter_row_major(num_rows, num_columns, iter); 549 | assert_eq!(result, Err(Error::NotEnoughElements)); 550 | } 551 | 552 | #[test] 553 | fn test_from_iter_column_major_not_enough() { 554 | let iter = 1..5; 555 | let num_rows = 2; 556 | let num_columns = 3; 557 | let result = Array2D::from_iter_column_major(num_rows, num_columns, iter); 558 | assert_eq!(result, Err(Error::NotEnoughElements)); 559 | } 560 | 561 | #[test] 562 | fn test_row_iter_out_of_bounds() { 563 | let element = 42; 564 | let num_rows = 2; 565 | let num_columns = 3; 566 | let array = Array2D::filled_with(num_rows, num_columns, element); 567 | let result = array.row_iter(num_rows); 568 | assert!(result.is_err()); 569 | } 570 | 571 | #[test] 572 | fn test_column_iter_out_of_bounds() { 573 | let element = 42; 574 | let num_rows = 2; 575 | let num_columns = 3; 576 | let array = Array2D::filled_with(num_rows, num_columns, element); 577 | let result = array.column_iter(num_columns); 578 | assert!(result.is_err()); 579 | } 580 | 581 | #[test] 582 | #[should_panic] 583 | fn test_index_out_of_bounds_row() { 584 | let element = 42; 585 | let num_rows = 2; 586 | let num_columns = 3; 587 | let array = Array2D::filled_with(num_rows, num_columns, element); 588 | let _ = array[(num_rows, 0)]; 589 | } 590 | 591 | #[test] 592 | #[should_panic] 593 | fn test_index_out_of_bounds_column() { 594 | let element = 42; 595 | let num_rows = 2; 596 | let num_columns = 3; 597 | let array = Array2D::filled_with(num_rows, num_columns, element); 598 | let _ = array[(0, num_columns)]; 599 | } 600 | 601 | #[test] 602 | #[should_panic] 603 | fn test_index_out_of_bounds_row_and_column() { 604 | let element = 42; 605 | let num_rows = 2; 606 | let num_columns = 3; 607 | let array = Array2D::filled_with(num_rows, num_columns, element); 608 | let _ = array[(num_rows, num_columns)]; 609 | } 610 | 611 | #[test] 612 | #[should_panic] 613 | fn test_index_mut_out_of_bounds_row() { 614 | let element = 42; 615 | let num_rows = 2; 616 | let num_columns = 3; 617 | let mut array = Array2D::filled_with(num_rows, num_columns, element); 618 | array[(num_rows, 0)] += 1; 619 | } 620 | 621 | #[test] 622 | #[should_panic] 623 | fn test_index_mut_out_of_bounds_column() { 624 | let element = 42; 625 | let num_rows = 2; 626 | let num_columns = 3; 627 | let mut array = Array2D::filled_with(num_rows, num_columns, element); 628 | array[(0, num_columns)] += 1; 629 | } 630 | 631 | #[test] 632 | #[should_panic] 633 | fn test_index_mut_out_of_bounds_row_and_column() { 634 | let element = 42; 635 | let num_rows = 2; 636 | let num_columns = 3; 637 | let mut array = Array2D::filled_with(num_rows, num_columns, element); 638 | array[(num_rows, num_columns)] += 1; 639 | } 640 | 641 | //////////////////////////////////////////////////////////////////////////////// 642 | // Empty Arrays //////////////////////////////////////////////////////////////// 643 | //////////////////////////////////////////////////////////////////////////////// 644 | 645 | #[test] 646 | fn test_empty_array_from_rows() -> Result<(), Error> { 647 | let rows: Vec> = vec![]; 648 | let array = Array2D::from_rows(&rows)?; 649 | assert_eq!(array.num_rows(), 0); 650 | assert_eq!(array.num_columns(), 0); 651 | assert_eq!(array.row_len(), 0); 652 | assert_eq!(array.column_len(), 0); 653 | Ok(()) 654 | } 655 | 656 | #[test] 657 | fn test_empty_array_from_row_major() -> Result<(), Error> { 658 | let row_major: Vec = vec![]; 659 | let array = Array2D::from_row_major(0, 0, &row_major)?; 660 | assert_eq!(array.num_rows(), 0); 661 | assert_eq!(array.num_columns(), 0); 662 | assert_eq!(array.row_len(), 0); 663 | assert_eq!(array.column_len(), 0); 664 | Ok(()) 665 | } 666 | 667 | #[test] 668 | fn test_empty_array_from_rows_many_empty_rows() -> Result<(), Error> { 669 | let rows: Vec> = vec![vec![], vec![], vec![]]; 670 | let array = Array2D::from_rows(&rows)?; 671 | assert_eq!(array.num_rows(), 3); 672 | assert_eq!(array.num_columns(), 0); 673 | assert_eq!(array.row_len(), 0); 674 | assert_eq!(array.column_len(), 3); 675 | Ok(()) 676 | } 677 | 678 | #[test] 679 | fn test_empty_array_from_row_major_non_zero_columns() -> Result<(), Error> { 680 | let row_major: Vec = vec![]; 681 | let array = Array2D::from_row_major(0, 4, &row_major)?; 682 | assert_eq!(array.num_rows(), 0); 683 | assert_eq!(array.num_columns(), 4); 684 | assert_eq!(array.row_len(), 4); 685 | assert_eq!(array.column_len(), 0); 686 | Ok(()) 687 | } 688 | 689 | //////////////////////////////////////////////////////////////////////////////// 690 | // Double-Ended Iterators ////////////////////////////////////////////////////// 691 | //////////////////////////////////////////////////////////////////////////////// 692 | 693 | #[test] 694 | fn test_double_ended_iterator_elements_row_major_iter() -> Result<(), Error> { 695 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 696 | let array = Array2D::from_rows(&rows)?; 697 | let reversed_columns = array 698 | .elements_row_major_iter() 699 | .cloned() 700 | .rev() 701 | .collect::>(); 702 | assert_eq!(reversed_columns, vec![6, 5, 4, 3, 2, 1]); 703 | Ok(()) 704 | } 705 | 706 | #[test] 707 | fn test_double_ended_iterator_elements_column_major_iter() -> Result<(), Error> { 708 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 709 | let array = Array2D::from_rows(&rows)?; 710 | let reversed_columns = array 711 | .elements_column_major_iter() 712 | .cloned() 713 | .rev() 714 | .collect::>(); 715 | assert_eq!(reversed_columns, vec![6, 3, 5, 2, 4, 1]); 716 | Ok(()) 717 | } 718 | 719 | #[test] 720 | fn test_double_ended_iterator_row_iter() -> Result<(), Error> { 721 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 722 | let array = Array2D::from_rows(&rows)?; 723 | let reversed_columns = array.row_iter(0)?.cloned().rev().collect::>(); 724 | assert_eq!(reversed_columns, vec![3, 2, 1]); 725 | Ok(()) 726 | } 727 | 728 | #[test] 729 | fn test_double_ended_iterator_column_iter() -> Result<(), Error> { 730 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 731 | let array = Array2D::from_rows(&rows)?; 732 | let reversed_columns = array.column_iter(1)?.cloned().rev().collect::>(); 733 | assert_eq!(reversed_columns, vec![5, 2]); 734 | Ok(()) 735 | } 736 | 737 | #[test] 738 | fn test_double_ended_iterator_rows_iter() -> Result<(), Error> { 739 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 740 | let array = Array2D::from_rows(&rows)?; 741 | let reversed_rows = array 742 | .rows_iter() 743 | .rev() 744 | .map(|row| row.cloned().collect::>()) 745 | .collect::>(); 746 | assert_eq!(reversed_rows, vec![vec![4, 5, 6], vec![1, 2, 3]]); 747 | Ok(()) 748 | } 749 | 750 | #[test] 751 | fn test_double_ended_iterator_columns_iter() -> Result<(), Error> { 752 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 753 | let array = Array2D::from_rows(&rows)?; 754 | let reversed_columns = array 755 | .columns_iter() 756 | .rev() 757 | .map(|row| row.cloned().collect::>()) 758 | .collect::>(); 759 | assert_eq!(reversed_columns, vec![vec![3, 6], vec![2, 5], vec![1, 4]]); 760 | Ok(()) 761 | } 762 | 763 | #[test] 764 | fn test_indices_row_major() -> Result<(), Error> { 765 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 766 | let array = Array2D::from_rows(&rows)?; 767 | let indices_row_major = array.indices_row_major().collect::>(); 768 | assert_eq!( 769 | indices_row_major, 770 | vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)] 771 | ); 772 | Ok(()) 773 | } 774 | 775 | #[test] 776 | fn test_indices_column_major() -> Result<(), Error> { 777 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 778 | let array = Array2D::from_rows(&rows)?; 779 | let indices_column_major = array.indices_column_major().collect::>(); 780 | assert_eq!( 781 | indices_column_major, 782 | vec![(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2)] 783 | ); 784 | Ok(()) 785 | } 786 | 787 | #[test] 788 | fn test_enumerate_row_major() -> Result<(), Error> { 789 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 790 | let array = Array2D::from_rows(&rows)?; 791 | let enumerate_row_major = array.enumerate_row_major().collect::>(); 792 | assert_eq!( 793 | enumerate_row_major, 794 | vec![ 795 | ((0, 0), &1), 796 | ((0, 1), &2), 797 | ((0, 2), &3), 798 | ((1, 0), &4), 799 | ((1, 1), &5), 800 | ((1, 2), &6) 801 | ] 802 | ); 803 | Ok(()) 804 | } 805 | 806 | fn main() -> Result<(), Error> { 807 | let rows = vec![vec![1, 2, 3], vec![4, 5, 6]]; 808 | let array = Array2D::from_rows(&rows)?; 809 | let enumerate_column_major = array.enumerate_column_major().collect::>(); 810 | assert_eq!( 811 | enumerate_column_major, 812 | vec![ 813 | ((0, 0), &1), 814 | ((1, 0), &4), 815 | ((0, 1), &2), 816 | ((1, 1), &5), 817 | ((0, 2), &3), 818 | ((1, 2), &6) 819 | ] 820 | ); 821 | Ok(()) 822 | } 823 | --------------------------------------------------------------------------------