1#[derive(Clone, Debug)]
2pub struct Cursor<'a, T: Copy + Default> {
4 index: usize,
5 collection: &'a [T],
6}
7
8impl<T: Copy + Default> core::fmt::Display for Cursor<'_, T> {
9 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10 write!(f, "index {} of {}", self.index, self.collection.len())
11 }
12}
13
14impl<'a, T: Copy + Default> Cursor<'a, T> {
15 pub fn read(&mut self, buffer: &mut [T]) -> usize {
26 let item_count = buffer.len().min(self.collection.len() - self.index);
27 if item_count == 0 {
28 return 0;
29 }
30 let data = self
31 .read_count(item_count)
32 .expect("read should never read out of bounds");
33 buffer
34 .get_mut(..item_count)
35 .expect("read should never read out of bounds")
36 .copy_from_slice(data);
37 item_count
38 }
39
40 pub fn read_array<const N: usize>(&mut self) -> Result<[T; N], OutOfBounds> {
42 let mut output = [T::default(); N];
43 let data = self.read_count(N)?;
44 output.copy_from_slice(data);
45 Ok(output)
46 }
47
48 pub fn read_count<N: Into<usize>>(&mut self, count: N) -> Result<&[T], OutOfBounds> {
50 let count = count.into();
51 let data = self
52 .collection
53 .get(self.index..self.index + count)
54 .ok_or_else(|| OutOfBounds::new(count))?;
55 self.index += count;
56
57 Ok(data)
58 }
59}
60
61impl std::io::Read for Cursor<'_, u8> {
62 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
63 Ok(self.read(buf))
64 }
65}
66
67#[derive(Clone, Copy, Debug)]
69#[non_exhaustive]
70pub struct OutOfBounds {
71 requested: usize,
72}
73impl OutOfBounds {
74 fn new(requested: usize) -> Self {
75 Self { requested }
76 }
77}
78impl core::fmt::Display for OutOfBounds {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 write!(
81 f,
82 "reading {} bytes would take the cursor out of bounds",
83 self.requested,
84 )
85 }
86}
87impl core::error::Error for OutOfBounds {}