1#[derive(Clone, Debug)]
4pub struct Cursor<'a, T: Copy + Default> {
6 index: usize,
8 collection: &'a [T],
10}
11
12impl<T: Copy + Default> core::fmt::Display for Cursor<'_, T> {
13 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14 write!(f, "index {} of {}", self.index, self.collection.len())
15 }
16}
17
18impl<'a, T: Copy + Default> Cursor<'a, T> {
19 pub fn new(collection: &'a [T]) -> Self {
21 Self {
22 index: 0,
23 collection,
24 }
25 }
26
27 pub fn remaining(&self) -> &[T] {
32 self.collection
33 .get(self.index..)
34 .expect("index should never be out of bounds")
35 }
36
37 pub fn read(&mut self, buffer: &mut [T]) -> usize {
48 let item_count = buffer.len().min(self.collection.len() - self.index);
49 if item_count == 0 {
50 return 0;
51 }
52 let data = self
53 .read_count(item_count)
54 .expect("read should never read out of bounds");
55 buffer
56 .get_mut(..item_count)
57 .expect("read should never read out of bounds")
58 .copy_from_slice(data);
59 item_count
60 }
61
62 pub fn read_array<const N: usize>(&mut self) -> Result<[T; N], OutOfBounds> {
64 let mut output = [T::default(); N];
65 let data = self.read_count(N)?;
66 output.copy_from_slice(data);
67 Ok(output)
68 }
69
70 pub fn read_count<N: Into<usize>>(&mut self, count: N) -> Result<&[T], OutOfBounds> {
72 let count = count.into();
73 let data = self
74 .collection
75 .get(self.index..self.index + count)
76 .ok_or_else(|| OutOfBounds::new(count))?;
77 self.index += count;
78
79 Ok(data)
80 }
81}
82
83impl std::io::Read for Cursor<'_, u8> {
84 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
85 Ok(self.read(buf))
86 }
87}
88
89#[derive(Clone, Copy, Debug)]
91#[non_exhaustive]
92pub struct OutOfBounds {
93 requested: usize,
95}
96impl OutOfBounds {
97 fn new(requested: usize) -> Self {
99 Self { requested }
100 }
101}
102impl core::fmt::Display for OutOfBounds {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 write!(
105 f,
106 "reading {} items would take the cursor out of bounds",
107 self.requested,
108 )
109 }
110}
111impl core::error::Error for OutOfBounds {}