umya-spreadsheet 3.0.0

umya-spreadsheet is a library written in pure Rust to read and write xlsx file.
Documentation
use std::{
    borrow::Cow,
    io,
    io::{
        Cursor,
        Write,
    },
};

use quick_xml::{
    Writer,
    escape::partial_escape,
    events::{
        BytesEnd,
        BytesStart,
        BytesText,
        Event,
    },
};

pub(crate) fn write_start_tag<'a, S>(
    writer: &mut Writer<Cursor<Vec<u8>>>,
    tag_name: S,
    attributes: crate::structs::AttrCollection,
    empty_flag: bool,
) where
    S: Into<Cow<'a, str>>,
{
    let tag_name = tag_name.into();
    let len = tag_name.len();
    let mut elem = BytesStart::from_content(tag_name, len);

    elem.extend_attributes(
        attributes
            .into_iter()
            .map(Into::into)
            .collect::<Vec<(&str, Cow<'_, str>)>>(),
    );

    if empty_flag {
        writer.write_event(Event::Empty(elem)).unwrap();
    } else {
        writer.write_event(Event::Start(elem)).unwrap();
    }
}

#[inline]
pub(crate) fn write_end_tag<'a, S>(writer: &mut Writer<Cursor<Vec<u8>>>, tag_name: S)
where
    S: Into<Cow<'a, str>>,
{
    writer
        .write_event(Event::End(BytesEnd::new(tag_name.into())))
        .unwrap();
}

#[inline]
pub(crate) fn write_text_node<'a, S>(writer: &mut Writer<Cursor<Vec<u8>>>, data: S)
where
    S: Into<Cow<'a, str>>,
{
    writer
        .write_event(Event::Text(BytesText::new(&data.into())))
        .unwrap();
}

#[inline]
pub(crate) fn write_text_node_no_escape<'a, S>(writer: &mut Writer<Cursor<Vec<u8>>>, data: S)
where
    S: Into<Cow<'a, str>>,
{
    writer.get_mut().write_all(data.into().as_bytes()).unwrap();
}

#[inline]
pub(crate) fn write_text_node_conversion<'a, S>(writer: &mut Writer<Cursor<Vec<u8>>>, data: S)
where
    S: Into<Cow<'a, str>>,
{
    write_text_node_no_escape(writer, partial_escape(data.into()));
}

#[inline]
pub(crate) fn write_new_line(writer: &mut Writer<Cursor<Vec<u8>>>) {
    write_text_node(writer, "\r\n");
}

#[inline]
pub(crate) fn make_file_from_writer<W: io::Seek + Write>(
    path: &str,
    arv: &mut zip::ZipWriter<W>,
    writer: Writer<Cursor<Vec<u8>>>,
    dir: Option<&str>,
    is_light: bool,
) -> Result<(), io::Error> {
    make_file_from_bin(path, arv, &writer.into_inner().into_inner(), dir, is_light)
}

#[inline]
pub(crate) fn make_file_from_bin<W: io::Seek + Write>(
    path: &str,
    arv: &mut zip::ZipWriter<W>,
    writer: &[u8],
    dir: Option<&str>,
    is_light: bool,
) -> Result<(), io::Error> {
    let zip_opt = if is_light {
        zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored)
    } else {
        zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::DEFLATE)
    };
    arv.start_file(to_path(path, dir), zip_opt)?;
    arv.write_all(writer)
}

#[inline]
pub(crate) fn to_path<'a>(path: &'a str, dir: Option<&'a str>) -> Cow<'a, str> {
    match dir {
        Some(dir) => Cow::Owned(format!("{dir}/{path}")),
        None => Cow::Borrowed(path),
    }
}