1
2use std::mem::size_of;
3use std::fmt::{ Debug, Formatter, Result as FmtResult };
4use bytemuck::{ Zeroable, Pod };
5use chrono::{ DateTime, Utc };
6
7#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
8pub struct Fixed(i16, u16);
9
10impl Fixed {
11 pub const ZERO: Self = Self(0, 0);
12 pub const ONE: Self = Self(1, 0);
13
14 pub const fn integer(&self) -> i16 { self.0 }
15 pub const fn fraction(&self) -> u16 { self.1 }
16
17 pub fn fraction_f32(&self) -> f32 { self.fraction() as f32 / 65536.0 } pub fn fraction_f64(&self) -> f64 { self.fraction() as f64 / 65536.0 } pub fn as_f32(&self) -> f32 { self.integer() as f32 + self.fraction_f32() }
21 pub fn as_f64(&self) -> f64 { self.integer() as f64 + self.fraction_f64() }
22}
23
24impl Debug for Fixed {
25 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
26 write!(f, "{}", self.as_f32())
27 }
28}
29
30#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
31pub struct F2Dot14(i16);
32
33impl F2Dot14 {
34 pub const ZERO: Self = Self(0);
35 pub const ONE: Self = Self(0x4000);
36
37 pub const fn integer(&self) -> i16 { self.0 >> 14 }
38 pub const fn fraction(&self) -> u16 { self.0 as u16 & 0x3FFF }
39
40 pub fn fraction_f32(&self) -> f32 { self.fraction() as f32 / 16384.0 } pub fn fraction_f64(&self) -> f64 { self.fraction() as f64 / 16384.0 } pub fn as_f32(&self) -> f32 { self.integer() as f32 + self.fraction_f32() }
44 pub fn as_f64(&self) -> f64 { self.integer() as f64 + self.fraction_f64() }
45}
46
47impl Debug for F2Dot14 {
48 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
49 write!(f, "{}", self.as_f32())
50 }
51}
52
53pub type LongDateTime = Result<DateTime<Utc>, i64>;
54
55#[derive(Clone, Copy, Zeroable, Pod, PartialEq, Eq, PartialOrd, Ord, Hash)]
56#[repr(transparent)]
57pub struct Tag([u8; 4]);
58
59impl Tag {
60 pub const fn new(value: &[u8; 4]) -> Self { Self(*value) }
61}
62
63impl From<[u8; 4]> for Tag {
64 fn from(value: [u8; 4]) -> Self { Self(value) }
65}
66
67impl AsRef<[u8; 4]> for Tag {
68 fn as_ref(&self) -> &[u8; 4] { &self.0 }
69}
70
71impl Debug for Tag {
72 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
73 write!(f, "{:?}", std::str::from_utf8(&self.0).unwrap())
74 }
75}
76
77#[derive(Clone, Copy)]
78pub struct Version16Dot16(pub u16, pub u16);
79
80impl Debug for Version16Dot16 {
81 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
82 write!(f, "Version16Dot16({}, {})", self.0, self.1)
83 }
84}
85
86pub trait RandomAccess<'a> {
89
90 fn bytes(&self) -> &'a [u8];
91
92 fn uint8(&self, offset: usize) -> u8 { u8::from_be_bytes(*self.item(offset)) }
93 fn uint16(&self, offset: usize) -> u16 { u16::from_be_bytes(*self.item(offset)) }
94 fn uint32(&self, offset: usize) -> u32 { u32::from_be_bytes(*self.item(offset)) }
95
96 fn uint24(&self, offset: usize) -> u32 {
97 let bytes: &[u8; 3] = self.item(offset);
98 u32::from_be_bytes([0, bytes[0], bytes[1], bytes[2]])
99 }
100
101 fn int8(&self, offset: usize) -> i8 { i8::from_be_bytes(*self.item(offset)) }
102 fn int16(&self, offset: usize) -> i16 { i16::from_be_bytes(*self.item(offset)) }
103 fn int32(&self, offset: usize) -> i32 { i32::from_be_bytes(*self.item(offset)) }
104
105 fn fixed(&self, offset: usize) -> Fixed {
106 let value = self.uint32(offset);
107 Fixed((value >> 16) as i16, (value & 0xFFFF) as u16)
108 }
109
110 fn f2dot14(&self, offset: usize) -> F2Dot14 { F2Dot14(self.int16(offset)) }
111
112 fn longdatetime(&self, offset: usize) -> LongDateTime {
113 let timestamp = i64::from_be_bytes(*self.item(offset));
114 DateTime::from_timestamp(timestamp - 2082844800, 0).ok_or(timestamp)
115 }
116
117 fn tag(&self, offset: usize) -> &'a Tag { self.item(offset) }
118
119 fn version16dot16(&self, offset: usize) -> Version16Dot16 {
120 let value = self.uint32(offset);
121 Version16Dot16((value >> 16) as u16, (value & 0xFFFF) as u16)
122 }
123
124 fn item<T: Pod>(&self, offset: usize) -> &'a T {
125 bytemuck::from_bytes(&self.bytes()[offset..offset + size_of::<T>()])
126 }
127
128 fn array<T: Pod>(&self, offset: usize, count: usize) -> &'a [T] {
129 bytemuck::cast_slice(&self.bytes()[offset..offset + size_of::<T>() * count])
130 }
131
132 fn uint16_array(&self, offset: usize, count: usize) -> U16Array<'a> {
133 let end = offset + (count << 1);
134 U16Array(&self.bytes()[offset..end])
135 }
136
137 fn int16_array(&self, offset: usize, count: usize) -> I16Array<'a> {
138 let end = offset + (count << 1);
139 I16Array(&self.bytes()[offset..end])
140 }
141
142 fn uint32_array(&self, offset: usize, count: usize) -> U32Array<'a> {
143 let end = offset + (count << 2);
144 U32Array(&self.bytes()[offset..end])
145 }
146}
147
148impl<'a> RandomAccess<'a> for &'a [u8] {
149 fn bytes(&self) -> &'a [u8] { self }
150}
151
152#[derive(Clone, Copy)]
155pub struct U16Array<'a>(&'a [u8]);
156
157impl<'a> RandomAccess<'a> for U16Array<'a> {
158 fn bytes(&self) -> &'a [u8] { self.0 }
159}
160
161impl<'a> U16Array<'a> {
162 pub fn len(&self) -> usize { self.0.len() >> 1 }
163 pub fn is_empty(&self) -> bool { self.len() == 0 }
164 pub fn get(&self, index: usize) -> u16 { self.0.uint16(index << 1) }
165 pub fn iter(&self) -> impl ExactSizeIterator<Item = u16> + '_ { (0..self.0.len()).step_by(2).map(|x| self.0.uint16(x)) }
166}
167
168impl<'a> Debug for U16Array<'a> {
169 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
170 f.debug_list()
171 .entries(self.iter())
172 .finish()
173 }
174}
175
176#[derive(Clone, Copy)]
179pub struct I16Array<'a>(&'a [u8]);
180
181impl<'a> RandomAccess<'a> for I16Array<'a> {
182 fn bytes(&self) -> &'a [u8] { self.0 }
183}
184
185impl<'a> I16Array<'a> {
186 pub fn len(&self) -> usize { self.0.len() >> 1 }
187 pub fn is_empty(&self) -> bool { self.len() == 0 }
188 pub fn get(&self, index: usize) -> i16 { self.0.int16(index << 1) }
189 pub fn iter(&self) -> impl ExactSizeIterator<Item = i16> + '_ { (0..self.0.len()).step_by(2).map(|x| self.0.int16(x)) }
190}
191
192impl<'a> Debug for I16Array<'a> {
193 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
194 f.debug_list()
195 .entries(self.iter())
196 .finish()
197 }
198}
199
200#[derive(Clone, Copy)]
203pub struct U32Array<'a>(&'a [u8]);
204
205impl<'a> RandomAccess<'a> for U32Array<'a> {
206 fn bytes(&self) -> &'a [u8] { self.0 }
207}
208
209impl<'a> U32Array<'a> {
210 pub fn len(&self) -> usize { self.0.len() >> 2 }
211 pub fn is_empty(&self) -> bool { self.len() == 0 }
212 pub fn get(&self, index: usize) -> u32 { self.0.uint32(index << 2) }
213 pub fn iter(&self) -> impl ExactSizeIterator<Item = u32> + '_ { (0..self.0.len()).step_by(4).map(|x| self.0.uint32(x)) }
214}
215
216impl<'a> Debug for U32Array<'a> {
217 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
218 f.debug_list()
219 .entries(self.iter())
220 .finish()
221 }
222}