move more stuff to traits
This commit is contained in:
parent
bbd1d643b9
commit
cabf1d32ed
5 changed files with 171 additions and 141 deletions
|
|
@ -154,33 +154,6 @@ impl From<CharGrid> for Vec<u8> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::{CharGridExt, SetValueSeriesError};
|
||||
|
||||
#[test]
|
||||
fn col_str() {
|
||||
let mut grid = CharGrid::new(2, 3);
|
||||
assert_eq!(grid.get_col_str(2), None);
|
||||
assert_eq!(grid.get_col_str(1), Some(String::from("\0\0\0")));
|
||||
assert_eq!(grid.set_col_str(1, "abc"), Ok(()));
|
||||
assert_eq!(grid.get_col_str(1), Some(String::from("abc")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row_str() {
|
||||
let mut grid = CharGrid::new(2, 3);
|
||||
assert_eq!(grid.get_row_str(3), None);
|
||||
assert_eq!(grid.get_row_str(1), Some(String::from("\0\0")));
|
||||
assert_eq!(
|
||||
grid.set_row_str(1, "abc"),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 2,
|
||||
actual: 3
|
||||
})
|
||||
);
|
||||
assert_eq!(grid.set_row_str(1, "ab"), Ok(()));
|
||||
assert_eq!(grid.get_row_str(1), Some(String::from("ab")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_char_grid() {
|
||||
// conversion with .to_string() covers one more line
|
||||
|
|
|
|||
|
|
@ -143,3 +143,33 @@ impl<G: GridMut<char>> CharGridMutExt for G {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{CharGrid, CharGridExt, CharGridMutExt, SetValueSeriesError};
|
||||
|
||||
#[test]
|
||||
fn col_str() {
|
||||
let mut grid = CharGrid::new(2, 3);
|
||||
assert_eq!(grid.get_col_str(2), None);
|
||||
assert_eq!(grid.get_col_str(1), Some(String::from("\0\0\0")));
|
||||
assert_eq!(grid.set_col_str(1, "abc"), Ok(()));
|
||||
assert_eq!(grid.get_col_str(1), Some(String::from("abc")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row_str() {
|
||||
let mut grid = CharGrid::new(2, 3);
|
||||
assert_eq!(grid.get_row_str(3), None);
|
||||
assert_eq!(grid.get_row_str(1), Some(String::from("\0\0")));
|
||||
assert_eq!(
|
||||
grid.set_row_str(1, "abc"),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 2,
|
||||
actual: 3
|
||||
})
|
||||
);
|
||||
assert_eq!(grid.set_row_str(1, "ab"), Ok(()));
|
||||
assert_eq!(grid.get_row_str(1), Some(String::from("ab")));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use crate::SetValueSeriesError;
|
||||
|
||||
/// A two-dimensional readonly grid of `T`
|
||||
pub trait Grid<T> {
|
||||
/// Get the current value at the specified position
|
||||
|
|
@ -90,7 +92,7 @@ pub trait Grid<T> {
|
|||
}
|
||||
|
||||
/// A two-dimensional mutable grid of `T`
|
||||
pub trait GridMut<T>: Grid<T> {
|
||||
pub trait GridMut<T: Clone>: Grid<T> {
|
||||
/// Sets the value at the specified position
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
@ -150,4 +152,122 @@ pub trait GridMut<T>: Grid<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Overwrites a column in the grid.
|
||||
///
|
||||
/// Returns [Err] if x is out of bounds or `col` is not of the correct size.
|
||||
fn set_col(
|
||||
&mut self,
|
||||
x: usize,
|
||||
col: &[T],
|
||||
) -> Result<(), SetValueSeriesError> {
|
||||
let height = self.height();
|
||||
if col.len() != height {
|
||||
return Err(SetValueSeriesError::InvalidLength {
|
||||
expected: height,
|
||||
actual: col.len(),
|
||||
});
|
||||
}
|
||||
|
||||
if x >= self.width() {
|
||||
return Err(SetValueSeriesError::OutOfBounds {
|
||||
size: self.width(),
|
||||
index: x,
|
||||
});
|
||||
}
|
||||
|
||||
for (y, item) in col.iter().enumerate().take(height) {
|
||||
self.set(x, y, item.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Overwrites a row in the grid.
|
||||
///
|
||||
/// Returns [Err] if y is out of bounds or `row` is not of the correct size.
|
||||
fn set_row(
|
||||
&mut self,
|
||||
y: usize,
|
||||
row: &[T],
|
||||
) -> Result<(), SetValueSeriesError> {
|
||||
let width = self.width();
|
||||
if row.len() != width {
|
||||
return Err(SetValueSeriesError::InvalidLength {
|
||||
expected: width,
|
||||
actual: row.len(),
|
||||
});
|
||||
}
|
||||
|
||||
if y >= self.height() {
|
||||
return Err(SetValueSeriesError::OutOfBounds {
|
||||
size: self.height(),
|
||||
index: y,
|
||||
});
|
||||
}
|
||||
|
||||
for (x, item) in row.iter().enumerate().take(width) {
|
||||
self.set(x, y, item.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{DataRef, Grid, GridMut, SetValueSeriesError, ValueGrid};
|
||||
|
||||
#[test]
|
||||
fn optional() {
|
||||
let mut grid = ValueGrid::load(2, 2, &[0, 1, 2, 3]).unwrap();
|
||||
assert!(grid.set_optional(0, 0, 5));
|
||||
assert!(!grid.set_optional(0, 8, 42));
|
||||
assert_eq!(grid.data_ref(), [5, 1, 2, 3]);
|
||||
|
||||
assert_eq!(grid.get_optional(0, 0), Some(5));
|
||||
assert_eq!(grid.get_optional(0, 8), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn col() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
assert_eq!(grid.get_col(0), Some(vec![0, 2, 4]));
|
||||
assert_eq!(grid.get_col(1), Some(vec![1, 3, 5]));
|
||||
assert_eq!(grid.get_col(2), None);
|
||||
assert_eq!(grid.set_col(0, &[5, 7, 9]), Ok(()));
|
||||
assert_eq!(
|
||||
grid.set_col(2, &[5, 7, 9]),
|
||||
Err(SetValueSeriesError::OutOfBounds { size: 2, index: 2 })
|
||||
);
|
||||
assert_eq!(
|
||||
grid.set_col(0, &[5, 7]),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 3,
|
||||
actual: 2
|
||||
})
|
||||
);
|
||||
assert_eq!(grid.get_col(0), Some(vec![5, 7, 9]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
assert_eq!(grid.get_row(0), Some(vec![0, 1]));
|
||||
assert_eq!(grid.get_row(2), Some(vec![4, 5]));
|
||||
assert_eq!(grid.get_row(3), None);
|
||||
assert_eq!(grid.set_row(0, &[5, 7]), Ok(()));
|
||||
assert_eq!(grid.get_row(0), Some(vec![5, 7]));
|
||||
assert_eq!(
|
||||
grid.set_row(3, &[5, 7]),
|
||||
Err(SetValueSeriesError::OutOfBounds { size: 3, index: 3 })
|
||||
);
|
||||
assert_eq!(
|
||||
grid.set_row(2, &[5, 7, 3]),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 2,
|
||||
actual: 3
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -224,66 +224,6 @@ impl<T: Value> ValueGrid<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Overwrites a column in the grid.
|
||||
///
|
||||
/// Returns [Err] if x is out of bounds or `col` is not of the correct size.
|
||||
pub fn set_col(
|
||||
&mut self,
|
||||
x: usize,
|
||||
col: &[T],
|
||||
) -> Result<(), SetValueSeriesError> {
|
||||
if col.len() != self.height() {
|
||||
return Err(SetValueSeriesError::InvalidLength {
|
||||
expected: self.height(),
|
||||
actual: col.len(),
|
||||
});
|
||||
}
|
||||
let width = self.width();
|
||||
if self
|
||||
.data
|
||||
.chunks_exact_mut(width)
|
||||
.zip(col.iter())
|
||||
.map(|(row, column_value)| {
|
||||
row.get_mut(x).map(move |cell| *cell = *column_value)
|
||||
})
|
||||
.all(|cell| cell.is_some())
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SetValueSeriesError::OutOfBounds {
|
||||
index: x,
|
||||
size: width,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Overwrites a row in the grid.
|
||||
///
|
||||
/// Returns [Err] if y is out of bounds or `row` is not of the correct size.
|
||||
pub fn set_row(
|
||||
&mut self,
|
||||
y: usize,
|
||||
row: &[T],
|
||||
) -> Result<(), SetValueSeriesError> {
|
||||
let width = self.width();
|
||||
if row.len() != width {
|
||||
return Err(SetValueSeriesError::InvalidLength {
|
||||
expected: width,
|
||||
actual: row.len(),
|
||||
});
|
||||
}
|
||||
|
||||
let Some(chunk) = self.data.chunks_exact_mut(width).nth(y) else {
|
||||
return Err(SetValueSeriesError::OutOfBounds {
|
||||
size: self.height(),
|
||||
index: y,
|
||||
});
|
||||
};
|
||||
|
||||
chunk.copy_from_slice(row);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Enumerates all values in the grid.
|
||||
pub fn enumerate(
|
||||
&self,
|
||||
|
|
@ -587,59 +527,6 @@ mod tests {
|
|||
assert_eq!(Some(&mut 8), vec.get_ref_mut_optional(2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optional() {
|
||||
let mut grid = ValueGrid::load(2, 2, &[0, 1, 2, 3]).unwrap();
|
||||
assert!(grid.set_optional(0, 0, 5));
|
||||
assert!(!grid.set_optional(0, 8, 42));
|
||||
assert_eq!(grid.data, [5, 1, 2, 3]);
|
||||
|
||||
assert_eq!(grid.get_optional(0, 0), Some(5));
|
||||
assert_eq!(grid.get_optional(0, 8), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn col() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
assert_eq!(grid.get_col(0), Some(vec![0, 2, 4]));
|
||||
assert_eq!(grid.get_col(1), Some(vec![1, 3, 5]));
|
||||
assert_eq!(grid.get_col(2), None);
|
||||
assert_eq!(grid.set_col(0, &[5, 7, 9]), Ok(()));
|
||||
assert_eq!(
|
||||
grid.set_col(2, &[5, 7, 9]),
|
||||
Err(SetValueSeriesError::OutOfBounds { size: 2, index: 2 })
|
||||
);
|
||||
assert_eq!(
|
||||
grid.set_col(0, &[5, 7]),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 3,
|
||||
actual: 2
|
||||
})
|
||||
);
|
||||
assert_eq!(grid.get_col(0), Some(vec![5, 7, 9]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
assert_eq!(grid.get_row(0), Some(vec![0, 1]));
|
||||
assert_eq!(grid.get_row(2), Some(vec![4, 5]));
|
||||
assert_eq!(grid.get_row(3), None);
|
||||
assert_eq!(grid.set_row(0, &[5, 7]), Ok(()));
|
||||
assert_eq!(grid.get_row(0), Some(vec![5, 7]));
|
||||
assert_eq!(
|
||||
grid.set_row(3, &[5, 7]),
|
||||
Err(SetValueSeriesError::OutOfBounds { size: 3, index: 3 })
|
||||
);
|
||||
assert_eq!(
|
||||
grid.set_row(2, &[5, 7, 3]),
|
||||
Err(SetValueSeriesError::InvalidLength {
|
||||
expected: 2,
|
||||
actual: 3
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrap() {
|
||||
let grid = ValueGrid::from_vec(2, vec![0, 1, 2, 3, 4, 5]).unwrap();
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ macro_rules! define_window {
|
|||
Window::new(self.grid, xs, ys)
|
||||
}
|
||||
|
||||
/// Splits the window horizontally, returning windows to the left and right parts.
|
||||
///
|
||||
/// The right window fills the remaining width, which may be zero.
|
||||
///
|
||||
/// Returns None for out-of-bounds.
|
||||
#[must_use]
|
||||
pub fn split_horizontal(
|
||||
&'t self,
|
||||
|
|
@ -79,6 +84,11 @@ macro_rules! define_window {
|
|||
Some((left, right))
|
||||
}
|
||||
|
||||
/// Splits the window vertically, returning windows to the top and bottom parts.
|
||||
///
|
||||
/// The bottom window fills the remaining height, which may be zero.
|
||||
///
|
||||
/// Returns None for out-of-bounds.
|
||||
#[must_use]
|
||||
pub fn split_vertical(
|
||||
&'t self,
|
||||
|
|
@ -164,6 +174,11 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> WindowMut<'_, TElement, TGrid> {
|
|||
WindowMut::new(self.grid, xs, ys)
|
||||
}
|
||||
|
||||
/// Splits the window horizontally, returning windows to the left and right parts.
|
||||
///
|
||||
/// The right window fills the remaining width, which may be zero.
|
||||
///
|
||||
/// Returns None for out-of-bounds.
|
||||
#[must_use]
|
||||
pub fn split_horizontal_mut<'t>(
|
||||
&'t mut self,
|
||||
|
|
@ -183,6 +198,11 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> WindowMut<'_, TElement, TGrid> {
|
|||
Some((left, right))
|
||||
}
|
||||
|
||||
/// Splits the window vertically, returning windows to the top and bottom parts.
|
||||
///
|
||||
/// The bottom window fills the remaining height, which may be zero.
|
||||
///
|
||||
/// Returns None for out-of-bounds.
|
||||
#[must_use]
|
||||
pub fn split_vertical_mut<'t>(
|
||||
&'t mut self,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue