servicepoint/src/containers/char_grid_ext.rs
Vinzenz Schroeter 49489aec64
All checks were successful
Rust / build (pull_request) Successful in 2m3s
clippy fixes, formatting
2025-07-10 21:59:18 +02:00

173 lines
4.5 KiB
Rust

use crate::{Grid, GridMut, SetValueSeriesError};
/// Extension methods for any [`Grid<char>`]
pub trait CharGridExt {
/// Copies a column from the grid as a String.
///
/// Returns [None] if x is out of bounds.
///
/// # Examples
///
/// ```
/// # use servicepoint::{CharGrid, CharGridExt};
/// let grid = CharGrid::from("ab\ncd");
/// let col = grid.get_col_str(0).unwrap(); // "ac"
/// ```
#[must_use]
fn get_col_str(&self, x: usize) -> Option<String>;
/// Copies a row from the grid as a String.
///
/// Returns [None] if y is out of bounds.
///
/// # Examples
///
/// ```
/// # use servicepoint::{CharGrid, CharGridExt};
/// let grid = CharGrid::from("ab\ncd");
/// let row = grid.get_row_str(0).unwrap(); // "ab"
/// ```
#[must_use]
fn get_row_str(&self, y: usize) -> Option<String>;
}
/// Extension methods for any [`GridMut<char>`].
pub trait CharGridMutExt {
/// Overwrites a row in the grid with a str.
///
/// Returns [`SetValueSeriesError`] if y is out of bounds or `row` is not of the correct size.
///
/// # Examples
///
/// ```
/// # use servicepoint::{CharGrid, CharGridMutExt};
/// let mut grid = CharGrid::from("ab\ncd");
/// grid.set_row_str(0, "ef").unwrap();
/// ```
fn set_row_str(
&mut self,
y: usize,
value: &str,
) -> Result<(), SetValueSeriesError>;
/// Overwrites a column in the grid with a str.
///
/// Returns [`SetValueSeriesError`] if y is out of bounds or `row` is not of the correct size.
///
/// # Examples
///
/// ```
/// # use servicepoint::{CharGrid, CharGridMutExt};
/// let mut grid = CharGrid::from("ab\ncd");
/// grid.set_col_str(0, "ef").unwrap();
/// ```
fn set_col_str(
&mut self,
x: usize,
value: &str,
) -> Result<(), SetValueSeriesError>;
}
impl<G: Grid<char>> CharGridExt for G {
fn get_col_str(&self, x: usize) -> Option<String> {
Some(String::from_iter(self.get_col(x)?))
}
fn get_row_str(&self, y: usize) -> Option<String> {
Some(String::from_iter(self.get_row(y)?))
}
}
impl<G: GridMut<char>> CharGridMutExt for G {
fn set_row_str(
&mut self,
y: usize,
value: &str,
) -> Result<(), SetValueSeriesError> {
let width = self.width();
let len = value.len();
if len > width {
return Err(SetValueSeriesError::InvalidLength {
actual: len,
expected: width,
});
}
let height = self.height();
if y >= height {
return Err(SetValueSeriesError::OutOfBounds {
index: y,
size: height,
});
}
let chars = value.chars().take(width);
for (x, c) in chars.enumerate() {
self.set(x, y, c);
}
Ok(())
}
fn set_col_str(
&mut self,
x: usize,
value: &str,
) -> Result<(), SetValueSeriesError> {
let height = self.height();
let len = value.len();
if len > height {
return Err(SetValueSeriesError::InvalidLength {
actual: len,
expected: height,
});
}
let width = self.width();
if x >= width {
return Err(SetValueSeriesError::OutOfBounds {
index: x,
size: width,
});
}
let chars = value.chars().take(height);
for (y, c) in chars.enumerate() {
self.set(x, y, c);
}
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")));
}
}