1use crate::{Error, Result};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub enum ByteOrder {
13 Little,
14 Big,
15}
16
17impl ByteOrder {
18 #[inline(always)]
19 pub fn u16(self, b: [u8; 2]) -> u16 {
20 match self {
21 ByteOrder::Little => u16::from_le_bytes(b),
22 ByteOrder::Big => u16::from_be_bytes(b),
23 }
24 }
25 #[inline(always)]
26 pub fn u32(self, b: [u8; 4]) -> u32 {
27 match self {
28 ByteOrder::Little => u32::from_le_bytes(b),
29 ByteOrder::Big => u32::from_be_bytes(b),
30 }
31 }
32 #[inline(always)]
33 pub fn u64(self, b: [u8; 8]) -> u64 {
34 match self {
35 ByteOrder::Little => u64::from_le_bytes(b),
36 ByteOrder::Big => u64::from_be_bytes(b),
37 }
38 }
39}
40
41#[inline]
43pub fn slice_at(data: &[u8], offset: usize, len: usize) -> Result<&[u8]> {
44 offset.checked_add(len).and_then(|end| data.get(offset..end)).ok_or_else(|| {
45 Error::corrupt_at(format!("range of {len} bytes exceeds file size {}", data.len()), offset as u64)
46 })
47}
48
49#[inline]
53pub fn slice_at_lenient(data: &[u8], offset: usize, len: usize) -> Result<&[u8]> {
54 if offset >= data.len() {
55 return Err(Error::corrupt_at("payload offset beyond end of file", offset as u64));
56 }
57 let end = offset.saturating_add(len).min(data.len());
58 Ok(&data[offset..end])
59}
60
61#[inline(always)]
62fn arr<const N: usize>(data: &[u8], offset: usize) -> Result<[u8; N]> {
63 match offset.checked_add(N).and_then(|end| data.get(offset..end)) {
64 Some(s) => {
65 let mut a = [0u8; N];
66 a.copy_from_slice(s);
67 Ok(a)
68 }
69 None => Err(Error::corrupt_at("read beyond end of data", offset as u64)),
70 }
71}
72
73pub trait ReadAt {
75 fn u8_at(&self, offset: usize) -> Result<u8>;
76 fn u16_at(&self, order: ByteOrder, offset: usize) -> Result<u16>;
77 fn u32_at(&self, order: ByteOrder, offset: usize) -> Result<u32>;
78 fn u64_at(&self, order: ByteOrder, offset: usize) -> Result<u64>;
79 fn u16le(&self, offset: usize) -> Result<u16> {
80 self.u16_at(ByteOrder::Little, offset)
81 }
82 fn u16be(&self, offset: usize) -> Result<u16> {
83 self.u16_at(ByteOrder::Big, offset)
84 }
85 fn u32le(&self, offset: usize) -> Result<u32> {
86 self.u32_at(ByteOrder::Little, offset)
87 }
88 fn u32be(&self, offset: usize) -> Result<u32> {
89 self.u32_at(ByteOrder::Big, offset)
90 }
91}
92
93impl ReadAt for [u8] {
94 #[inline]
95 fn u8_at(&self, offset: usize) -> Result<u8> {
96 self.get(offset).copied().ok_or_else(|| Error::corrupt_at("read beyond end of data", offset as u64))
97 }
98 #[inline]
99 fn u16_at(&self, order: ByteOrder, offset: usize) -> Result<u16> {
100 Ok(order.u16(arr(self, offset)?))
101 }
102 #[inline]
103 fn u32_at(&self, order: ByteOrder, offset: usize) -> Result<u32> {
104 Ok(order.u32(arr(self, offset)?))
105 }
106 #[inline]
107 fn u64_at(&self, order: ByteOrder, offset: usize) -> Result<u64> {
108 Ok(order.u64(arr(self, offset)?))
109 }
110}
111
112#[derive(Debug, Clone)]
114pub struct Cursor<'a> {
115 data: &'a [u8],
116 pos: usize,
117 order: ByteOrder,
118}
119
120impl<'a> Cursor<'a> {
121 pub fn new(data: &'a [u8], order: ByteOrder) -> Self {
122 Cursor { data, pos: 0, order }
123 }
124 pub fn at(data: &'a [u8], pos: usize, order: ByteOrder) -> Self {
125 Cursor { data, pos, order }
126 }
127 #[inline]
128 pub fn data(&self) -> &'a [u8] {
129 self.data
130 }
131 #[inline]
132 pub fn pos(&self) -> usize {
133 self.pos
134 }
135 #[inline]
136 pub fn order(&self) -> ByteOrder {
137 self.order
138 }
139 pub fn set_order(&mut self, order: ByteOrder) {
140 self.order = order;
141 }
142 pub fn seek(&mut self, pos: usize) {
143 self.pos = pos;
144 }
145 #[inline]
146 pub fn remaining(&self) -> usize {
147 self.data.len().saturating_sub(self.pos)
148 }
149 pub fn skip(&mut self, n: usize) -> Result<()> {
150 let np = self.pos.checked_add(n).ok_or_else(|| Error::corrupt("cursor overflow"))?;
151 if np > self.data.len() {
152 return Err(Error::corrupt_at("skip beyond end of data", self.pos as u64));
153 }
154 self.pos = np;
155 Ok(())
156 }
157 #[inline]
158 pub fn bytes(&mut self, n: usize) -> Result<&'a [u8]> {
159 let s = slice_at(self.data, self.pos, n)?;
160 self.pos += n;
161 Ok(s)
162 }
163 #[inline]
164 pub fn u8(&mut self) -> Result<u8> {
165 let v = self.data.u8_at(self.pos)?;
166 self.pos += 1;
167 Ok(v)
168 }
169 #[inline]
170 pub fn u16(&mut self) -> Result<u16> {
171 let v = self.data.u16_at(self.order, self.pos)?;
172 self.pos += 2;
173 Ok(v)
174 }
175 #[inline]
176 pub fn u32(&mut self) -> Result<u32> {
177 let v = self.data.u32_at(self.order, self.pos)?;
178 self.pos += 4;
179 Ok(v)
180 }
181 #[inline]
182 pub fn u64(&mut self) -> Result<u64> {
183 let v = self.data.u64_at(self.order, self.pos)?;
184 self.pos += 8;
185 Ok(v)
186 }
187 #[inline]
188 pub fn i16(&mut self) -> Result<i16> {
189 Ok(self.u16()? as i16)
190 }
191 #[inline]
192 pub fn i32(&mut self) -> Result<i32> {
193 Ok(self.u32()? as i32)
194 }
195 pub fn u16be(&mut self) -> Result<u16> {
196 let v = self.data.u16be(self.pos)?;
197 self.pos += 2;
198 Ok(v)
199 }
200 pub fn u32be(&mut self) -> Result<u32> {
201 let v = self.data.u32be(self.pos)?;
202 self.pos += 4;
203 Ok(v)
204 }
205}
206
207pub fn ascii_field(bytes: &[u8]) -> String {
209 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
210 let s: String = bytes[..end].iter().map(|&b| if b.is_ascii() && b >= 0x20 { b as char } else { ' ' }).collect();
211 s.trim().to_string()
212}
213
214pub fn find(hay: &[u8], needle: &[u8]) -> Option<usize> {
216 if needle.is_empty() || hay.len() < needle.len() {
217 return None;
218 }
219 hay.windows(needle.len()).position(|w| w == needle)
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn checked_reads() {
228 let d = [1u8, 2, 3, 4];
229 assert_eq!(d.u16le(0).unwrap(), 0x0201);
230 assert_eq!(d.u16be(2).unwrap(), 0x0304);
231 assert_eq!(d.u32be(0).unwrap(), 0x01020304);
232 assert!(d.u32le(1).is_err());
233 assert!(d.u16le(usize::MAX).is_err());
234 assert!(slice_at(&d, usize::MAX - 1, 4).is_err());
235 assert_eq!(slice_at_lenient(&d, 2, 100).unwrap(), &[3, 4]);
236 }
237
238 #[test]
239 fn cursor() {
240 let d = [0u8, 1, 0, 0, 0, 2];
241 let mut c = Cursor::new(&d, ByteOrder::Big);
242 assert_eq!(c.u16().unwrap(), 1);
243 assert_eq!(c.u32().unwrap(), 2);
244 assert!(c.u8().is_err());
245 }
246
247 #[test]
248 fn ascii() {
249 assert_eq!(ascii_field(b"NIKON \0garbage"), "NIKON");
250 }
251}