1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
3#[repr(i32)]
4pub enum DataType {
5 #[default]
7 Char = 0,
8 Byte = 1,
10 Short = 2,
12 UShort = 3,
14 Int = 4,
16 UInt = 5,
18 Float = 6,
20 Double = 7,
22}
23
24impl DataType {
25 pub fn from_i32(v: i32) -> Option<Self> {
27 match v {
28 0 => Some(Self::Char),
29 1 => Some(Self::Byte),
30 2 => Some(Self::Short),
31 3 => Some(Self::UShort),
32 4 => Some(Self::Int),
33 5 => Some(Self::UInt),
34 6 => Some(Self::Float),
35 7 => Some(Self::Double),
36 _ => None,
37 }
38 }
39
40 pub fn size(self) -> usize {
42 match self {
43 Self::Char | Self::Byte => 1,
44 Self::Short | Self::UShort => 2,
45 Self::Int | Self::UInt | Self::Float => 4,
46 Self::Double => 8,
47 }
48 }
49
50 pub fn is_integer(self) -> bool {
52 !matches!(self, Self::Float | Self::Double)
53 }
54
55 pub fn is_signed(self) -> bool {
57 matches!(self, Self::Char | Self::Short | Self::Int)
58 }
59}
60
61pub(crate) mod sealed {
62 pub trait Sealed {}
63}
64
65pub trait Sample: sealed::Sealed + Copy + PartialOrd + Default + core::fmt::Debug {
69 const DATA_TYPE: DataType;
71 const BYTES: usize;
73
74 fn to_f64(self) -> f64;
76 fn from_f64(v: f64) -> Self;
78 fn to_bits_u64(self) -> u64;
80 fn from_bits_u64(v: u64) -> Self;
82 fn is_integer() -> bool;
84
85 fn into_lerc_data(v: alloc::vec::Vec<Self>) -> super::SampleData;
87
88 fn try_ref_lerc_data(data: &super::SampleData) -> Option<&[Self]>;
90
91 fn try_from_lerc_data(
93 data: super::SampleData,
94 ) -> core::result::Result<alloc::vec::Vec<Self>, super::SampleData>;
95
96 fn from_le_slice(s: &[u8]) -> Self;
98
99 fn extend_le_bytes(self, buf: &mut alloc::vec::Vec<u8>);
101
102 fn min_representable() -> f64;
104}
105
106macro_rules! impl_lerc_data_type {
107 ($ty:ty, $dt:expr, $is_int:expr, $variant:ident, $n:literal) => {
108 impl sealed::Sealed for $ty {}
109 impl Sample for $ty {
110 const DATA_TYPE: DataType = $dt;
111 const BYTES: usize = $n;
112
113 #[inline]
114 fn to_f64(self) -> f64 {
115 self as f64
116 }
117
118 #[inline]
119 fn from_f64(v: f64) -> Self {
120 v as Self
121 }
122
123 #[inline]
124 fn to_bits_u64(self) -> u64 {
125 self as u64
126 }
127
128 #[inline]
129 fn from_bits_u64(v: u64) -> Self {
130 v as Self
131 }
132
133 #[inline]
134 fn is_integer() -> bool {
135 $is_int
136 }
137
138 fn into_lerc_data(v: alloc::vec::Vec<Self>) -> super::SampleData {
139 super::SampleData::$variant(v)
140 }
141
142 fn try_ref_lerc_data(data: &super::SampleData) -> Option<&[Self]> {
143 match data {
144 super::SampleData::$variant(v) => Some(v),
145 _ => None,
146 }
147 }
148
149 fn try_from_lerc_data(
150 data: super::SampleData,
151 ) -> core::result::Result<alloc::vec::Vec<Self>, super::SampleData> {
152 match data {
153 super::SampleData::$variant(v) => Ok(v),
154 other => Err(other),
155 }
156 }
157
158 #[inline]
159 fn from_le_slice(s: &[u8]) -> Self {
160 let mut buf = [0u8; $n];
161 buf.copy_from_slice(&s[..$n]);
162 <$ty>::from_le_bytes(buf)
163 }
164
165 #[inline]
166 fn extend_le_bytes(self, buf: &mut alloc::vec::Vec<u8>) {
167 buf.extend_from_slice(&self.to_le_bytes());
168 }
169
170 #[inline]
171 fn min_representable() -> f64 {
172 <$ty>::MIN as f64
173 }
174 }
175 };
176}
177
178impl_lerc_data_type!(i8, DataType::Char, true, I8, 1);
179impl_lerc_data_type!(u8, DataType::Byte, true, U8, 1);
180impl_lerc_data_type!(i16, DataType::Short, true, I16, 2);
181impl_lerc_data_type!(u16, DataType::UShort, true, U16, 2);
182impl_lerc_data_type!(i32, DataType::Int, true, I32, 4);
183impl_lerc_data_type!(u32, DataType::UInt, true, U32, 4);
184
185impl sealed::Sealed for f32 {}
186impl Sample for f32 {
187 const DATA_TYPE: DataType = DataType::Float;
188 const BYTES: usize = 4;
189
190 #[inline]
191 fn to_f64(self) -> f64 {
192 self as f64
193 }
194
195 #[inline]
196 fn from_f64(v: f64) -> Self {
197 v as Self
198 }
199
200 #[inline]
201 fn to_bits_u64(self) -> u64 {
202 self.to_bits() as u64
203 }
204
205 #[inline]
206 fn from_bits_u64(v: u64) -> Self {
207 Self::from_bits(v as u32)
208 }
209
210 #[inline]
211 fn is_integer() -> bool {
212 false
213 }
214
215 fn into_lerc_data(v: alloc::vec::Vec<Self>) -> super::SampleData {
216 super::SampleData::F32(v)
217 }
218
219 fn try_ref_lerc_data(data: &super::SampleData) -> Option<&[Self]> {
220 match data {
221 super::SampleData::F32(v) => Some(v),
222 _ => None,
223 }
224 }
225
226 fn try_from_lerc_data(
227 data: super::SampleData,
228 ) -> core::result::Result<alloc::vec::Vec<Self>, super::SampleData> {
229 match data {
230 super::SampleData::F32(v) => Ok(v),
231 other => Err(other),
232 }
233 }
234
235 #[inline]
236 fn from_le_slice(s: &[u8]) -> Self {
237 Self::from_bits(u32::from_le_bytes([s[0], s[1], s[2], s[3]]))
238 }
239
240 #[inline]
241 fn extend_le_bytes(self, buf: &mut alloc::vec::Vec<u8>) {
242 buf.extend_from_slice(&self.to_le_bytes());
243 }
244
245 #[inline]
246 fn min_representable() -> f64 {
247 f64::MIN
248 }
249}
250
251impl sealed::Sealed for f64 {}
252impl Sample for f64 {
253 const DATA_TYPE: DataType = DataType::Double;
254 const BYTES: usize = 8;
255
256 #[inline]
257 fn to_f64(self) -> f64 {
258 self
259 }
260
261 #[inline]
262 fn from_f64(v: f64) -> Self {
263 v
264 }
265
266 #[inline]
267 fn to_bits_u64(self) -> u64 {
268 self.to_bits()
269 }
270
271 #[inline]
272 fn from_bits_u64(v: u64) -> Self {
273 Self::from_bits(v)
274 }
275
276 #[inline]
277 fn is_integer() -> bool {
278 false
279 }
280
281 fn into_lerc_data(v: alloc::vec::Vec<Self>) -> super::SampleData {
282 super::SampleData::F64(v)
283 }
284
285 fn try_ref_lerc_data(data: &super::SampleData) -> Option<&[Self]> {
286 match data {
287 super::SampleData::F64(v) => Some(v),
288 _ => None,
289 }
290 }
291
292 fn try_from_lerc_data(
293 data: super::SampleData,
294 ) -> core::result::Result<alloc::vec::Vec<Self>, super::SampleData> {
295 match data {
296 super::SampleData::F64(v) => Ok(v),
297 other => Err(other),
298 }
299 }
300
301 #[inline]
302 fn from_le_slice(s: &[u8]) -> Self {
303 Self::from_bits(u64::from_le_bytes([
304 s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
305 ]))
306 }
307
308 #[inline]
309 fn extend_le_bytes(self, buf: &mut alloc::vec::Vec<u8>) {
310 buf.extend_from_slice(&self.to_le_bytes());
311 }
312
313 #[inline]
314 fn min_representable() -> f64 {
315 f64::MIN
316 }
317}
318
319#[derive(Debug, Clone, Copy, PartialEq, Eq)]
321#[repr(u8)]
322pub(crate) enum ImageEncodeMode {
323 Tiling = 0,
324 DeltaHuffman = 1,
325 Huffman = 2,
326 DeltaDeltaHuffman = 3,
327}
328
329impl TryFrom<u8> for ImageEncodeMode {
330 type Error = crate::error::LercError;
331 fn try_from(v: u8) -> core::result::Result<Self, Self::Error> {
332 match v {
333 0 => Ok(Self::Tiling),
334 1 => Ok(Self::DeltaHuffman),
335 2 => Ok(Self::Huffman),
336 3 => Ok(Self::DeltaDeltaHuffman),
337 _ => Err(crate::error::LercError::UnsupportedEncoding(v)),
338 }
339 }
340}
341
342#[derive(Debug, Clone, Copy)]
344pub(crate) struct TileRect {
345 pub i0: usize,
347 pub i1: usize,
349 pub j0: usize,
351 pub j1: usize,
353}
354
355#[derive(Debug, Clone, Copy, PartialEq, Eq)]
362#[repr(u8)]
363pub(crate) enum TileCompressionMode {
364 RawBinary = 0,
365 BitStuffed = 1,
366 ConstZero = 2,
367 ConstOffset = 3,
368}
369
370pub(crate) mod tile_flags {
372 pub const MODE_MASK: u8 = 0x03;
374 pub const DIFF_ENCODING: u8 = 0x04;
376 pub const TYPE_REDUCTION_SHIFT: u8 = 6;
378}
379
380#[cfg(test)]
381mod tests {
382 use super::*;
383
384 #[test]
390 fn image_encode_mode_matches_cpp() {
391 assert_eq!(ImageEncodeMode::Tiling as u8, 0);
392 assert_eq!(ImageEncodeMode::DeltaHuffman as u8, 1);
393 assert_eq!(ImageEncodeMode::Huffman as u8, 2);
394 assert_eq!(ImageEncodeMode::DeltaDeltaHuffman as u8, 3);
395 }
396
397 #[test]
398 fn tile_compression_mode_matches_cpp() {
399 assert_eq!(TileCompressionMode::RawBinary as u8, 0);
402 assert_eq!(TileCompressionMode::BitStuffed as u8, 1);
403 assert_eq!(TileCompressionMode::ConstZero as u8, 2);
404 assert_eq!(TileCompressionMode::ConstOffset as u8, 3);
405 }
406
407 #[test]
408 fn data_type_matches_cpp() {
409 assert_eq!(DataType::Char as i32, 0);
410 assert_eq!(DataType::Byte as i32, 1);
411 assert_eq!(DataType::Short as i32, 2);
412 assert_eq!(DataType::UShort as i32, 3);
413 assert_eq!(DataType::Int as i32, 4);
414 assert_eq!(DataType::UInt as i32, 5);
415 assert_eq!(DataType::Float as i32, 6);
416 assert_eq!(DataType::Double as i32, 7);
417 }
418
419 #[test]
420 fn tile_flags_matches_cpp() {
421 assert_eq!(tile_flags::MODE_MASK, 0x03);
422 assert_eq!(tile_flags::DIFF_ENCODING, 0x04);
423 assert_eq!(tile_flags::TYPE_REDUCTION_SHIFT, 6);
424 }
425
426 #[test]
427 fn image_encode_mode_try_from_round_trip() {
428 for v in 0..=3u8 {
429 let mode = ImageEncodeMode::try_from(v).unwrap();
430 assert_eq!(mode as u8, v);
431 }
432 assert!(ImageEncodeMode::try_from(4).is_err());
433 assert!(ImageEncodeMode::try_from(255).is_err());
434 }
435}