diff --git a/bingus/src/lib.rs b/bingus/src/lib.rs index 23b0207..b13513a 100644 --- a/bingus/src/lib.rs +++ b/bingus/src/lib.rs @@ -40,7 +40,7 @@ mod dynamic { use cfg_if::cfg_if; #[cfg(feature = "fonts")] use font_kit::error::FontLoadingError; - use infer::MatcherType; + pub use infer::MatcherType; #[cfg(feature = "documents")] use printpdf::PdfDocument; #[cfg(feature = "documents")] diff --git a/bingus/src/snd.rs b/bingus/src/snd.rs index 1de55b0..dda4d48 100644 --- a/bingus/src/snd.rs +++ b/bingus/src/snd.rs @@ -1,4 +1,4 @@ -pub use symphonia::core::sample::Sample; +pub use symphonia::core::*; mod raw; pub use raw::*; mod simphonia; diff --git a/bingus/src/snd/raw.rs b/bingus/src/snd/raw.rs index 6a01b62..0f57acb 100644 --- a/bingus/src/snd/raw.rs +++ b/bingus/src/snd/raw.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use super::Sample; +use super::sample::Sample; use cfg_if::cfg_if; use derive_wrapper::{AsRef, From}; use num::{ diff --git a/bingus/src/snd/simphonia.rs b/bingus/src/snd/simphonia.rs index 20ef032..d79c598 100644 --- a/bingus/src/snd/simphonia.rs +++ b/bingus/src/snd/simphonia.rs @@ -17,7 +17,7 @@ use thiserror::Error; use crate::IntoDataBytes; -use super::{RawSamples, Sample}; +use super::{sample::Sample, RawSamples}; /// Audio, unlike DynamicImage, isn't directly bendable /// because its underlying data format isn't decided automatically diff --git a/bong/Cargo.toml b/bong/Cargo.toml index 4916ea1..f4350e0 100644 --- a/bong/Cargo.toml +++ b/bong/Cargo.toml @@ -11,7 +11,10 @@ keywords.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0" +anyhow = "*" bingus = { path = "../bingus" } -clap = { version = "4.5", features = ["derive"] } -unwrap-infallible = "0.1" +strum = { version = "*", features = ["derive"] } +derive-new = "*" +clap = { version = "4.5.40", features = ["derive"] } +derive_wrapper = "0.1.7" +# unwrap-infallible = "0.1" diff --git a/bong/src/cli.rs b/bong/src/cli.rs index d9571a3..c8cbed0 100644 --- a/bong/src/cli.rs +++ b/bong/src/cli.rs @@ -1,11 +1,130 @@ -use std::path::PathBuf; +use std::{ + io::{self, stdin, stdout}, + ops::Not, + str::FromStr, +}; use clap::Parser; +use derive_new::new; +use derive_wrapper::AsRef; +use strum::{AsRefStr, EnumIter, EnumString}; +#[derive(new, Parser)] +#[clap(version, author, about)] /// CLI from the Bent project -#[derive(Parser)] pub(super) struct Cli { - /// Input file or standard input. - pub(super) input: PathBuf, - pub(super) output: PathBuf, + /// Input format (leave empty for auto mode) + #[arg(short, long)] + pub(super) input_format: Option, + /// Input file or standard input ("-"). + pub(super) input: FileOrStd, + // /// List of commands (process or bend to another format) + // pub(super) commands: Vec, + /// Onput file or standard output ("-"). + pub(super) output: FileOrStd, +} + +#[derive(AsRef)] +#[cfg_attr(debug_assertions, derive(Debug))] +struct File(std::fs::File); + +impl Clone for File { + fn clone(&self) -> Self { + File( + self.0 + .try_clone() + .expect("can't clone this file's handle :("), + ) + } +} + +impl FromStr for File { + type Err = io::Error; + fn from_str(s: &str) -> Result { + std::fs::File::open(s).map(File) + } +} + +#[derive(Clone, Copy, Default)] +struct Stdin; +#[derive(Clone, Copy, Default)] +struct Stdout; + +trait New { + type Real; + fn new() -> Self::Real; +} + +impl New for Stdin { + type Real = std::io::Stdin; + fn new() -> Self::Real { + stdin() + } +} + +impl New for Stdout { + type Real = std::io::Stdout; + fn new() -> Self::Real { + stdout() + } +} + +impl FromStr for FileOrStd { + type Err = io::Error; + fn from_str(s: &str) -> Result { + s.is_empty() + .not() + .then_some(s.parse().map(FileOrStd::File)) + .unwrap_or(Ok(FileOrStd::Std(Default::default()))) + } +} + +#[derive(Clone)] +#[cfg_attr(debug_assertions, derive(Debug))] +pub(super) enum FileOrStd { + File(File), + Std(S), +} + +pub(super) enum OutputFormat {} + +// #[derive(Clone)] +// pub(super) enum Command { +// Into(Bendable), +// Process(Process), +// } + +#[derive(EnumString, AsRefStr, Clone)] +pub(super) enum Bendable { + #[strum(serialize = "bin", serialize = "binary")] + Binary, +} + +#[derive(Clone)] +pub(super) enum Process {} + +#[derive(EnumString, EnumIter, Clone, Copy)] +enum MatcherType { + Audio, + Doc, + Font, + Image, + Pdf, + Text, + Raw, +} + +impl From for bingus::MatcherType { + fn from(value: MatcherType) -> Self { + use bingus::MatcherType::*; + match value { + MatcherType::Audio => Audio, + MatcherType::Doc => Doc, + MatcherType::Font => Font, + MatcherType::Image => Image, + MatcherType::Pdf => Archive, + MatcherType::Text => Text, + MatcherType::Raw => Custom, + } + } } diff --git a/bong/src/main.rs b/bong/src/main.rs index d629076..fe46634 100644 --- a/bong/src/main.rs +++ b/bong/src/main.rs @@ -1,40 +1,9 @@ -use std::fs::File; - -use anyhow::{anyhow, Context, Error}; -use bingus::{ - img::{Dimensions, RgbImage}, - txt::{DocumentType, ShivaDocument, ShivaFormat}, - Bendable, Bytes, -}; use clap::Parser; use cli::Cli; -use unwrap_infallible::UnwrapInfallible; mod cli; -fn main() -> Result<(), Error> { - let args = Cli::parse(); - let bytes = File::open(args.input_file) - .context("opening file")? - .bend_into::( - ShivaFormat::new(DocumentType::PDF, DocumentType::DOCX), - Default::default(), - ) - .map_err(|e| anyhow!("parsing PDF: {e}"))? - .bend_into::((), Default::default()) - .unwrap_infallible(); - let dimensions = { - let c = bytes.len().isqrt().try_into().context("image too big")?; - Dimensions { - width: c, - height: c, - } - }; - bytes - .bend_into::(dimensions, Default::default()) - .context("bending into an image")? - .save(args.output_file) - .context("saving output file")?; - +fn main() -> anyhow::Result<()> { + Cli::parse(); Ok(()) }