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
#[cfg(feature = "alloc")]
extern crate alloc;
use crate::{buf::GridBuf, ops::layout};
use core::marker::PhantomData;
impl<T, B, L> GridBuf<T, B, L>
where
B: AsRef<[T]>,
L: layout::Linear,
{
/// Returns a grid from an existing buffer with a given width in columns.
///
/// The height is inferred from the buffer length and width.
///
/// Any data type that can be represented as a slice can be used as the buffer type, including
/// arrays, slices, and vectors.
///
/// ## Panics
///
/// This panics if the buffer length is not a multiple of the width.
///
/// ## Example
///
/// ```rust
/// use grixy::prelude::*;
///
/// let buffer = vec![1, 2, 3, 4, 5, 6];
/// let grid = GridBuf::<_, _, RowMajor>::from_buffer(buffer, 3);
///
/// assert_eq!(grid.get(Pos::new(0, 0)), Some(&1));
/// assert_eq!(grid.get(Pos::new(1, 0)), Some(&2));
/// assert_eq!(grid.get(Pos::new(2, 1)), Some(&6));
/// assert_eq!(grid.get(Pos::new(3, 1)), None); // Out of bounds
/// ```
#[must_use]
pub fn from_buffer(buffer: B, width: usize) -> Self {
let height = buffer.as_ref().len() / width;
assert!(
height * width == buffer.as_ref().len(),
"Buffer length must be a multiple of width"
);
Self {
buffer,
width,
height,
_layout: PhantomData,
_element: PhantomData,
}
}
}
#[cfg(feature = "alloc")]
impl<T> GridBuf<T, alloc::vec::Vec<T>, layout::RowMajor> {
/// Creates a new grid with the specified width and height, filled with a default value.
///
/// This creates a grid with a row-major layout; see [`new_filled_with_layout`][] to customize.
///
/// [`new_filled_with_layout`]: GridBuf::new_filled_with_layout
///
/// ## Example
///
/// ```rust
/// use grixy::prelude::*;
///
/// let grid = GridBuf::<u8, _, _>::new(3, 3);
/// assert_eq!(grid.get(Pos::new(0, 0)), Some(&0));
/// assert_eq!(grid.get(Pos::new(2, 2)), Some(&0));
/// assert_eq!(grid.get(Pos::new(3, 3)), None); // Out of bounds
/// ```
#[must_use]
pub fn new(width: usize, height: usize) -> Self
where
T: Copy + Default,
{
Self::new_filled(width, height, T::default())
}
/// Creates a new grid with the specified width and height, filled with a specified value.
///
/// This creates a grid with a row-major layout; see [`new_filled_with_layout`][] to customize.
///
/// [`new_filled_with_layout`]: GridBuf::new_filled_with_layout
///
/// ## Example
///
/// ```rust
/// use grixy::prelude::*;
///
/// let grid = GridBuf::new_filled(5, 4, 42);
///
/// assert_eq!(grid.get(Pos::new(0, 0)), Some(&42));
/// assert_eq!(grid.get(Pos::new(4, 3)), Some(&42));
/// assert_eq!(grid.get(Pos::new(5, 3)), None); // Out of bounds
/// ```
#[must_use]
pub fn new_filled(width: usize, height: usize, value: T) -> Self
where
T: Copy,
{
let buffer = alloc::vec![value; width * height];
Self {
buffer,
width,
height,
_layout: PhantomData,
_element: PhantomData,
}
}
}
#[cfg(feature = "alloc")]
impl<T, L> GridBuf<T, alloc::vec::Vec<T>, L>
where
L: layout::Linear,
{
/// Creates a new grid with the specified width and height, filled with a default value.
///
/// The layout is specified by the type parameter `L`, allowing for different memory layouts.
///
/// ## Example
#[must_use]
pub fn new_filled_with_layout(width: usize, height: usize, value: T) -> Self
where
T: Copy,
L: layout::Linear,
{
let buffer = alloc::vec![value; width * height];
Self {
buffer,
width,
height,
_layout: PhantomData,
_element: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
extern crate alloc;
use super::*;
use crate::{core::Pos, ops::GridRead as _, ops::layout::RowMajor};
use alloc::vec;
#[test]
#[should_panic(expected = "Buffer length must be a multiple of width")]
fn test_from_buffer_panics_on_invalid_length() {
let buffer = vec![1, 2, 3];
let _grid = GridBuf::<_, _, RowMajor>::from_buffer(buffer, 2);
}
#[test]
fn new_filled_with_layout() {
let grid = GridBuf::<_, _, RowMajor>::new_filled_with_layout(3, 2, 42);
assert_eq!(grid.get(Pos::new(0, 0)), Some(&42));
assert_eq!(grid.get(Pos::new(2, 1)), Some(&42));
assert_eq!(grid.get(Pos::new(3, 1)), None); // Out of bounds
}
}