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