1use std::io::{Cursor, Seek};
2use std::slice::SliceIndex;
3use std::sync::Arc;
4
5use crate::math::*;
6
7pub trait GetExt<T> {
8 fn e_get<I: SliceIndex<[T]>>(
9 &self,
10 index: I,
11 ) -> Result<&<I as SliceIndex<[T]>>::Output, ReadError>;
12
13 fn e_get_mut<I: SliceIndex<[T]>>(
14 &mut self,
15 index: I,
16 ) -> Result<&mut <I as SliceIndex<[T]>>::Output, ReadError>;
17}
18
19impl<T> GetExt<T> for [T] {
20 fn e_get<I: SliceIndex<[T]>>(
21 &self,
22 index: I,
23 ) -> Result<&<I as SliceIndex<[T]>>::Output, ReadError> {
24 self.get(index).ok_or(ReadError::InvalidIndex)
25 }
26
27 fn e_get_mut<I: SliceIndex<[T]>>(
28 &mut self,
29 index: I,
30 ) -> Result<&mut <I as SliceIndex<[T]>>::Output, ReadError> {
31 self.get_mut(index).ok_or(ReadError::InvalidIndex)
32 }
33}
34
35pub trait ReadExt: std::io::BufRead + std::io::Seek {
36 fn read_array<const T: usize>(&mut self) -> Result<[u8; T], ReadError> {
37 let buf = &mut [0; T];
38 self.read_exact(buf)?;
39 Ok(*buf)
40 }
41
42 fn read_byte(&mut self) -> Result<u8, ReadError> {
43 let buf = &mut [0; 1];
44 self.read_exact(buf)?;
45 Ok(buf[0])
46 }
47}
48
49impl<T: AsRef<[u8]>> ReadExt for Cursor<T> {}
50
51pub trait SliceExt<'a>: std::io::BufRead + std::io::Seek {
52 fn slice_until(&mut self, byte: u8) -> Result<&'a [u8], ReadError>;
53 fn slice_to_end(&mut self) -> Result<&'a [u8], ReadError>;
54}
55
56impl<'a> SliceExt<'a> for Cursor<&'a [u8]> {
57 fn slice_until(&mut self, byte: u8) -> Result<&'a [u8], ReadError> {
68 let start = self.position().usize()?;
69 let len = self
70 .get_ref()
71 .iter()
72 .skip(start)
73 .take_while(|x| **x != byte)
74 .count();
75 let end = start.safe_add(len)?;
76
77 self.seek_relative(len.safe_add(1)?.i64()?)?;
78
79 Ok(self.get_ref().get(start..end).unwrap())
80 }
81
82 fn slice_to_end(&mut self) -> Result<&'a [u8], ReadError> {
92 let start = self.position().usize()?;
93 let end = self.get_ref().len();
94
95 self.seek(std::io::SeekFrom::Start(end.u64()?))?;
96
97 Ok(self.get_ref().get(start..end).unwrap())
98 }
99}
100
101#[derive(Debug, thiserror::Error, Clone)]
102pub enum ReadError {
103 #[error("Math: {0}")]
104 Math(#[from] MathError),
105 #[error("IO: {0}")]
106 Io(#[from] Arc<std::io::Error>),
107 #[error("Invalid index")]
108 InvalidIndex,
109}
110
111impl From<std::io::Error> for ReadError {
112 fn from(value: std::io::Error) -> Self {
113 Arc::new(value).into()
114 }
115}