do not panic in ValueGrid
This commit is contained in:
parent
b178b48834
commit
18db901fb5
|
@ -38,7 +38,7 @@ impl TryFrom<Packet> for BrightnessGridCommand {
|
|||
payload,
|
||||
} = packet;
|
||||
|
||||
let grid = ByteGrid::load(width as usize, height as usize, &payload);
|
||||
let grid = ByteGrid::load(width as usize, height as usize, &payload).unwrap();
|
||||
let grid = match BrightnessGrid::try_from(grid) {
|
||||
Ok(grid) => grid,
|
||||
Err(val) => return Err(TryFromPacketError::InvalidBrightness(val)),
|
||||
|
|
|
@ -52,7 +52,7 @@ impl TryFrom<Packet> for CharGridCommand {
|
|||
String::from_utf8(payload.clone())?.chars().collect();
|
||||
Ok(Self {
|
||||
origin: Origin::new(a as usize, b as usize),
|
||||
grid: CharGrid::load(c as usize, d as usize, &payload),
|
||||
grid: CharGrid::load(c as usize, d as usize, &payload).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ impl TryFrom<Packet> for Cp437GridCommand {
|
|||
} = packet;
|
||||
Ok(Self {
|
||||
origin: Origin::new(a as usize, b as usize),
|
||||
grid: Cp437Grid::load(c as usize, d as usize, &payload),
|
||||
grid: Cp437Grid::load(c as usize, d as usize, &payload).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ mod tests {
|
|||
8,
|
||||
1,
|
||||
&[true, false, true, false, true, false, true, false],
|
||||
);
|
||||
).unwrap();
|
||||
let converted = Bitmap::try_from(&original).unwrap();
|
||||
let reconverted = ValueGrid::from(&converted);
|
||||
assert_eq!(original, reconverted);
|
||||
|
|
|
@ -21,7 +21,7 @@ pub type BrightnessGrid = ValueGrid<Brightness>;
|
|||
impl BrightnessGrid {
|
||||
/// Like [Self::load], but ignoring any out-of-range brightness values
|
||||
pub fn saturating_load(width: usize, height: usize, data: &[u8]) -> Self {
|
||||
ValueGrid::load(width, height, data).map(Brightness::saturating_from)
|
||||
ValueGrid::load(width, height, data).unwrap().map(Brightness::saturating_from)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ impl From<&BrightnessGrid> for ByteGrid {
|
|||
.iter()
|
||||
.map(|brightness| (*brightness).into())
|
||||
.collect::<Vec<u8>>();
|
||||
ValueGrid::load(value.width(), value.height(), &u8s)
|
||||
ValueGrid::load(value.width(), value.height(), &u8s).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ impl TryFrom<ByteGrid> for BrightnessGrid {
|
|||
value.width(),
|
||||
value.height(),
|
||||
&brightnesses,
|
||||
))
|
||||
).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ mod tests {
|
|||
Brightness::MIN,
|
||||
Brightness::MAX
|
||||
]
|
||||
),
|
||||
).unwrap(),
|
||||
BrightnessGrid::saturating_load(2, 2, &[255u8, 23, 0, 42])
|
||||
);
|
||||
}
|
||||
|
|
|
@ -140,7 +140,11 @@ impl CharGrid {
|
|||
bytes: Vec<u8>,
|
||||
) -> Result<CharGrid, LoadUtf8Error> {
|
||||
let s: Vec<char> = String::from_utf8(bytes)?.chars().collect();
|
||||
Ok(CharGrid::try_load(width, height, s)?)
|
||||
Ok(CharGrid::load(width, height, &s).ok_or(
|
||||
LoadUtf8Error::TryLoadError(
|
||||
TryLoadValueGridError::InvalidDimensions,
|
||||
),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ mod tests {
|
|||
fn load_ascii_nowrap() {
|
||||
let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
|
||||
.map(move |c| c as u8);
|
||||
let expected = Cp437Grid::load(5, 2, &chars);
|
||||
let expected = Cp437Grid::load(5, 2, &chars).unwrap();
|
||||
|
||||
let actual = Cp437Grid::load_ascii("Hello,\nWorld!", 5, false).unwrap();
|
||||
// comma will be removed because line is too long and wrap is off
|
||||
|
@ -97,7 +97,7 @@ mod tests {
|
|||
fn load_ascii_wrap() {
|
||||
let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
|
||||
.map(move |c| c as u8);
|
||||
let expected = Cp437Grid::load(5, 2, &chars);
|
||||
let expected = Cp437Grid::load(5, 2, &chars).unwrap();
|
||||
|
||||
let actual = Cp437Grid::load_ascii("HelloWorld", 5, true).unwrap();
|
||||
// line break will be added
|
||||
|
|
|
@ -60,86 +60,57 @@ impl<T: Value> ValueGrid<T> {
|
|||
|
||||
/// Loads a [ValueGrid] with the specified dimensions from the provided data.
|
||||
///
|
||||
/// returns: [ValueGrid] that contains a copy of the provided data
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when the dimensions and data size do not match exactly.
|
||||
/// returns: [ValueGrid] that contains a copy of the provided data,
|
||||
/// or None if the dimensions do not match the data size.
|
||||
#[must_use]
|
||||
pub fn load(width: usize, height: usize, data: &[T]) -> Self {
|
||||
assert_eq!(
|
||||
width * height,
|
||||
data.len(),
|
||||
"dimension mismatch for data {data:?}"
|
||||
);
|
||||
Self {
|
||||
pub fn load(width: usize, height: usize, data: &[T]) -> Option<Self> {
|
||||
if width * height != data.len() {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
data: Vec::from(data),
|
||||
width,
|
||||
height,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a [ValueGrid] with the specified width from the provided data without copying it.
|
||||
/// Creates a [ValueGrid] with the specified width from the provided data,
|
||||
/// wrapping to as many rows as needed,
|
||||
/// without copying the vec.
|
||||
///
|
||||
/// returns: [ValueGrid] that contains the provided data.
|
||||
/// returns: [ValueGrid] that contains the provided data,
|
||||
/// or None if the data size is not divisible by the width.
|
||||
///
|
||||
/// # Panics
|
||||
/// # Examples
|
||||
///
|
||||
/// - when the data size is not dividable by the width.
|
||||
/// ```
|
||||
/// # use servicepoint::ValueGrid;
|
||||
/// let grid = ValueGrid::from_vec(2, vec![0, 1, 2, 3, 4, 5]).unwrap();
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn from_vec(width: usize, data: Vec<T>) -> Self {
|
||||
pub fn from_vec(width: usize, data: Vec<T>) -> Option<Self> {
|
||||
let len = data.len();
|
||||
let height = len / width;
|
||||
assert_eq!(
|
||||
0,
|
||||
len % width,
|
||||
"dimension mismatch - len {len} is not dividable by {width}"
|
||||
);
|
||||
Self {
|
||||
if len % width != 0 {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Loads a [ValueGrid] with the specified width from the provided data, wrapping to as many rows as needed.
|
||||
///
|
||||
/// returns: [ValueGrid] that contains a copy of the provided data or [TryLoadValueGridError].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use servicepoint::ValueGrid;
|
||||
/// let grid = ValueGrid::wrap(2, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn wrap(
|
||||
width: usize,
|
||||
data: &[T],
|
||||
) -> Result<Self, TryLoadValueGridError> {
|
||||
let len = data.len();
|
||||
if len % width != 0 {
|
||||
return Err(TryLoadValueGridError::InvalidDimensions);
|
||||
}
|
||||
Ok(Self::load(width, len / width, data))
|
||||
}
|
||||
|
||||
/// Loads a [ValueGrid] with the specified dimensions from the provided data.
|
||||
///
|
||||
/// returns: [ValueGrid] that contains a copy of the provided data or [TryLoadValueGridError].
|
||||
pub fn try_load(
|
||||
width: usize,
|
||||
height: usize,
|
||||
data: Vec<T>,
|
||||
) -> Result<Self, TryLoadValueGridError> {
|
||||
if width * height != data.len() {
|
||||
return Err(TryLoadValueGridError::InvalidDimensions);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
) -> Option<Self> {
|
||||
Self::from_vec(width, data.to_vec())
|
||||
}
|
||||
|
||||
/// Iterate over all cells in [ValueGrid].
|
||||
|
@ -230,7 +201,7 @@ impl<T: Value> ValueGrid<T> {
|
|||
.iter()
|
||||
.map(|elem| f(*elem))
|
||||
.collect::<Vec<_>>();
|
||||
ValueGrid::load(self.width(), self.height(), &data)
|
||||
ValueGrid::load(self.width(), self.height(), &data).unwrap()
|
||||
}
|
||||
|
||||
/// Copies a row from the grid.
|
||||
|
@ -486,7 +457,7 @@ mod tests {
|
|||
|
||||
let data: Vec<u8> = grid.into();
|
||||
|
||||
let grid = ValueGrid::load(2, 3, &data);
|
||||
let grid = ValueGrid::load(2, 3, &data).unwrap();
|
||||
assert_eq!(grid.data, [0, 1, 1, 2, 2, 3]);
|
||||
}
|
||||
|
||||
|
@ -525,7 +496,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn iter_rows() {
|
||||
let vec = ValueGrid::load(2, 3, &[0, 1, 1, 2, 2, 3]);
|
||||
let vec = ValueGrid::load(2, 3, &[0, 1, 1, 2, 2, 3]).unwrap();
|
||||
for (y, row) in vec.iter_rows().enumerate() {
|
||||
for (x, val) in row.enumerate() {
|
||||
assert_eq!(*val, (x + y) as u8);
|
||||
|
@ -536,20 +507,20 @@ mod tests {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn out_of_bounds_x() {
|
||||
let mut vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]);
|
||||
let mut vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]).unwrap();
|
||||
vec.set(2, 1, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn out_of_bounds_y() {
|
||||
let vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]);
|
||||
let vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]).unwrap();
|
||||
vec.get(1, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ref_mut() {
|
||||
let mut vec = ValueGrid::from_vec(3, vec![0, 1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let mut vec = ValueGrid::from_vec(3, vec![0, 1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
|
||||
|
||||
let top_left = vec.get_ref_mut(0, 0);
|
||||
*top_left += 5;
|
||||
|
@ -565,7 +536,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn optional() {
|
||||
let mut grid = ValueGrid::load(2, 2, &[0, 1, 2, 3]);
|
||||
let mut grid = ValueGrid::load(2, 2, &[0, 1, 2, 3]).unwrap();
|
||||
grid.set_optional(0, 0, 5);
|
||||
grid.set_optional(-1, 0, 8);
|
||||
grid.set_optional(0, 8, 42);
|
||||
|
@ -577,7 +548,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn col() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]);
|
||||
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);
|
||||
|
@ -598,7 +569,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn row() {
|
||||
let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]);
|
||||
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);
|
||||
|
@ -619,10 +590,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn wrap() {
|
||||
let grid = ValueGrid::wrap(2, &[0, 1, 2, 3, 4, 5]).unwrap();
|
||||
let grid = ValueGrid::from_vec(2, vec![0, 1, 2, 3, 4, 5]).unwrap();
|
||||
assert_eq!(grid.height(), 3);
|
||||
|
||||
let grid = ValueGrid::wrap(4, &[0, 1, 2, 3, 4, 5]);
|
||||
assert_eq!(grid.err(), Some(TryLoadValueGridError::InvalidDimensions));
|
||||
let grid = ValueGrid::from_vec(4, vec![0, 1, 2, 3, 4, 5]);
|
||||
assert_eq!(grid, None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ mod tests_feature_cp437 {
|
|||
|
||||
#[test]
|
||||
fn round_trip_cp437() {
|
||||
let utf8 = CharGrid::load(2, 2, &['Ä', 'x', '\n', '$']);
|
||||
let utf8 = CharGrid::load(2, 2, &['Ä', 'x', '\n', '$']).unwrap();
|
||||
let cp437 = Cp437Grid::from(utf8.clone());
|
||||
let actual = CharGrid::from(cp437);
|
||||
assert_eq!(actual, utf8);
|
||||
|
|
Loading…
Reference in a new issue