bong CLI template

This commit is contained in:
brevalferrari 2025-06-14 20:56:57 +02:00
parent 52c15986a8
commit 6bb627d77b
7 changed files with 136 additions and 45 deletions

View file

@ -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")]

View file

@ -1,4 +1,4 @@
pub use symphonia::core::sample::Sample;
pub use symphonia::core::*;
mod raw;
pub use raw::*;
mod simphonia;

View file

@ -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::{

View file

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

View file

@ -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"

View file

@ -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<MatcherType>,
/// Input file or standard input ("-").
pub(super) input: FileOrStd<Stdin>,
// /// List of commands (process or bend to another format)
// pub(super) commands: Vec<Command>,
/// Onput file or standard output ("-").
pub(super) output: FileOrStd<Stdout>,
}
#[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<Self, Self::Err> {
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<S: Clone + Default> FromStr for FileOrStd<S> {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<S: Clone> {
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<MatcherType> 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,
}
}
}

View file

@ -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::<ShivaDocument>(
ShivaFormat::new(DocumentType::PDF, DocumentType::DOCX),
Default::default(),
)
.map_err(|e| anyhow!("parsing PDF: {e}"))?
.bend_into::<Bytes>((), 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::<RgbImage>(dimensions, Default::default())
.context("bending into an image")?
.save(args.output_file)
.context("saving output file")?;
fn main() -> anyhow::Result<()> {
Cli::parse();
Ok(())
}