From 2f9b99c2b008e310131b13427cc05cecb73bea8c Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Fri, 29 Nov 2024 00:10:52 +0100 Subject: [PATCH] geometry: cut down on <> noise with associated types --- src/buffers.rs | 8 +-- src/geometry.rs | 98 +++++++++++++++------------------- src/mappings.rs | 63 +++++++++++++--------- src/platform/smart_leds_lib.rs | 31 +++++------ src/render.rs | 6 +-- 5 files changed, 100 insertions(+), 106 deletions(-) diff --git a/src/buffers.rs b/src/buffers.rs index 1a0f7eb..6d7b587 100644 --- a/src/buffers.rs +++ b/src/buffers.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, Mutex}; #[derive(Debug)] pub struct ShaderBinding { shader: Option>, - rect: Rectangle, + rect: Rectangle, opacity: u8 } @@ -45,7 +45,7 @@ impl Default for BoundSurface>>{ } impl Surface for BoundSurface>> { - fn rect(&self) -> Rectangle { + fn rect(&self) -> Rectangle { self.binding.borrow().rect.clone() } @@ -63,7 +63,7 @@ impl Surface for BoundSurface>> { self.binding.borrow_mut().shader = None; } - fn set_rect(&mut self, rect: &Rectangle) { + fn set_rect(&mut self, rect: &Rectangle) { self.binding.borrow_mut().rect = rect.clone(); } @@ -159,7 +159,7 @@ impl SurfacePool { } impl Surfaces for SurfacePool { - fn new_surface(&mut self, area: &Rectangle) -> Result { + fn new_surface(&mut self, area: &Rectangle) -> Result { let mut surface = S::default(); surface.set_rect(area); self.surfaces.push(surface.clone()); diff --git a/src/geometry.rs b/src/geometry.rs index 6791bd9..3382272 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,19 +1,26 @@ use std::fmt::{Debug, Formatter}; -use std::marker::PhantomData; use std::ops::{Mul, Sub, Add}; use num::{One, pow, integer::Roots}; use std::cmp::{min, max}; -pub trait CoordinateSpace {} - -#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] -pub struct Coordinates, S: CoordinateSpace> { - pub x: T, - pub y: T, - space: PhantomData, +pub trait CoordinateOp: PartialOrd + PartialEq + Sub + Clone + Mul + Copy + One + Add + Eq + Debug where +Self: Sub { + const MIN: Self; + const MAX: Self; + fn distance(x1: Self, y1: Self, x2: Self, y2: Self) -> Self; } -impl + Debug, S: CoordinateSpace> Debug for Coordinates { +pub trait CoordinateSpace { + type Data: CoordinateOp; +} + +#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] +pub struct Coordinates { + pub x: S::Data, + pub y: S::Data, +} + +impl Debug for Coordinates where S::Data: Debug { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_tuple("@") .field(&self.x) @@ -22,16 +29,7 @@ impl + Debug, S: CoordinateSpace> Debug for Coordinates } } -pub trait CoordLimits: PartialOrd + PartialEq + Sub + Clone + Mul + Copy + One + Add { - type Data: CoordLimits; - const MIN: Self::Data; - const MAX: Self::Data; - - fn distance(x1: Self, y1: Self, x2: Self, y2: Self) -> Self; -} - -impl CoordLimits for u8 { - type Data = u8; +impl CoordinateOp for u8 { const MIN: u8 = 0; const MAX: u8 = 255; @@ -41,8 +39,7 @@ impl CoordLimits for u8 { } } -impl CoordLimits for u16 { - type Data = u16; +impl CoordinateOp for u16 { const MIN: u16 = u16::MIN; const MAX: u16 = u16::MAX; @@ -51,8 +48,7 @@ impl CoordLimits for u16 { } } -impl CoordLimits for usize { - type Data = usize; +impl CoordinateOp for usize { const MIN: usize = usize::MIN; const MAX: usize = usize::MAX; @@ -61,57 +57,51 @@ impl CoordLimits for usize { } } -impl, S: CoordinateSpace> Coordinates { - pub const fn new(x: T, y: T) -> Self { +impl Coordinates { + pub const fn new(x: S::Data, y: S::Data) -> Self { Self { x, - y, - space: PhantomData, + y } } fn top_left() -> Self { - Self::new(T::MIN, T::MIN) + Self::new(S::Data::MIN, S::Data::MIN) } fn top_right() -> Self { - Self::new(T::MAX, T::MIN) + Self::new(S::Data::MAX, S::Data::MIN) } fn bottom_left() -> Self { - Self::new(T::MIN, T::MAX) + Self::new(S::Data::MIN, S::Data::MAX) } fn bottom_right() -> Self { - Self::new(T::MAX, T::MAX) + Self::new(S::Data::MAX, S::Data::MAX) } - pub fn distance_to(&self, other: &Self) -> T { - T::distance(self.x, other.x, self.y, other.y) + pub fn distance_to(&self, other: &Self) -> S::Data { + S::Data::distance(self.x, other.x, self.y, other.y) } } #[derive(PartialEq, Debug, Copy, Clone)] pub struct Virtual {} -impl CoordinateSpace for Virtual {} - -#[derive(PartialEq, Debug, Copy, Clone)] -pub struct Coord8 { - x: u8, - y: u8, - space: PhantomData +impl CoordinateSpace for Virtual { + type Data = u8; } -pub type VirtualCoordinates = Coordinates; +pub type VirtualCoordinates = Coordinates; #[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd)] -pub struct Rectangle, Space: CoordinateSpace> { - pub top_left: Coordinates, - pub bottom_right: Coordinates +pub struct Rectangle { + pub top_left: Coordinates, + pub bottom_right: Coordinates } -impl + Sub, Space: CoordinateSpace> Rectangle { - pub fn new(top_left: Coordinates, bottom_right: Coordinates) -> Self { +impl Rectangle { + pub fn new(top_left: Coordinates, bottom_right: Coordinates) -> Self { debug_assert!(top_left.x <= bottom_right.x); debug_assert!(top_left.y <= bottom_right.y); Self { @@ -122,32 +112,32 @@ impl + Sub, Space: Co pub fn everything() -> Self { Self { - top_left: Coordinates::::top_left(), - bottom_right: Coordinates::::bottom_right() + top_left: Coordinates::::top_left(), + bottom_right: Coordinates::::bottom_right() } } - pub fn width(&self) -> CoordData { + pub fn width(&self) -> Space::Data { self.bottom_right.x.clone() - self.top_left.x.clone() } - pub fn height(&self) -> CoordData { + pub fn height(&self) -> Space::Data { self.bottom_right.y.clone() - self.top_left.y.clone() } - pub const fn left(&self) -> CoordData { + pub const fn left(&self) -> Space::Data { self.top_left.x } - pub const fn top(&self) -> CoordData { + pub const fn top(&self) -> Space::Data { self.top_left.y } - pub const fn right (&self) -> CoordData { + pub const fn right (&self) -> Space::Data { self.bottom_right.x } - pub const fn bottom(&self) -> CoordData { + pub const fn bottom(&self) -> Space::Data { self.bottom_right.y } } diff --git a/src/mappings.rs b/src/mappings.rs index 30708f6..28b689a 100644 --- a/src/mappings.rs +++ b/src/mappings.rs @@ -7,20 +7,22 @@ use std::fmt::{Formatter, Debug}; use ansi_term::Color; use rgb::Rgb; -pub trait CoordinateView, Space: CoordinateSpace>: Debug { - fn next(&mut self) -> Option<(Coordinates, Coordinates)>; +pub trait CoordinateView: Debug { + type Space: CoordinateSpace; + fn next(&mut self) -> Option<(Coordinates, Coordinates)>; } -pub trait PixelMapping, Space: CoordinateSpace> { - fn select(&self, rect: &Rectangle) -> impl CoordinateView; - fn to_idx(&self, coords: &Coordinates) -> usize; +pub trait PixelMapping { + type Space: CoordinateSpace; + fn select(&self, rect: &Rectangle) -> impl CoordinateView; + fn to_idx(&self, coords: &Coordinates) -> usize; } -pub trait DisplayDump, CoordData: CoordLimits, Space: CoordinateSpace> { +pub trait DisplayDump { fn dump(&self, map: &T); } -impl DisplayDump for [Rgb; PIXEL_NUM] { +impl DisplayDump for [Rgb; PIXEL_NUM] { fn dump(&self, _map: &LinearPixelMapping) { for ref pixel in self { print!("{}", Color::RGB(pixel.r, pixel.g, pixel.b).paint("█")); @@ -29,7 +31,7 @@ impl DisplayDump } } -impl DisplayDump for [Rgb; PIXEL_NUM] { +impl DisplayDump for [Rgb; PIXEL_NUM] { fn dump(&self, map: &StrideMapping) { for y in 0..map.stride_count { let stride = &map.strides[y]; @@ -55,15 +57,19 @@ impl DisplayDump for [Rg #[derive(Debug)] struct LinearCoordView { - rect: Rectangle, + rect: Rectangle, idx: usize, } pub struct LinearSpace {} -impl CoordinateSpace for LinearSpace {} -pub type LinearCoords = Coordinates; +impl CoordinateSpace for LinearSpace { + type Data = usize; +} -impl CoordinateView for LinearCoordView { +pub type LinearCoords = Coordinates; + +impl CoordinateView for LinearCoordView { + type Space = LinearSpace; fn next(&mut self) -> Option<(VirtualCoordinates, LinearCoords)> { if self.idx as u8 == self.rect.bottom_right.x { None @@ -88,15 +94,16 @@ impl LinearPixelMapping { } } -impl PixelMapping for LinearPixelMapping { - fn select(&self, rect: &Rectangle) -> impl CoordinateView { +impl PixelMapping for LinearPixelMapping { + type Space = LinearSpace; + fn select(&self, rect: &Rectangle) -> impl CoordinateView { LinearCoordView { rect: rect.clone(), idx: 0, } } - fn to_idx(&self, coords: &Coordinates) -> usize { + fn to_idx(&self, coords: &Coordinates) -> usize { coords.x } } @@ -125,7 +132,7 @@ pub struct StrideMapping { pub strides: [Stride; STRIDE_NUM], pub stride_count: usize, pub pixel_count: usize, - pub size: Rectangle + pub size: Rectangle } impl StrideMapping { @@ -183,7 +190,7 @@ impl StrideMapping { let mut strides = [Stride::default(); STRIDE_NUM]; let stride_count = stride_json.len(); let mut physical_idx = 0; - let mut size: Option> = None;//Rectangle::new(Coordinates::new(usize::MAX, usize::MAX), Coordinates::new(0, 0)); + let mut size: Option> = None;//Rectangle::new(Coordinates::new(usize::MAX, usize::MAX), Coordinates::new(0, 0)); for stride_idx in 0..stride_count { let json_data = stride_json[stride_idx]; let x = json_data.0; @@ -230,24 +237,27 @@ impl StrideMapping { } } -impl PixelMapping for StrideMapping { - fn select(&self, rect: &Rectangle) -> impl CoordinateView { +impl PixelMapping for StrideMapping { + type Space = StrideSpace; + fn select(&self, rect: &Rectangle) -> impl CoordinateView { StrideView::new(self, rect) } - fn to_idx(&self, coords: &Coordinates) -> usize { + fn to_idx(&self, coords: &Coordinates) -> usize { self.strides[coords.x as usize].pixel_idx_for_offset(coords.y) } } #[derive(Debug, Clone, Copy)] pub struct StrideSpace {} -impl CoordinateSpace for StrideSpace {} -pub type StrideCoords = Coordinates; +impl CoordinateSpace for StrideSpace { + type Data = u8; +} +pub type StrideCoords = Coordinates; struct StrideView<'a> { map: &'a StrideMapping, - range: Rectangle, + range: Rectangle, cur: StrideCoords, step_size: VirtualCoordinates } @@ -262,9 +272,9 @@ impl<'a> Debug for StrideView<'a> { } impl<'a> StrideView<'a> { - fn new(map: &'a StrideMapping, rect: &Rectangle) -> Self { + fn new(map: &'a StrideMapping, rect: &Rectangle) -> Self { // Zero-index shape of the pixel picking area - let range: Rectangle = Rectangle::new( + let range: Rectangle = Rectangle::new( Coordinates::new( scale8(map.size.width() as u8, rect.top_left.x) + map.size.left() as u8, scale8(map.size.height() as u8, rect.top_left.y) + map.size.top() as u8 @@ -300,7 +310,8 @@ impl<'a> StrideView<'a> { } } -impl<'a> CoordinateView for StrideView<'a> { +impl<'a> CoordinateView for StrideView<'a> { + type Space = StrideSpace; fn next(&mut self) -> Option<(VirtualCoordinates, StrideCoords)> { // Keep scanning until we reach the far right of the range while self.cur.x <= self.range.bottom_right.x { diff --git a/src/platform/smart_leds_lib.rs b/src/platform/smart_leds_lib.rs index e584a07..6086f50 100644 --- a/src/platform/smart_leds_lib.rs +++ b/src/platform/smart_leds_lib.rs @@ -17,13 +17,15 @@ use std::ops::IndexMut; pub trait HardwarePixel: Send + Sync + Rgb8Blend + Copy + AsMilliwatts + Default + From> + Fract8Ops {} impl HardwarePixel for T where T: Send + Sync + Rgb8Blend + Copy + AsMilliwatts + Default + From> + Fract8Ops {} -pub trait Pixbuf: AsMilliwatts + IndexMut { +pub trait Pixbuf: AsMilliwatts + IndexMut { + type Pixel: HardwarePixel; fn new() -> Self; fn blank(&mut self); - fn iter_with_brightness(&self, brightness: u8) -> impl Iterator + Send; + fn iter_with_brightness(&self, brightness: u8) -> impl Iterator + Send; } -impl Pixbuf for [T; PIXEL_NUM] { +impl Pixbuf for [T; PIXEL_NUM] { + type Pixel = T; fn new() -> Self { [T::default(); PIXEL_NUM] } @@ -37,7 +39,7 @@ impl Pixbuf for [T; PIXEL_NUM] { } } -struct SmartLedDisplay> { +struct SmartLedDisplay> { surfaces : Option>, pixmap: StrideMapping, target: T, @@ -46,7 +48,7 @@ struct SmartLedDisplay> { frame: usize } -impl> Debug for SmartLedDisplay { +impl> Debug for SmartLedDisplay { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { f.debug_struct("SmartLedDisplay") .field("total_mw", &self.pixbuf.as_milliwatts()) @@ -55,7 +57,7 @@ impl> Debug for SmartLedDisplay> SmartLedDisplay { +impl> SmartLedDisplay { fn new(target: T, max_mw: u32, pixmap: StrideMapping, pixbuf: P) -> Self { SmartLedDisplay { pixbuf, @@ -68,20 +70,11 @@ impl> SmartLedDisplay { } } -impl AsMilliwatts for SmartLedDisplay where -T: FastWrite, -S: Surface, -P: Pixbuf { - fn as_milliwatts(&self) -> u32 { - self.pixbuf.as_milliwatts() - } -} - impl Surfaces for SmartLedDisplay where T: FastWrite, S: Surface, -P: Pixbuf { - fn new_surface(&mut self, area: &Rectangle) -> Result { +P: Pixbuf { + fn new_surface(&mut self, area: &Rectangle) -> Result { if let Some(ref mut s) = self.surfaces { s.new_surface(area) } else { @@ -93,7 +86,7 @@ P: Pixbuf { impl Display for SmartLedDisplay where T: FastWrite, S: Surface, -P: Pixbuf { +P: Pixbuf { fn render_frame(&mut self) { let surfaces = self.surfaces.take().unwrap(); for surface in surfaces.iter() { @@ -126,7 +119,7 @@ trait FastWrite { impl Framed for SmartLedDisplay where T: FastWrite, S: Surface, -P: Pixbuf { +P: Pixbuf { fn start_frame(&mut self) { self.pixbuf.blank(); diff --git a/src/render.rs b/src/render.rs index 03674f6..7b03530 100644 --- a/src/render.rs +++ b/src/render.rs @@ -13,7 +13,7 @@ pub trait Shader: Send + Debug { } pub trait Surfaces: Debug { - fn new_surface(&mut self, area: &Rectangle) -> Result; + fn new_surface(&mut self, area: &Rectangle) -> Result; } pub trait Surface: Default + Clone + Debug { @@ -21,8 +21,8 @@ pub trait Surface: Default + Clone + Debug { fn set_shader(&mut self, shader: Box); fn clear_shader(&mut self); - fn rect(&self) -> Rectangle; - fn set_rect(&mut self, rect: &Rectangle); + fn rect(&self) -> Rectangle; + fn set_rect(&mut self, rect: &Rectangle); fn opacity(&self) -> u8; fn set_opacity(&mut self, opacity: u8); }