use crate::encode::{encode, EncodeError};
use crate::header::{AudioFormat, Loop, StreamInfo};
use crate::read::Reader;
use std::{
io::{Read, Write},
num::{NonZeroU32, NonZeroU8},
};
#[derive(Debug, PartialEq, Eq)]
pub struct LazyStream<'bank, R: Read> {
index: u32,
format: AudioFormat,
flags: u32,
info: &'bank StreamInfo,
reader: &'bank mut Reader<R>,
}
impl<'bank, R: Read> LazyStream<'bank, R> {
pub(crate) fn new(
index: u32,
format: AudioFormat,
flags: u32,
info: &'bank StreamInfo,
reader: &'bank mut Reader<R>,
) -> Self {
Self {
index,
format,
flags,
info,
reader,
}
}
#[must_use]
pub fn index(&self) -> u32 {
self.index
}
#[must_use]
pub fn format(&self) -> AudioFormat {
self.format
}
#[must_use]
pub fn sample_rate(&self) -> NonZeroU32 {
self.info.sample_rate
}
#[must_use]
pub fn channels(&self) -> NonZeroU8 {
self.info.channels
}
#[must_use]
pub fn sample_count(&self) -> NonZeroU32 {
self.info.num_samples
}
#[must_use]
pub fn loop_info(&self) -> Option<Loop> {
self.info.stream_loop
}
#[must_use]
pub fn size(&self) -> NonZeroU32 {
self.info.size
}
#[must_use]
pub fn name(&self) -> Option<&str> {
match &self.info.name {
Some(name) => Some(name),
None => None,
}
}
pub fn write<W: Write>(self, sink: W) -> Result<W, EncodeError> {
encode(self.format, self.flags, self.info, self.reader, sink)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Stream {
format: AudioFormat,
flags: u32,
info: StreamInfo,
data: Box<[u8]>,
}
impl Stream {
pub(crate) fn new(format: AudioFormat, flags: u32, info: StreamInfo, data: Box<[u8]>) -> Self {
Self {
format,
flags,
info,
data,
}
}
#[must_use]
pub fn format(&self) -> AudioFormat {
self.format
}
#[must_use]
pub fn sample_rate(&self) -> NonZeroU32 {
self.info.sample_rate
}
#[must_use]
pub fn channels(&self) -> NonZeroU8 {
self.info.channels
}
#[must_use]
pub fn sample_count(&self) -> NonZeroU32 {
self.info.num_samples
}
#[must_use]
pub fn loop_info(&self) -> Option<Loop> {
self.info.stream_loop
}
#[must_use]
pub fn size(&self) -> NonZeroU32 {
self.info.size
}
#[must_use]
pub fn name(&self) -> Option<&str> {
match &self.info.name {
Some(name) => Some(name),
None => None,
}
}
pub fn write<W: Write>(self, sink: W) -> Result<W, EncodeError> {
let mut reader = Reader::new(&*self.data);
encode(self.format, self.flags, &self.info, &mut reader, sink)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StreamIntoIter<R: Read> {
index: u32,
format: AudioFormat,
flags: u32,
info: Box<[StreamInfo]>,
reader: Reader<R>,
}
impl<R: Read> StreamIntoIter<R> {
pub(crate) fn new(
format: AudioFormat,
flags: u32,
info: Box<[StreamInfo]>,
reader: Reader<R>,
) -> Self {
Self {
index: 0,
format,
flags,
info,
reader,
}
}
}
impl<R: Read> Iterator for StreamIntoIter<R> {
type Item = Stream;
fn next(&mut self) -> Option<Self::Item> {
let stream = self.info.get(self.index as usize).cloned().and_then(|info| {
let size = u32::from(info.size) as usize;
let start_pos = self.reader.position();
let stream =
self.reader.take(size).ok().map(|data| {
Stream::new(self.format, self.flags, info, data.into_boxed_slice())
});
self.reader.advance_to(start_pos + size).ok()?;
stream
});
self.index += 1;
stream
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.info.len();
(len, Some(len))
}
}
impl<R: Read> ExactSizeIterator for StreamIntoIter<R> {
fn len(&self) -> usize {
self.info.len()
}
}