text & doc support (+dynamic)
This commit is contained in:
parent
ae6e2edafa
commit
0c3439d788
6 changed files with 157 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
/target
|
/target
|
||||||
*.lock
|
*.lock
|
||||||
bmp/out.*
|
bmp/out.*
|
||||||
|
fonts
|
||||||
|
|
|
@ -34,6 +34,8 @@ printpdf = { version = "0.8.2", features = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"webp",
|
"webp",
|
||||||
] }
|
] }
|
||||||
|
shiva = "1.4.9"
|
||||||
|
anyhow = "1.0.97"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
project-root = "0"
|
project-root = "0"
|
||||||
|
|
|
@ -11,10 +11,12 @@ mod dynamic {
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
string::FromUtf8Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
snd::{self, Audio},
|
snd::{self, Audio},
|
||||||
|
txt::{ShivaDocument, Text},
|
||||||
Bendable, IntoDataBytes, TryFromDataBytes,
|
Bendable, IntoDataBytes, TryFromDataBytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,20 +27,34 @@ mod dynamic {
|
||||||
|
|
||||||
use infer::MatcherType;
|
use infer::MatcherType;
|
||||||
use printpdf::PdfDocument;
|
use printpdf::PdfDocument;
|
||||||
|
use shiva::core::{bytes, Document, DocumentType};
|
||||||
use strum::EnumDiscriminants;
|
use strum::EnumDiscriminants;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(EnumDiscriminants)]
|
#[derive(EnumDiscriminants)]
|
||||||
#[strum_discriminants(name(Format))]
|
#[strum_discriminants(name(Format))]
|
||||||
pub enum DynamicBendable {
|
pub enum DynamicBendable<'a> {
|
||||||
Image(DynamicImage),
|
Image(DynamicImage),
|
||||||
Binary(Bytes),
|
Binary(Bytes),
|
||||||
Sound(Audio),
|
Sound(Audio),
|
||||||
Text,
|
Text(Text<'a>),
|
||||||
|
Doc(ShivaDocument),
|
||||||
Archive(PdfDocument),
|
Archive(PdfDocument),
|
||||||
Meta,
|
Meta,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
#[error("extension is unknown by Shiva")]
|
||||||
|
pub struct ShivaUnknownExtensionError;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum ShivaError {
|
||||||
|
#[error("{0}")]
|
||||||
|
UnknownExtension(#[from] ShivaUnknownExtensionError),
|
||||||
|
#[error("{0}")]
|
||||||
|
Anyhow(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum OpenError {
|
pub enum OpenError {
|
||||||
#[error("io: {0}")]
|
#[error("io: {0}")]
|
||||||
|
@ -49,6 +65,10 @@ mod dynamic {
|
||||||
Audio(#[from] snd::AudioOpenError),
|
Audio(#[from] snd::AudioOpenError),
|
||||||
#[error("pdf: {0}")]
|
#[error("pdf: {0}")]
|
||||||
Pdf(String),
|
Pdf(String),
|
||||||
|
#[error("text: {0}")]
|
||||||
|
Text(#[from] FromUtf8Error),
|
||||||
|
#[error("document: {0}")]
|
||||||
|
Document(#[from] ShivaError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFromDataBytes for File {
|
impl TryFromDataBytes for File {
|
||||||
|
@ -91,7 +111,7 @@ mod dynamic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Option<DynamicBendable>, 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)?
|
||||||
.map(|t| (t.matcher_type(), t.extension()))
|
.map(|t| (t.matcher_type(), t.extension()))
|
||||||
|
@ -106,7 +126,7 @@ mod dynamic {
|
||||||
})),
|
})),
|
||||||
App => unreachable!(),
|
App => unreachable!(),
|
||||||
Audio => Some(DynamicBendable::Sound(crate::snd::Audio::open(path)?)),
|
Audio => Some(DynamicBendable::Sound(crate::snd::Audio::open(path)?)),
|
||||||
Archive => Some(DynamicBendable::Archive(
|
Archive if extension == "pdf" => Some(DynamicBendable::Archive(
|
||||||
PdfDocument::try_from_data_bytes(
|
PdfDocument::try_from_data_bytes(
|
||||||
File::open(path)?
|
File::open(path)?
|
||||||
.bytes()
|
.bytes()
|
||||||
|
@ -116,10 +136,31 @@ mod dynamic {
|
||||||
)
|
)
|
||||||
.map_err(OpenError::Pdf)?,
|
.map_err(OpenError::Pdf)?,
|
||||||
)),
|
)),
|
||||||
|
Archive => {
|
||||||
|
let document_type = DocumentType::from_extension(extension)
|
||||||
|
.ok_or(ShivaUnknownExtensionError)
|
||||||
|
.map_err(ShivaError::UnknownExtension)?;
|
||||||
|
Some(DynamicBendable::Doc(ShivaDocument::new(
|
||||||
|
Document::parse(
|
||||||
|
&bytes::Bytes::from(std::fs::read(path)?),
|
||||||
|
document_type,
|
||||||
|
)
|
||||||
|
.map_err(ShivaError::Anyhow)?,
|
||||||
|
document_type,
|
||||||
|
)))
|
||||||
|
}
|
||||||
Book => todo!(),
|
Book => todo!(),
|
||||||
Doc => todo!(),
|
Doc => todo!(),
|
||||||
Font => todo!(),
|
Font => todo!(),
|
||||||
Text => todo!(),
|
Text => Some(DynamicBendable::Text(
|
||||||
|
crate::txt::Text::try_from_data_bytes(
|
||||||
|
File::open(path)?
|
||||||
|
.bytes()
|
||||||
|
.collect::<Result<Bytes, io::Error>>()?,
|
||||||
|
(),
|
||||||
|
Default::default(),
|
||||||
|
)?,
|
||||||
|
)),
|
||||||
Video => todo!(),
|
Video => todo!(),
|
||||||
Custom => None,
|
Custom => None,
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
mod bare;
|
||||||
|
pub use bare::*;
|
||||||
|
mod shiva;
|
||||||
|
pub use shiva::*;
|
38
bingus/src/txt/bare.rs
Normal file
38
bingus/src/txt/bare.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use std::{borrow::Cow, string::FromUtf8Error};
|
||||||
|
|
||||||
|
use crate::{Bendable, Bytes, IntoDataBytes, TryFromDataBytes};
|
||||||
|
|
||||||
|
pub type Text<'a> = Cow<'a, str>;
|
||||||
|
|
||||||
|
impl TryFromDataBytes for Text<'_> {
|
||||||
|
type Error = FromUtf8Error;
|
||||||
|
type Format = ();
|
||||||
|
fn try_from_data_bytes(
|
||||||
|
bytes: Bytes,
|
||||||
|
_format: Self::Format,
|
||||||
|
_crop: crate::Crop,
|
||||||
|
) -> Result<Self, Self::Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
String::from_utf8(bytes).map(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoDataBytes for Text<'_> {
|
||||||
|
fn into_data_bytes(self) -> Bytes {
|
||||||
|
self.as_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bendable for Text<'_> {
|
||||||
|
type Unit = char;
|
||||||
|
|
||||||
|
fn map<F: Fn(&Self::Unit) -> Self::Unit + Sync>(self, f: F) -> Self {
|
||||||
|
self.chars().map(|c| f(&c)).collect::<String>().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format() -> crate::Format {
|
||||||
|
crate::Format::Text
|
||||||
|
}
|
||||||
|
}
|
66
bingus/src/txt/shiva.rs
Normal file
66
bingus/src/txt/shiva.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use derive_new::new;
|
||||||
|
pub use shiva::core::DocumentType;
|
||||||
|
use shiva::core::{bytes::Bytes, Document, Element};
|
||||||
|
|
||||||
|
use crate::{Bendable, IntoDataBytes, TryFromDataBytes};
|
||||||
|
|
||||||
|
#[derive(new)]
|
||||||
|
pub struct ShivaDocument {
|
||||||
|
document: Document,
|
||||||
|
output_format: DocumentType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(new)]
|
||||||
|
pub struct ShivaFormat {
|
||||||
|
input_format: DocumentType,
|
||||||
|
output_format: DocumentType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFromDataBytes for ShivaDocument {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
type Format = ShivaFormat;
|
||||||
|
|
||||||
|
fn try_from_data_bytes(
|
||||||
|
bytes: crate::Bytes,
|
||||||
|
format: Self::Format,
|
||||||
|
_crop: crate::Crop,
|
||||||
|
) -> Result<Self, Self::Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Ok(ShivaDocument::new(
|
||||||
|
Document::parse(&Bytes::from(bytes), format.input_format)?,
|
||||||
|
format.output_format,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoDataBytes for ShivaDocument {
|
||||||
|
fn into_data_bytes(self) -> crate::Bytes {
|
||||||
|
self.document
|
||||||
|
.generate(self.output_format)
|
||||||
|
.expect("can't crash here! so close!")
|
||||||
|
.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bendable for ShivaDocument {
|
||||||
|
type Unit = Element;
|
||||||
|
|
||||||
|
fn map<F: Fn(&Self::Unit) -> Self::Unit + Sync>(self, f: F) -> Self {
|
||||||
|
ShivaDocument::new(
|
||||||
|
Document::new(
|
||||||
|
self.document
|
||||||
|
.get_all_elements()
|
||||||
|
.into_iter()
|
||||||
|
.map(f)
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
self.output_format,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format() -> crate::Format {
|
||||||
|
crate::Format::Text
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue