1use num_traits::{Float, PrimInt};
2
3#[cfg(feature = "audio")]
4use audio_core::Sample;
5
6#[derive(Debug, Clone, Copy)]
8pub struct I24LE<const N: usize>([u8; N]);
9
10#[derive(Debug, Clone, Copy)]
12pub struct I24BE<const N: usize>([u8; N]);
13
14#[derive(Debug, Clone, Copy)]
16pub struct U24LE<const N: usize>([u8; N]);
17
18#[derive(Debug, Clone, Copy)]
20pub struct U24BE<const N: usize>([u8; N]);
21
22#[derive(Debug, Clone, Copy)]
24pub struct I32LE([u8; 4]);
25
26#[derive(Debug, Clone, Copy)]
28pub struct I32BE([u8; 4]);
29
30#[derive(Debug, Clone, Copy)]
32pub struct I64LE([u8; 8]);
33
34#[derive(Debug, Clone, Copy)]
36pub struct I64BE([u8; 8]);
37
38#[derive(Debug, Clone, Copy)]
40pub struct I16LE([u8; 2]);
41
42#[derive(Debug, Clone, Copy)]
44pub struct I16BE([u8; 2]);
45
46#[derive(Debug, Clone, Copy)]
48pub struct U32LE([u8; 4]);
49
50#[derive(Debug, Clone, Copy)]
52pub struct U32BE([u8; 4]);
53
54#[derive(Debug, Clone, Copy)]
56pub struct U64LE([u8; 8]);
57
58#[derive(Debug, Clone, Copy)]
60pub struct U64BE([u8; 8]);
61
62#[derive(Debug, Clone, Copy)]
64pub struct U16LE([u8; 2]);
65
66#[derive(Debug, Clone, Copy)]
68pub struct U16BE([u8; 2]);
69
70#[derive(Debug, Clone, Copy)]
72pub struct F32LE([u8; 4]);
73
74#[derive(Debug, Clone, Copy)]
76pub struct F32BE([u8; 4]);
77
78#[derive(Debug, Clone, Copy)]
80pub struct F64LE([u8; 8]);
81
82#[derive(Debug, Clone, Copy)]
84pub struct F64BE([u8; 8]);
85
86fn to_clamped_int<T: Float, U: PrimInt>(value: T, converted: Option<U>) -> ConversionResult<U> {
88 if let Some(val) = converted {
89 return ConversionResult {
90 clipped: false,
91 value: val,
92 };
93 }
94 if value.is_nan() {
95 return ConversionResult {
96 clipped: true,
97 value: U::zero(),
98 };
99 }
100 if value > T::zero() {
101 return ConversionResult {
102 clipped: true,
103 value: U::max_value(),
104 };
105 }
106 ConversionResult {
107 clipped: true,
108 value: U::min_value(),
109 }
110}
111
112pub struct ConversionResult<T> {
115 pub clipped: bool,
116 pub value: T,
117}
118
119pub trait RawSample
129where
130 Self: Sized,
131{
132 fn to_scaled_float<T: Float>(&self) -> T;
134
135 fn from_scaled_float<T: Float>(value: T) -> ConversionResult<Self>;
138}
139
140pub trait BytesSample {
152 type NumericType: Copy;
154
155 const BYTES_PER_SAMPLE: usize;
157
158 fn from_slice(bytes: &[u8]) -> Self;
162
163 fn as_slice(&self) -> &[u8];
165
166 fn as_mut_slice(&mut self) -> &mut [u8];
168
169 fn to_number(&self) -> Self::NumericType;
171
172 fn from_number(value: Self::NumericType) -> Self;
174}
175
176macro_rules! rawsample_for_int {
177 ($type:ident, $to:ident) => {
178 impl RawSample for $type {
179 fn to_scaled_float<T: Float>(&self) -> T {
180 T::from(*self).unwrap() / (T::from($type::MAX).unwrap() + T::one())
181 }
182
183 fn from_scaled_float<T: Float>(value: T) -> ConversionResult<Self> {
184 let scaled = value * (T::from($type::MAX).unwrap() + T::one());
185 let converted = scaled.$to();
186 to_clamped_int(scaled, converted)
187 }
188 }
189 };
190}
191
192rawsample_for_int!(i8, to_i8);
193rawsample_for_int!(i16, to_i16);
194rawsample_for_int!(i32, to_i32);
195rawsample_for_int!(i64, to_i64);
196
197macro_rules! rawsample_for_uint {
198 ($type:ident, $to:ident) => {
199 impl RawSample for $type {
200 fn to_scaled_float<T: Float>(&self) -> T {
201 let max_ampl = (T::from($type::MAX).unwrap() + T::one()) / T::from(2).unwrap();
202 (T::from(*self).unwrap() - max_ampl) / max_ampl
203 }
204
205 fn from_scaled_float<T: Float>(value: T) -> ConversionResult<Self> {
206 let max_ampl = (T::from($type::MAX).unwrap() + T::one()) / T::from(2).unwrap();
207 let scaled = value * max_ampl + max_ampl;
208 let converted = scaled.$to();
209 to_clamped_int(scaled, converted)
210 }
211 }
212 };
213}
214
215rawsample_for_uint!(u8, to_u8);
216rawsample_for_uint!(u16, to_u16);
217rawsample_for_uint!(u32, to_u32);
218rawsample_for_uint!(u64, to_u64);
219
220macro_rules! rawsample_for_float {
221 ($type:ident, $to:ident) => {
222 impl RawSample for $type {
223 fn to_scaled_float<T: Float>(&self) -> T {
224 T::from(*self).unwrap_or(T::zero())
225 }
226
227 fn from_scaled_float<T: Float>(value: T) -> ConversionResult<Self> {
228 ConversionResult {
230 clipped: false,
231 value: value.$to().unwrap_or(0.0),
232 }
233 }
234 }
235 };
236}
237
238rawsample_for_float!(f32, to_f32);
239rawsample_for_float!(f64, to_f64);
240
241impl BytesSample for I24LE<4> {
246 type NumericType = i32;
247 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
248
249 fn from_slice(bytes: &[u8]) -> Self {
250 Self(bytes[0..4].try_into().unwrap())
251 }
252
253 fn as_slice(&self) -> &[u8] {
254 &self.0
255 }
256
257 fn as_mut_slice(&mut self) -> &mut [u8] {
258 &mut self.0
259 }
260
261 fn to_number(&self) -> Self::NumericType {
262 let padded = [0, self.0[0], self.0[1], self.0[2]];
263 i32::from_le_bytes(padded)
264 }
265
266 fn from_number(value: Self::NumericType) -> Self {
267 let bytes = value.to_le_bytes();
268 Self([bytes[1], bytes[2], bytes[3], 0])
269 }
270}
271
272impl BytesSample for I24LE<3> {
274 type NumericType = i32;
275 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
276
277 fn from_slice(bytes: &[u8]) -> Self {
278 Self(bytes[0..3].try_into().unwrap())
279 }
280
281 fn as_slice(&self) -> &[u8] {
282 &self.0
283 }
284
285 fn as_mut_slice(&mut self) -> &mut [u8] {
286 &mut self.0
287 }
288
289 fn to_number(&self) -> Self::NumericType {
290 let padded = [0, self.0[0], self.0[1], self.0[2]];
291 i32::from_le_bytes(padded)
292 }
293
294 fn from_number(value: Self::NumericType) -> Self {
295 let bytes = value.to_le_bytes();
296 Self([bytes[1], bytes[2], bytes[3]])
297 }
298}
299
300impl BytesSample for I24BE<4> {
302 type NumericType = i32;
303 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
304
305 fn from_slice(bytes: &[u8]) -> Self {
306 Self(bytes[0..4].try_into().unwrap())
307 }
308
309 fn as_slice(&self) -> &[u8] {
310 &self.0
311 }
312
313 fn as_mut_slice(&mut self) -> &mut [u8] {
314 &mut self.0
315 }
316
317 fn to_number(&self) -> Self::NumericType {
318 let padded = [self.0[1], self.0[2], self.0[3], 0];
319 i32::from_be_bytes(padded)
320 }
321
322 fn from_number(value: Self::NumericType) -> Self {
323 let bytes = value.to_be_bytes();
324 Self([0, bytes[0], bytes[1], bytes[2]])
325 }
326}
327
328impl BytesSample for I24BE<3> {
330 type NumericType = i32;
331 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
332
333 fn from_slice(bytes: &[u8]) -> Self {
334 Self(bytes[0..3].try_into().unwrap())
335 }
336
337 fn as_slice(&self) -> &[u8] {
338 &self.0
339 }
340
341 fn as_mut_slice(&mut self) -> &mut [u8] {
342 &mut self.0
343 }
344
345 fn to_number(&self) -> Self::NumericType {
346 let padded = [self.0[0], self.0[1], self.0[2], 0];
347 i32::from_be_bytes(padded)
348 }
349
350 fn from_number(value: Self::NumericType) -> Self {
351 let bytes = value.to_be_bytes();
352 Self([bytes[0], bytes[1], bytes[2]])
353 }
354}
355
356impl BytesSample for U24LE<4> {
358 type NumericType = u32;
359 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
360
361 fn from_slice(bytes: &[u8]) -> Self {
362 Self(bytes[0..4].try_into().unwrap())
363 }
364
365 fn as_slice(&self) -> &[u8] {
366 &self.0
367 }
368
369 fn as_mut_slice(&mut self) -> &mut [u8] {
370 &mut self.0
371 }
372
373 fn to_number(&self) -> Self::NumericType {
374 let padded = [0, self.0[0], self.0[1], self.0[2]];
375 u32::from_le_bytes(padded)
376 }
377
378 fn from_number(value: Self::NumericType) -> Self {
379 let bytes = value.to_le_bytes();
380 Self([bytes[1], bytes[2], bytes[3], 0])
381 }
382}
383
384impl BytesSample for U24LE<3> {
386 type NumericType = u32;
387 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
388
389 fn from_slice(bytes: &[u8]) -> Self {
390 Self(bytes[0..3].try_into().unwrap())
391 }
392
393 fn as_slice(&self) -> &[u8] {
394 &self.0
395 }
396
397 fn as_mut_slice(&mut self) -> &mut [u8] {
398 &mut self.0
399 }
400
401 fn to_number(&self) -> Self::NumericType {
402 let padded = [0, self.0[0], self.0[1], self.0[2]];
403 u32::from_le_bytes(padded)
404 }
405
406 fn from_number(value: Self::NumericType) -> Self {
407 let bytes = value.to_le_bytes();
408 Self([bytes[1], bytes[2], bytes[3]])
409 }
410}
411
412impl BytesSample for U24BE<4> {
414 type NumericType = u32;
415 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
416
417 fn from_slice(bytes: &[u8]) -> Self {
418 Self(bytes[0..4].try_into().unwrap())
419 }
420
421 fn as_slice(&self) -> &[u8] {
422 &self.0
423 }
424
425 fn as_mut_slice(&mut self) -> &mut [u8] {
426 &mut self.0
427 }
428
429 fn to_number(&self) -> Self::NumericType {
430 let padded = [self.0[1], self.0[2], self.0[3], 0];
431 u32::from_be_bytes(padded)
432 }
433
434 fn from_number(value: Self::NumericType) -> Self {
435 let bytes = value.to_be_bytes();
436 Self([0, bytes[0], bytes[1], bytes[2]])
437 }
438}
439
440impl BytesSample for U24BE<3> {
442 type NumericType = u32;
443 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
444
445 fn from_slice(bytes: &[u8]) -> Self {
446 Self(bytes[0..3].try_into().unwrap())
447 }
448
449 fn as_slice(&self) -> &[u8] {
450 &self.0
451 }
452
453 fn as_mut_slice(&mut self) -> &mut [u8] {
454 &mut self.0
455 }
456
457 fn to_number(&self) -> Self::NumericType {
458 let padded = [self.0[0], self.0[1], self.0[2], 0];
459 u32::from_be_bytes(padded)
460 }
461
462 fn from_number(value: Self::NumericType) -> Self {
463 let bytes = value.to_be_bytes();
464 Self([bytes[0], bytes[1], bytes[2]])
465 }
466}
467
468macro_rules! bytessample_for_newtype {
469 ($type:ident, $newtype:ident, $from:ident, $to:ident) => {
470 impl BytesSample for $newtype {
471 type NumericType = $type;
472 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<$type>();
473
474 fn from_slice(bytes: &[u8]) -> Self {
475 Self(bytes.try_into().unwrap())
476 }
477
478 fn as_slice(&self) -> &[u8] {
479 &self.0
480 }
481
482 fn as_mut_slice(&mut self) -> &mut [u8] {
483 &mut self.0
484 }
485
486 fn to_number(&self) -> Self::NumericType {
487 $type::$from(self.0)
488 }
489
490 fn from_number(value: Self::NumericType) -> Self {
491 Self(value.$to())
492 }
493 }
494 };
495}
496
497bytessample_for_newtype!(i64, I64LE, from_le_bytes, to_le_bytes);
498bytessample_for_newtype!(u64, U64LE, from_le_bytes, to_le_bytes);
499bytessample_for_newtype!(i64, I64BE, from_be_bytes, to_be_bytes);
500bytessample_for_newtype!(u64, U64BE, from_be_bytes, to_be_bytes);
501
502bytessample_for_newtype!(i16, I16LE, from_le_bytes, to_le_bytes);
503bytessample_for_newtype!(u16, U16LE, from_le_bytes, to_le_bytes);
504bytessample_for_newtype!(i16, I16BE, from_be_bytes, to_be_bytes);
505bytessample_for_newtype!(u16, U16BE, from_be_bytes, to_be_bytes);
506
507bytessample_for_newtype!(i32, I32LE, from_le_bytes, to_le_bytes);
508bytessample_for_newtype!(u32, U32LE, from_le_bytes, to_le_bytes);
509bytessample_for_newtype!(i32, I32BE, from_be_bytes, to_be_bytes);
510bytessample_for_newtype!(u32, U32BE, from_be_bytes, to_be_bytes);
511
512bytessample_for_newtype!(f32, F32LE, from_le_bytes, to_le_bytes);
513bytessample_for_newtype!(f32, F32BE, from_be_bytes, to_be_bytes);
514bytessample_for_newtype!(f64, F64LE, from_le_bytes, to_le_bytes);
515bytessample_for_newtype!(f64, F64BE, from_be_bytes, to_be_bytes);
516
517impl<V> RawSample for V
518where
519 V: BytesSample,
520 <V as BytesSample>::NumericType: RawSample,
521{
522 fn to_scaled_float<T: Float>(&self) -> T {
523 let value = self.to_number();
524 value.to_scaled_float()
525 }
526
527 fn from_scaled_float<T: Float>(value: T) -> ConversionResult<Self> {
528 let value = <V as BytesSample>::NumericType::from_scaled_float(value);
529 ConversionResult {
530 clipped: value.clipped,
531 value: V::from_number(value.value),
532 }
533 }
534}
535
536#[cfg(feature = "audio")]
538macro_rules! impl_sample_for_newtype {
539 ($newtype:ident, $bytes:expr) => {
540 unsafe impl Sample for $newtype {
541 const ZERO: $newtype = $newtype([0; $bytes]);
542 }
543 };
544}
545
546#[cfg(feature = "audio")]
547impl_sample_for_newtype!(I64LE, 8);
548#[cfg(feature = "audio")]
549impl_sample_for_newtype!(U64LE, 8);
550#[cfg(feature = "audio")]
551impl_sample_for_newtype!(I64BE, 8);
552#[cfg(feature = "audio")]
553impl_sample_for_newtype!(U64BE, 8);
554#[cfg(feature = "audio")]
555impl_sample_for_newtype!(I16LE, 2);
556#[cfg(feature = "audio")]
557impl_sample_for_newtype!(U16LE, 2);
558#[cfg(feature = "audio")]
559impl_sample_for_newtype!(I16BE, 2);
560#[cfg(feature = "audio")]
561impl_sample_for_newtype!(U16BE, 2);
562#[cfg(feature = "audio")]
563impl_sample_for_newtype!(I32LE, 4);
564#[cfg(feature = "audio")]
565impl_sample_for_newtype!(U32LE, 4);
566#[cfg(feature = "audio")]
567impl_sample_for_newtype!(I32BE, 4);
568#[cfg(feature = "audio")]
569impl_sample_for_newtype!(U32BE, 4);
570#[cfg(feature = "audio")]
571impl_sample_for_newtype!(F32LE, 4);
572#[cfg(feature = "audio")]
573impl_sample_for_newtype!(F32BE, 4);
574#[cfg(feature = "audio")]
575impl_sample_for_newtype!(F64LE, 8);
576#[cfg(feature = "audio")]
577impl_sample_for_newtype!(F64BE, 8);
578
579#[cfg(feature = "audio")]
580macro_rules! impl_sample_for_generic_newtype {
581 ($newtype:ident, $bytes:expr) => {
582 unsafe impl Sample for $newtype<$bytes> {
583 const ZERO: $newtype<$bytes> = $newtype([0; $bytes]);
584 }
585 };
586}
587#[cfg(feature = "audio")]
588impl_sample_for_generic_newtype!(I24BE, 3);
589#[cfg(feature = "audio")]
590impl_sample_for_generic_newtype!(I24LE, 3);
591#[cfg(feature = "audio")]
592impl_sample_for_generic_newtype!(U24BE, 3);
593#[cfg(feature = "audio")]
594impl_sample_for_generic_newtype!(U24LE, 3);
595#[cfg(feature = "audio")]
596impl_sample_for_generic_newtype!(I24BE, 4);
597#[cfg(feature = "audio")]
598impl_sample_for_generic_newtype!(I24LE, 4);
599#[cfg(feature = "audio")]
600impl_sample_for_generic_newtype!(U24BE, 4);
601#[cfg(feature = "audio")]
602impl_sample_for_generic_newtype!(U24LE, 4);
603
604#[cfg(test)]
605mod tests {
606 use super::*;
607
608 macro_rules! assert_conversion_eq {
609 ($result:expr, $value:expr, $clipped:expr, $desc:expr) => {
610 assert_eq!($result.value, $value, $desc);
611 assert_eq!($result.clipped, $clipped, $desc);
612 };
613 }
614
615 macro_rules! test_to_signed_int {
616 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
617 #[test]
618 fn $fname() {
619 let val: $float = 0.25;
620 assert_conversion_eq!(
621 $int::from_scaled_float(val),
622 1 << ($bits - 3),
623 false,
624 "check +0.25"
625 );
626 let val: $float = -0.25;
627 assert_conversion_eq!(
628 $int::from_scaled_float(val),
629 -1 << ($bits - 3),
630 false,
631 "check -0.25"
632 );
633 let val: $float = 1.1;
634 assert_conversion_eq!(
635 $int::from_scaled_float(val),
636 $int::MAX,
637 true,
638 "clipped positive"
639 );
640 let val: $float = -1.1;
641 assert_conversion_eq!(
642 $int::from_scaled_float(val),
643 $int::MIN,
644 true,
645 "clipped negative"
646 );
647 }
648 };
649 }
650
651 macro_rules! test_to_unsigned_int {
652 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
653 #[test]
654 fn $fname() {
655 let val: $float = -0.5;
656 assert_conversion_eq!(
657 $int::from_scaled_float(val),
658 1 << ($bits - 2),
659 false,
660 "check -0.5"
661 );
662 let val: $float = 0.5;
663 assert_conversion_eq!(
664 $int::from_scaled_float(val),
665 $int::MAX - (1 << ($bits - 2)) + 1,
666 false,
667 "check 0.5"
668 );
669 let val: $float = 1.1;
670 assert_conversion_eq!(
671 $int::from_scaled_float(val),
672 $int::MAX,
673 true,
674 "clipped positive"
675 );
676 let val: $float = -1.1;
677 assert_conversion_eq!(
678 $int::from_scaled_float(val),
679 $int::MIN,
680 true,
681 "clipped negative"
682 );
683 }
684 };
685 }
686
687 test_to_signed_int!(convert_f32_to_i8, f32, i8, 8);
688 test_to_signed_int!(convert_642_to_i8, f64, i8, 8);
689 test_to_signed_int!(convert_f32_to_i16, f32, i16, 16);
690 test_to_signed_int!(convert_f64_to_i16, f64, i16, 16);
691 test_to_signed_int!(convert_f32_to_i32, f32, i32, 32);
692 test_to_signed_int!(convert_f64_to_i32, f64, i32, 32);
693 test_to_signed_int!(convert_f32_to_i64, f32, i64, 64);
694 test_to_signed_int!(convert_f64_to_i64, f64, i64, 64);
695
696 test_to_unsigned_int!(convert_f32_to_u8, f32, u8, 8);
697 test_to_unsigned_int!(convert_f64_to_u8, f64, u8, 8);
698 test_to_unsigned_int!(convert_f32_to_u16, f32, u16, 16);
699 test_to_unsigned_int!(convert_f64_to_u16, f64, u16, 16);
700 test_to_unsigned_int!(convert_f32_to_u32, f32, u32, 32);
701 test_to_unsigned_int!(convert_f64_to_u32, f64, u32, 32);
702 test_to_unsigned_int!(convert_f32_to_u64, f32, u64, 64);
703 test_to_unsigned_int!(convert_f64_to_u64, f64, u64, 64);
704
705 macro_rules! test_from_signed_int {
706 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
707 #[test]
708 fn $fname() {
709 let val: $int = -1 << ($bits - 2);
710 assert_eq!(val.to_scaled_float::<$float>(), -0.5, "check -0.5");
711 let val: $int = 1 << ($bits - 2);
712 assert_eq!(val.to_scaled_float::<$float>(), 0.5, "check 0.5");
713 let val: $int = $int::MIN;
714 assert_eq!(val.to_scaled_float::<$float>(), -1.0, "negative limit");
715 }
716 };
717 }
718
719 macro_rules! test_from_unsigned_int {
720 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
721 #[test]
722 fn $fname() {
723 let val: $int = 1 << ($bits - 2);
724 assert_eq!(val.to_scaled_float::<$float>(), -0.5, "check -0.5");
725 let val: $int = $int::MAX - (1 << ($bits - 2)) + 1;
726 assert_eq!(val.to_scaled_float::<$float>(), 0.5, "check 0.5");
727 let val: $int = 0;
728 assert_eq!(val.to_scaled_float::<$float>(), -1.0, "negative limit");
729 }
730 };
731 }
732
733 test_from_signed_int!(convert_f32_from_i8, f32, i8, 8);
734 test_from_signed_int!(convert_f64_from_i8, f64, i8, 8);
735 test_from_signed_int!(convert_f32_from_i16, f32, i16, 16);
736 test_from_signed_int!(convert_f64_from_i16, f64, i16, 16);
737 test_from_signed_int!(convert_f32_from_i32, f32, i32, 32);
738 test_from_signed_int!(convert_f64_from_i32, f64, i32, 32);
739 test_from_signed_int!(convert_f32_from_i64, f32, i64, 64);
740 test_from_signed_int!(convert_f64_from_i64, f64, i64, 64);
741
742 test_from_unsigned_int!(convert_f32_from_u8, f32, u8, 8);
743 test_from_unsigned_int!(convert_f64_from_u8, f64, u8, 8);
744 test_from_unsigned_int!(convert_f32_from_u16, f32, u16, 16);
745 test_from_unsigned_int!(convert_f64_from_u16, f64, u16, 16);
746 test_from_unsigned_int!(convert_f32_from_u32, f32, u32, 32);
747 test_from_unsigned_int!(convert_f64_from_u32, f64, u32, 32);
748 test_from_unsigned_int!(convert_f32_from_u64, f32, u64, 64);
749 test_from_unsigned_int!(convert_f64_from_u64, f64, u64, 64);
750
751 #[test]
752 fn test_to_clamped_int() {
753 let converted = to_clamped_int::<f32, i32>(12345.0, Some(12345));
754 assert_conversion_eq!(converted, 12345, false, "in range f32 i32");
755
756 let converted = to_clamped_int::<f32, i32>(1.0e10, None);
757 assert_conversion_eq!(converted, i32::MAX, true, "above range f32 i32");
758
759 let converted = to_clamped_int::<f32, i32>(-1.0e10, None);
760 assert_conversion_eq!(converted, i32::MIN, true, "below range f32 i32");
761
762 let converted = to_clamped_int::<f64, i32>(12345.0, Some(12345));
763 assert_conversion_eq!(converted, 12345, false, "in range f64 i32");
764
765 let converted = to_clamped_int::<f64, i32>(1.0e10, None);
766 assert_conversion_eq!(converted, i32::MAX, true, "above range f64 i32");
767
768 let converted = to_clamped_int::<f64, i32>(-1.0e10, None);
769 assert_conversion_eq!(converted, i32::MIN, true, "below range f64 i32");
770 }
771
772 #[test]
773 fn test_to_clamped_uint() {
774 let converted = to_clamped_int::<f32, u32>(12345.0, Some(12345));
775 assert_conversion_eq!(converted, 12345, false, "in range f32 u32");
776
777 let converted = to_clamped_int::<f32, u32>(1.0e10, None);
778 assert_conversion_eq!(converted, u32::MAX, true, "above range f32 u32");
779
780 let converted = to_clamped_int::<f32, u32>(-1.0, None);
781 assert_conversion_eq!(converted, u32::MIN, true, "below range f32 u32");
782
783 let converted = to_clamped_int::<f64, u32>(12345.0, Some(12345));
784 assert_conversion_eq!(converted, 12345, false, "in range f64 u32");
785
786 let converted = to_clamped_int::<f64, u32>(1.0e10, None);
787 assert_conversion_eq!(converted, u32::MAX, true, "above range f64 u32");
788
789 let converted = to_clamped_int::<f64, u32>(-1.0, None);
790 assert_conversion_eq!(converted, u32::MIN, true, "below range f64 u32");
791 }
792
793 macro_rules! test_simple_int_bytes {
794 ($fname:ident, $number:ty, $wrapper:ident, $to_bytes_fn:ident) => {
795 #[test]
796 #[allow(non_snake_case)]
797 fn $fname() {
798 let number: $number = <$number>::MAX / 5 * 4;
799 let wrapped = $wrapper(number.$to_bytes_fn());
800 assert_eq!(number, wrapped.to_number());
801 }
802 };
803 }
804
805 macro_rules! test_float_bytes {
806 ($fname:ident, $number:ty, $wrapper:ident, $to_bytes_fn:ident) => {
807 #[test]
808 #[allow(non_snake_case)]
809 fn $fname() {
810 let number: $number = 12345.0;
811 let wrapped = $wrapper(number.$to_bytes_fn());
812 assert_eq!(number, wrapped.to_number());
813 }
814 };
815 }
816
817 test_simple_int_bytes!(convert_i16_from_I16LE, i16, I16LE, to_le_bytes);
818 test_simple_int_bytes!(convert_i16_from_I16BE, i16, I16BE, to_be_bytes);
819 test_simple_int_bytes!(convert_i32_from_I32LE, i32, I32LE, to_le_bytes);
820 test_simple_int_bytes!(convert_i32_from_I32BE, i32, I32BE, to_be_bytes);
821 test_simple_int_bytes!(convert_i64_from_I64LE, i64, I64LE, to_le_bytes);
822 test_simple_int_bytes!(convert_i64_from_I64BE, i64, I64BE, to_be_bytes);
823
824 test_simple_int_bytes!(convert_u16_from_U16LE, u16, U16LE, to_le_bytes);
825 test_simple_int_bytes!(convert_u16_from_U16BE, u16, U16BE, to_be_bytes);
826 test_simple_int_bytes!(convert_u32_from_U32LE, u32, U32LE, to_le_bytes);
827 test_simple_int_bytes!(convert_u32_from_U32BE, u32, U32BE, to_be_bytes);
828 test_simple_int_bytes!(convert_u64_from_U64LE, u64, U64LE, to_le_bytes);
829 test_simple_int_bytes!(convert_u64_from_U64BE, u64, U64BE, to_be_bytes);
830
831 test_float_bytes!(convert_f32_fom_F32LE, f32, F32LE, to_le_bytes);
832 test_float_bytes!(convert_f32_fom_F32BE, f32, F32BE, to_be_bytes);
833 test_float_bytes!(convert_f64_fom_F64LE, f64, F64LE, to_le_bytes);
834 test_float_bytes!(convert_f64_fom_F64BE, f64, F64BE, to_be_bytes);
835
836 #[test]
837 #[allow(non_snake_case)]
838 fn test_I24LE_3bytes() {
839 let number = i32::MAX / 5 * 4;
840
841 let number = number >> 8;
843 let number = number << 8;
844
845 let allbytes = number.to_le_bytes();
846 let bytes = [allbytes[1], allbytes[2], allbytes[3]];
849
850 let wrapped = I24LE(bytes);
851 assert_eq!(number, wrapped.to_number());
852 }
853
854 #[test]
855 #[allow(non_snake_case)]
856 fn test_I24BE_3bytes() {
857 let number = i32::MAX / 5 * 4;
858
859 let number = number >> 8;
861 let number = number << 8;
862
863 let allbytes = number.to_be_bytes();
864 let bytes = [allbytes[0], allbytes[1], allbytes[2]];
867
868 let wrapped = I24BE(bytes);
869 assert_eq!(number, wrapped.to_number());
870 }
871
872 #[test]
873 #[allow(non_snake_case)]
874 fn test_I24LE_4bytes() {
875 let number = i32::MAX / 5 * 4;
876
877 let number = number >> 8;
879 let number = number << 8;
880
881 let allbytes = number.to_le_bytes();
882 let bytes = [allbytes[1], allbytes[2], allbytes[3], 0];
885
886 let wrapped = I24LE(bytes);
887 assert_eq!(number, wrapped.to_number());
888 }
889
890 #[test]
891 #[allow(non_snake_case)]
892 fn test_I24BE_4bytes() {
893 let number = i32::MAX / 5 * 4;
894
895 let number = number >> 8;
897 let number = number << 8;
898
899 let allbytes = number.to_be_bytes();
900 let bytes = [0, allbytes[0], allbytes[1], allbytes[2]];
903
904 let wrapped = I24BE(bytes);
905 assert_eq!(number, wrapped.to_number());
906 }
907
908 #[test]
909 #[allow(non_snake_case)]
910 fn test_U24LE_3bytes() {
911 let number = u32::MAX / 5 * 4;
912
913 let number = number >> 8;
915 let number = number << 8;
916
917 let allbytes = number.to_le_bytes();
918 let bytes = [allbytes[1], allbytes[2], allbytes[3]];
921
922 let wrapped = U24LE(bytes);
923 assert_eq!(number, wrapped.to_number());
924 }
925
926 #[test]
927 #[allow(non_snake_case)]
928 fn test_U24BE_3bytes() {
929 let number = u32::MAX / 5 * 4;
930
931 let number = number >> 8;
933 let number = number << 8;
934
935 let allbytes = number.to_be_bytes();
936 let bytes = [allbytes[0], allbytes[1], allbytes[2]];
939
940 let wrapped = U24BE(bytes);
941 assert_eq!(number, wrapped.to_number());
942 }
943
944 #[test]
945 #[allow(non_snake_case)]
946 fn test_U24LE_4bytes() {
947 let number = u32::MAX / 5 * 4;
948
949 let number = number >> 8;
951 let number = number << 8;
952
953 let allbytes = number.to_le_bytes();
954 let bytes = [allbytes[1], allbytes[2], allbytes[3], 0];
957
958 let wrapped = U24LE(bytes);
959 assert_eq!(number, wrapped.to_number());
960 }
961
962 #[test]
963 #[allow(non_snake_case)]
964 fn test_U24BE_4bytes() {
965 let number = u32::MAX / 5 * 4;
966
967 let number = number >> 8;
969 let number = number << 8;
970
971 let allbytes = number.to_be_bytes();
972 let bytes = [0, allbytes[0], allbytes[1], allbytes[2]];
975
976 let wrapped = U24BE(bytes);
977 assert_eq!(number, wrapped.to_number());
978 }
979}