umya-spreadsheet 3.0.0

umya-spreadsheet is a library written in pure Rust to read and write xlsx file.
Documentation
use std::io;

use quick_xml::{
    Reader,
    escape,
    events::Event,
};

use super::{
    XlsxError,
    driver::get_attribute,
};
use crate::{
    helper::const_str::PKG_WORKBOOK,
    structs::{
        DefinedName,
        Workbook,
        WorkbookProtection,
        WorkbookView,
        Worksheet,
    },
    xml_read_loop,
};

pub(crate) fn read<R: io::Read + io::Seek>(
    arv: &mut zip::read::ZipArchive<R>,
) -> Result<Workbook, XlsxError> {
    let r = io::BufReader::new(super::driver::zip_by_name(arv, PKG_WORKBOOK)?);
    let mut reader = Reader::from_reader(r);
    reader.config_mut().trim_text(true);
    let mut wb = Workbook::default();

    let mut defined_names: Vec<DefinedName> = Vec::new();

    xml_read_loop!(
        reader,
        Event::Empty(ref e) => {
            match e.name().into_inner() {
                b"workbookView" => {
                    let mut obj = WorkbookView::default();
                    obj.set_attributes(&mut reader, e);
                    wb.set_workbook_view(obj);
                }
                b"workbookProtection" => {
                    let mut obj = WorkbookProtection::default();
                    obj.set_attributes(&mut reader, e);
                    wb.set_workbook_protection(obj);
                }
                b"sheet" => {
                    let name_value = get_attribute(e, b"name").unwrap();
                    let sheet_id_value = get_attribute(e, b"sheetId").unwrap();
                    let r_id_value = get_attribute(e, b"r:id").unwrap();
                    let state = get_attribute(e, b"state");
                    let mut worksheet = Worksheet::default();
                    worksheet.set_name(escape::unescape(&name_value).unwrap());
                    worksheet.set_sheet_id(sheet_id_value);
                    worksheet.set_r_id(r_id_value);
                    if let Some(v) = state {
                        worksheet.set_state_str(&v);
                    }
                    wb.add_sheet(worksheet).unwrap();
                }
                b"pivotCache" => {
                    let cache_id = get_attribute(e, b"cacheId").unwrap();
                    let r_id = get_attribute(e, b"r:id").unwrap();
                    wb.add_pivot_caches((r_id, cache_id, String::new()));
                }
                _ => (),
            }
        },
        Event::Start(ref e) => {
            if e.name().into_inner() == b"definedName" {
                let mut obj = DefinedName::default();
                obj.set_attributes(&mut reader, e);
                defined_names.push(obj);
            }
        },
        Event::Eof => break
    );

    for defined_name in &defined_names {
        if defined_name.has_local_sheet_id() {
            let local_sheet_id = defined_name.local_sheet_id() as usize;
            wb.sheet_mut(local_sheet_id)
                .unwrap()
                .add_defined_names(defined_name.clone());
        } else {
            if let Some(v) = defined_name.address_obj().first() {
                if let Ok(s) = wb.sheet_by_name_mut(v.sheet_name()) {
                    s.add_defined_names(defined_name.clone());
                    continue;
                }
            }
            wb.add_defined_names(defined_name.clone());
        }
    }

    Ok(wb)
}