Skip to content

Commit

Permalink
Optimistic the speed of files open.
Browse files Browse the repository at this point in the history
  • Loading branch information
pt committed Apr 16, 2024
1 parent f03e279 commit 85c1eb2
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 199 deletions.
46 changes: 17 additions & 29 deletions src/api/workbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{Properties, xml};
use crate::xml::content_types::ContentTypes;
use crate::xml::core_properties::CoreProperties;
use crate::xml::app_properties::AppProperties;
use crate::xml::io::Io;
use crate::xml::io::{Io, IoV2};
use crate::xml::medias::Medias;
use crate::xml::metadata::Metadata;
use crate::xml::style::StyleSheet;
Expand Down Expand Up @@ -190,54 +190,43 @@ impl Workbook {
}

impl Workbook {
async fn from_path_async<P: AsRef<Path>>(file_path: P) -> WorkbookResult<Workbook> {
fn from_path_v2<P: AsRef<Path>>(file_path: P) -> WorkbookResult<Workbook> {
let file_name = file_path.as_ref().file_name().ok_or(ZipError::FileNotFound)?;
let tmp_path = format!("./~${}_{:X}", file_name.to_str().ok_or(ZipError::FileNotFound)?, id_util::new_id());
let file = File::open(&file_path)?;
let mut archive = zip::ZipArchive::new(file)?;
let (mut workbook_xml, mut workbook_rel
, mut content_types, mut style_sheet
, mut metadata, mut shared_string) =
(None, None, None, None, None, None);
let mut medias = Medias::default();
let mut workbook_xml = xml::workbook::Workbook::from_zip_file(&mut archive, "xl/workbook.xml");
let mut workbook_rel = Relationships::from_zip_file(&mut archive, "xl/_rels/workbook.xml.rels");
let mut content_types = ContentTypes::from_zip_file(&mut archive, "[Content_Types].xml");
let mut style_sheet = StyleSheet::from_zip_file(&mut archive, "xl/styles.xml");
let mut metadata = Metadata::from_zip_file(&mut archive, "xl/metadata.xml");
let mut shared_string = SharedString::from_zip_file(&mut archive, "xl/sharedStrings.xml");
for i in 0..archive.len() {
let mut file = archive.by_index(i)?;
let file_name = file.name();
match file_name {
"xl/workbook.xml" => workbook_xml = Some(xml::workbook::Workbook::from_zip_file(&mut file)),
"xl/_rels/workbook.xml.rels" => workbook_rel = Some(Relationships::from_zip_file(&mut file)),
"[Content_Types].xml" => content_types = Some(ContentTypes::from_zip_file(&mut file)),
"xl/styles.xml" => style_sheet = Some(StyleSheet::from_zip_file(&mut file)),
"xl/metadata.xml" => metadata = Some(Metadata::from_zip_file(&mut file)),
"xl/sharedStrings.xml" => shared_string = Some(SharedString::from_zip_file(&mut file)),
_ => {
if file_name.starts_with("xl/media/") {
medias.add_existed_media(&file_name);
}
},
if file_name.starts_with("xl/media/") {
medias.add_existed_media(&file_name);
}
}

let workbook = Rc::new(RefCell::new(workbook_xml.unwrap_or_default()));
let workbook_rel = Rc::new(RefCell::new(workbook_rel.unwrap_or_default()));
let content_types = Rc::new(RefCell::new(content_types.unwrap_or_default()));
let style_sheet = Rc::new(RefCell::new(style_sheet.unwrap_or_default()));
let metadata = Rc::new(RefCell::new(metadata.unwrap_or_default()));
let shared_string = Rc::new(shared_string.unwrap_or_default());
let medias = Rc::new(RefCell::new(
medias
));

let medias = Rc::new(RefCell::new(medias));
let sheets = workbook.borrow().sheets.sheets.iter().map(
|sheet_xml| {
let binding = workbook_rel.borrow();
let (target, target_id) = binding.get_target(&sheet_xml.r_id);
WorkSheet::from_xml(
WorkSheet::from_archive(
sheet_xml.sheet_id,
&sheet_xml.name,
target,
target_id,
&file_path,
&mut archive,
Rc::clone(&workbook),
Rc::clone(&workbook_rel),
Rc::clone(&style_sheet),
Expand All @@ -247,8 +236,7 @@ impl Workbook {
Rc::clone(&shared_string),
)
}).collect::<Vec<WorkSheet>>();

let workbook = Workbook {
let api_workbook = Workbook {
sheets,
tmp_path,
file_path: file_path.as_ref().to_str().unwrap().to_string(),
Expand All @@ -263,12 +251,12 @@ impl Workbook {
app_properties: None,
shared_string,
};
Ok(workbook)
Ok(api_workbook)
}

pub fn from_path<P: AsRef<Path>>(file_path: P) -> WorkbookResult<Workbook> {
let workbook = Self::from_path_async(file_path);
let workbook = block_on(workbook);
let workbook = Self::from_path_v2(file_path);
// let workbook = block_on(workbook);
workbook
}

Expand Down
41 changes: 12 additions & 29 deletions src/api/worksheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::rc::Rc;
use zip::read::ZipFile;
use zip::ZipArchive;
use crate::{Filters, FormatColor, xml};
use crate::api::cell::location::{Location, LocationRange};
use crate::api::worksheet::col::WorkSheetCol;
Expand All @@ -24,6 +26,7 @@ use crate::file::XlsxFileType;
use crate::result::{WorkSheetError, WorkSheetResult};
use crate::xml::drawings::Drawings;
use crate::xml::drawings::vml_drawing::VmlDrawing;
use crate::xml::io::IoV2;
use crate::xml::metadata::Metadata;
use crate::xml::relationships::Relationships;
use crate::xml::shared_string::SharedString;
Expand Down Expand Up @@ -306,12 +309,13 @@ impl WorkSheet {
}
}

pub(crate) fn from_xml<P: AsRef<Path>>(
pub(crate) fn from_archive<P: AsRef<Path>>(
sheet_id: u32,
name: &str,
target: &str,
target_id: u32,
file_path: P,
archive: &mut ZipArchive<File>,
workbook: Rc<RefCell<Workbook>>,
workbook_rel: Rc<RefCell<Relationships>>,
style_sheet: Rc<RefCell<StyleSheet>>,
Expand All @@ -320,37 +324,16 @@ impl WorkSheet {
metadata: Rc<RefCell<Metadata>>,
shared_string: Rc<SharedString>,
) -> WorkSheet {
let file = File::open(&file_path).unwrap();
let mut archive = zip::ZipArchive::new(file).unwrap();
// Read worksheet from zip dir
let mut worksheet = XmlWorkSheet::default();
let mut worksheet_rel = Relationships::default();
{
let worksheet_file = archive.by_name(&format!("xl/{target}"));
if let Ok(mut worksheet_file) = worksheet_file {
worksheet = XmlWorkSheet::from_zip_file(&mut worksheet_file);
// Prevent incorrect results from being filled into cells
worksheet.sheet_data.clean_formula_value();
};
}
{
let worksheet_rel_id: String = target.chars().filter(|&c| c >= '0' && c <= '9').collect();
if let Ok(mut worksheet_rel_file) = archive.by_name(&format!("xl/worksheets/_rels/sheet{worksheet_rel_id}.xml.rels")) {
worksheet_rel = Relationships::from_zip_file(&mut worksheet_rel_file);
}
}
let mut worksheet = XmlWorkSheet::from_zip_file(archive, &format!("xl/{target}")).unwrap_or_default();
worksheet.sheet_data.clean_formula_value();
let worksheet_rel_id: String = target.chars().filter(|&c| c >= '0' && c <= '9').collect();
let worksheet_rel = Relationships::from_zip_file(archive, &format!("xl/worksheets/_rels/sheet{worksheet_rel_id}.xml.rels")).unwrap_or_default();
// load drawings
let drawings_id = worksheet_rel.get_drawings_rid();
let (mut drawings, mut drawings_rel) = (None, None);
if let Some(drawings_id) = drawings_id {
{
let mut drawings_file = archive.by_name(&format!("xl/drawings/drawing{drawings_id}.xml")).unwrap();
drawings = Some(Drawings::from_zip_file(&mut drawings_file));
}
{
let mut drawings_rel_file = archive.by_name(&format!("xl/drawings/_rels/drawing{drawings_id}.xml.rels")).unwrap();
drawings_rel = Some(Relationships::from_zip_file(&mut drawings_rel_file));
}
if let Some(drawings_id) = worksheet_rel.get_drawings_rid() {
drawings = Drawings::from_zip_file(archive, &format!("xl/drawings/drawing{drawings_id}.xml"));
drawings_rel = Relationships::from_zip_file(archive, &format!("xl/drawings/_rels/drawing{drawings_id}.xml.rels"));
};
let vml_drawing = match worksheet_rel.get_vml_drawing_rid() {
Some(vml_drawing_id) => VmlDrawing::from_path(&file_path, vml_drawing_id).ok(),
Expand Down
10 changes: 0 additions & 10 deletions src/utils/zip_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use zip::result::ZipError;
use zip::write::FileOptions;

pub(crate) fn extract_dir<P: AsRef<Path>>(file_path: P, target: &str) -> zip::result::ZipResult<String> {
// parse the file name
let file_name = file_path.as_ref().file_name().ok_or(ZipError::FileNotFound)?;
// read file from file path
let file = File::open(&file_path)?;
let mut archive = zip::ZipArchive::new(file)?;
Expand All @@ -33,15 +31,8 @@ pub(crate) fn extract_dir<P: AsRef<Path>>(file_path: P, target: &str) -> zip::re
}
}
if (*file.name()).ends_with('/') {
// println!("File {} extracted to \"{}\"", i, out_path.display());
fs::create_dir_all(&out_path)?;
} else {
// println!(
// "File {} extracted to \"{}\" ({} bytes)",
// i,
// out_path.display(),
// file.size()
// );
if let Some(p) = out_path.parent() {
if !p.exists() {
fs::create_dir_all(p)?;
Expand All @@ -60,7 +51,6 @@ pub(crate) fn extract_dir<P: AsRef<Path>>(file_path: P, target: &str) -> zip::re
}
}
}

let tmp_dir = base_path.to_str().ok_or(ZipError::FileNotFound)?.to_string();
Ok(tmp_dir)
}
Expand Down
15 changes: 1 addition & 14 deletions src/xml/content_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::path::Path;
use quick_xml::{de, se};
use serde::{Deserialize, Serialize};
use zip::read::ZipFile;
use zip::ZipArchive;
use crate::file::{XlsxFileReader, XlsxFileType, XlsxFileWriter};
use crate::xml::io::Io;
use crate::xml::relationships::Relationships;
Expand Down Expand Up @@ -114,20 +115,6 @@ impl ContentTypes {
}

impl Io<ContentTypes> for ContentTypes {
fn from_zip_file(mut file: &mut ZipFile) -> Self {
let mut xml = String::new();
file.read_to_string(&mut xml).unwrap();
de::from_str(&xml).unwrap_or_default()
}

fn from_path<P: AsRef<Path>>(file_path: P) -> io::Result<ContentTypes> {
let mut file = XlsxFileReader::from_path(file_path, XlsxFileType::ContentTypes)?;
let mut xml = String::new();
file.read_to_string(&mut xml).unwrap();
let types: ContentTypes = de::from_str(&xml).unwrap();
Ok(types)
}

fn save<P: AsRef<Path>>(& self, file_path: P) {
let xml = se::to_string_with_root("Types", &self).unwrap();
let xml = format!("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n{}", xml);
Expand Down
8 changes: 0 additions & 8 deletions src/xml/drawings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,6 @@ struct AvLst {}
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
struct ClientData {}

impl Drawings {
pub(crate) fn from_zip_file(mut file: &mut ZipFile) -> Self {
let mut xml = String::new();
file.read_to_string(&mut xml).unwrap();
de::from_str(&xml).unwrap_or_default()
}
}

impl Drawings {
pub(crate) fn from_path<P: AsRef<Path>>(file_path: P, drawing_id: u32) -> io::Result<Drawings> {
let mut file = XlsxFileReader::from_path(file_path, XlsxFileType::Drawings(drawing_id))?;
Expand Down
39 changes: 32 additions & 7 deletions src/xml/io.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
use std::fs::File;
use std::io;
use std::io::Read;
use std::path::Path;
use quick_xml::de;
use zip::read::ZipFile;
use serde::Deserialize;
use zip::ZipArchive;
use crate::xml::content_types::ContentTypes;
use crate::xml::drawings::Drawings;
use crate::xml::metadata::Metadata;
use crate::xml::relationships::Relationships;
use crate::xml::shared_string::SharedString;
use crate::xml::style::StyleSheet;
use crate::xml::workbook::Workbook;
use crate::xml::worksheet::WorkSheet;

pub(crate) trait Io<T: Default> {
fn from_path<P: AsRef<Path>>(file_path: P) -> io::Result<T>;
fn save<P: AsRef<Path>>(&self, file_path: P);
async fn from_path_async<P: AsRef<Path>>(file_path: P) -> io::Result<T> {
Self::from_path(file_path)
}
async fn save_async<P: AsRef<Path>>(&self, file_path: P) {
self.save(file_path)
}
}

pub(crate) trait IoV2<T: for<'de> Deserialize<'de>> {
fn from_zip_file(archive: &mut ZipArchive<File>, path: &str) -> Option<T> {
if let Ok(mut file) = archive.by_name(path) {
let mut xml = String::new();
file.read_to_string(&mut xml).unwrap();
de::from_str(&xml).ok()
} else {
None
}
}
}

fn from_zip_file(file: &mut ZipFile) -> T;
}
impl IoV2<Workbook> for Workbook {}
impl IoV2<WorkSheet> for WorkSheet{}
impl IoV2<StyleSheet> for StyleSheet {}
impl IoV2<ContentTypes> for ContentTypes{}
impl IoV2<Relationships> for Relationships{}
impl IoV2<Metadata> for Metadata{}
impl IoV2<SharedString> for SharedString{}
impl IoV2<Drawings> for Drawings{}
50 changes: 19 additions & 31 deletions src/xml/medias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,29 @@ impl Medias {
}

impl Io<Medias> for Medias {
fn from_path<P: AsRef<Path>>(file_path: P) -> io::Result<Medias> {
let mut medias = Medias { medias: vec![] };
let mut id = 1;
Ok(loop {
let extension = &file_path.as_ref().extension().unwrap_or("png".as_ref()).to_string_lossy();
let file_name = format!("image{}.{}", id, extension);
let file = XlsxFileReader::from_path(&file_path, XlsxFileType::Medias(file_name));
match file {
Ok(file) => {
let media = Media::new(id, file.file_path);
medias.medias.push(media);
id += 1;
},
Err(_) => {
break medias;
},
}
})
}
// fn from_path<P: AsRef<Path>>(file_path: P) -> io::Result<Medias> {
// let mut medias = Medias { medias: vec![] };
// let mut id = 1;
// Ok(loop {
// let extension = &file_path.as_ref().extension().unwrap_or("png".as_ref()).to_string_lossy();
// let file_name = format!("image{}.{}", id, extension);
// let file = XlsxFileReader::from_path(&file_path, XlsxFileType::Medias(file_name));
// match file {
// Ok(file) => {
// let media = Media::new(id, file.file_path);
// medias.medias.push(media);
// id += 1;
// },
// Err(_) => {
// break medias;
// },
// }
// })
// }

fn save<P: AsRef<Path>>(& self, file_path: P) {
self.medias.iter().for_each(|m| { m.save(&file_path) });
}

fn from_zip_file(file: &mut ZipFile) -> Medias {
todo!()
}
}

#[derive(Debug, Default)]
Expand All @@ -88,19 +84,11 @@ impl Media {
}

impl Io<Media> for Media {
fn from_path<P: AsRef<Path>>(_file_path: P) -> io::Result<Media> {
todo!()
}

fn save<P: AsRef<Path>>(&self, file_path: P) {
if let Some(path) = &self.file_path {
let extension = path.extension().unwrap_or("png".as_ref()).to_string_lossy();
let file_name = format!("image{}.{}", self.id, extension);
XlsxFileWriter::copy_from(&file_path, XlsxFileType::Medias(file_name), &path).unwrap();
}
}

fn from_zip_file(file: &mut ZipFile) -> Media {
todo!()
}
}
Loading

0 comments on commit 85c1eb2

Please sign in to comment.