1#![allow(non_camel_case_types)]
2
3use num_traits::{PrimInt, ToPrimitive, float::FloatCore};
4
5#[cfg(feature = "audio")]
6use audio_core::Sample;
7
8#[derive(Debug, Clone, Copy)]
12pub struct I16_LE([u8; 2]);
13
14#[derive(Debug, Clone, Copy)]
16pub struct I16_BE([u8; 2]);
17
18#[derive(Debug, Clone, Copy)]
20pub struct U16_LE([u8; 2]);
21
22#[derive(Debug, Clone, Copy)]
24pub struct U16_BE([u8; 2]);
25
26#[derive(Debug, Clone, Copy)]
30pub struct I24_LE([u8; 3]);
31
32#[derive(Debug, Clone, Copy)]
36pub struct I24_4LJ_LE([u8; 4]);
37
38#[derive(Debug, Clone, Copy)]
42pub struct I24_4RJ_LE([u8; 4]);
43
44#[derive(Debug, Clone, Copy)]
46pub struct I24_BE([u8; 3]);
47
48#[derive(Debug, Clone, Copy)]
52pub struct I24_4LJ_BE([u8; 4]);
53
54#[derive(Debug, Clone, Copy)]
58pub struct I24_4RJ_BE([u8; 4]);
59
60#[derive(Debug, Clone, Copy)]
62pub struct U24_LE([u8; 3]);
63
64#[derive(Debug, Clone, Copy)]
68pub struct U24_4LJ_LE([u8; 4]);
69
70#[derive(Debug, Clone, Copy)]
74pub struct U24_4RJ_LE([u8; 4]);
75
76#[derive(Debug, Clone, Copy)]
78pub struct U24_BE([u8; 3]);
79
80#[derive(Debug, Clone, Copy)]
84pub struct U24_4LJ_BE([u8; 4]);
85
86#[derive(Debug, Clone, Copy)]
90pub struct U24_4RJ_BE([u8; 4]);
91
92#[derive(Debug, Clone, Copy)]
96pub struct I32_LE([u8; 4]);
97
98#[derive(Debug, Clone, Copy)]
100pub struct I32_BE([u8; 4]);
101
102#[derive(Debug, Clone, Copy)]
104pub struct U32_LE([u8; 4]);
105
106#[derive(Debug, Clone, Copy)]
108pub struct U32_BE([u8; 4]);
109
110#[derive(Debug, Clone, Copy)]
114pub struct I64_LE([u8; 8]);
115
116#[derive(Debug, Clone, Copy)]
118pub struct I64_BE([u8; 8]);
119
120#[derive(Debug, Clone, Copy)]
122pub struct U64_LE([u8; 8]);
123
124#[derive(Debug, Clone, Copy)]
126pub struct U64_BE([u8; 8]);
127
128#[derive(Debug, Clone, Copy)]
132pub struct F32_LE([u8; 4]);
133
134#[derive(Debug, Clone, Copy)]
136pub struct F32_BE([u8; 4]);
137
138#[derive(Debug, Clone, Copy)]
140pub struct F64_LE([u8; 8]);
141
142#[derive(Debug, Clone, Copy)]
144pub struct F64_BE([u8; 8]);
145
146fn to_clamped_int<T: FloatCore + ToPrimitive, U: PrimInt>(
148 value: T,
149 converted: Option<U>,
150) -> ConversionResult<U> {
151 if let Some(val) = converted {
152 return ConversionResult {
153 clipped: false,
154 value: val,
155 };
156 }
157 if value.is_nan() {
158 return ConversionResult {
159 clipped: true,
160 value: U::zero(),
161 };
162 }
163 if value > T::zero() {
164 return ConversionResult {
165 clipped: true,
166 value: U::max_value(),
167 };
168 }
169 ConversionResult {
170 clipped: true,
171 value: U::min_value(),
172 }
173}
174
175pub struct ConversionResult<T> {
178 pub clipped: bool,
179 pub value: T,
180}
181
182pub trait RawSample
192where
193 Self: Sized,
194{
195 fn to_scaled_float<T: FloatCore + ToPrimitive>(&self) -> T;
197
198 fn from_scaled_float<T: FloatCore + ToPrimitive>(value: T) -> ConversionResult<Self>;
201}
202
203pub trait BytesSample {
215 type NumericType: Copy;
217
218 const BYTES_PER_SAMPLE: usize;
220
221 fn from_slice(bytes: &[u8]) -> Self;
225
226 fn as_slice(&self) -> &[u8];
228
229 fn as_mut_slice(&mut self) -> &mut [u8];
231
232 fn to_number(&self) -> Self::NumericType;
234
235 fn from_number(value: Self::NumericType) -> Self;
237}
238
239macro_rules! rawsample_for_int {
240 ($type:ident, $to:ident) => {
241 impl RawSample for $type {
242 fn to_scaled_float<T: FloatCore + ToPrimitive>(&self) -> T {
243 T::from(*self).unwrap() / (T::from($type::MAX).unwrap() + T::one())
244 }
245
246 fn from_scaled_float<T: FloatCore + ToPrimitive>(value: T) -> ConversionResult<Self> {
247 let scaled = value * (T::from($type::MAX).unwrap() + T::one());
248 let converted = scaled.$to();
249 to_clamped_int(scaled, converted)
250 }
251 }
252 };
253}
254
255rawsample_for_int!(i8, to_i8);
256rawsample_for_int!(i16, to_i16);
257rawsample_for_int!(i32, to_i32);
258rawsample_for_int!(i64, to_i64);
259
260macro_rules! rawsample_for_uint {
261 ($type:ident, $to:ident) => {
262 impl RawSample for $type {
263 fn to_scaled_float<T: FloatCore + ToPrimitive>(&self) -> T {
264 let max_ampl = (T::from($type::MAX).unwrap() + T::one()) / T::from(2).unwrap();
265 (T::from(*self).unwrap() - max_ampl) / max_ampl
266 }
267
268 fn from_scaled_float<T: FloatCore + ToPrimitive>(value: T) -> ConversionResult<Self> {
269 let max_ampl = (T::from($type::MAX).unwrap() + T::one()) / T::from(2).unwrap();
270 let scaled = value * max_ampl + max_ampl;
271 let converted = scaled.$to();
272 to_clamped_int(scaled, converted)
273 }
274 }
275 };
276}
277
278rawsample_for_uint!(u8, to_u8);
279rawsample_for_uint!(u16, to_u16);
280rawsample_for_uint!(u32, to_u32);
281rawsample_for_uint!(u64, to_u64);
282
283macro_rules! rawsample_for_float {
284 ($type:ident, $to:ident) => {
285 impl RawSample for $type {
286 fn to_scaled_float<T: FloatCore + ToPrimitive>(&self) -> T {
287 T::from(*self).unwrap_or(T::zero())
288 }
289
290 fn from_scaled_float<T: FloatCore + ToPrimitive>(value: T) -> ConversionResult<Self> {
291 ConversionResult {
293 clipped: false,
294 value: value.$to().unwrap_or(0.0),
295 }
296 }
297 }
298 };
299}
300
301rawsample_for_float!(f32, to_f32);
302rawsample_for_float!(f64, to_f64);
303
304impl BytesSample for I24_4RJ_LE {
310 type NumericType = i32;
311 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
312
313 fn from_slice(bytes: &[u8]) -> Self {
314 Self(bytes[0..4].try_into().unwrap())
315 }
316
317 fn as_slice(&self) -> &[u8] {
318 &self.0
319 }
320
321 fn as_mut_slice(&mut self) -> &mut [u8] {
322 &mut self.0
323 }
324
325 fn to_number(&self) -> Self::NumericType {
326 let padded = [0, self.0[0], self.0[1], self.0[2]];
327 i32::from_le_bytes(padded)
328 }
329
330 fn from_number(value: Self::NumericType) -> Self {
331 let bytes = value.to_le_bytes();
332 Self([bytes[1], bytes[2], bytes[3], 0])
333 }
334}
335
336impl BytesSample for I24_4LJ_LE {
339 type NumericType = i32;
340 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
341
342 fn from_slice(bytes: &[u8]) -> Self {
343 Self(bytes[0..4].try_into().unwrap())
344 }
345
346 fn as_slice(&self) -> &[u8] {
347 &self.0
348 }
349
350 fn as_mut_slice(&mut self) -> &mut [u8] {
351 &mut self.0
352 }
353
354 fn to_number(&self) -> Self::NumericType {
355 let padded = [0, self.0[1], self.0[2], self.0[3]];
356 i32::from_le_bytes(padded)
357 }
358
359 fn from_number(value: Self::NumericType) -> Self {
360 let bytes = value.to_le_bytes();
361 Self([0, bytes[1], bytes[2], bytes[3]])
362 }
363}
364
365impl BytesSample for I24_LE {
367 type NumericType = i32;
368 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
369
370 fn from_slice(bytes: &[u8]) -> Self {
371 Self(bytes[0..3].try_into().unwrap())
372 }
373
374 fn as_slice(&self) -> &[u8] {
375 &self.0
376 }
377
378 fn as_mut_slice(&mut self) -> &mut [u8] {
379 &mut self.0
380 }
381
382 fn to_number(&self) -> Self::NumericType {
383 let padded = [0, self.0[0], self.0[1], self.0[2]];
384 i32::from_le_bytes(padded)
385 }
386
387 fn from_number(value: Self::NumericType) -> Self {
388 let bytes = value.to_le_bytes();
389 Self([bytes[1], bytes[2], bytes[3]])
390 }
391}
392
393impl BytesSample for I24_4RJ_BE {
396 type NumericType = i32;
397 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
398
399 fn from_slice(bytes: &[u8]) -> Self {
400 Self(bytes[0..4].try_into().unwrap())
401 }
402
403 fn as_slice(&self) -> &[u8] {
404 &self.0
405 }
406
407 fn as_mut_slice(&mut self) -> &mut [u8] {
408 &mut self.0
409 }
410
411 fn to_number(&self) -> Self::NumericType {
412 let padded = [self.0[1], self.0[2], self.0[3], 0];
413 i32::from_be_bytes(padded)
414 }
415
416 fn from_number(value: Self::NumericType) -> Self {
417 let bytes = value.to_be_bytes();
418 Self([0, bytes[0], bytes[1], bytes[2]])
419 }
420}
421
422impl BytesSample for I24_4LJ_BE {
425 type NumericType = i32;
426 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
427
428 fn from_slice(bytes: &[u8]) -> Self {
429 Self(bytes[0..4].try_into().unwrap())
430 }
431
432 fn as_slice(&self) -> &[u8] {
433 &self.0
434 }
435
436 fn as_mut_slice(&mut self) -> &mut [u8] {
437 &mut self.0
438 }
439
440 fn to_number(&self) -> Self::NumericType {
441 let padded = [self.0[0], self.0[1], self.0[2], 0];
442 i32::from_be_bytes(padded)
443 }
444
445 fn from_number(value: Self::NumericType) -> Self {
446 let bytes = value.to_be_bytes();
447 Self([bytes[0], bytes[1], bytes[2], 0])
448 }
449}
450
451impl BytesSample for I24_BE {
453 type NumericType = i32;
454 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
455
456 fn from_slice(bytes: &[u8]) -> Self {
457 Self(bytes[0..3].try_into().unwrap())
458 }
459
460 fn as_slice(&self) -> &[u8] {
461 &self.0
462 }
463
464 fn as_mut_slice(&mut self) -> &mut [u8] {
465 &mut self.0
466 }
467
468 fn to_number(&self) -> Self::NumericType {
469 let padded = [self.0[0], self.0[1], self.0[2], 0];
470 i32::from_be_bytes(padded)
471 }
472
473 fn from_number(value: Self::NumericType) -> Self {
474 let bytes = value.to_be_bytes();
475 Self([bytes[0], bytes[1], bytes[2]])
476 }
477}
478
479impl BytesSample for U24_4RJ_LE {
482 type NumericType = u32;
483 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
484
485 fn from_slice(bytes: &[u8]) -> Self {
486 Self(bytes[0..4].try_into().unwrap())
487 }
488
489 fn as_slice(&self) -> &[u8] {
490 &self.0
491 }
492
493 fn as_mut_slice(&mut self) -> &mut [u8] {
494 &mut self.0
495 }
496
497 fn to_number(&self) -> Self::NumericType {
498 let padded = [0, self.0[0], self.0[1], self.0[2]];
499 u32::from_le_bytes(padded)
500 }
501
502 fn from_number(value: Self::NumericType) -> Self {
503 let bytes = value.to_le_bytes();
504 Self([bytes[1], bytes[2], bytes[3], 0])
505 }
506}
507
508impl BytesSample for U24_4LJ_LE {
511 type NumericType = u32;
512 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
513
514 fn from_slice(bytes: &[u8]) -> Self {
515 Self(bytes[0..4].try_into().unwrap())
516 }
517
518 fn as_slice(&self) -> &[u8] {
519 &self.0
520 }
521
522 fn as_mut_slice(&mut self) -> &mut [u8] {
523 &mut self.0
524 }
525
526 fn to_number(&self) -> Self::NumericType {
527 let padded = [0, self.0[1], self.0[2], self.0[3]];
528 u32::from_le_bytes(padded)
529 }
530
531 fn from_number(value: Self::NumericType) -> Self {
532 let bytes = value.to_le_bytes();
533 Self([0, bytes[1], bytes[2], bytes[3]])
534 }
535}
536
537impl BytesSample for U24_LE {
539 type NumericType = u32;
540 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
541
542 fn from_slice(bytes: &[u8]) -> Self {
543 Self(bytes[0..3].try_into().unwrap())
544 }
545
546 fn as_slice(&self) -> &[u8] {
547 &self.0
548 }
549
550 fn as_mut_slice(&mut self) -> &mut [u8] {
551 &mut self.0
552 }
553
554 fn to_number(&self) -> Self::NumericType {
555 let padded = [0, self.0[0], self.0[1], self.0[2]];
556 u32::from_le_bytes(padded)
557 }
558
559 fn from_number(value: Self::NumericType) -> Self {
560 let bytes = value.to_le_bytes();
561 Self([bytes[1], bytes[2], bytes[3]])
562 }
563}
564
565impl BytesSample for U24_4RJ_BE {
568 type NumericType = u32;
569 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
570
571 fn from_slice(bytes: &[u8]) -> Self {
572 Self(bytes[0..4].try_into().unwrap())
573 }
574
575 fn as_slice(&self) -> &[u8] {
576 &self.0
577 }
578
579 fn as_mut_slice(&mut self) -> &mut [u8] {
580 &mut self.0
581 }
582
583 fn to_number(&self) -> Self::NumericType {
584 let padded = [self.0[1], self.0[2], self.0[3], 0];
585 u32::from_be_bytes(padded)
586 }
587
588 fn from_number(value: Self::NumericType) -> Self {
589 let bytes = value.to_be_bytes();
590 Self([0, bytes[0], bytes[1], bytes[2]])
591 }
592}
593
594impl BytesSample for U24_4LJ_BE {
597 type NumericType = u32;
598 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
599
600 fn from_slice(bytes: &[u8]) -> Self {
601 Self(bytes[0..4].try_into().unwrap())
602 }
603
604 fn as_slice(&self) -> &[u8] {
605 &self.0
606 }
607
608 fn as_mut_slice(&mut self) -> &mut [u8] {
609 &mut self.0
610 }
611
612 fn to_number(&self) -> Self::NumericType {
613 let padded = [self.0[0], self.0[1], self.0[2], 0];
614 u32::from_be_bytes(padded)
615 }
616
617 fn from_number(value: Self::NumericType) -> Self {
618 let bytes = value.to_be_bytes();
619 Self([bytes[0], bytes[1], bytes[2], 0])
620 }
621}
622
623impl BytesSample for U24_BE {
625 type NumericType = u32;
626 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<Self>();
627
628 fn from_slice(bytes: &[u8]) -> Self {
629 Self(bytes[0..3].try_into().unwrap())
630 }
631
632 fn as_slice(&self) -> &[u8] {
633 &self.0
634 }
635
636 fn as_mut_slice(&mut self) -> &mut [u8] {
637 &mut self.0
638 }
639
640 fn to_number(&self) -> Self::NumericType {
641 let padded = [self.0[0], self.0[1], self.0[2], 0];
642 u32::from_be_bytes(padded)
643 }
644
645 fn from_number(value: Self::NumericType) -> Self {
646 let bytes = value.to_be_bytes();
647 Self([bytes[0], bytes[1], bytes[2]])
648 }
649}
650
651macro_rules! bytessample_for_newtype {
652 ($type:ident, $newtype:ident, $from:ident, $to:ident) => {
653 impl BytesSample for $newtype {
654 type NumericType = $type;
655 const BYTES_PER_SAMPLE: usize = core::mem::size_of::<$type>();
656
657 fn from_slice(bytes: &[u8]) -> Self {
658 Self(bytes.try_into().unwrap())
659 }
660
661 fn as_slice(&self) -> &[u8] {
662 &self.0
663 }
664
665 fn as_mut_slice(&mut self) -> &mut [u8] {
666 &mut self.0
667 }
668
669 fn to_number(&self) -> Self::NumericType {
670 $type::$from(self.0)
671 }
672
673 fn from_number(value: Self::NumericType) -> Self {
674 Self(value.$to())
675 }
676 }
677 };
678}
679
680bytessample_for_newtype!(i64, I64_LE, from_le_bytes, to_le_bytes);
681bytessample_for_newtype!(u64, U64_LE, from_le_bytes, to_le_bytes);
682bytessample_for_newtype!(i64, I64_BE, from_be_bytes, to_be_bytes);
683bytessample_for_newtype!(u64, U64_BE, from_be_bytes, to_be_bytes);
684
685bytessample_for_newtype!(i16, I16_LE, from_le_bytes, to_le_bytes);
686bytessample_for_newtype!(u16, U16_LE, from_le_bytes, to_le_bytes);
687bytessample_for_newtype!(i16, I16_BE, from_be_bytes, to_be_bytes);
688bytessample_for_newtype!(u16, U16_BE, from_be_bytes, to_be_bytes);
689
690bytessample_for_newtype!(i32, I32_LE, from_le_bytes, to_le_bytes);
691bytessample_for_newtype!(u32, U32_LE, from_le_bytes, to_le_bytes);
692bytessample_for_newtype!(i32, I32_BE, from_be_bytes, to_be_bytes);
693bytessample_for_newtype!(u32, U32_BE, from_be_bytes, to_be_bytes);
694
695bytessample_for_newtype!(f32, F32_LE, from_le_bytes, to_le_bytes);
696bytessample_for_newtype!(f32, F32_BE, from_be_bytes, to_be_bytes);
697bytessample_for_newtype!(f64, F64_LE, from_le_bytes, to_le_bytes);
698bytessample_for_newtype!(f64, F64_BE, from_be_bytes, to_be_bytes);
699
700impl<V> RawSample for V
701where
702 V: BytesSample,
703 <V as BytesSample>::NumericType: RawSample,
704{
705 fn to_scaled_float<T: FloatCore + ToPrimitive>(&self) -> T {
706 let value = self.to_number();
707 value.to_scaled_float()
708 }
709
710 fn from_scaled_float<T: FloatCore + ToPrimitive>(value: T) -> ConversionResult<Self> {
711 let value = <V as BytesSample>::NumericType::from_scaled_float(value);
712 ConversionResult {
713 clipped: value.clipped,
714 value: V::from_number(value.value),
715 }
716 }
717}
718
719#[cfg(feature = "audio")]
721macro_rules! impl_sample_for_newtype {
722 ($newtype:ident, $bytes:expr) => {
723 unsafe impl Sample for $newtype {
724 const ZERO: $newtype = $newtype([0; $bytes]);
725 }
726 };
727}
728
729#[cfg(feature = "audio")]
730impl_sample_for_newtype!(I16_LE, 2);
731#[cfg(feature = "audio")]
732impl_sample_for_newtype!(U16_LE, 2);
733#[cfg(feature = "audio")]
734impl_sample_for_newtype!(I16_BE, 2);
735#[cfg(feature = "audio")]
736impl_sample_for_newtype!(U16_BE, 2);
737#[cfg(feature = "audio")]
738impl_sample_for_newtype!(I24_LE, 3);
739#[cfg(feature = "audio")]
740impl_sample_for_newtype!(I24_4LJ_LE, 4);
741#[cfg(feature = "audio")]
742impl_sample_for_newtype!(I24_4RJ_LE, 4);
743#[cfg(feature = "audio")]
744impl_sample_for_newtype!(U24_LE, 3);
745#[cfg(feature = "audio")]
746impl_sample_for_newtype!(U24_4LJ_LE, 4);
747#[cfg(feature = "audio")]
748impl_sample_for_newtype!(U24_4RJ_LE, 4);
749#[cfg(feature = "audio")]
750impl_sample_for_newtype!(I24_BE, 3);
751#[cfg(feature = "audio")]
752impl_sample_for_newtype!(I24_4LJ_BE, 4);
753#[cfg(feature = "audio")]
754impl_sample_for_newtype!(I24_4RJ_BE, 4);
755#[cfg(feature = "audio")]
756impl_sample_for_newtype!(U24_BE, 3);
757#[cfg(feature = "audio")]
758impl_sample_for_newtype!(U24_4LJ_BE, 4);
759#[cfg(feature = "audio")]
760impl_sample_for_newtype!(U24_4RJ_BE, 4);
761#[cfg(feature = "audio")]
762impl_sample_for_newtype!(I32_LE, 4);
763#[cfg(feature = "audio")]
764impl_sample_for_newtype!(U32_LE, 4);
765#[cfg(feature = "audio")]
766impl_sample_for_newtype!(I32_BE, 4);
767#[cfg(feature = "audio")]
768impl_sample_for_newtype!(U32_BE, 4);
769#[cfg(feature = "audio")]
770impl_sample_for_newtype!(I64_LE, 8);
771#[cfg(feature = "audio")]
772impl_sample_for_newtype!(U64_LE, 8);
773#[cfg(feature = "audio")]
774impl_sample_for_newtype!(I64_BE, 8);
775#[cfg(feature = "audio")]
776impl_sample_for_newtype!(U64_BE, 8);
777#[cfg(feature = "audio")]
778impl_sample_for_newtype!(F32_LE, 4);
779#[cfg(feature = "audio")]
780impl_sample_for_newtype!(F32_BE, 4);
781#[cfg(feature = "audio")]
782impl_sample_for_newtype!(F64_LE, 8);
783#[cfg(feature = "audio")]
784impl_sample_for_newtype!(F64_BE, 8);
785
786#[cfg(test)]
787mod tests {
788 use super::*;
789
790 macro_rules! assert_conversion_eq {
791 ($result:expr, $value:expr, $clipped:expr, $desc:expr) => {
792 assert_eq!($result.value, $value, $desc);
793 assert_eq!($result.clipped, $clipped, $desc);
794 };
795 }
796
797 macro_rules! test_to_signed_int {
798 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
799 #[test]
800 fn $fname() {
801 let val: $float = 0.25;
802 assert_conversion_eq!(
803 $int::from_scaled_float(val),
804 1 << ($bits - 3),
805 false,
806 "check +0.25"
807 );
808 let val: $float = -0.25;
809 assert_conversion_eq!(
810 $int::from_scaled_float(val),
811 -1 << ($bits - 3),
812 false,
813 "check -0.25"
814 );
815 let val: $float = 1.1;
816 assert_conversion_eq!(
817 $int::from_scaled_float(val),
818 $int::MAX,
819 true,
820 "clipped positive"
821 );
822 let val: $float = -1.1;
823 assert_conversion_eq!(
824 $int::from_scaled_float(val),
825 $int::MIN,
826 true,
827 "clipped negative"
828 );
829 }
830 };
831 }
832
833 macro_rules! test_to_unsigned_int {
834 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
835 #[test]
836 fn $fname() {
837 let val: $float = -0.5;
838 assert_conversion_eq!(
839 $int::from_scaled_float(val),
840 1 << ($bits - 2),
841 false,
842 "check -0.5"
843 );
844 let val: $float = 0.5;
845 assert_conversion_eq!(
846 $int::from_scaled_float(val),
847 $int::MAX - (1 << ($bits - 2)) + 1,
848 false,
849 "check 0.5"
850 );
851 let val: $float = 1.1;
852 assert_conversion_eq!(
853 $int::from_scaled_float(val),
854 $int::MAX,
855 true,
856 "clipped positive"
857 );
858 let val: $float = -1.1;
859 assert_conversion_eq!(
860 $int::from_scaled_float(val),
861 $int::MIN,
862 true,
863 "clipped negative"
864 );
865 }
866 };
867 }
868
869 test_to_signed_int!(convert_f32_to_i8, f32, i8, 8);
870 test_to_signed_int!(convert_642_to_i8, f64, i8, 8);
871 test_to_signed_int!(convert_f32_to_i16, f32, i16, 16);
872 test_to_signed_int!(convert_f64_to_i16, f64, i16, 16);
873 test_to_signed_int!(convert_f32_to_i32, f32, i32, 32);
874 test_to_signed_int!(convert_f64_to_i32, f64, i32, 32);
875 test_to_signed_int!(convert_f32_to_i64, f32, i64, 64);
876 test_to_signed_int!(convert_f64_to_i64, f64, i64, 64);
877
878 test_to_unsigned_int!(convert_f32_to_u8, f32, u8, 8);
879 test_to_unsigned_int!(convert_f64_to_u8, f64, u8, 8);
880 test_to_unsigned_int!(convert_f32_to_u16, f32, u16, 16);
881 test_to_unsigned_int!(convert_f64_to_u16, f64, u16, 16);
882 test_to_unsigned_int!(convert_f32_to_u32, f32, u32, 32);
883 test_to_unsigned_int!(convert_f64_to_u32, f64, u32, 32);
884 test_to_unsigned_int!(convert_f32_to_u64, f32, u64, 64);
885 test_to_unsigned_int!(convert_f64_to_u64, f64, u64, 64);
886
887 macro_rules! test_from_signed_int {
888 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
889 #[test]
890 fn $fname() {
891 let val: $int = -1 << ($bits - 2);
892 assert_eq!(val.to_scaled_float::<$float>(), -0.5, "check -0.5");
893 let val: $int = 1 << ($bits - 2);
894 assert_eq!(val.to_scaled_float::<$float>(), 0.5, "check 0.5");
895 let val: $int = $int::MIN;
896 assert_eq!(val.to_scaled_float::<$float>(), -1.0, "negative limit");
897 }
898 };
899 }
900
901 macro_rules! test_from_unsigned_int {
902 ($fname:ident, $float:ty, $int:ident, $bits:expr) => {
903 #[test]
904 fn $fname() {
905 let val: $int = 1 << ($bits - 2);
906 assert_eq!(val.to_scaled_float::<$float>(), -0.5, "check -0.5");
907 let val: $int = $int::MAX - (1 << ($bits - 2)) + 1;
908 assert_eq!(val.to_scaled_float::<$float>(), 0.5, "check 0.5");
909 let val: $int = 0;
910 assert_eq!(val.to_scaled_float::<$float>(), -1.0, "negative limit");
911 }
912 };
913 }
914
915 test_from_signed_int!(convert_f32_from_i8, f32, i8, 8);
916 test_from_signed_int!(convert_f64_from_i8, f64, i8, 8);
917 test_from_signed_int!(convert_f32_from_i16, f32, i16, 16);
918 test_from_signed_int!(convert_f64_from_i16, f64, i16, 16);
919 test_from_signed_int!(convert_f32_from_i32, f32, i32, 32);
920 test_from_signed_int!(convert_f64_from_i32, f64, i32, 32);
921 test_from_signed_int!(convert_f32_from_i64, f32, i64, 64);
922 test_from_signed_int!(convert_f64_from_i64, f64, i64, 64);
923
924 test_from_unsigned_int!(convert_f32_from_u8, f32, u8, 8);
925 test_from_unsigned_int!(convert_f64_from_u8, f64, u8, 8);
926 test_from_unsigned_int!(convert_f32_from_u16, f32, u16, 16);
927 test_from_unsigned_int!(convert_f64_from_u16, f64, u16, 16);
928 test_from_unsigned_int!(convert_f32_from_u32, f32, u32, 32);
929 test_from_unsigned_int!(convert_f64_from_u32, f64, u32, 32);
930 test_from_unsigned_int!(convert_f32_from_u64, f32, u64, 64);
931 test_from_unsigned_int!(convert_f64_from_u64, f64, u64, 64);
932
933 #[test]
934 fn test_to_clamped_int() {
935 let converted = to_clamped_int::<f32, i32>(12345.0, Some(12345));
936 assert_conversion_eq!(converted, 12345, false, "in range f32 i32");
937
938 let converted = to_clamped_int::<f32, i32>(1.0e10, None);
939 assert_conversion_eq!(converted, i32::MAX, true, "above range f32 i32");
940
941 let converted = to_clamped_int::<f32, i32>(-1.0e10, None);
942 assert_conversion_eq!(converted, i32::MIN, true, "below range f32 i32");
943
944 let converted = to_clamped_int::<f64, i32>(12345.0, Some(12345));
945 assert_conversion_eq!(converted, 12345, false, "in range f64 i32");
946
947 let converted = to_clamped_int::<f64, i32>(1.0e10, None);
948 assert_conversion_eq!(converted, i32::MAX, true, "above range f64 i32");
949
950 let converted = to_clamped_int::<f64, i32>(-1.0e10, None);
951 assert_conversion_eq!(converted, i32::MIN, true, "below range f64 i32");
952 }
953
954 #[test]
955 fn test_to_clamped_uint() {
956 let converted = to_clamped_int::<f32, u32>(12345.0, Some(12345));
957 assert_conversion_eq!(converted, 12345, false, "in range f32 u32");
958
959 let converted = to_clamped_int::<f32, u32>(1.0e10, None);
960 assert_conversion_eq!(converted, u32::MAX, true, "above range f32 u32");
961
962 let converted = to_clamped_int::<f32, u32>(-1.0, None);
963 assert_conversion_eq!(converted, u32::MIN, true, "below range f32 u32");
964
965 let converted = to_clamped_int::<f64, u32>(12345.0, Some(12345));
966 assert_conversion_eq!(converted, 12345, false, "in range f64 u32");
967
968 let converted = to_clamped_int::<f64, u32>(1.0e10, None);
969 assert_conversion_eq!(converted, u32::MAX, true, "above range f64 u32");
970
971 let converted = to_clamped_int::<f64, u32>(-1.0, None);
972 assert_conversion_eq!(converted, u32::MIN, true, "below range f64 u32");
973 }
974
975 macro_rules! test_simple_int_bytes {
976 ($fname:ident, $number:ty, $wrapper:ident, $to_bytes_fn:ident) => {
977 #[test]
978 #[allow(non_snake_case)]
979 fn $fname() {
980 let number: $number = <$number>::MAX / 5 * 4;
981 let wrapped = $wrapper(number.$to_bytes_fn());
982 assert_eq!(number, wrapped.to_number());
983 }
984 };
985 }
986
987 macro_rules! test_float_bytes {
988 ($fname:ident, $number:ty, $wrapper:ident, $to_bytes_fn:ident) => {
989 #[test]
990 #[allow(non_snake_case)]
991 fn $fname() {
992 let number: $number = 12345.0;
993 let wrapped = $wrapper(number.$to_bytes_fn());
994 assert_eq!(number, wrapped.to_number());
995 }
996 };
997 }
998
999 test_simple_int_bytes!(convert_i16_from_I16_LE, i16, I16_LE, to_le_bytes);
1000 test_simple_int_bytes!(convert_i16_from_I16_BE, i16, I16_BE, to_be_bytes);
1001 test_simple_int_bytes!(convert_i32_from_I32_LE, i32, I32_LE, to_le_bytes);
1002 test_simple_int_bytes!(convert_i32_from_I32_BE, i32, I32_BE, to_be_bytes);
1003 test_simple_int_bytes!(convert_i64_from_I64_LE, i64, I64_LE, to_le_bytes);
1004 test_simple_int_bytes!(convert_i64_from_I64_BE, i64, I64_BE, to_be_bytes);
1005
1006 test_simple_int_bytes!(convert_u16_from_U16_LE, u16, U16_LE, to_le_bytes);
1007 test_simple_int_bytes!(convert_u16_from_U16_BE, u16, U16_BE, to_be_bytes);
1008 test_simple_int_bytes!(convert_u32_from_U32_LE, u32, U32_LE, to_le_bytes);
1009 test_simple_int_bytes!(convert_u32_from_U32_BE, u32, U32_BE, to_be_bytes);
1010 test_simple_int_bytes!(convert_u64_from_U64_LE, u64, U64_LE, to_le_bytes);
1011 test_simple_int_bytes!(convert_u64_from_U64_BE, u64, U64_BE, to_be_bytes);
1012
1013 test_float_bytes!(convert_f32_fom_F32_LE, f32, F32_LE, to_le_bytes);
1014 test_float_bytes!(convert_f32_fom_F32_BE, f32, F32_BE, to_be_bytes);
1015 test_float_bytes!(convert_f64_fom_F64_LE, f64, F64_LE, to_le_bytes);
1016 test_float_bytes!(convert_f64_fom_F64_BE, f64, F64_BE, to_be_bytes);
1017
1018 #[test]
1019 #[allow(non_snake_case)]
1020 fn test_I24_LE() {
1021 let number = i32::MAX / 5 * 4;
1022
1023 let number = number >> 8;
1025 let number = number << 8;
1026
1027 let allbytes = number.to_le_bytes();
1028 let bytes = [allbytes[1], allbytes[2], allbytes[3]];
1031
1032 let wrapped = I24_LE(bytes);
1033 assert_eq!(number, wrapped.to_number());
1034 }
1035
1036 #[test]
1037 #[allow(non_snake_case)]
1038 fn test_I24_BE() {
1039 let number = i32::MAX / 5 * 4;
1040
1041 let number = number >> 8;
1043 let number = number << 8;
1044
1045 let allbytes = number.to_be_bytes();
1046 let bytes = [allbytes[0], allbytes[1], allbytes[2]];
1049
1050 let wrapped = I24_BE(bytes);
1051 assert_eq!(number, wrapped.to_number());
1052 }
1053
1054 #[test]
1055 #[allow(non_snake_case)]
1056 fn test_I24_4RJ_LE() {
1057 let number = i32::MAX / 5 * 4;
1058
1059 let number = number >> 8;
1061 let number = number << 8;
1062
1063 let allbytes = number.to_le_bytes();
1064 let bytes = [allbytes[1], allbytes[2], allbytes[3], 0];
1067
1068 let wrapped = I24_4RJ_LE(bytes);
1069 assert_eq!(number, wrapped.to_number());
1070 }
1071
1072 #[test]
1073 #[allow(non_snake_case)]
1074 fn test_I24_4RJ_BE() {
1075 let number = i32::MAX / 5 * 4;
1076
1077 let number = number >> 8;
1079 let number = number << 8;
1080
1081 let allbytes = number.to_be_bytes();
1082 let bytes = [0, allbytes[0], allbytes[1], allbytes[2]];
1085
1086 let wrapped = I24_4RJ_BE(bytes);
1087 assert_eq!(number, wrapped.to_number());
1088 }
1089
1090 #[test]
1091 #[allow(non_snake_case)]
1092 fn test_I24_4LJ_LE() {
1093 let number = i32::MAX / 5 * 4;
1094
1095 let number = number >> 8;
1097 let number = number << 8;
1098
1099 let allbytes = number.to_le_bytes();
1100 let bytes = [0, allbytes[1], allbytes[2], allbytes[3]];
1103
1104 let wrapped = I24_4LJ_LE(bytes);
1105 assert_eq!(number, wrapped.to_number());
1106 }
1107
1108 #[test]
1109 #[allow(non_snake_case)]
1110 fn test_I24_4LJ_BE() {
1111 let number = i32::MAX / 5 * 4;
1112
1113 let number = number >> 8;
1115 let number = number << 8;
1116
1117 let allbytes = number.to_be_bytes();
1118 let bytes = [allbytes[0], allbytes[1], allbytes[2], 0];
1121
1122 let wrapped = I24_4LJ_BE(bytes);
1123 assert_eq!(number, wrapped.to_number());
1124 }
1125
1126 #[test]
1127 #[allow(non_snake_case)]
1128 fn test_U24_LE() {
1129 let number = u32::MAX / 5 * 4;
1130
1131 let number = number >> 8;
1133 let number = number << 8;
1134
1135 let allbytes = number.to_le_bytes();
1136 let bytes = [allbytes[1], allbytes[2], allbytes[3]];
1139
1140 let wrapped = U24_LE(bytes);
1141 assert_eq!(number, wrapped.to_number());
1142 }
1143
1144 #[test]
1145 #[allow(non_snake_case)]
1146 fn test_U24_BE() {
1147 let number = u32::MAX / 5 * 4;
1148
1149 let number = number >> 8;
1151 let number = number << 8;
1152
1153 let allbytes = number.to_be_bytes();
1154 let bytes = [allbytes[0], allbytes[1], allbytes[2]];
1157
1158 let wrapped = U24_BE(bytes);
1159 assert_eq!(number, wrapped.to_number());
1160 }
1161
1162 #[test]
1163 #[allow(non_snake_case)]
1164 fn test_U24_4RJ_LE() {
1165 let number = u32::MAX / 5 * 4;
1166
1167 let number = number >> 8;
1169 let number = number << 8;
1170
1171 let allbytes = number.to_le_bytes();
1172 let bytes = [allbytes[1], allbytes[2], allbytes[3], 0];
1175
1176 let wrapped = U24_4RJ_LE(bytes);
1177 assert_eq!(number, wrapped.to_number());
1178 }
1179
1180 #[test]
1181 #[allow(non_snake_case)]
1182 fn test_U24_4RJ_BE() {
1183 let number = u32::MAX / 5 * 4;
1184
1185 let number = number >> 8;
1187 let number = number << 8;
1188
1189 let allbytes = number.to_be_bytes();
1190 let bytes = [0, allbytes[0], allbytes[1], allbytes[2]];
1193
1194 let wrapped = U24_4RJ_BE(bytes);
1195 assert_eq!(number, wrapped.to_number());
1196 }
1197
1198 #[test]
1199 #[allow(non_snake_case)]
1200 fn test_U24_4LJ_LE() {
1201 let number = u32::MAX / 5 * 4;
1202
1203 let number = number >> 8;
1205 let number = number << 8;
1206
1207 let allbytes = number.to_le_bytes();
1208 let bytes = [0, allbytes[1], allbytes[2], allbytes[3]];
1211
1212 let wrapped = U24_4LJ_LE(bytes);
1213 assert_eq!(number, wrapped.to_number());
1214 }
1215
1216 #[test]
1217 #[allow(non_snake_case)]
1218 fn test_U24_4LJ_BE() {
1219 let number = u32::MAX / 5 * 4;
1220
1221 let number = number >> 8;
1223 let number = number << 8;
1224
1225 let allbytes = number.to_be_bytes();
1226 let bytes = [allbytes[0], allbytes[1], allbytes[2], 0];
1229
1230 let wrapped = U24_4LJ_BE(bytes);
1231 assert_eq!(number, wrapped.to_number());
1232 }
1233}