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;
let ID3FindResults(id3v1_header, id3v1) =
find_id3v1(reader, parse_options.read_tags, parse_options.parsing_mode)
.map_err(TagParseError::from)?;
if id3v1_header.is_some() {
id3v1_tag = id3v1;
let Some(new_stream_length) = stream_length.checked_sub(128) else {
return Err(SizeMismatchError.into());
};
stream_length = new_stream_length;
}
let ID3FindResults(_, lyrics3v2_size) = find_lyrics3v2(reader)?;
let Some(new_stream_length) = stream_length.checked_sub(u64::from(lyrics3v2_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()
},
})
}