use crate::errors::*;
use crate::units::inches;
use std::env;
use std::path::Path;
pub type Files = Vec<(String, String)>;
pub type Margins = (Option<f64>, Option<f64>, Option<f64>, Option<f64>);
pub type PaperSize = (Option<f64>, Option<f64>);
pub type WindowSize = Option<(u32, u32)>;
pub type Scale = Option<f64>;
pub type Timeout = Option<u64>;
pub const PDF_EXTENSION: &str = "pdf";
pub const JPEG_EXTENSION: &str = "jpg";
pub const PNG_EXTENSION: &str = "png";
pub const WEBP_EXTENSION: &str = "webp";
pub const HTML_EXTENSION: &str = "html";
pub const MIN_PAPER_LENGTH: f64 = 0.19;
pub const MAX_PAPER_LENGTH: f64 = 100.0;
#[derive(Copy, Clone)]
pub enum ScreenshotFormat {
Jpeg,
Png,
Webp,
}
impl ScreenshotFormat {
pub fn extension(&self) -> &'static str {
match self {
ScreenshotFormat::Jpeg => JPEG_EXTENSION,
ScreenshotFormat::Png => PNG_EXTENSION,
ScreenshotFormat::Webp => WEBP_EXTENSION,
}
}
}
pub fn margin(opt_margin: Option<String>) -> Result<Margins> {
if let Some(margin) = opt_margin {
let parts = margin.split(' ').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect::<Vec<String>>();
let lengths = inches(parts)?;
match lengths.len() {
1 => Ok((Some(lengths[0]), Some(lengths[0]), Some(lengths[0]), Some(lengths[0]))),
2 => Ok((Some(lengths[0]), Some(lengths[1]), Some(lengths[0]), Some(lengths[1]))),
4 => Ok((Some(lengths[0]), Some(lengths[1]), Some(lengths[2]), Some(lengths[3]))),
_ => Err(err_invalid_margin(&margin)),
}
} else {
Ok((None, None, None, None))
}
}
pub fn scale(opt_scale: Option<String>) -> Result<Scale> {
if let Some(scale) = opt_scale {
if let Some(prefix) = scale.strip_suffix('%') {
Ok(Some(str_to_f64(prefix)? / 100.0))
} else {
Ok(Some(str_to_f64(&scale)?))
}
} else {
Ok(None)
}
}
pub fn window_size(opt_window_size: Option<String>) -> Result<WindowSize> {
if let Some(window_size) = opt_window_size {
let parts = window_size.split(',').map(|s| s.trim().to_string()).collect::<Vec<String>>();
if parts.len() == 2 {
let width = parts[0].parse::<u32>().map_err(|_| err_invalid_width(&parts[0]))?;
let height = parts[1].parse::<u32>().map_err(|_| err_invalid_height(&parts[1]))?;
Ok(Some((width, height)))
} else {
Err(err_invalid_window_size(&window_size))
}
} else {
Ok(None)
}
}
pub fn file_url(file_path: &Path) -> Result<String> {
Ok(format!(
"file://{}",
file_path.canonicalize().map_err(|e| err_canonicalize(file_path, e.to_string()))?.to_string_lossy()
))
}
pub fn file_url_unchecked(file_path: &Path) -> String {
format!("file://{}", file_path.canonicalize().unwrap().to_string_lossy())
}
pub fn replace_file_extension(path: &Path, screenshot_format: Option<ScreenshotFormat>) -> String {
let file_extension = if let Some(screenshot_format) = screenshot_format {
screenshot_format.extension()
} else {
PDF_EXTENSION
};
path.with_extension(file_extension).to_string_lossy().to_string()
}
pub fn file_name(path: &Path, screenshot_format: Option<ScreenshotFormat>) -> String {
let file_extension = if let Some(screenshot_format) = screenshot_format {
screenshot_format.extension()
} else {
PDF_EXTENSION
};
path.with_extension(file_extension).file_name().unwrap().to_string_lossy().to_string()
}
pub fn has_html_extension(path: &Path) -> bool {
if let Some(extension) = path.extension() {
extension == HTML_EXTENSION
} else {
false
}
}
pub fn init_logger(opt_log_level: Option<String>) {
match env::var("RUST_LOG").unwrap_or("off".to_string()).as_str() {
"error" | "warn" | "info" | "debug" | "trace" => {}
_ => unsafe { env::set_var("RUST_LOG", "off") },
}
if let Some(log_level) = opt_log_level {
unsafe {
env::set_var("RUST_LOG", log_level);
}
}
env_logger::init();
}
pub fn str_to_f64(s: &str) -> Result<f64> {
s.parse::<f64>().map_err(|_| err_invalid_number(s))
}