Skip to content
This repository has been archived by the owner on Jul 5, 2022. It is now read-only.

Commit

Permalink
Add XFDF file format support
Browse files Browse the repository at this point in the history
Also changed PDF file format to use XFDF as intermediate format to
better support UTF-8
  • Loading branch information
esensar committed Apr 13, 2022
1 parent b424d8a commit 194932d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
2 changes: 1 addition & 1 deletion examples/user_info.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Ensar Sarajcic",
"name": "Ensar Sarajčić",
"jmbg": "12345678901234",
"address": "EnsarSarajcic Com"
}
29 changes: 25 additions & 4 deletions src/commands/ams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::{
pub enum OutputFormat {
Pdf,
Fdf,
Xfdf,
Json,
}

Expand All @@ -26,6 +27,7 @@ impl std::fmt::Display for OutputFormat {
f.write_str(match &self {
OutputFormat::Pdf => "pdf",
OutputFormat::Fdf => "fdf",
OutputFormat::Xfdf => "xfdf",
OutputFormat::Json => "json",
})
}
Expand All @@ -36,6 +38,7 @@ impl std::fmt::Debug for OutputFormat {
f.write_str(match &self {
OutputFormat::Pdf => "pdf",
OutputFormat::Fdf => "fdf",
OutputFormat::Xfdf => "xfdf",
OutputFormat::Json => "json",
})
}
Expand All @@ -48,6 +51,7 @@ impl std::str::FromStr for OutputFormat {
match s {
"pdf" => Ok(OutputFormat::Pdf),
"fdf" => Ok(OutputFormat::Fdf),
"xfdf" => Ok(OutputFormat::Xfdf),
"json" => Ok(OutputFormat::Json),
_ => Err("Unknown format passed!".to_string()),
}
Expand All @@ -56,9 +60,10 @@ impl std::str::FromStr for OutputFormat {

struct PdfPrinter<'a> {
config: &'a Config,
fdf_printer: &'a FdfPrinter,
xfdf_printer: &'a XfdfPrinter,
}
struct FdfPrinter {}
struct XfdfPrinter {}
struct JsonPrinter {}

trait AmsPrinter {
Expand All @@ -68,9 +73,9 @@ trait AmsPrinter {
impl<'a> AmsPrinter for PdfPrinter<'a> {
fn write_to_file(&self, form: &mut amsform::AmsForm, file: &str) {
let mut tmp_fdf_file = temp_dir();
tmp_fdf_file.push("fbihtax.fdf");
tmp_fdf_file.push("fbihtax.xfdf");
let tmp_fdf_file_str = tmp_fdf_file.to_str().expect("Can't create temporary file");
self.fdf_printer.write_to_file(form, tmp_fdf_file_str);
self.xfdf_printer.write_to_file(form, tmp_fdf_file_str);
let _process = std::process::Command::new(&self.config.pdf.pdftk_path)
.args(&[
self.config.pdf.cache_location.clone(),
Expand All @@ -93,6 +98,14 @@ impl AmsPrinter for FdfPrinter {
}
}

impl AmsPrinter for XfdfPrinter {
fn write_to_file(&self, form: &mut amsform::AmsForm, file: &str) {
let dict = form.to_dict();
let fdf_data = FdfData::from_dict(dict);
fdf_generator::write_xfdf(fdf_data, file.to_string());
}
}

impl AmsPrinter for JsonPrinter {
fn write_to_file(&self, form: &mut amsform::AmsForm, file: &str) {
let breakdown_writer = File::create(file).expect("Failed creating output JSON");
Expand Down Expand Up @@ -137,15 +150,17 @@ pub fn handle_command(config: Config, args: &AmsArgs) {
let mut form = amsform::load_ams_form(config.pdf.cache_location.clone());

let fdf_printer = FdfPrinter {};
let xfdf_printer = XfdfPrinter {};
let json_printer = JsonPrinter {};
let pdf_printer = PdfPrinter {
config: &config,
fdf_printer: &fdf_printer,
xfdf_printer: &xfdf_printer,
};

let printer: &dyn AmsPrinter = match args.output_format {
OutputFormat::Pdf => &pdf_printer,
OutputFormat::Fdf => &fdf_printer,
OutputFormat::Xfdf => &xfdf_printer,
OutputFormat::Json => &json_printer,
};

Expand Down Expand Up @@ -213,6 +228,7 @@ mod tests {
assert_eq!(OutputFormat::Pdf, OutputFormat::from_str("pdf").unwrap());
assert_eq!(OutputFormat::Json, OutputFormat::from_str("json").unwrap());
assert_eq!(OutputFormat::Fdf, OutputFormat::from_str("fdf").unwrap());
assert_eq!(OutputFormat::Xfdf, OutputFormat::from_str("xfdf").unwrap());
}

#[test]
Expand All @@ -226,6 +242,7 @@ mod tests {
assert!(OutputFormat::from_str("PDF").is_err());
assert!(OutputFormat::from_str("JSON").is_err());
assert!(OutputFormat::from_str("FDF").is_err());
assert!(OutputFormat::from_str("XFDF").is_err());
}

#[test]
Expand All @@ -236,5 +253,9 @@ mod tests {
format!("format is {}", OutputFormat::Json)
);
assert_eq!("format is fdf", format!("format is {}", OutputFormat::Fdf));
assert_eq!(
"format is xfdf",
format!("format is {}", OutputFormat::Xfdf)
);
}
}
27 changes: 27 additions & 0 deletions src/fdf/fdf_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ static FOOTER: &str = concat!(
"<</Root 1 0 R>>\n",
"%%EOF"
);
static XFDF_HEADER: &str = concat!(
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n",
"<xfdf xmlns=\"http://ns.adobe.com/xfdf/\" xml:space=\"preserve\">\n",
" <fields>\n"
);
static XFDF_FOOTER: &str = concat!(" </fields>\n", "</xfdf>");

pub struct FdfData {
entries: Vec<FdfDataEntry>,
Expand Down Expand Up @@ -37,6 +43,27 @@ impl FdfData {
}
}

pub fn write_xfdf(data: FdfData, output_file: String) {
let mut fdf_file = File::create(output_file).expect("Failed creating xfdf file!");
fdf_file
.write_all(XFDF_HEADER.as_bytes())
.expect("Writing xfdf file failed!");
for entry in data.entries {
fdf_file
.write_all(
format!(
" <field name=\"{}\"><value>{}</value></field>\n",
entry.title, entry.value
)
.as_bytes(),
)
.expect("Writing xfdf file failed!");
}
fdf_file
.write_all(XFDF_FOOTER.as_bytes())
.expect("Writing xfdf file failed!");
}

pub fn write_fdf(data: FdfData, output_file: String) {
let mut fdf_file = File::create(output_file).expect("Failed creating fdf file!");
fdf_file
Expand Down

0 comments on commit 194932d

Please sign in to comment.