2021-08-19 19:07:40 +00:00
|
|
|
use crate::files::*;
|
|
|
|
use crate::types::file::AudioFile;
|
|
|
|
use crate::{FileType, LoftyError, Result, TaggedFile};
|
2021-08-02 21:25:31 +00:00
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
use std::io::{Cursor, Read, Seek};
|
2021-08-02 21:25:31 +00:00
|
|
|
use std::path::Path;
|
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Provides a way to extract a [`FileType`] or [`TaggedFile`] from a reader
|
|
|
|
pub struct Probe;
|
2021-08-02 21:25:31 +00:00
|
|
|
|
|
|
|
impl Probe {
|
|
|
|
/// Create a new `Probe`
|
|
|
|
pub fn new() -> Self {
|
2021-08-19 19:07:40 +00:00
|
|
|
Self
|
2021-08-02 21:25:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Attempts to get the [`FileType`] based on the data in the reader
|
|
|
|
pub fn file_type<R>(&self, reader: &mut R) -> Option<FileType>
|
|
|
|
where
|
|
|
|
R: Read + Seek,
|
|
|
|
{
|
|
|
|
FileType::try_from_sig(reader).ok()
|
|
|
|
}
|
2021-08-02 21:25:31 +00:00
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Attempts to get a [`FileType`] from a path
|
|
|
|
///
|
|
|
|
/// NOTE: This is based on the content of the file.
|
|
|
|
/// If you want to guess based on extension, see [`Probe::file_type_from_extension`](Self::file_type_from_extension)
|
|
|
|
pub fn file_type_from_path(&self, path: impl AsRef<Path>) -> Option<FileType> {
|
|
|
|
if let Ok(content) = std::fs::read(&path) {
|
|
|
|
let mut cursor = Cursor::new(content);
|
|
|
|
return self.file_type(&mut cursor);
|
|
|
|
}
|
2021-08-02 21:25:31 +00:00
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
None
|
2021-08-02 21:25:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Attempts to get the [`FileType`] based on the file extension
|
2021-08-02 21:25:31 +00:00
|
|
|
///
|
2021-08-19 19:07:40 +00:00
|
|
|
/// NOTE: Since this only looks at the extension, the result could be incorrect.
|
|
|
|
pub fn file_type_from_extension(&self, path: impl AsRef<Path>) -> Option<FileType> {
|
|
|
|
if let Some(ext_os) = path.as_ref().extension() {
|
|
|
|
if let Some(ext) = ext_os.to_str() {
|
2021-08-19 22:26:58 +00:00
|
|
|
return FileType::try_from_ext(&*ext.to_lowercase()).ok();
|
2021-08-19 19:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-02 21:25:31 +00:00
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
None
|
2021-08-02 21:25:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Attempts to extract a [`TaggedFile`] from a reader
|
2021-08-02 21:25:31 +00:00
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
2021-08-19 19:07:40 +00:00
|
|
|
/// * The format couldn't be determined
|
|
|
|
pub fn read_from<R>(self, reader: &mut R) -> Result<TaggedFile>
|
2021-08-02 21:25:31 +00:00
|
|
|
where
|
|
|
|
R: Read + Seek,
|
|
|
|
{
|
2021-08-19 19:07:40 +00:00
|
|
|
match FileType::try_from_sig(reader) {
|
|
|
|
Ok(f_type) => _read_from(reader, f_type),
|
|
|
|
Err(_) => Err(LoftyError::UnknownFormat),
|
|
|
|
}
|
|
|
|
}
|
2021-08-02 21:25:31 +00:00
|
|
|
|
2021-08-19 19:07:40 +00:00
|
|
|
/// Attempts to extract a [`TaggedFile`] from a path
|
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
|
|
|
/// * `path` does not exist
|
|
|
|
/// * The format couldn't be determined
|
|
|
|
pub fn read_from_path(self, path: impl AsRef<Path>) -> Result<TaggedFile> {
|
|
|
|
let mut cursor = Cursor::new(std::fs::read(&path)?);
|
|
|
|
self.read_from(&mut cursor)
|
2021-08-02 21:25:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _read_from<R>(reader: &mut R, file_type: FileType) -> Result<TaggedFile>
|
|
|
|
where
|
|
|
|
R: Read + Seek,
|
|
|
|
{
|
|
|
|
match file_type {
|
2021-08-19 19:07:40 +00:00
|
|
|
FileType::AIFF => Ok(AiffFile::read_from(reader)?.into()),
|
|
|
|
FileType::APE => Ok(ApeFile::read_from(reader)?.into()),
|
|
|
|
FileType::FLAC => Ok(FlacFile::read_from(reader)?.into()),
|
|
|
|
FileType::MP3 => Ok(MpegFile::read_from(reader)?.into()),
|
|
|
|
FileType::Opus => Ok(OpusFile::read_from(reader)?.into()),
|
|
|
|
FileType::Vorbis => Ok(VorbisFile::read_from(reader)?.into()),
|
|
|
|
FileType::WAV => Ok(WavFile::read_from(reader)?.into()),
|
|
|
|
_ => Err(LoftyError::UnknownFormat), // FileType::MP4 => {}, TODO,
|
2021-08-02 21:25:31 +00:00
|
|
|
}
|
2021-08-19 19:07:40 +00:00
|
|
|
}
|