mttf/
core.rs

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 } // TODO is it faster to encode it myself?
18	pub fn fraction_f64(&self) -> f64 { self.fraction() as f64 / 65536.0 } // TODO is it faster to encode it myself?
19
20	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 } // TODO is it faster to encode it myself?
41	pub fn fraction_f64(&self) -> f64 { self.fraction() as f64 / 16384.0 } // TODO is it faster to encode it myself?
42
43	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
86// Random Access
87
88pub 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// U16Array
153
154#[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// I16Array
177
178#[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// U32Array
201
202#[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}