1use core::convert::TryInto;
2
3pub struct StreamSliceU8<'a>(&'a [u8]);
4pub struct StreamSliceU16<'a>(&'a [u8]);
5pub struct StreamSliceU32<'a>(&'a [u8]);
6impl<'a> StreamSliceU8<'a> {
7 #[inline]
8 pub fn get(&self, index: usize) -> Option<u8> {
9 const SIZE: usize = 1;
10 let offset: usize = index * SIZE;
11 let slice: &[u8] = self.0.get(index:offset..offset + SIZE)?;
12 Some(slice[0])
13 }
14}
15impl<'a> StreamSliceU16<'a> {
16 #[inline]
17 pub fn get(&self, index: usize) -> Option<u16> {
18 const SIZE: usize = 2;
19 let offset: usize = index * SIZE;
20 let slice: &[u8] = self.0.get(index:offset..offset + SIZE)?;
21 Some(u16::from_be_bytes(slice.try_into().unwrap()))
22 }
23}
24impl<'a> StreamSliceU32<'a> {
25 #[inline]
26 pub fn get(&self, index: usize) -> Option<u32> {
27 const SIZE: usize = 4;
28 let offset: usize = index * SIZE;
29 let slice: &[u8] = self.0.get(index:offset..offset + SIZE)?;
30 Some(u32::from_be_bytes(slice.try_into().unwrap()))
31 }
32}
33
34pub struct StreamSliceI8<'a>(StreamSliceU8<'a>);
35pub struct StreamSliceI16<'a>(StreamSliceU16<'a>);
36pub struct StreamSliceI32<'a>(StreamSliceU32<'a>);
37impl<'a> StreamSliceI8<'a> {
38 #[inline]
39 pub fn get(&self, index: usize) -> Option<i8> {
40 Some(unsafe { core::mem::transmute(self.0.get(index)?) })
41 }
42}
43impl<'a> StreamSliceI16<'a> {
44 #[inline]
45 pub fn get(&self, index: usize) -> Option<i16> {
46 Some(unsafe { core::mem::transmute(self.0.get(index)?) })
47 }
48}
49impl<'a> StreamSliceI32<'a> {
50 #[inline]
51 pub fn get(&self, index: usize) -> Option<i32> {
52 Some(unsafe { core::mem::transmute(self.0.get(index)?) })
53 }
54}
55
56pub struct Stream<'a> {
57 bytes: &'a [u8],
58 offset: usize,
59}
60
61impl<'a> Stream<'a> {
62 pub const fn new(bytes: &'a [u8]) -> Stream<'a> {
63 Stream {
64 bytes,
65 offset: 0,
66 }
67 }
68
69 // UTILITY
70
71 #[inline]
72 pub fn reset(&mut self) {
73 self.offset = 0;
74 }
75
76 #[inline]
77 pub const fn offset(&self) -> usize {
78 self.offset
79 }
80
81 #[inline]
82 pub fn seek(&mut self, offset: usize) {
83 self.offset = offset;
84 }
85
86 #[inline]
87 pub fn skip(&mut self, offset: usize) {
88 self.offset += offset;
89 }
90
91 // UNSIGNED SLICE
92
93 #[inline]
94 pub fn read_u8_slice(&mut self, len: usize) -> Option<StreamSliceU8<'a>> {
95 let end = self.offset + len;
96 self.bytes.get(self.offset..end).map(|slice| {
97 self.offset = end;
98 StreamSliceU8(slice)
99 })
100 }
101
102 #[inline]
103 pub fn read_u16_slice(&mut self, len: usize) -> Option<StreamSliceU16<'a>> {
104 let end = self.offset + len * 2;
105 self.bytes.get(self.offset..end).map(|slice| {
106 self.offset = end;
107 StreamSliceU16(slice)
108 })
109 }
110
111 #[inline]
112 pub fn read_u32_slice(&mut self, len: usize) -> Option<StreamSliceU32<'a>> {
113 let end = self.offset + len * 4;
114 self.bytes.get(self.offset..end).map(|slice| {
115 self.offset = end;
116 StreamSliceU32(slice)
117 })
118 }
119
120 // SIGNED SLICE
121
122 #[inline]
123 pub fn read_i8_slice(&mut self, len: usize) -> Option<StreamSliceI8<'a>> {
124 Some(StreamSliceI8(self.read_u8_slice(len)?))
125 }
126
127 #[inline]
128 pub fn read_i16_slice(&mut self, len: usize) -> Option<StreamSliceI16<'a>> {
129 Some(StreamSliceI16(self.read_u16_slice(len)?))
130 }
131
132 #[inline]
133 pub fn read_i32_slice(&mut self, len: usize) -> Option<StreamSliceI32<'a>> {
134 Some(StreamSliceI32(self.read_u32_slice(len)?))
135 }
136
137 // UNSIGNED
138
139 #[inline]
140 pub fn read_u8(&mut self) -> Option<u8> {
141 const SIZE: usize = 1;
142 let slice = self.bytes.get(self.offset..self.offset + SIZE)?;
143 self.offset += SIZE;
144 Some(slice[0])
145 }
146
147 #[inline]
148 pub fn read_u16(&mut self) -> Option<u16> {
149 const SIZE: usize = 2;
150 let slice = self.bytes.get(self.offset..self.offset + SIZE)?;
151 self.offset += SIZE;
152 Some(u16::from_be_bytes(slice.try_into().unwrap()))
153 }
154
155 #[inline]
156 pub fn read_u32(&mut self) -> Option<u32> {
157 const SIZE: usize = 4;
158 let slice = self.bytes.get(self.offset..self.offset + SIZE)?;
159 self.offset += SIZE;
160 Some(u32::from_be_bytes(slice.try_into().unwrap()))
161 }
162
163 // SIGNED
164
165 #[inline]
166 pub fn read_i8(&mut self) -> Option<i8> {
167 Some(unsafe { core::mem::transmute(self.read_u8()?) })
168 }
169
170 #[inline]
171 pub fn read_i16(&mut self) -> Option<i16> {
172 Some(unsafe { core::mem::transmute(self.read_u16()?) })
173 }
174
175 #[inline]
176 pub fn read_i32(&mut self) -> Option<i32> {
177 Some(unsafe { core::mem::transmute(self.read_u32()?) })
178 }
179
180 // FONT
181
182 #[inline]
183 pub fn read_f2dot14(&mut self) -> Option<f32> {
184 let val = self.read_i16()?;
185 let result = val as f32 * (1.0 / (1 << 14) as f32);
186 Some(result)
187 }
188
189 #[inline]
190 pub fn read_tag(&mut self) -> Option<[u8; 4]> {
191 const SIZE: usize = 4;
192 let slice = self.bytes.get(self.offset..self.offset + SIZE)?;
193 self.offset += SIZE;
194 Some(slice.try_into().unwrap())
195 }
196}
197