use super::WavPackFile;
use super::properties::WavPackProperties;
use crate::config::ParseOptions;
use crate::error::{SizeMismatchError, TagParseError};
use crate::id3::{ID3FindResults, find_id3v1, find_lyrics3v2};
use crate::wavpack::error::WavPackParseError;
use std::io::{Read, Seek, SeekFrom};
pub(super) fn read_from<R>(
reader: &mut R,
parse_options: ParseOptions,
) -> Result<WavPackFile, WavPackParseError>
where
R: Read + Seek,
{
let current_pos = reader.stream_position()?;
let mut stream_length = reader.seek(SeekFrom::End(0))?;
reader.seek(SeekFrom::Start(current_pos))?;
let mut id3v1_tag = None;
let mut ape_tag = None;
if let Some(ID3FindResults {
header: _,
content,
range: _,
}) = find_id3v1(reader, parse_options.read_tags, parse_options.parsing_mode)
.map_err(TagParseError::from)?
{
id3v1_tag = content;
let Some(new_stream_length) = stream_length.checked_sub(128) else {
return Err(SizeMismatchError.into());
};
stream_length = new_stream_length;
}
if let Some(ID3FindResults {
header: _,
content: size,
range: _,
}) = find_lyrics3v2(reader)?
{
let Some(new_stream_length) = stream_length.checked_sub(u64::from(size)) else {
return Err(SizeMismatchError.into());
};
stream_length = new_stream_length;
}
reader.seek(SeekFrom::Current(-32))?;
if let (tag, Some(header)) = crate::ape::tag::read::read_ape_tag(reader, true, parse_options)
.map_err(TagParseError::from)?
{
stream_length -= u64::from(header.size);
ape_tag = tag;
}
Ok(WavPackFile {
id3v1_tag,
ape_tag,
properties: if parse_options.read_properties {
super::properties::read_properties(reader, stream_length, parse_options.parsing_mode)?
} else {
WavPackProperties::default()
},
})
}