use std::{ops::Deref, string::FromUtf8Error};
#[derive(Debug)]
pub enum IError {
Io(std::io::Error),
InvalidArchive(&'static str),
UnsupportedArchive(&'static str),
FileNotFound,
InvalidPassword,
Utf8(std::string::FromUtf8Error),
Xml(quick_xml::Error),
Unknown,
}
impl std::fmt::Display for IError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub type IResult<T> = Result<T, IError>;
impl From<std::io::Error> for IError {
fn from(value: std::io::Error) -> Self {
IError::Io(value)
}
}
impl From<quick_xml::Error> for IError {
fn from(value: quick_xml::Error) -> Self {
match value {
quick_xml::Error::Io(e) => IError::Io(std::io::Error::other(e)),
_ => IError::Xml(value),
}
}
}
impl From<FromUtf8Error> for IError{
fn from(value: FromUtf8Error) -> Self {
IError::Utf8(value)
}
}
#[derive(Debug, Default)]
pub(crate) struct BookInfo {
pub(crate) title: String,
pub(crate) identifier: String,
pub(crate) creator: Option<String>,
pub(crate) description: Option<String>,
pub(crate) contributor: Option<String>,
pub(crate) date: Option<String>,
pub(crate) format: Option<String>,
pub(crate) publisher: Option<String>,
pub(crate) subject: Option<String>,
}
impl BookInfo {
pub(crate) fn append_creator(&mut self, v: &str) {
if let Some(c) = &mut self.creator {
c.push_str(",");
c.push_str(v);
} else {
self.creator = Some(String::from(v));
}
}
}
pub(crate) fn unescape_html(v:&str)->String{
let mut reader = quick_xml::reader::Reader::from_str(v);
reader.config_mut().trim_text(true);
let mut buf = Vec::new();
let mut txt = String::new();
loop {
match reader.read_event_into(&mut buf) {
Ok(quick_xml::events::Event::Text(e) )=> {
if let Ok(t) = e.unescape(){
txt.push_str(&t.deref());
}
},
Ok(quick_xml::events::Event::Eof) => {
break;
}
_ => (),
}
buf.clear();
}
txt
}
pub(crate) fn time_display(value:u64)->String{
do_time_display(value, 1970)
}
pub(crate) fn do_time_display(value: u64,start_year:u64) -> String {
let per_year_sec = 365 * 24 * 60 * 60;
let mut year = value / per_year_sec;
let last_sec = value - (year) * per_year_sec;
year += start_year;
let mut leap_year_sec = 0;
for y in start_year..year {
if is_leap(y) {
leap_year_sec += 86400;
}
}
if last_sec < leap_year_sec {
year -= 1;
if is_leap(year) {
leap_year_sec -= 86400;
}
}
let mut time = value - leap_year_sec - (year - start_year) * per_year_sec;
let mut day_of_year: [u64; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let sec = time % 60;
time /= 60;
let min = time % 60;
time /= 60;
let hour = time % 24;
time /= 24;
if is_leap(year) {
day_of_year[1] += 1;
}
let mut month = 0;
for (index, ele) in day_of_year.iter().enumerate() {
if &time < ele {
month = index + 1;
time += 1; break;
}
time -= ele;
}
return format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
year, month, time, hour, min, sec
);
}
fn is_leap(year: u64) -> bool {
return year % 4 == 0 && ((year % 100) != 0 || year % 400 == 0);
}
pub(crate) fn time_format() -> String {
let time = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|v| v.as_secs())
.unwrap_or(0);
time_display(time)
}