lofty-rs/src/probe.rs

93 lines
2.6 KiB
Rust
Raw Normal View History

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
}