1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
use core::{
    marker::PhantomData,
    ops::{Deref, DerefMut, Index, IndexMut},
};

/// Point type.
pub type Point = mint::Point2<u32>;
/// Size type.
pub type Size = mint::Vector2<u32>;

/// Quickly construct a `Point`.
#[inline]
pub const fn point(x: u32, y: u32) -> Point {
    Point { x, y }
}

/// Quickly construct a `Size`.
#[inline]
pub const fn size(x: u32, y: u32) -> Size {
    Size { x, y }
}

/// 2D immutable surface trait.
pub trait Surface<T> {
    /// Surface size.
    fn surface_size(&self) -> Size;

    /// Get a value at (pt.x, pt.y).
    fn surface_get(&self, pt: Point) -> Option<&T>;
}

/// 2D mutable surface trait.
pub trait SurfaceMut<T>: Surface<T> {
    /// Get a mutable value at (pt.x, pt.y).
    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut T>;
}

/// Generic surface with width and height.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GenericSurface<Slice, Item> {
    slice: Slice,
    size: Size,
    ghost: PhantomData<Item>,
}

impl<Slice, Item> GenericSurface<Slice, Item>
where
    Slice: AsRef<[Item]>,
{
    /// Construct a new surface.
    ///
    /// Returns `None` if `slice.len() != size.x * size.y`.
    #[inline]
    pub fn new(slice: Slice, size: Size) -> Option<Self> {
        if slice.as_ref().len() == (size.x * size.y) as _ {
            Some(Self {
                slice,
                size,
                ghost: PhantomData,
            })
        } else {
            None
        }
    }

    /// Constructs a new surface.
    ///
    /// Infers the height from slice length and width.
    #[inline]
    pub fn new_infer(slice: Slice, width: u32) -> Self {
        Self {
            size: size(width, slice.as_ref().len() as u32 / width),
            slice,
            ghost: PhantomData,
        }
    }
}

impl<Slice, Item> Deref for GenericSurface<Slice, Item>
where
    Slice: AsRef<[Item]>,
{
    type Target = [Item];

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.slice.as_ref()
    }
}

impl<Slice, Item> DerefMut for GenericSurface<Slice, Item>
where
    Slice: AsRef<[Item]> + AsMut<[Item]>,
{
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.slice.as_mut()
    }
}

impl<Slice, Item> Surface<Item> for GenericSurface<Slice, Item>
where
    Slice: AsRef<[Item]>,
{
    #[inline]
    fn surface_size(&self) -> Size {
        self.size
    }

    #[inline]
    fn surface_get(&self, pt: Point) -> Option<&Item> {
        if pt.x < self.size.x && pt.y < self.size.y {
            Some(
                self.slice
                    .as_ref()
                    .index((pt.y * self.size.x + pt.x) as usize),
            )
        } else {
            None
        }
    }
}

impl<Slice, Item> SurfaceMut<Item> for GenericSurface<Slice, Item>
where
    Slice: AsRef<[Item]> + AsMut<[Item]>,
{
    #[inline]
    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut Item> {
        if pt.x < self.size.x && pt.y < self.size.y {
            Some(
                self.slice
                    .as_mut()
                    .index_mut((pt.y * self.size.x + pt.x) as usize),
            )
        } else {
            None
        }
    }
}

/// A 'surface' that holds a single value, like a plain-colored rectangle.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SingleValueSurface<T> {
    /// Surface size.
    pub size: Size,
    /// Stored value, likely a color.
    pub value: T,
}

impl<T> SingleValueSurface<T> {
    /// Construct a new surface.
    #[inline]
    pub const fn new(value: T, size: Size) -> Self {
        Self { size, value }
    }
}

impl<T> Surface<T> for SingleValueSurface<T> {
    #[inline]
    fn surface_size(&self) -> Size {
        self.size
    }

    #[inline]
    fn surface_get(&self, _pt: Point) -> Option<&T> {
        Some(&self.value)
    }
}

impl<T> SurfaceMut<T> for SingleValueSurface<T> {
    #[inline]
    fn surface_get_mut(&mut self, _pt: Point) -> Option<&mut T> {
        Some(&mut self.value)
    }
}