lofty-rs/src/probe.rs

93 lines
2.7 KiB
Rust
Raw Normal View History

2021-08-24 23:35:28 -04:00
use crate::logic::ape::ApeFile;
2021-08-24 23:38:56 -04:00
use crate::logic::iff::aiff::AiffFile;
use crate::logic::iff::wav::WavFile;
use crate::logic::mp3::Mp3File;
2021-09-05 19:22:29 -04:00
use crate::logic::mp4::Mp4File;
2021-08-24 23:38:56 -04:00
use crate::logic::ogg::flac::FlacFile;
2021-08-24 23:35:28 -04:00
use crate::logic::ogg::opus::OpusFile;
use crate::logic::ogg::vorbis::VorbisFile;
2021-08-19 15:07:40 -04:00
use crate::types::file::AudioFile;
use crate::{FileType, LoftyError, Result, TaggedFile};
2021-08-02 17:25:31 -04:00
2021-08-19 15:07:40 -04:00
use std::io::{Cursor, Read, Seek};
2021-08-02 17:25:31 -04:00
use std::path::Path;
2021-08-19 15:07:40 -04:00
/// Provides a way to extract a [`FileType`] or [`TaggedFile`] from a reader
pub struct Probe;
2021-08-02 17:25:31 -04:00
impl Probe {
/// Create a new `Probe`
pub fn new() -> Self {
2021-08-19 15:07:40 -04:00
Self
2021-08-02 17:25:31 -04:00
}
2021-08-19 15:07:40 -04: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 17:25:31 -04:00
2021-08-19 15:07:40 -04: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 17:25:31 -04:00
2021-08-19 15:07:40 -04:00
None
2021-08-02 17:25:31 -04:00
}
2021-08-19 15:07:40 -04:00
/// Attempts to get the [`FileType`] based on the file extension
2021-08-02 17:25:31 -04:00
///
2021-08-19 15:07:40 -04: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 18:26:58 -04:00
return FileType::try_from_ext(&*ext.to_lowercase()).ok();
2021-08-19 15:07:40 -04:00
}
}
2021-08-02 17:25:31 -04:00
2021-08-19 15:07:40 -04:00
None
2021-08-02 17:25:31 -04:00
}
2021-08-19 15:07:40 -04:00
/// Attempts to extract a [`TaggedFile`] from a reader
2021-08-02 17:25:31 -04:00
///
/// # Errors
///
2021-08-19 15:07:40 -04:00
/// * The format couldn't be determined
pub fn read_from<R>(self, reader: &mut R) -> Result<TaggedFile>
2021-08-02 17:25:31 -04:00
where
R: Read + Seek,
{
2021-08-19 15:07:40 -04:00
match FileType::try_from_sig(reader) {
Ok(f_type) => Ok(match f_type {
FileType::AIFF => AiffFile::read_from(reader)?.into(),
FileType::APE => ApeFile::read_from(reader)?.into(),
FileType::FLAC => FlacFile::read_from(reader)?.into(),
FileType::MP3 => Mp3File::read_from(reader)?.into(),
FileType::Opus => OpusFile::read_from(reader)?.into(),
FileType::Vorbis => VorbisFile::read_from(reader)?.into(),
FileType::WAV => WavFile::read_from(reader)?.into(),
FileType::MP4 => Mp4File::read_from(reader)?.into(),
}),
2021-08-19 15:07:40 -04:00
Err(_) => Err(LoftyError::UnknownFormat),
}
}
2021-08-02 17:25:31 -04:00
2021-08-19 15:07:40 -04: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 17:25:31 -04:00
}
}