use crate::{cast, AuError, AuReadInfo, AuResult, Read, SampleFormat, Seek, SeekFrom};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Sample {
I8(i8),
I16(i16),
I24(i32),
I32(i32),
F32(f32),
F64(f64)
}
trait SampleRead {
fn read_sample_for_iter(&mut self) -> AuResult<Option<Sample>>;
fn size_hint(&self) -> (usize, Option<usize>);
}
#[derive(Debug)]
pub struct Samples<'a, R> {
reader: &'a mut R,
has_returned_error: bool
}
impl<'a, R> Samples<'a, R> {
fn new(reader: &'a mut R) -> Samples<'a, R> {
Samples {
reader,
has_returned_error: false
}
}
}
impl<R: SampleRead> Iterator for Samples<'_, R> {
type Item = AuResult<Sample>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.has_returned_error {
return None;
}
match self.reader.read_sample_for_iter() {
Ok(Some(s)) => Some(Ok(s)),
Ok(None) => None,
Err(e) => {
self.has_returned_error = true;
Some(Err(e))
},
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.reader.size_hint()
}
}
#[derive(Debug)]
pub struct AuReader<R> {
info: AuReadInfo,
desc_bytes_unread_len: u64,
sample_data_start_pos: u64,
sample_data_read_pos: u64,
resolved_data_len: Option<u64>,
handle: R,
}
impl<R: Read> AuReader<R> {
#[allow(dead_code)]
fn new_read(mut inner: R) -> AuResult<AuReader<R>> {
let hdr = read_header(&mut inner, 0, None)?;
let r = AuReader {
info: hdr.info,
desc_bytes_unread_len: hdr.desc_bytes_unread_len,
sample_data_start_pos: hdr.sample_data_start_pos,
sample_data_read_pos: hdr.sample_data_start_pos,
resolved_data_len: hdr.resolved_data_len,
handle: inner,
};
Ok(r)
}
pub fn info(&self) -> &AuReadInfo {
&self.info
}
pub fn read_description(&mut self, out_buf: &mut [u8]) -> AuResult<usize> {
if out_buf.is_empty() || self.desc_bytes_unread_len == 0 {
return Ok(0);
}
let out_buf_len_u64 = u64::try_from(out_buf.len()).unwrap_or(u64::MAX);
let read_buf = if out_buf_len_u64 <= self.desc_bytes_unread_len {
out_buf
} else {
let desc_len_usize = usize::try_from(self.desc_bytes_unread_len).unwrap_or(usize::MAX);
&mut out_buf[0..desc_len_usize]
};
let rs = self.handle.read(read_buf)?;
self.desc_bytes_unread_len -= u64::try_from(rs).unwrap_or(self.desc_bytes_unread_len);
Ok(rs)
}
pub fn seek_to_first_sample(&mut self) -> AuResult<()> {
if self.sample_data_read_pos != self.sample_data_start_pos {
return Err(AuError::SeekError);
}
self.skip_description()
}
fn skip_description(&mut self) -> AuResult<()> {
if self.desc_bytes_unread_len == 0 {
return Ok(());
}
let mut skip_buf = [0u8; 1];
for _ in 0..self.desc_bytes_unread_len {
self.handle.read_exact(&mut skip_buf)?;
}
self.desc_bytes_unread_len = 0;
Ok(())
}
#[inline(always)]
pub fn read_sample(&mut self) -> AuResult<Option<Sample>> {
if self.desc_bytes_unread_len != 0 {
self.skip_description()?;
}
let sf = self.info.sample_format;
let bsize = sf.bytesize_u64();
if let Some(slen) = self.resolved_data_len {
if self.sample_data_read_pos - self.sample_data_start_pos + bsize > slen {
return Ok(None);
}
}
let sample = match self.read_sample_for_format(sf) {
Ok(Some(s)) => Ok(Some(s)),
Ok(None) => {
if self.resolved_data_len.is_none() {
self.resolved_data_len = Some(self.sample_data_read_pos -
self.sample_data_start_pos);
Ok(None)
} else {
return Err(AuError::StdIoError(
std::io::Error::from(std::io::ErrorKind::UnexpectedEof)));
}
},
Err(e) => {
return Err(e);
},
};
self.sample_data_read_pos = self.sample_data_read_pos.saturating_add(bsize);
sample
}
fn read_sample_for_format(&mut self, sample_format: SampleFormat) -> AuResult<Option<Sample>> {
match sample_format {
SampleFormat::I8 => self.read_sample_i8(),
SampleFormat::I16 => self.read_sample_i16(),
SampleFormat::I24 => self.read_sample_i24(),
SampleFormat::I32 => self.read_sample_i32(),
SampleFormat::F32 => self.read_sample_f32(),
SampleFormat::F64 => self.read_sample_f64(),
SampleFormat::CompressedUlaw => {
let val = self.read_sample_u8()?;
Ok(Some(Sample::I16(audio_codec_algorithms::decode_ulaw(val))))
},
SampleFormat::CompressedAlaw => {
let val = self.read_sample_u8()?;
Ok(Some(Sample::I16(audio_codec_algorithms::decode_alaw(val))))
},
SampleFormat::Custom(_) => {
Err(AuError::Unsupported)
}
}
}
fn read_sample_u8(&mut self) -> AuResult<u8> {
let mut buf = [ 0u8; 1 ];
self.handle.read_exact(&mut buf)?;
Ok(buf[0])
}
fn read_sample_i8(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 1 ];
self.handle.read_exact(&mut buf)?;
Ok(Some(Sample::I8(cast::u8_as_i8(buf[0]))))
}
fn read_sample_i16(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 2 ];
match self.handle.read_exact(&mut buf[0..1]) {
Ok(()) => {},
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
},
Err(e) => {
return Err(e)?;
},
}
self.handle.read_exact(&mut buf[1..2])?;
Ok(Some(Sample::I16(i16::from_be_bytes(buf))))
}
fn read_sample_i24(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 3 ];
match self.handle.read_exact(&mut buf[0..1]) {
Ok(()) => {},
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
},
Err(e) => {
return Err(e)?;
},
}
self.handle.read_exact(&mut buf[1..3])?;
let mut res = i32::from(buf[0]) << 16 | i32::from(buf[1]) << 8 | i32::from(buf[2]);
if res >= 8388608 {
res -= 16777216;
}
Ok(Some(Sample::I24(res)))
}
fn read_sample_i32(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 4 ];
match self.handle.read_exact(&mut buf[0..1]) {
Ok(()) => {},
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
},
Err(e) => {
return Err(e)?;
},
}
self.handle.read_exact(&mut buf[1..4])?;
Ok(Some(Sample::I32(i32::from_be_bytes(buf))))
}
fn read_sample_f32(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 4 ];
match self.handle.read_exact(&mut buf[0..1]) {
Ok(()) => {},
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
},
Err(e) => {
return Err(e)?;
},
}
self.handle.read_exact(&mut buf[1..4])?;
Ok(Some(Sample::F32(f32::from_be_bytes(buf))))
}
fn read_sample_f64(&mut self) -> AuResult<Option<Sample>> {
let mut buf = [ 0u8; 8 ];
match self.handle.read_exact(&mut buf[0..1]) {
Ok(()) => {},
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
},
Err(e) => {
return Err(e)?;
},
}
self.handle.read_exact(&mut buf[1..8])?;
Ok(Some(Sample::F64(f64::from_be_bytes(buf))))
}
pub fn samples(&mut self) -> AuResult<Samples<'_, AuReader<R>>> {
self.skip_description()?;
if let SampleFormat::Custom(_) = self.info.sample_format {
return Err(AuError::Unsupported);
}
Ok(Samples::new(self))
}
pub fn into_inner(self) -> R {
self.handle
}
pub const fn get_ref(&self) -> &R {
&self.handle
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.handle
}
}
impl<R: Read> SampleRead for AuReader<R> {
#[inline(always)]
fn read_sample_for_iter(&mut self) -> AuResult<Option<Sample>> {
self.read_sample()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sample_size = self.info.sample_format.bytesize_u64();
let Some(slen) = self.resolved_data_len else { return (0, None);
};
let sample_count = (self.sample_data_start_pos + slen - self.sample_data_read_pos) /
sample_size;
if let Ok(ss) = usize::try_from(sample_count) {
(ss, Some(ss))
} else { (usize::MAX, None)
}
}
}
impl<R: Read + Seek> AuReader<R> {
pub fn new(mut inner: R) -> AuResult<AuReader<R>> {
let initpos = inner.stream_position()?;
let initlen = inner.seek(SeekFrom::End(0))?;
inner.seek(SeekFrom::Start(initpos))?;
let hdr = read_header(&mut inner, initpos, Some(initlen))?;
let r = AuReader {
info: hdr.info,
desc_bytes_unread_len: hdr.desc_bytes_unread_len,
sample_data_start_pos: hdr.sample_data_start_pos,
sample_data_read_pos: hdr.sample_data_start_pos,
resolved_data_len: hdr.resolved_data_len,
handle: inner,
};
Ok(r)
}
pub fn resolved_sample_len(&self) -> AuResult<u64> {
let Some(slen) = self.resolved_data_len else {
return Err(AuError::InvalidReadState);
};
if let SampleFormat::Custom(_) = self.info.sample_format {
return Err(AuError::Unsupported);
}
Ok(slen / self.info.sample_format.bytesize_u64())
}
pub fn resolved_sample_byte_len(&self) -> AuResult<u64> {
let Some(slen) = self.resolved_data_len else {
return Err(AuError::InvalidReadState);
};
Ok(slen)
}
pub fn seek(&mut self, sample_position: u64) -> AuResult<()> {
let sample_size = self.info.sample_format.bytesize_u64();
if let SampleFormat::Custom(_) = self.info.sample_format {
return Err(AuError::Unsupported);
}
let total_samples = match self.resolved_sample_len() {
Ok(sl) => sl,
Err(_) => { return Err(AuError::SeekError); }
};
if sample_position > total_samples {
return Err(AuError::SeekError);
}
let Some(new_pos) = sample_position.checked_mul(sample_size)
.and_then(|val| val.checked_add(self.sample_data_start_pos)) else {
return Err(AuError::SeekError);
};
let Some(seek_offset) = i64::try_from(new_pos)
.ok()
.and_then(|p| p.checked_sub_unsigned(self.sample_data_read_pos)) else {
return Err(AuError::SeekError);
};
self.skip_description()?;
self.handle.seek(SeekFrom::Current(seek_offset))?;
self.sample_data_read_pos = new_pos;
self.desc_bytes_unread_len = 0;
Ok(())
}
}
struct HeaderData {
info: AuReadInfo,
sample_data_start_pos: u64,
resolved_data_len: Option<u64>,
desc_bytes_unread_len: u64
}
fn read_header(handle: &mut dyn Read, initial_stream_pos: u64, initial_stream_len: Option<u64>)
-> AuResult<HeaderData> {
let mut header = [0u8; crate::HEADER_SIZE as usize];
handle.read_exact(&mut header)?;
let (sample_data_start_pos, info) = AuReadInfo::parse_bytes(&header)?;
#[allow(clippy::manual_map)]
let resolved_data_len = if let Some(sbl) = info.sample_byte_len {
Some(u64::from(sbl))
} else if let Some(isl) = initial_stream_len {
Some(isl - sample_data_start_pos - initial_stream_pos)
} else {
None
};
let desc_bytes_unread_len = sample_data_start_pos - u64::from(crate::HEADER_SIZE);
Ok(HeaderData {
info,
sample_data_start_pos,
resolved_data_len,
desc_bytes_unread_len
})
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use super::*;
struct AppendableReader {
data: Vec<u8>,
pos: u64,
}
impl AppendableReader {
pub fn new() -> AppendableReader {
AppendableReader {
data: vec![],
pos: 0
}
}
pub fn append(&mut self, data: &[u8]) {
self.data.extend_from_slice(data);
}
pub fn clear(&mut self) {
self.data.clear();
}
}
impl Read for AppendableReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
let Ok(mut p) = usize::try_from(self.pos) else {
return Err(std::io::Error::from(std::io::ErrorKind::Other));
};
if self.data.len() < p {
return Err(std::io::Error::from(std::io::ErrorKind::Other));
}
let len = buf.len().min(self.data.len() - p);
for b in buf.iter_mut().take(len) {
*b = self.data[p];
p += 1;
self.pos += 1;
}
Ok(len)
}
}
impl Seek for AppendableReader {
fn seek(&mut self, sf: SeekFrom) -> std::io::Result<u64> {
match sf {
SeekFrom::Start(p) => { self.pos = p; },
SeekFrom::End(p) => {
let Ok(dlen) = i64::try_from(self.data.len()) else {
return Err(std::io::Error::from(std::io::ErrorKind::Other));
};
self.pos = u64::try_from(dlen + p)
.map_err(|_| std::io::Error::from(std::io::ErrorKind::Other))?;
},
SeekFrom::Current(p) => {
self.pos = match self.pos.checked_add_signed(p) {
Some(v) => v,
None => { return Err(std::io::Error::from(std::io::ErrorKind::Other)); }
}
},
}
Ok(self.pos)
}
}
#[test]
fn test_appendable_reader() -> AuResult<()> {
let mut ar = AppendableReader::new();
ar.append(&[ 1, 2, 3, 4, 5, 6 ]);
let mut buf = [0u8; 20];
assert_eq!(ar.read(&mut buf)?, 6);
assert_eq!(buf[0..6], [ 1, 2, 3, 4, 5, 6 ]);
assert_eq!(ar.read(&mut buf)?, 0);
ar.append(&[ 7, 8, 9 ]);
assert_eq!(ar.read(&mut buf)?, 3);
assert_eq!(buf[0..3], [ 7, 8, 9 ]);
assert_eq!(ar.read(&mut buf)?, 0);
ar.append(&[ 10, 11 ]);
assert_eq!(ar.read(&mut buf)?, 2);
assert_eq!(buf[0..2], [ 10, 11 ]);
assert_eq!(ar.read(&mut buf)?, 0);
assert_eq!(ar.read(&mut buf)?, 0);
ar.append(&[ 12 ]);
assert_eq!(ar.read(&mut buf)?, 1);
assert_eq!(buf[0..1], [ 12 ]);
assert_eq!(ar.read(&mut buf)?, 0);
Ok(())
}
fn create_au_hdr(dummy_data_len: usize, data_size: u32, format: SampleFormat,
rate: u32, channels: u32) -> Vec<u8> {
create_au_hdr_with_desc(dummy_data_len, data_size, format, rate, channels, &[])
}
fn create_au_hdr_with_desc(dummy_data_len: usize, data_size: u32, format: SampleFormat,
rate: u32, channels: u32, desc: &[u8]) -> Vec<u8> {
let header_size = (24 + desc.len()) as u32;
let mut data = vec![];
data.extend_from_slice(&[ 0xff, 0xfe, 0xfd, 0xfc ][0..dummy_data_len]);
data.extend_from_slice(&[ b'.', b's', b'n', b'd' ]); data.extend_from_slice(&header_size.to_be_bytes()); data.extend_from_slice(&data_size.to_be_bytes()); data.extend_from_slice(&format.as_u32().to_be_bytes()); data.extend_from_slice(&rate.to_be_bytes()); data.extend_from_slice(&channels.to_be_bytes()); data.extend_from_slice(&desc); data
}
fn read_dummy_data(cursor: &mut impl Read, len: usize) -> AuResult<()> {
let mut init_buf = vec![0u8; len];
Ok(cursor.read_exact(&mut init_buf)?)
}
#[test]
fn test_new_transferring_ownership() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let reader = AuReader::new(cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
Ok(())
}
#[test]
fn test_new_taking_mut_ref() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let mut cursor = Cursor::new(&au);
let reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
Ok(())
}
#[test]
fn test_new_ref_slice() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let mut rd: &[u8] = au.as_ref();
let reader = AuReader::new_read(&mut rd)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
Ok(())
}
#[test]
fn test_into_inner() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
assert_eq!(reader.samples()?.next().expect("sample read error")?, Sample::I8(11));
let mut cr = reader.into_inner();
let mut buf = [0u8; 1];
assert_eq!(cr.read(&mut buf)?, 1);
assert_eq!(buf[0], 12);
Ok(())
}
#[test]
fn test_get_ref() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
let cr = reader.get_ref();
assert_eq!(cr.position(), 24);
assert_eq!(reader.samples()?.next().expect("sample read error")?, Sample::I8(11));
Ok(())
}
#[test]
fn test_get_mut() -> AuResult<()> {
let mut au = create_au_hdr(0, 8, SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I8);
assert_eq!(reader.samples()?.next().expect("sample read error")?, Sample::I8(11));
let cr = reader.get_mut();
let mut buf = [0u8; 1];
assert_eq!(cr.read(&mut buf)?, 1);
assert_eq!(buf[0], 12);
Ok(())
}
#[test]
fn test_read_info() -> AuResult<()> {
for data_size in [16, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I16, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.channels, 1);
assert_eq!(info.sample_format, SampleFormat::I16);
assert_eq!(info.sample_rate, 44100);
assert_eq!(info.description_byte_len, 4);
if data_size != 0xffffffff {
assert_eq!(info.sample_len, Some(8));
assert_eq!(info.sample_byte_len, Some(16));
} else {
assert_eq!(info.sample_len, None);
assert_eq!(info.sample_byte_len, None);
}
}
Ok(())
}
#[test]
fn test_read_info_for_unsupported_encoding() -> AuResult<()> {
for data_size in [16, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::Custom(0x402), 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.channels, 1);
assert_eq!(info.sample_format, SampleFormat::Custom(0x402));
assert_eq!(info.sample_rate, 44100);
assert_eq!(info.description_byte_len, 4);
assert_eq!(info.sample_len, None);
if data_size != 0xffffffff {
assert_eq!(info.sample_byte_len, Some(16));
} else {
assert_eq!(info.sample_byte_len, None);
}
}
Ok(())
}
#[test]
fn test_read_description() -> AuResult<()> {
for data_size in [8, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.description_byte_len, 0);
assert_eq!(reader.read_description(&mut [])?, 0);
assert_eq!(reader.read_description(&mut [])?, 0);
let mut desc = [ 99, 99 ];
assert_eq!(reader.read_description(&mut desc)?, 0);
assert_eq!(desc, [ 99, 99 ]);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
assert_eq!(reader.read_description(&mut [])?, 0);
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ b'W', b'O', b'R', b'L', b'D', 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.channels, 1);
assert_eq!(info.sample_format, SampleFormat::I8);
assert_eq!(info.sample_rate, 44100);
assert_eq!(reader.read_description(&mut [])?, 0);
assert_eq!(reader.read_description(&mut [])?, 0);
let mut desc = vec![0u8; 4];
assert_eq!(reader.read_description(&mut desc)?, 4);
assert_eq!(desc, &[ b'W', b'O', b'R', b'L' ]);
assert_eq!(reader.read_description(&mut desc)?, 2);
assert_eq!(desc, &[ b'D', 0, b'R', b'L' ]);
assert_eq!(reader.read_description(&mut desc)?, 0);
assert_eq!(reader.read_description(&mut [])?, 0);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
assert_eq!(reader.read_description(&mut [])?, 0);
assert_eq!(reader.read_description(&mut desc)?, 0);
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.read_description(&mut [])?, 0);
let mut desc = vec![0u8; 4];
assert_eq!(reader.read_description(&mut desc)?, 4);
assert_eq!(desc, &[ 0, 0, 0, 0 ]);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 99 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let mut desc = vec![0u8; 4];
assert_eq!(reader.read_description(&mut desc)?, 1);
assert_eq!(desc, &[ 99, 0, 0, 0 ]);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 65, 66, 67, 68, 69, 70, 71, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let mut desc = vec![0u8; 8];
let _ = reader.read_description(&mut desc)?;
assert_eq!(desc, &[ 65, 66, 67, 68, 69, 70, 71, 0 ]);
}
Ok(())
}
#[test]
fn test_seek_to_first_sample() -> AuResult<()> {
let mut au = create_au_hdr(0, 8,
SampleFormat::Custom(0x402), 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
assert!(reader.seek_to_first_sample().is_ok());
let mut au = create_au_hdr(0, 8,
SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
assert_eq!(reader.read_sample().expect("sample error"), Some(Sample::I8(11)));
assert!(reader.seek_to_first_sample().is_err());
let mut au = create_au_hdr(0, 8,
SampleFormat::I8, 44100, 1);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18 ]);
let cursor = Cursor::new(&au);
let mut reader = AuReader::new(cursor)?;
reader.seek(1)?;
assert!(reader.seek_to_first_sample().is_err());
reader.seek(0)?;
assert!(reader.seek_to_first_sample().is_ok());
let mut au = create_au_hdr_with_desc(3, 8,
SampleFormat::Custom(0x402), 44100, 1, &[ 65, 65, 65, 0 ]);
au.extend_from_slice(&[ 11, 12, 13, 14, 15, 16, 17, 18, 98, 99 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::Custom(0x402));
assert_eq!(info.sample_len, None);
assert_eq!(reader.resolved_sample_byte_len().expect("len failed"), 8);
assert!(reader.seek_to_first_sample().is_ok());
let mut cr = reader.into_inner();
let mut buf = [0u8; 8];
assert_eq!(cr.read(&mut buf)?, 8);
assert_eq!(buf, [ 11, 12, 13, 14, 15, 16, 17, 18 ]);
Ok(())
}
#[test]
fn test_read_samples_skips_description() -> AuResult<()> {
for data_size in [32, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1,
&[ b'H', b'E', b'L', b'L', b'O', 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.channels, 1);
assert_eq!(info.sample_format, SampleFormat::I8);
assert_eq!(info.sample_rate, 44100);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
let mut desc = vec![0u8; 10];
assert_eq!(reader.read_description(&mut desc)?, 0);
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1,
&[ b'H', b'E', b'L', b'L', b'O', 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.channels, 1);
assert_eq!(info.sample_format, SampleFormat::I8);
assert_eq!(info.sample_rate, 44100);
let mut desc = vec![0u8; 3];
assert_eq!(reader.read_description(&mut desc)?, 3);
assert_eq!(desc, &[ b'H', b'E', b'L' ]);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
let mut desc = vec![0u8; 10];
assert_eq!(reader.read_description(&mut desc)?, 0);
}
Ok(())
}
#[test]
fn test_read_sample() -> AuResult<()> {
for data_size in [32, 0xffffffff] {
let mut au = create_au_hdr(3, data_size,
SampleFormat::I32, 44100, 1);
au.extend_from_slice(&[ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4,
0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
let info = reader.info();
assert_eq!(info.sample_format, SampleFormat::I32);
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(1)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(2)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(3)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(4)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(5)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(6)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(7)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I32(8)));
assert!(reader.read_sample().expect("sample read error").is_none());
}
Ok(())
}
#[test]
fn test_read_samples_appending_new_data() -> AuResult<()> {
let mut buffer = AppendableReader::new();
let au = create_au_hdr(3, 0xffffffff,
SampleFormat::I32, 44100, 1);
buffer.append(&au);
buffer.append(&[ 0, 0, 0, 1 ]);
let mut init_buf = vec![0u8; 3];
buffer.read_exact(&mut init_buf)?;
let mut reader = AuReader::new(&mut buffer)?;
assert_eq!(reader.samples()?.next().expect("sample read error")?, Sample::I32(1));
reader.get_mut().append(&[ 0, 0, 0, 2 ]);
assert!(reader.samples()?.next().is_none());
let mut buffer = AppendableReader::new();
let au = create_au_hdr(3, 0xffffffff,
SampleFormat::I32, 44100, 1);
buffer.append(&au);
buffer.append(&[ 0, 0, 0, 1, 0, 0 ]);
let mut init_buf = vec![0u8; 3];
buffer.read_exact(&mut init_buf)?;
let mut reader = AuReader::new(&mut buffer)?;
assert_eq!(reader.samples()?.next().expect("sample read error")?, Sample::I32(1));
reader.get_mut().append(&[ 0, 2, 0, 0, 0, 3 ]);
assert!(reader.samples()?.next().is_none());
Ok(())
}
#[test]
fn test_read_sample_for_broken_last_sample_read_only() -> AuResult<()> {
let mut au = create_au_hdr_with_desc(3, 0xffffffff,
SampleFormat::F32, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 0, 0, 0, 0, ]);
let mut rd: &[u8] = au.as_ref();
read_dummy_data(&mut rd, 3)?;
let mut reader = AuReader::new_read(&mut rd)?;
assert_eq!(reader.read_sample()?, Some(Sample::F32(0.0)));
assert_eq!(reader.read_sample()?, None);
struct TestCase { sf: SampleFormat, sample: Sample, count: u32 }
let test_cases: [TestCase; 5] = [
TestCase { sf: SampleFormat::I16, sample: Sample::I16(0), count: 5 },
TestCase { sf: SampleFormat::I24, sample: Sample::I24(0), count: 3 },
TestCase { sf: SampleFormat::I32, sample: Sample::I32(0), count: 2 },
TestCase { sf: SampleFormat::F32, sample: Sample::F32(0.0), count: 2 },
TestCase { sf: SampleFormat::F64, sample: Sample::F64(0.0), count: 1 },
];
for test_case in test_cases {
let mut au = create_au_hdr_with_desc(3, 0xffffffff,
test_case.sf, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]);
let mut rd: &[u8] = au.as_ref();
read_dummy_data(&mut rd, 3)?;
let mut reader = AuReader::new_read(&mut rd)?;
for _ in 0..test_case.count {
assert_eq!(reader.read_sample()?, Some(test_case.sample));
}
assert!(reader.read_sample().is_err());
}
Ok(())
}
#[test]
fn test_read_samples_stream_cleared() -> AuResult<()> {
let mut buffer = AppendableReader::new();
let au = create_au_hdr_with_desc(3, 0xffffffff,
SampleFormat::I32, 44100, 1, &[ b'd', b's', b'c', 0 ]);
buffer.append(&au);
buffer.append(&[ 0, 0, 0, 1, 0, 0, 0, 2 ]);
let mut init_buf = vec![0u8; 3];
buffer.read_exact(&mut init_buf)?;
let mut reader = AuReader::new(&mut buffer)?;
reader.get_mut().clear();
let mut dbuf = vec![ 0, 0, 0 ];
assert!(reader.read_description(&mut dbuf).is_err());
let mut buffer = AppendableReader::new();
let au = create_au_hdr(3, 0xffffffff,
SampleFormat::I32, 44100, 1);
buffer.append(&au);
buffer.append(&[ 0, 0, 0, 1, 0, 0, 0, 2 ]);
let mut init_buf = vec![0u8; 3];
buffer.read_exact(&mut init_buf)?;
let mut reader = AuReader::new(&mut buffer)?;
reader.get_mut().clear();
assert!(reader.read_sample().is_err());
assert!(reader.samples()?.next().expect("sample read error").is_err());
assert!(reader.seek(1).is_ok());
assert!(reader.read_sample().is_err());
Ok(())
}
#[test]
fn test_samples_iterator_and_size_hint() -> AuResult<()> {
for data_size in [8, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
{
let mut siter = reader.samples()?;
assert_eq!(siter.size_hint(), (8, Some(8)));
assert_eq!(siter.next().expect("sample read error")?, Sample::I8(1));
assert_eq!(siter.size_hint(), (7, Some(7)));
}
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(2)));
{
let siter = reader.samples()?;
assert_eq!(siter.size_hint(), (6, Some(6)));
}
let expected = vec![
Sample::I8(3), Sample::I8(4),
Sample::I8(5), Sample::I8(6), Sample::I8(7), Sample::I8(8),
];
let mut count = 0;
for (i, sample) in reader.samples()?.enumerate() {
assert_eq!(sample.expect("no sample"), expected[i]);
count += 1;
}
assert_eq!(count, 6);
{
let siter = reader.samples()?;
assert_eq!(siter.size_hint(), (0, Some(0)));
assert_eq!(siter.count(), 0);
}
assert!(reader.read_sample().expect("read sample error").is_none());
assert_eq!(reader.resolved_sample_len().expect("invalid len"), 8);
}
Ok(())
}
#[test]
fn test_samples_iterator_and_size_hint_for_read_only() -> AuResult<()> {
for data_size in [8, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
let mut rd: &[u8] = au.as_ref();
read_dummy_data(&mut rd, 3)?;
let mut reader = AuReader::new_read(&mut rd)?;
{
let mut siter = reader.samples()?;
if data_size != 0xffffffff {
assert_eq!(siter.size_hint(), (8, Some(8)));
} else {
assert_eq!(siter.size_hint(), (0, None));
}
assert_eq!(siter.next().expect("sample read error")?, Sample::I8(1));
if data_size != 0xffffffff {
assert_eq!(siter.size_hint(), (7, Some(7)));
} else {
assert_eq!(siter.size_hint(), (0, None));
}
}
}
Ok(())
}
#[test]
fn test_samples_iterator_errors() -> AuResult<()> {
let mut au = create_au_hdr_with_desc(3, 0xffffffff,
SampleFormat::I32, 44100, 1, &[ 0, 0, 0, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6 ]);
let mut rd: &[u8] = au.as_ref();
read_dummy_data(&mut rd, 3)?;
let mut reader = AuReader::new_read(&mut rd)?;
let mut siter = reader.samples()?;
assert_eq!(siter.size_hint(), (0, None));
assert_eq!(siter.next().expect("iterator ended early")?, Sample::I32(0x01020304));
assert!(siter.next().expect("iterator ended early").is_err());
assert!(siter.next().is_none());
Ok(())
}
#[test]
fn test_resolved_sample_len_and_byte_len() -> AuResult<()> {
let mut au = create_au_hdr(3, 8,
SampleFormat::I16, 44100, 1);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.resolved_sample_len().expect("invalid len"), 4);
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 8);
let mut au = create_au_hdr(3, 9,
SampleFormat::I16, 44100, 1);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.resolved_sample_len().expect("invalid len"), 4);
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 9);
let mut au = create_au_hdr(3, 0xffffffff,
SampleFormat::I16, 44100, 1);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.resolved_sample_len().expect("invalid len"), 8);
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 16);
let mut au = create_au_hdr(3, 0xffffffff,
SampleFormat::I16, 44100, 1);
au.extend_from_slice(&[ 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.resolved_sample_len().expect("invalid len"), 7);
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 15);
Ok(())
}
#[test]
fn test_resolved_sample_len_and_byte_len_for_unsupported_encoding() -> AuResult<()> {
let mut au = create_au_hdr(3, 9,
SampleFormat::Custom(0x402), 44100, 1);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert!(reader.resolved_sample_len().is_err());
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 9);
let mut au = create_au_hdr(3, 0xffffffff,
SampleFormat::Custom(0x402), 44100, 1);
au.extend_from_slice(&[ 1, 2, 3, 4, 5 ]);
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let reader = AuReader::new(&mut cursor)?;
assert!(reader.resolved_sample_len().is_err());
assert_eq!(reader.resolved_sample_byte_len().expect("invalid len"), 5);
Ok(())
}
#[test]
fn test_seek() -> AuResult<()> {
for data_size in [8, 0xffffffff] {
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 65, 65, 65, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
if data_size != 0xffffffff {
au.extend_from_slice(&[ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85 ]);
}
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(2)));
reader.seek(0)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(1)));
reader.seek(4)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(5)));
reader.seek(7)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(8)));
reader.seek(8)?;
assert!(reader.read_sample().expect("sample read error").is_none());
assert!(reader.seek(9).is_err());
assert!(reader.read_sample().expect("sample read error").is_none());
assert!(reader.seek(u64::MAX).is_err());
assert!(reader.read_sample().expect("sample read error").is_none());
reader.seek(4)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(5)));
let mut au = create_au_hdr_with_desc(3, data_size,
SampleFormat::I8, 44100, 1, &[ 65, 65, 65, 0 ]);
au.extend_from_slice(&[ 1, 2, 3, 4, 5, 6, 7, 8 ]);
if data_size != 0xffffffff {
au.extend_from_slice(&[ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85 ]);
}
let mut cursor = Cursor::new(&au);
read_dummy_data(&mut cursor, 3)?;
let mut reader = AuReader::new(&mut cursor)?;
reader.seek(4)?;
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(5)));
assert_eq!(reader.read_sample().expect("sample read error"), Some(Sample::I8(6)));
}
Ok(())
}
}