From 51ab13b3ef21efe6dda4cc56c97aba7eac926261 Mon Sep 17 00:00:00 2001 From: Breval Ferrari Date: Sat, 19 Apr 2025 17:26:58 -0400 Subject: [PATCH] feature flags everywhere (warnings but no errors so far) --- bingus/Cargo.toml | 35 ++++++-- bingus/src/doc.rs | 4 + bingus/src/{txt => doc}/shiva.rs | 2 +- bingus/src/fnt/fontkit.rs | 18 +++- bingus/src/lib.rs | 144 +++++++++++++++++++++++++++++-- bingus/src/txt.rs | 2 - bong/src/cli.rs | 6 +- 7 files changed, 186 insertions(+), 25 deletions(-) rename bingus/src/{txt => doc}/shiva.rs (98%) diff --git a/bingus/Cargo.toml b/bingus/Cargo.toml index 48a6eba..bc52178 100644 --- a/bingus/Cargo.toml +++ b/bingus/Cargo.toml @@ -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"] diff --git a/bingus/src/doc.rs b/bingus/src/doc.rs index abcf649..57af55a 100644 --- a/bingus/src/doc.rs +++ b/bingus/src/doc.rs @@ -1,2 +1,6 @@ pub use printpdf; mod pdf; +#[cfg(feature = "shiva")] +mod shiva; +#[cfg(feature = "shiva")] +pub use shiva::*; diff --git a/bingus/src/txt/shiva.rs b/bingus/src/doc/shiva.rs similarity index 98% rename from bingus/src/txt/shiva.rs rename to bingus/src/doc/shiva.rs index 5b4c7bd..cde0f74 100644 --- a/bingus/src/txt/shiva.rs +++ b/bingus/src/doc/shiva.rs @@ -64,6 +64,6 @@ impl Bendable for ShivaDocument { } fn format() -> crate::Format { - crate::Format::Text + crate::Format::Doc } } diff --git a/bingus/src/fnt/fontkit.rs b/bingus/src/fnt/fontkit.rs index caff993..b8a28e0 100644 --- a/bingus/src/fnt/fontkit.rs +++ b/bingus/src/fnt/fontkit.rs @@ -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) -> 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 { diff --git a/bingus/src/lib.rs b/bingus/src/lib.rs index d4765fb..376c089 100644 --- a/bingus/src/lib.rs +++ b/bingus/src/lib.rs @@ -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; 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) -> 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::>()).expect("couldn't write file"); + } + } self } @@ -111,6 +165,8 @@ mod dynamic { } } + cfg_if! { + if #[cfg(feature = "text")] { pub fn open>(path: P) -> Result>, OpenError> { use MatcherType::*; infer::get_from_path(&path)? @@ -118,8 +174,11 @@ mod dynamic { .map( |(matcher, extension)| -> Result { 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>(path: P) -> Result, OpenError> { + use MatcherType::*; + infer::get_from_path(&path)? + .map(|t| (t.matcher_type(), t.extension())) + .map( + |(matcher, extension)| -> Result { + 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::>()?, + (), + 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::>()?, + (), + 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}; diff --git a/bingus/src/txt.rs b/bingus/src/txt.rs index 3a1eb41..1fc6ce6 100644 --- a/bingus/src/txt.rs +++ b/bingus/src/txt.rs @@ -1,4 +1,2 @@ mod bare; pub use bare::*; -mod shiva; -pub use shiva::*; diff --git a/bong/src/cli.rs b/bong/src/cli.rs index ef03136..d9571a3 100644 --- a/bong/src/cli.rs +++ b/bong/src/cli.rs @@ -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, }