feature flags everywhere (warnings but no errors so far)

This commit is contained in:
Breval Ferrari 2025-04-19 17:26:58 -04:00
parent 84a3b182ab
commit 51ab13b3ef
Signed by: breval
GPG key ID: A2EEBF62257FF960
7 changed files with 186 additions and 25 deletions

View file

@ -10,15 +10,15 @@ keywords.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
image = { version = "0.25" }
num = "0"
image = { version = "0.25", optional = true }
num = { version = "0", optional = true }
rayon = { version = "1", optional = true }
infer = "0"
thiserror = "2"
derive-new = "0"
strum = { version = "0.27", features = ["derive"] }
derive_wrapper = "0.1"
symphonia = { version = "0.5", features = ["all"] }
symphonia = { version = "0.5", features = ["all"], optional = true }
printpdf = { version = "0.8.2", features = [
"bmp",
"dds",
@ -32,10 +32,12 @@ printpdf = { version = "0.8.2", features = [
"tiff",
"js-sys",
"webp",
] }
shiva = "1.4.9"
anyhow = "1.0"
font-kit = { version = "0.14.2", features = ["loader-freetype-default"] }
], optional = true }
shiva = { version = "1.4.9", optional = true }
anyhow = { version = "1.0", optional = true }
font-kit = { version = "0.14.2", features = [
"loader-freetype-default",
], optional = true }
cfg-if = "1.0.0"
[dev-dependencies]
@ -43,5 +45,20 @@ project-root = "0"
pretty_assertions = "1"
[features]
default = []
rayon = ["image/rayon", "printpdf/rayon", "dep:rayon"]
default = ["all-formats"]
all-formats = ["binary", "documents", "fonts", "pictures", "music", "text"]
binary = []
documents = ["shiva", "printpdf"]
fonts = ["font-kit"]
pictures = ["image"]
music = ["symphonia", "dep:num"]
text = []
shiva = ["dep:shiva", "dep:anyhow"]
printpdf = ["dep:printpdf"]
font-kit = ["dep:font-kit"]
image = ["dep:image", "dep:num"]
symphonia = ["dep:symphonia"]
rayon = ["image?/rayon", "printpdf?/rayon", "dep:rayon"]

View file

@ -1,2 +1,6 @@
pub use printpdf;
mod pdf;
#[cfg(feature = "shiva")]
mod shiva;
#[cfg(feature = "shiva")]
pub use shiva::*;

View file

@ -64,6 +64,6 @@ impl Bendable for ShivaDocument {
}
fn format() -> crate::Format {
crate::Format::Text
crate::Format::Doc
}
}

View file

@ -1,3 +1,4 @@
use cfg_if::cfg_if;
use font_kit::error::FontLoadingError;
pub use font_kit::font::Font;
use std::{borrow::Cow, sync::Arc};
@ -32,8 +33,21 @@ impl Bendable for Font {
type Unit = u8;
fn map<F: Fn(Cow<Self::Unit>) -> Self::Unit + Sync>(self, f: F) -> Self {
Self::try_from_data_bytes(self.into_data_bytes().map(f), (), Default::default())
.expect("coudn't get font back from bytes after map")
Self::try_from_data_bytes(
{
let bytes = self.into_data_bytes();
cfg_if! {
if #[cfg(feature = "binary")] {
bytes.map(f)
} else {
bytes.into_iter().map(|e| f(Cow::Owned(e))).collect()
}
}
},
(),
Default::default(),
)
.expect("coudn't get font back from bytes after map")
}
fn format() -> crate::Format {

View file

@ -1,52 +1,95 @@
#[cfg(feature = "binary")]
pub mod bin;
#[cfg(feature = "documents")]
pub mod doc;
#[cfg(feature = "fonts")]
pub mod fnt;
#[cfg(feature = "pictures")]
pub mod img;
#[cfg(feature = "music")]
pub mod snd;
#[cfg(feature = "text")]
pub mod txt;
pub type Bytes = Vec<u8>;
mod dynamic {
#[cfg(feature = "text")]
use std::string::FromUtf8Error;
use std::{
borrow::Cow,
fs::File,
io::{self, Read, Write},
path::Path,
string::FromUtf8Error,
};
use super::{
fnt::Font,
img::{self, DynamicImage},
snd::{self, Audio},
txt::{ShivaDocument, Text},
Bendable, Bytes, IntoDataBytes, TryFromDataBytes,
};
#[cfg(feature = "documents")]
use super::doc::ShivaDocument;
#[cfg(feature = "fonts")]
use super::fnt::Font;
#[cfg(feature = "pictures")]
use super::img::{self, DynamicImage};
#[cfg(feature = "music")]
use super::snd::{self, Audio};
#[cfg(feature = "text")]
use super::txt::Text;
use super::{Bendable, Bytes, IntoDataBytes, TryFromDataBytes};
use cfg_if::cfg_if;
use infer::MatcherType;
#[cfg(feature = "documents")]
use printpdf::PdfDocument;
#[cfg(feature = "documents")]
use shiva::core::{bytes, Document, DocumentType};
use strum::EnumDiscriminants;
use thiserror::Error;
cfg_if! {
if #[cfg(feature = "text")] {
#[derive(EnumDiscriminants)]
#[strum_discriminants(name(Format))]
pub enum DynamicBendable<'a> {
#[cfg(feature = "pictures")]
Image(DynamicImage),
#[cfg(feature = "binary")]
Binary(Bytes),
#[cfg(feature = "music")]
Sound(Audio),
#[cfg(feature = "text")]
Text(Text<'a>),
#[cfg(feature = "documents")]
Doc(ShivaDocument),
#[cfg(feature = "documents")]
Archive(PdfDocument),
Meta,
#[cfg(feature = "fonts")]
Font(Font),
}} 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(feature = "documents")]
Doc(ShivaDocument),
#[cfg(feature = "documents")]
Archive(PdfDocument),
Meta,
#[cfg(feature = "fonts")]
Font(Font),
}
}}
#[cfg(feature = "shiva")]
#[derive(Debug, Error)]
#[error("extension is unknown by Shiva")]
pub struct ShivaUnknownExtensionError;
#[cfg(feature = "shiva")]
#[derive(Debug, Error)]
pub enum ShivaError {
#[error("{0}")]
@ -59,14 +102,19 @@ mod dynamic {
pub enum OpenError {
#[error("io: {0}")]
Io(#[from] io::Error),
#[cfg(feature = "pictures")]
#[error("image: {0}")]
Image(#[from] img::ImageError),
#[cfg(feature = "music")]
#[error("audio: {0}")]
Audio(#[from] snd::AudioOpenError),
#[cfg(feature = "documents")]
#[error("pdf: {0}")]
Pdf(String),
#[cfg(feature = "text")]
#[error("text: {0}")]
Text(#[from] FromUtf8Error),
#[cfg(feature = "documents")]
#[error("document: {0}")]
Document(#[from] ShivaError),
}
@ -102,7 +150,13 @@ mod dynamic {
fn map<F: Fn(Cow<Self::Unit>) -> Self::Unit + Sync>(mut self, f: F) -> Self {
let mut bytes = Vec::new();
self.read_to_end(&mut bytes).expect("couldn't read file");
self.write_all(&bytes.map(f)).expect("couldn't write file");
cfg_if! {
if #[cfg(feature = "binary")] {
self.write_all(&bytes.map(f)).expect("couldn't write file");
} else {
self.write_all(&bytes.into_iter().map(|e| f(Cow::Owned(e))).collect::<Vec<u8>>()).expect("couldn't write file");
}
}
self
}
@ -111,6 +165,8 @@ mod dynamic {
}
}
cfg_if! {
if #[cfg(feature = "text")] {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Option<DynamicBendable<'static>>, OpenError> {
use MatcherType::*;
infer::get_from_path(&path)?
@ -118,8 +174,11 @@ mod dynamic {
.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)?
@ -130,6 +189,7 @@ mod dynamic {
)
.map_err(OpenError::Pdf)?,
),
#[cfg(feature = "documents")]
Archive => {
let document_type = DocumentType::from_extension(extension)
.ok_or(ShivaUnknownExtensionError)
@ -145,7 +205,9 @@ mod dynamic {
}
Book => todo!(),
Doc => todo!(),
#[cfg(feature = "fonts")]
Font => todo!(),
#[cfg(feature = "text")]
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
File::open(path)?
.bytes()
@ -153,16 +215,80 @@ mod dynamic {
(),
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 available to open this thing"),
})
},
)
.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 => {
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,
))
}
Book => todo!(),
Doc => todo!(),
#[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()
}
}}
}
use std::{borrow::Cow, convert::Infallible};

View file

@ -1,4 +1,2 @@
mod bare;
pub use bare::*;
mod shiva;
pub use shiva::*;

View file

@ -2,8 +2,10 @@ use std::path::PathBuf;
use clap::Parser;
/// CLI from the Bent project
#[derive(Parser)]
pub(super) struct Cli {
pub(super) input_file: PathBuf,
pub(super) output_file: PathBuf,
/// Input file or standard input.
pub(super) input: PathBuf,
pub(super) output: PathBuf,
}