remove duplicate code, open from any Read sources

This commit is contained in:
Breval Ferrari 2025-04-30 17:07:44 -04:00
parent 130a75d0ca
commit 53bdd265b3
Signed by: breval
GPG key ID: A2EEBF62257FF960
3 changed files with 94 additions and 164 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "bingus"
version = "0.4.1"
version = "0.5.0"
edition.workspace = true
license.workspace = true
description.workspace = true

View file

@ -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};

View file

@ -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());