#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[repr(transparent)]
pub struct BufferFlags(pub i32);
impl BufferFlags {
pub const INVALID: Self = Self(0);
pub const VALID: Self = Self(1);
pub const SILENT: Self = Self(2);
#[inline]
#[must_use]
pub const fn is_valid(self) -> bool {
self.0 == Self::VALID.0
}
#[inline]
#[must_use]
pub const fn is_silent(self) -> bool {
self.0 == Self::SILENT.0
}
#[inline]
#[must_use]
pub const fn is_invalid(self) -> bool {
self.0 == Self::INVALID.0
}
}
impl Default for BufferFlags {
#[inline]
fn default() -> Self {
Self::INVALID
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct ConnectionProperty {
pub buffer: usize,
pub valid_frame_count: u32,
pub flags: BufferFlags,
pub signature: u32,
}
impl ConnectionProperty {
#[inline]
#[must_use]
pub const fn empty() -> Self {
Self {
buffer: 0,
valid_frame_count: 0,
flags: BufferFlags::INVALID,
signature: CONNECTION_PROPERTY_SIGNATURE,
}
}
}
pub const CONNECTION_PROPERTY_SIGNATURE: u32 = u32::from_be_bytes([b'A', b'P', b'O', b'C']);
#[cfg(windows)]
impl From<windows::Win32::Media::Audio::Apo::APO_BUFFER_FLAGS> for BufferFlags {
#[inline]
fn from(value: windows::Win32::Media::Audio::Apo::APO_BUFFER_FLAGS) -> Self {
Self(value.0)
}
}
#[cfg(windows)]
impl From<BufferFlags> for windows::Win32::Media::Audio::Apo::APO_BUFFER_FLAGS {
#[inline]
fn from(value: BufferFlags) -> Self {
Self(value.0)
}
}
#[cfg(windows)]
impl From<windows::Win32::Media::Audio::Apo::APO_CONNECTION_PROPERTY> for ConnectionProperty {
#[inline]
fn from(value: windows::Win32::Media::Audio::Apo::APO_CONNECTION_PROPERTY) -> Self {
Self {
buffer: value.pBuffer,
valid_frame_count: value.u32ValidFrameCount,
flags: value.u32BufferFlags.into(),
signature: value.u32Signature,
}
}
}
#[cfg(windows)]
impl From<ConnectionProperty> for windows::Win32::Media::Audio::Apo::APO_CONNECTION_PROPERTY {
#[inline]
fn from(value: ConnectionProperty) -> Self {
Self {
pBuffer: value.buffer,
u32ValidFrameCount: value.valid_frame_count,
u32BufferFlags: value.flags.into(),
u32Signature: value.signature,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn buffer_flag_constants_match_microsoft_values() {
assert_eq!(BufferFlags::INVALID.0, 0);
assert_eq!(BufferFlags::VALID.0, 1);
assert_eq!(BufferFlags::SILENT.0, 2);
}
#[test]
fn buffer_flag_predicates_classify_correctly() {
assert!(BufferFlags::VALID.is_valid());
assert!(!BufferFlags::VALID.is_silent());
assert!(!BufferFlags::VALID.is_invalid());
assert!(BufferFlags::SILENT.is_silent());
assert!(!BufferFlags::SILENT.is_valid());
assert!(BufferFlags::INVALID.is_invalid());
assert!(!BufferFlags::INVALID.is_valid());
}
#[test]
fn buffer_flags_default_is_invalid() {
assert_eq!(BufferFlags::default(), BufferFlags::INVALID);
}
#[test]
fn buffer_flags_unknown_value_round_trips() {
let f = BufferFlags(99);
assert!(!f.is_valid());
assert!(!f.is_silent());
assert!(!f.is_invalid());
assert_eq!(f.0, 99);
}
#[test]
fn connection_property_empty_has_signature() {
let cp = ConnectionProperty::empty();
assert_eq!(cp.signature, CONNECTION_PROPERTY_SIGNATURE);
assert_eq!(cp.buffer, 0);
assert_eq!(cp.valid_frame_count, 0);
assert!(cp.flags.is_invalid());
}
#[test]
fn signature_value_spells_apoc_in_be_bytes() {
assert_eq!(CONNECTION_PROPERTY_SIGNATURE, 0x4150_4F43);
let bytes = CONNECTION_PROPERTY_SIGNATURE.to_be_bytes();
assert_eq!(&bytes, b"APOC");
}
#[cfg(windows)]
#[test]
fn buffer_flags_round_trip_through_windows_type() {
use windows::Win32::Media::Audio::Apo::APO_BUFFER_FLAGS;
for f in [
BufferFlags::INVALID,
BufferFlags::VALID,
BufferFlags::SILENT,
BufferFlags(42),
] {
let w: APO_BUFFER_FLAGS = f.into();
let back: BufferFlags = w.into();
assert_eq!(f, back);
}
}
#[cfg(windows)]
#[test]
fn buffer_flags_constants_match_windows_constants() {
use windows::Win32::Media::Audio::Apo::{BUFFER_INVALID, BUFFER_SILENT, BUFFER_VALID};
assert_eq!(BufferFlags::INVALID, BUFFER_INVALID.into());
assert_eq!(BufferFlags::VALID, BUFFER_VALID.into());
assert_eq!(BufferFlags::SILENT, BUFFER_SILENT.into());
}
#[cfg(windows)]
#[test]
fn connection_property_round_trips_through_windows_type() {
use windows::Win32::Media::Audio::Apo::APO_CONNECTION_PROPERTY;
let cp = ConnectionProperty {
buffer: 0xDEAD_BEEF,
valid_frame_count: 1024,
flags: BufferFlags::VALID,
signature: CONNECTION_PROPERTY_SIGNATURE,
};
let w: APO_CONNECTION_PROPERTY = cp.into();
assert_eq!(w.pBuffer, 0xDEAD_BEEF);
assert_eq!(w.u32ValidFrameCount, 1024);
assert_eq!(w.u32BufferFlags.0, 1);
assert_eq!(w.u32Signature, CONNECTION_PROPERTY_SIGNATURE);
let back: ConnectionProperty = w.into();
assert_eq!(cp, back);
}
}