audio_device/alsa/
sample.rs

1use crate::alsa::Format;
2
3/// Trait used to designate types which are sample-appropriate for
4/// [Pcm][super::Pcm].
5///
6/// # Safety
7///
8/// This trait is unsafe to implement, because an incorrectly implemented format
9/// test might have safety implications.
10pub unsafe trait Sample {
11    /// The default format to use for this sample.
12    const DEFAULT_FORMAT: Format;
13
14    /// Test if the given format is appropriate for this sample type.
15    fn test(format: Format) -> bool;
16
17    /// A static description of the sample type.
18    fn describe() -> &'static str;
19}
20
21macro_rules! implement {
22    ($ty:ty, $le:ident, $be:ident) => {
23        unsafe impl Sample for $ty {
24            #[cfg(target_endian = "little")]
25            const DEFAULT_FORMAT: Format = Format::$le;
26            #[cfg(target_endian = "big")]
27            const DEFAULT_FORMAT: Format = Format::$be;
28
29            fn test(format: Format) -> bool {
30                match format {
31                    #[cfg(target_endian = "little")]
32                    Format::$le => true,
33                    #[cfg(target_endian = "big")]
34                    Format::$be => true,
35                    _ => false,
36                }
37            }
38
39            #[cfg(target_endian = "little")]
40            fn describe() -> &'static str {
41                concat!(stringify!($ty), " (little endian)")
42            }
43
44            #[cfg(target_endian = "big")]
45            fn describe() -> &'static str {
46                concat!(stringify!($ty), " (big endian)")
47            }
48        }
49    };
50}
51
52unsafe impl Sample for u8 {
53    const DEFAULT_FORMAT: Format = Format::U8;
54
55    fn test(format: Format) -> bool {
56        matches!(format, Format::U8)
57    }
58
59    #[cfg(target_endian = "little")]
60    fn describe() -> &'static str {
61        "u8 (little endian)"
62    }
63
64    #[cfg(target_endian = "big")]
65    fn describe() -> &'static str {
66        "u8 (big endian)"
67    }
68}
69
70unsafe impl Sample for i8 {
71    const DEFAULT_FORMAT: Format = Format::S8;
72
73    fn test(format: Format) -> bool {
74        matches!(format, Format::S8)
75    }
76
77    #[cfg(target_endian = "little")]
78    fn describe() -> &'static str {
79        "i8 (little endian)"
80    }
81
82    #[cfg(target_endian = "big")]
83    fn describe() -> &'static str {
84        "i8 (big endian)"
85    }
86}
87
88implement!(i16, S16LE, S16BE);
89implement!(u16, U16LE, U16BE);
90implement!(i32, S32LE, S32BE);
91implement!(u32, U32LE, U32BE);
92implement!(f32, FloatLE, FloatBE);
93implement!(f64, Float64LE, Float64BE);