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 read(&mut self, buffer: &mut [T]) -> usize {
30 let item_count = buffer.len().min(self.collection.len() - self.index);
31 if item_count == 0 {
32 return 0;
33 }
34 let data = self
35 .read_count(item_count)
36 .expect("read should never read out of bounds");
37 buffer
38 .get_mut(..item_count)
39 .expect("read should never read out of bounds")
40 .copy_from_slice(data);
41 item_count
42 }
43
44 pub fn read_array<const N: usize>(&mut self) -> Result<[T; N], OutOfBounds> {
46 let mut output = [T::default(); N];
47 let data = self.read_count(N)?;
48 output.copy_from_slice(data);
49 Ok(output)
50 }
51
52 pub fn read_count<N: Into<usize>>(&mut self, count: N) -> Result<&[T], OutOfBounds> {
54 let count = count.into();
55 let data = self
56 .collection
57 .get(self.index..self.index + count)
58 .ok_or_else(|| OutOfBounds::new(count))?;
59 self.index += count;
60
61 Ok(data)
62 }
63}
64
65impl std::io::Read for Cursor<'_, u8> {
66 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
67 Ok(self.read(buf))
68 }
69}
70
71#[derive(Clone, Copy, Debug)]
73#[non_exhaustive]
74pub struct OutOfBounds {
75 requested: usize,
77}
78impl OutOfBounds {
79 fn new(requested: usize) -> Self {
81 Self { requested }
82 }
83}
84impl core::fmt::Display for OutOfBounds {
85 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
86 write!(
87 f,
88 "reading {} items would take the cursor out of bounds",
89 self.requested,
90 )
91 }
92}
93impl core::error::Error for OutOfBounds {}