use crate::error::OoxmlError;
use serde::{Deserialize, Serialize};
use std::io::prelude::*;
use std::{fmt, fs::File, path::Path};
pub const SHARED_STRINGS_TAG: &str = "sst";
pub const SHARED_STRING_TAG: &str = "si";
use crate::packaging::element::*;
use crate::packaging::namespace::Namespaces;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all(deserialize = "camelCase"), rename = "t")]
pub struct Value(String);
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all(deserialize = "camelCase"), rename = "si")]
pub struct SharedString {
t: Value,
}
impl SharedString {
pub fn as_str(&self) -> &str {
self.t.0.as_str()
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all(deserialize = "camelCase"), rename = "sst")]
pub struct SharedStringsPart {
count: usize,
unique_count: usize,
#[serde(flatten)]
namespaces: Namespaces,
#[serde(rename = "si")]
strings: Vec<SharedString>,
}
impl SharedStringsPart {
pub fn get_shared_string(&self, idx: usize) -> Option<&str> {
match self.strings.get(idx) {
None => None,
Some(ss) => Some(ss.as_str()),
}
}
}
impl OpenXmlElementInfo for SharedStringsPart {
fn tag_name() -> &'static str {
"sst"
}
fn element_type() -> OpenXmlElementType {
OpenXmlElementType::Root
}
}
impl OpenXmlDeserializeDefault for SharedStringsPart {}
impl fmt::Display for SharedStringsPart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut container = Vec::new();
let mut cursor = std::io::Cursor::new(&mut container);
self.write(&mut cursor).expect("write xml to memory error");
let s = String::from_utf8_lossy(&container);
write!(f, "{}", s)?;
Ok(())
}
}
impl SharedStringsPart {
pub fn parse_from_xml_reader<R: BufRead>(reader: R) -> Self {
quick_xml::de::from_reader(reader).unwrap()
}
pub fn parse_from_xml_str(reader: &str) -> Self {
quick_xml::de::from_str(reader).unwrap()
}
pub fn save_as<P: AsRef<Path>>(&self, path: P) -> Result<(), OoxmlError> {
let file = File::create(path)?;
self.write(file)
}
pub fn write<W: std::io::Write>(&self, writer: W) -> Result<(), OoxmlError> {
let mut xml = quick_xml::Writer::new(writer);
use quick_xml::events::attributes::Attribute;
use quick_xml::events::*;
xml.write_event(Event::Decl(BytesDecl::new(
b"1.0",
Some(b"UTF-8"),
Some(b"yes"),
)))?;
let mut elem = BytesStart::borrowed_name(SHARED_STRINGS_TAG.as_bytes());
elem.extend_attributes(self.namespaces.to_xml_attributes());
elem.extend_attributes(vec![
Attribute {
key: b"count",
value: format!("{}", self.count).as_bytes().into(),
},
Attribute {
key: b"uniqueCount",
value: format!("{}", self.unique_count).as_bytes().into(),
},
]);
xml.write_event(Event::Start(elem))?;
for si in &self.strings {
let elem = BytesStart::borrowed_name(SHARED_STRING_TAG.as_bytes());
xml.write_event(Event::Start(elem))?;
quick_xml::se::to_writer(xml.inner(), &si.t)?;
let end = BytesEnd::borrowed(SHARED_STRING_TAG.as_bytes());
xml.write_event(Event::End(end))?;
}
let end = BytesEnd::borrowed(SHARED_STRINGS_TAG.as_bytes());
xml.write_event(Event::End(end))?;
Ok(())
}
}
#[test]
fn test_de() {
let value = SharedStringsPart::from_xml_file("examples/simple-spreadsheet/xl/sharedStrings.xml").unwrap();
println!("{:?}", value);
let display = format!("{}", value);
println!("{}", display);
}