use crate::device::MAX_TARGET_DIMENSION;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DeviceRect {
x: u32,
y: u32,
width: u32,
height: u32,
}
impl DeviceRect {
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Result<DeviceRect, Error> {
if width == 0 || height == 0 {
return Err(Error::TargetEmpty { width, height });
}
if width > MAX_TARGET_DIMENSION
|| height > MAX_TARGET_DIMENSION
|| x.checked_add(width).is_none()
|| y.checked_add(height).is_none()
{
return Err(Error::TargetTooLarge {
width,
height,
limit: MAX_TARGET_DIMENSION,
});
}
Ok(DeviceRect {
x,
y,
width,
height,
})
}
#[must_use]
pub fn x(&self) -> u32 {
self.x
}
#[must_use]
pub fn y(&self) -> u32 {
self.y
}
#[must_use]
pub fn width(&self) -> u32 {
self.width
}
#[must_use]
pub fn height(&self) -> u32 {
self.height
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Region {
#[default]
Whole,
Rect(DeviceRect),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_rect_is_non_empty_and_within_the_backend_limit() {
assert!(DeviceRect::new(0, 0, 1, 1).is_ok());
assert!(DeviceRect::new(u32::MAX - 65535, 0, 65535, 1).is_ok());
assert_eq!(
DeviceRect::new(0, 0, 0, 5),
Err(Error::TargetEmpty {
width: 0,
height: 5
})
);
assert!(matches!(
DeviceRect::new(0, 0, 65536, 5),
Err(Error::TargetTooLarge { .. })
));
assert!(matches!(
DeviceRect::new(u32::MAX, 0, 1, 1),
Err(Error::TargetTooLarge { .. })
));
}
}