remove duplicate code, open from any Read sources
This commit is contained in:
parent
130a75d0ca
commit
53bdd265b3
3 changed files with 94 additions and 164 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bingus"
|
||||
version = "0.4.1"
|
||||
version = "0.5.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
description.workspace = true
|
||||
|
|
|
@ -19,7 +19,7 @@ mod dynamic {
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
fs::File,
|
||||
io::{self, Read, Write},
|
||||
io::{self, Cursor, Read, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,8 @@ mod dynamic {
|
|||
#[cfg(feature = "text")]
|
||||
use super::txt::Text;
|
||||
use super::{Bendable, Bytes, IntoDataBytes, TryFromDataBytes};
|
||||
#[cfg(not(feature = "text"))]
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
#[cfg(feature = "fonts")]
|
||||
|
@ -46,8 +48,6 @@ mod dynamic {
|
|||
use strum::EnumDiscriminants;
|
||||
use thiserror::Error;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "text")] {
|
||||
#[derive(EnumDiscriminants)]
|
||||
#[strum_discriminants(name(Format))]
|
||||
pub enum DynamicBendable<'a> {
|
||||
|
@ -59,23 +59,8 @@ mod dynamic {
|
|||
Sound(Audio),
|
||||
#[cfg(feature = "text")]
|
||||
Text(Text<'a>),
|
||||
#[cfg(feature = "documents")]
|
||||
Doc(ShivaDocument),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive(PdfDocument),
|
||||
Meta,
|
||||
#[cfg(feature = "fonts")]
|
||||
Font(FontKitFont),
|
||||
}} else {
|
||||
#[derive(EnumDiscriminants)]
|
||||
#[strum_discriminants(name(Format))]
|
||||
pub enum DynamicBendable {
|
||||
#[cfg(feature = "pictures")]
|
||||
Image(DynamicImage),
|
||||
#[cfg(feature = "binary")]
|
||||
Binary(Bytes),
|
||||
#[cfg(feature = "music")]
|
||||
Sound(Audio),
|
||||
#[cfg(not(feature = "text"))]
|
||||
Phantom(PhantomData<&'a ()>),
|
||||
#[cfg(feature = "documents")]
|
||||
Doc(ShivaDocument),
|
||||
#[cfg(feature = "documents")]
|
||||
|
@ -84,7 +69,6 @@ mod dynamic {
|
|||
#[cfg(feature = "fonts")]
|
||||
Font(FontKitFont),
|
||||
}
|
||||
}}
|
||||
|
||||
#[cfg(feature = "shiva")]
|
||||
#[derive(Debug, Error)]
|
||||
|
@ -170,132 +154,75 @@ mod dynamic {
|
|||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "text")] {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Option<DynamicBendable<'static>>, OpenError> {
|
||||
pub type DynamicResult = Result<Option<DynamicBendable<'static>>, OpenError>;
|
||||
|
||||
fn guess(t: Option<infer::Type>, bytes: Bytes) -> DynamicResult {
|
||||
use MatcherType::*;
|
||||
infer::get_from_path(&path)?
|
||||
.map(|t| (t.matcher_type(), t.extension()))
|
||||
.map(
|
||||
|(matcher, extension)| -> Result<DynamicBendable, OpenError> {
|
||||
Ok(match matcher {
|
||||
#[cfg(feature = "pictures")]
|
||||
Image => DynamicBendable::Image(img::open(path)?),
|
||||
#[cfg(feature = "music")]
|
||||
Audio => DynamicBendable::Sound(crate::snd::Audio::open(path)?),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive if extension == "pdf" => DynamicBendable::Archive(
|
||||
PdfDocument::try_from_data_bytes(
|
||||
File::open(path)?
|
||||
.bytes()
|
||||
.collect::<Result<Bytes, io::Error>>()?,
|
||||
(),
|
||||
Default::default(),
|
||||
)
|
||||
.map_err(OpenError::Pdf)?,
|
||||
),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive | Doc => {
|
||||
let document_type = DocumentType::from_extension(extension)
|
||||
.ok_or(ShivaUnknownExtensionError)
|
||||
.map_err(ShivaError::UnknownExtension)?;
|
||||
DynamicBendable::Doc(ShivaDocument::new(
|
||||
Document::parse(
|
||||
&bytes::Bytes::from(std::fs::read(path)?),
|
||||
document_type,
|
||||
)
|
||||
.map_err(ShivaError::Anyhow)?,
|
||||
t.map(|t| (t.matcher_type(), t.extension()))
|
||||
.map(
|
||||
|(matcher, extension)| -> Result<DynamicBendable, OpenError> {
|
||||
Ok(match matcher {
|
||||
#[cfg(feature = "pictures")]
|
||||
Image => DynamicBendable::Image(img::load_from_memory(&bytes)?),
|
||||
#[cfg(feature = "music")]
|
||||
Audio => DynamicBendable::Sound(crate::snd::Audio::open(Cursor::new(bytes), None)?),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive if extension == "pdf" => DynamicBendable::Archive(
|
||||
PdfDocument::try_from_data_bytes(
|
||||
bytes,
|
||||
(),
|
||||
Default::default(),
|
||||
)
|
||||
.map_err(OpenError::Pdf)?,
|
||||
),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive | Doc => {
|
||||
let document_type = DocumentType::from_extension(extension)
|
||||
.ok_or(ShivaUnknownExtensionError)
|
||||
.map_err(ShivaError::UnknownExtension)?;
|
||||
DynamicBendable::Doc(ShivaDocument::new(
|
||||
Document::parse(
|
||||
&bytes::Bytes::from(bytes),
|
||||
document_type,
|
||||
))
|
||||
}
|
||||
#[cfg(feature = "fonts")]
|
||||
Font => DynamicBendable::Font(FontKitFont::try_from_data_bytes(
|
||||
File::open(path)?
|
||||
.bytes()
|
||||
.collect::<Result<Bytes, io::Error>>()?,
|
||||
(),
|
||||
Default::default(),
|
||||
)?),
|
||||
#[cfg(feature = "text")]
|
||||
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
|
||||
File::open(path)?
|
||||
.bytes()
|
||||
.collect::<Result<Bytes, io::Error>>()?,
|
||||
(),
|
||||
Default::default(),
|
||||
)?),
|
||||
#[cfg(feature = "binary")]
|
||||
_ => DynamicBendable::Binary({
|
||||
let mut buf = Vec::new();
|
||||
File::open(path)?.read_to_end(&mut buf)?;
|
||||
buf
|
||||
}),
|
||||
#[cfg(not(feature = "binary"))]
|
||||
_ => unimplemented!("no format reader available to open this thing (turn on the 'binary' feature to default to binary data)"),
|
||||
})
|
||||
},
|
||||
)
|
||||
.transpose()
|
||||
}} else {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Option<DynamicBendable>, OpenError> {
|
||||
use MatcherType::*;
|
||||
infer::get_from_path(&path)?
|
||||
.map(|t| (t.matcher_type(), t.extension()))
|
||||
.map(
|
||||
|(matcher, extension)| -> Result<DynamicBendable, OpenError> {
|
||||
Ok(match matcher {
|
||||
#[cfg(feature = "pictures")]
|
||||
Image => DynamicBendable::Image(img::open(path)?),
|
||||
#[cfg(feature = "music")]
|
||||
Audio => DynamicBendable::Sound(crate::snd::Audio::open(path)?),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive if extension == "pdf" => DynamicBendable::Archive(
|
||||
PdfDocument::try_from_data_bytes(
|
||||
File::open(path)?
|
||||
.bytes()
|
||||
.collect::<Result<Bytes, io::Error>>()?,
|
||||
(),
|
||||
Default::default(),
|
||||
)
|
||||
.map_err(OpenError::Pdf)?,
|
||||
),
|
||||
#[cfg(feature = "documents")]
|
||||
Archive | Doc => {
|
||||
let document_type = DocumentType::from_extension(extension)
|
||||
.ok_or(ShivaUnknownExtensionError)
|
||||
.map_err(ShivaError::UnknownExtension)?;
|
||||
DynamicBendable::Doc(ShivaDocument::new(
|
||||
Document::parse(
|
||||
&bytes::Bytes::from(std::fs::read(path)?),
|
||||
document_type,
|
||||
)
|
||||
.map_err(ShivaError::Anyhow)?,
|
||||
document_type,
|
||||
))
|
||||
}
|
||||
#[cfg(feature = "fonts")]
|
||||
Font => todo!(),
|
||||
#[cfg(feature = "text")]
|
||||
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
|
||||
File::open(path)?
|
||||
.bytes()
|
||||
.collect::<Result<Bytes, io::Error>>()?,
|
||||
(),
|
||||
Default::default(),
|
||||
)?),
|
||||
#[cfg(feature = "binary")]
|
||||
_ => DynamicBendable::Binary({
|
||||
let mut buf = Vec::new();
|
||||
File::open(path)?.read_to_end(&mut buf)?;
|
||||
buf
|
||||
}),
|
||||
_ => unimplemented!("no format available to open this thing"),
|
||||
})
|
||||
},
|
||||
)
|
||||
.transpose()
|
||||
.map_err(ShivaError::Anyhow)?,
|
||||
document_type,
|
||||
))
|
||||
}
|
||||
#[cfg(feature = "fonts")]
|
||||
Font => DynamicBendable::Font(FontKitFont::try_from_data_bytes(
|
||||
bytes,
|
||||
(),
|
||||
Default::default(),
|
||||
)?),
|
||||
#[cfg(feature = "text")]
|
||||
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
|
||||
bytes,
|
||||
(),
|
||||
Default::default(),
|
||||
)?),
|
||||
#[cfg(feature = "binary")]
|
||||
_ => DynamicBendable::Binary(bytes),
|
||||
#[cfg(not(feature = "binary"))]
|
||||
_ => unimplemented!("no format reader available to open this thing (turn on the 'binary' feature to default to binary data)"),
|
||||
})
|
||||
},
|
||||
)
|
||||
.transpose()
|
||||
}
|
||||
|
||||
pub fn open_file(path: impl AsRef<Path>) -> DynamicResult {
|
||||
open(&mut File::open(path)?)
|
||||
}
|
||||
|
||||
pub fn open(source: &mut impl Read) -> DynamicResult {
|
||||
let contents = {
|
||||
let mut c = Vec::new();
|
||||
source.read_to_end(&mut c)?;
|
||||
c
|
||||
};
|
||||
guess(infer::get(&contents), contents)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
use std::{borrow::Cow, convert::Infallible};
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::{self, Read},
|
||||
path::Path,
|
||||
};
|
||||
use std::io::{self, Read};
|
||||
|
||||
use derive_new::new;
|
||||
use symphonia::{
|
||||
|
@ -11,7 +7,7 @@ use symphonia::{
|
|||
codecs::{Decoder, CODEC_TYPE_NULL},
|
||||
conv::FromSample,
|
||||
formats::FormatReader,
|
||||
io::MediaSourceStream,
|
||||
io::{MediaSource, MediaSourceStream},
|
||||
probe::Hint,
|
||||
sample::{i24, u24},
|
||||
},
|
||||
|
@ -51,19 +47,22 @@ impl PartialEq for AudioOpenError {
|
|||
}
|
||||
|
||||
impl Audio {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Audio, AudioOpenError> {
|
||||
pub fn open(
|
||||
source: impl MediaSource + 'static,
|
||||
extension: Option<&str>,
|
||||
) -> Result<Audio, AudioOpenError> {
|
||||
let registry = default::get_codecs();
|
||||
let probe = default::get_probe();
|
||||
let mediasource = File::open(path.as_ref())?;
|
||||
let mss = MediaSourceStream::new(Box::new(mediasource), Default::default());
|
||||
let mss = MediaSourceStream::new(Box::new(source), Default::default());
|
||||
let reader = probe
|
||||
.format(
|
||||
Hint::new().with_extension(
|
||||
path.as_ref()
|
||||
.extension()
|
||||
.and_then(|os_str| os_str.to_str())
|
||||
.unwrap_or("mp3"),
|
||||
),
|
||||
&{
|
||||
let mut hint = Hint::new();
|
||||
if let Some(e) = extension {
|
||||
hint.with_extension(e);
|
||||
}
|
||||
hint
|
||||
},
|
||||
mss,
|
||||
&Default::default(),
|
||||
&Default::default(),
|
||||
|
@ -161,6 +160,8 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
|
||||
use project_root::get_project_root;
|
||||
|
||||
use crate::IntoDataBytes;
|
||||
|
@ -171,12 +172,14 @@ mod tests {
|
|||
fn open_sample_file() {
|
||||
let original =
|
||||
&include_bytes!("../../../testing material/sound/sample-3s.mp3")[52079 - 51826..];
|
||||
let path = get_project_root()
|
||||
.expect("can't find project root!")
|
||||
.join("testing material")
|
||||
.join("sound")
|
||||
.join("sample-3s.mp3");
|
||||
let result = Audio::open(
|
||||
get_project_root()
|
||||
.expect("can't find project root!")
|
||||
.join("testing material")
|
||||
.join("sound")
|
||||
.join("sample-3s.mp3"),
|
||||
File::open(&path).expect("can't find test file!"),
|
||||
path.extension().and_then(|s| s.to_str()),
|
||||
)
|
||||
.map(|audio| audio.into_data_bytes());
|
||||
dbg!(original.len());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue