use std::fmt;
use std::io::{Error as IOError, ErrorKind};
use std::env;
use std::path::PathBuf;
use std::process::Command;
const LIBREOFFICE_CMD: &str = "soffice";
const LIBREOFFICE_ENV: &str = "LIBREOFFICE_CMD";
pub enum LibreOfficeError {
NotFound(String),
ExecutionFailed(PathBuf, PathBuf, String),
CallFailed(IOError),
}
impl fmt::Display for LibreOfficeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
LibreOfficeError::NotFound(executable) => match executable == &LIBREOFFICE_CMD {
true => write!(
f,
"couldn't find \"{}\" on your system, use the env \"{}\" to define a non default executable name",
LIBREOFFICE_CMD,
LIBREOFFICE_ENV,
),
false => write!(
f,
"couldn't find libreoffice with the executable name \"{}\" use env \"{}\" to specify otherwise",
executable,
LIBREOFFICE_ENV,
),
},
LibreOfficeError::ExecutionFailed(input, output, err) => write!(
f,
"couldn't convert {} to {}, {}",
input.display(),
output.display(),
err,
),
LibreOfficeError::CallFailed(err) => write!(
f,
"couldn't call libreoffice {}",
err,
),
}
}
}
pub struct LibreOffice(String);
impl LibreOffice {
pub fn new() -> Self {
Self(match env::var(LIBREOFFICE_ENV) {
Ok(x) => x,
Err(_) => String::from(LIBREOFFICE_CMD),
})
}
pub fn convert_to_pdf(
&self,
input: &PathBuf,
) -> Result<(), LibreOfficeError> {
let mut cmd = Command::new(self.0.clone());
cmd.arg("--headless")
.arg("--convert-to")
.arg("pdf:writer_pdf_Export")
.arg("-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}")
.arg(input);
match cmd.output() {
Ok(x) => {
if x.status.success() {
Ok(())
} else {
Err(LibreOfficeError::ExecutionFailed(input.to_path_buf(), PathBuf::from("ho"), String::from_utf8(x.stderr).unwrap()))
}
}
Err(e) => {
if let ErrorKind::NotFound = e.kind() {
Err(LibreOfficeError::NotFound(self.0.clone()))
} else {
Err(LibreOfficeError::CallFailed(e))
}
}
}
}
}