feature flags everywhere (warnings but no errors so far)
This commit is contained in:
parent
84a3b182ab
commit
51ab13b3ef
7 changed files with 186 additions and 25 deletions
|
@ -10,15 +10,15 @@ keywords.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
[dependencies]
|
[dependencies]
|
||||||
image = { version = "0.25" }
|
image = { version = "0.25", optional = true }
|
||||||
num = "0"
|
num = { version = "0", optional = true }
|
||||||
rayon = { version = "1", optional = true }
|
rayon = { version = "1", optional = true }
|
||||||
infer = "0"
|
infer = "0"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
derive-new = "0"
|
derive-new = "0"
|
||||||
strum = { version = "0.27", features = ["derive"] }
|
strum = { version = "0.27", features = ["derive"] }
|
||||||
derive_wrapper = "0.1"
|
derive_wrapper = "0.1"
|
||||||
symphonia = { version = "0.5", features = ["all"] }
|
symphonia = { version = "0.5", features = ["all"], optional = true }
|
||||||
printpdf = { version = "0.8.2", features = [
|
printpdf = { version = "0.8.2", features = [
|
||||||
"bmp",
|
"bmp",
|
||||||
"dds",
|
"dds",
|
||||||
|
@ -32,10 +32,12 @@ printpdf = { version = "0.8.2", features = [
|
||||||
"tiff",
|
"tiff",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"webp",
|
"webp",
|
||||||
] }
|
], optional = true }
|
||||||
shiva = "1.4.9"
|
shiva = { version = "1.4.9", optional = true }
|
||||||
anyhow = "1.0"
|
anyhow = { version = "1.0", optional = true }
|
||||||
font-kit = { version = "0.14.2", features = ["loader-freetype-default"] }
|
font-kit = { version = "0.14.2", features = [
|
||||||
|
"loader-freetype-default",
|
||||||
|
], optional = true }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -43,5 +45,20 @@ project-root = "0"
|
||||||
pretty_assertions = "1"
|
pretty_assertions = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["all-formats"]
|
||||||
rayon = ["image/rayon", "printpdf/rayon", "dep:rayon"]
|
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"]
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
pub use printpdf;
|
pub use printpdf;
|
||||||
mod pdf;
|
mod pdf;
|
||||||
|
#[cfg(feature = "shiva")]
|
||||||
|
mod shiva;
|
||||||
|
#[cfg(feature = "shiva")]
|
||||||
|
pub use shiva::*;
|
||||||
|
|
|
@ -64,6 +64,6 @@ impl Bendable for ShivaDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format() -> crate::Format {
|
fn format() -> crate::Format {
|
||||||
crate::Format::Text
|
crate::Format::Doc
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
use cfg_if::cfg_if;
|
||||||
use font_kit::error::FontLoadingError;
|
use font_kit::error::FontLoadingError;
|
||||||
pub use font_kit::font::Font;
|
pub use font_kit::font::Font;
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
@ -32,7 +33,20 @@ impl Bendable for Font {
|
||||||
type Unit = u8;
|
type Unit = u8;
|
||||||
|
|
||||||
fn map<F: Fn(Cow<Self::Unit>) -> Self::Unit + Sync>(self, f: F) -> Self {
|
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())
|
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")
|
.expect("coudn't get font back from bytes after map")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,95 @@
|
||||||
|
#[cfg(feature = "binary")]
|
||||||
pub mod bin;
|
pub mod bin;
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
pub mod doc;
|
pub mod doc;
|
||||||
|
#[cfg(feature = "fonts")]
|
||||||
pub mod fnt;
|
pub mod fnt;
|
||||||
|
#[cfg(feature = "pictures")]
|
||||||
pub mod img;
|
pub mod img;
|
||||||
|
#[cfg(feature = "music")]
|
||||||
pub mod snd;
|
pub mod snd;
|
||||||
|
#[cfg(feature = "text")]
|
||||||
pub mod txt;
|
pub mod txt;
|
||||||
|
|
||||||
pub type Bytes = Vec<u8>;
|
pub type Bytes = Vec<u8>;
|
||||||
|
|
||||||
mod dynamic {
|
mod dynamic {
|
||||||
|
#[cfg(feature = "text")]
|
||||||
|
use std::string::FromUtf8Error;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
string::FromUtf8Error,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
#[cfg(feature = "documents")]
|
||||||
fnt::Font,
|
use super::doc::ShivaDocument;
|
||||||
img::{self, DynamicImage},
|
#[cfg(feature = "fonts")]
|
||||||
snd::{self, Audio},
|
use super::fnt::Font;
|
||||||
txt::{ShivaDocument, Text},
|
#[cfg(feature = "pictures")]
|
||||||
Bendable, Bytes, IntoDataBytes, TryFromDataBytes,
|
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;
|
use infer::MatcherType;
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
use printpdf::PdfDocument;
|
use printpdf::PdfDocument;
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
use shiva::core::{bytes, Document, DocumentType};
|
use shiva::core::{bytes, Document, DocumentType};
|
||||||
use strum::EnumDiscriminants;
|
use strum::EnumDiscriminants;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "text")] {
|
||||||
#[derive(EnumDiscriminants)]
|
#[derive(EnumDiscriminants)]
|
||||||
#[strum_discriminants(name(Format))]
|
#[strum_discriminants(name(Format))]
|
||||||
pub enum DynamicBendable<'a> {
|
pub enum DynamicBendable<'a> {
|
||||||
|
#[cfg(feature = "pictures")]
|
||||||
Image(DynamicImage),
|
Image(DynamicImage),
|
||||||
|
#[cfg(feature = "binary")]
|
||||||
Binary(Bytes),
|
Binary(Bytes),
|
||||||
|
#[cfg(feature = "music")]
|
||||||
Sound(Audio),
|
Sound(Audio),
|
||||||
|
#[cfg(feature = "text")]
|
||||||
Text(Text<'a>),
|
Text(Text<'a>),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
Doc(ShivaDocument),
|
Doc(ShivaDocument),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
Archive(PdfDocument),
|
Archive(PdfDocument),
|
||||||
Meta,
|
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),
|
Font(Font),
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
#[cfg(feature = "shiva")]
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
#[error("extension is unknown by Shiva")]
|
#[error("extension is unknown by Shiva")]
|
||||||
pub struct ShivaUnknownExtensionError;
|
pub struct ShivaUnknownExtensionError;
|
||||||
|
|
||||||
|
#[cfg(feature = "shiva")]
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ShivaError {
|
pub enum ShivaError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
|
@ -59,14 +102,19 @@ mod dynamic {
|
||||||
pub enum OpenError {
|
pub enum OpenError {
|
||||||
#[error("io: {0}")]
|
#[error("io: {0}")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
|
#[cfg(feature = "pictures")]
|
||||||
#[error("image: {0}")]
|
#[error("image: {0}")]
|
||||||
Image(#[from] img::ImageError),
|
Image(#[from] img::ImageError),
|
||||||
|
#[cfg(feature = "music")]
|
||||||
#[error("audio: {0}")]
|
#[error("audio: {0}")]
|
||||||
Audio(#[from] snd::AudioOpenError),
|
Audio(#[from] snd::AudioOpenError),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
#[error("pdf: {0}")]
|
#[error("pdf: {0}")]
|
||||||
Pdf(String),
|
Pdf(String),
|
||||||
|
#[cfg(feature = "text")]
|
||||||
#[error("text: {0}")]
|
#[error("text: {0}")]
|
||||||
Text(#[from] FromUtf8Error),
|
Text(#[from] FromUtf8Error),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
#[error("document: {0}")]
|
#[error("document: {0}")]
|
||||||
Document(#[from] ShivaError),
|
Document(#[from] ShivaError),
|
||||||
}
|
}
|
||||||
|
@ -102,7 +150,13 @@ mod dynamic {
|
||||||
fn map<F: Fn(Cow<Self::Unit>) -> Self::Unit + Sync>(mut self, f: F) -> Self {
|
fn map<F: Fn(Cow<Self::Unit>) -> Self::Unit + Sync>(mut self, f: F) -> Self {
|
||||||
let mut bytes = Vec::new();
|
let mut bytes = Vec::new();
|
||||||
self.read_to_end(&mut bytes).expect("couldn't read file");
|
self.read_to_end(&mut bytes).expect("couldn't read file");
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "binary")] {
|
||||||
self.write_all(&bytes.map(f)).expect("couldn't write file");
|
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
|
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> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<Option<DynamicBendable<'static>>, OpenError> {
|
||||||
use MatcherType::*;
|
use MatcherType::*;
|
||||||
infer::get_from_path(&path)?
|
infer::get_from_path(&path)?
|
||||||
|
@ -118,8 +174,11 @@ mod dynamic {
|
||||||
.map(
|
.map(
|
||||||
|(matcher, extension)| -> Result<DynamicBendable, OpenError> {
|
|(matcher, extension)| -> Result<DynamicBendable, OpenError> {
|
||||||
Ok(match matcher {
|
Ok(match matcher {
|
||||||
|
#[cfg(feature = "pictures")]
|
||||||
Image => DynamicBendable::Image(img::open(path)?),
|
Image => DynamicBendable::Image(img::open(path)?),
|
||||||
|
#[cfg(feature = "music")]
|
||||||
Audio => DynamicBendable::Sound(crate::snd::Audio::open(path)?),
|
Audio => DynamicBendable::Sound(crate::snd::Audio::open(path)?),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
Archive if extension == "pdf" => DynamicBendable::Archive(
|
Archive if extension == "pdf" => DynamicBendable::Archive(
|
||||||
PdfDocument::try_from_data_bytes(
|
PdfDocument::try_from_data_bytes(
|
||||||
File::open(path)?
|
File::open(path)?
|
||||||
|
@ -130,6 +189,7 @@ mod dynamic {
|
||||||
)
|
)
|
||||||
.map_err(OpenError::Pdf)?,
|
.map_err(OpenError::Pdf)?,
|
||||||
),
|
),
|
||||||
|
#[cfg(feature = "documents")]
|
||||||
Archive => {
|
Archive => {
|
||||||
let document_type = DocumentType::from_extension(extension)
|
let document_type = DocumentType::from_extension(extension)
|
||||||
.ok_or(ShivaUnknownExtensionError)
|
.ok_or(ShivaUnknownExtensionError)
|
||||||
|
@ -145,7 +205,9 @@ mod dynamic {
|
||||||
}
|
}
|
||||||
Book => todo!(),
|
Book => todo!(),
|
||||||
Doc => todo!(),
|
Doc => todo!(),
|
||||||
|
#[cfg(feature = "fonts")]
|
||||||
Font => todo!(),
|
Font => todo!(),
|
||||||
|
#[cfg(feature = "text")]
|
||||||
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
|
Text => DynamicBendable::Text(crate::txt::Text::try_from_data_bytes(
|
||||||
File::open(path)?
|
File::open(path)?
|
||||||
.bytes()
|
.bytes()
|
||||||
|
@ -153,16 +215,80 @@ mod dynamic {
|
||||||
(),
|
(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)?),
|
)?),
|
||||||
|
#[cfg(feature = "binary")]
|
||||||
_ => DynamicBendable::Binary({
|
_ => DynamicBendable::Binary({
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
File::open(path)?.read_to_end(&mut buf)?;
|
File::open(path)?.read_to_end(&mut buf)?;
|
||||||
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()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::{borrow::Cow, convert::Infallible};
|
use std::{borrow::Cow, convert::Infallible};
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
mod bare;
|
mod bare;
|
||||||
pub use bare::*;
|
pub use bare::*;
|
||||||
mod shiva;
|
|
||||||
pub use shiva::*;
|
|
||||||
|
|
|
@ -2,8 +2,10 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
/// CLI from the Bent project
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub(super) struct Cli {
|
pub(super) struct Cli {
|
||||||
pub(super) input_file: PathBuf,
|
/// Input file or standard input.
|
||||||
pub(super) output_file: PathBuf,
|
pub(super) input: PathBuf,
|
||||||
|
pub(super) output: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue