mirror of
https://github.com/mbilker/kbinxml-rs.git
synced 2026-09-07 01:55:13 -05:00
lib: remove minidom support
This commit is contained in:
@@ -13,7 +13,6 @@ failure = "0.1.1"
|
||||
indexmap = "1.0.1"
|
||||
lazy_static = "1.0.0"
|
||||
log = "0.4.6"
|
||||
minidom = "0.11.0"
|
||||
quick-xml = "0.14.0"
|
||||
rustc-hex = "2.0.1"
|
||||
|
||||
|
||||
86
src/lib.rs
86
src/lib.rs
@@ -4,10 +4,7 @@
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
use std::fmt::Write as FmtWrite;
|
||||
|
||||
use bytes::Bytes;
|
||||
use minidom::Element;
|
||||
|
||||
mod byte_buffer;
|
||||
mod compression;
|
||||
@@ -20,13 +17,11 @@ mod printer;
|
||||
mod reader;
|
||||
mod sixbit;
|
||||
mod text_reader;
|
||||
mod to_element;
|
||||
mod to_text_xml;
|
||||
mod types;
|
||||
mod value;
|
||||
mod writer;
|
||||
|
||||
use crate::node::NodeDefinition;
|
||||
use crate::text_reader::TextXmlReader;
|
||||
use crate::to_text_xml::TextXmlWriter;
|
||||
|
||||
@@ -39,7 +34,6 @@ pub use crate::error::{KbinError, KbinErrorKind, Result};
|
||||
pub use crate::node::{Node, NodeCollection};
|
||||
pub use crate::node_types::StandardType;
|
||||
pub use crate::options::Options;
|
||||
pub use crate::to_element::ToElement;
|
||||
pub use crate::to_text_xml::ToTextXml;
|
||||
pub use crate::value::{Value, ValueArray};
|
||||
pub use crate::writer::{Writer, Writeable};
|
||||
@@ -55,86 +49,6 @@ pub fn is_binary_xml(input: &[u8]) -> bool {
|
||||
input.len() > 2 && input[0] == SIGNATURE && (input[1] == SIG_COMPRESSED || input[1] == SIG_UNCOMPRESSED)
|
||||
}
|
||||
|
||||
fn read_node(reader: &mut Reader, def: NodeDefinition) -> Result<Element> {
|
||||
let key = def.key()?.ok_or(KbinErrorKind::InvalidNodeType(def.node_type))?;
|
||||
let mut elem = Element::bare(key);
|
||||
|
||||
// Don't make the assumption that there cannot be a sub-node when a node has a value.
|
||||
// Example: `netlog` module
|
||||
if def.node_type != StandardType::NodeStart {
|
||||
elem.set_attr("__type", def.node_type.name);
|
||||
|
||||
match def.value()? {
|
||||
Value::Binary(data) => {
|
||||
elem.set_attr("__size", data.len());
|
||||
|
||||
let len = data.len() * 2;
|
||||
let value = data.into_iter().fold(String::with_capacity(len), |mut val, x| {
|
||||
write!(val, "{:02x}", x).expect("Failed to append hex char");
|
||||
val
|
||||
});
|
||||
debug!("KbinXml::read_node(name: {}) => binary value: {}", elem.name(), value);
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
Value::String(value) => {
|
||||
debug!("KbinXml::read_node(name: {}) => string value: {:?}", elem.name(), value);
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
Value::Array(values) => {
|
||||
elem.set_attr("__count", values.len());
|
||||
|
||||
let value = values.to_string();
|
||||
debug!("KbinXml::read_node(name: {}) => value: {:?}", elem.name(), value);
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
value => {
|
||||
let value = value.to_string();
|
||||
debug!("KbinXml::read_node(name: {}) => value: {:?}", elem.name(), value);
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
let def = reader.read_node_definition()?;
|
||||
|
||||
match def.node_type {
|
||||
StandardType::NodeEnd => break,
|
||||
StandardType::NodeStart => {
|
||||
let child = read_node(reader, def)?;
|
||||
elem.append_child(child);
|
||||
|
||||
continue;
|
||||
},
|
||||
StandardType::Attribute => {
|
||||
let node = def.as_node()?;
|
||||
let (key, value) = node.into_key_and_value();
|
||||
if let Some(Value::Attribute(value)) = value {
|
||||
elem.set_attr(key, value);
|
||||
} else {
|
||||
return Err(KbinErrorKind::InvalidState.into());
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let child = read_node(reader, def)?;
|
||||
elem.append_child(child);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Ok(elem)
|
||||
}
|
||||
|
||||
pub fn element_from_binary(input: &[u8]) -> Result<(Element, EncodingType)> {
|
||||
let mut reader = Reader::new(Bytes::from(input))?;
|
||||
let base = reader.read_node_definition()?;
|
||||
|
||||
let elem = read_node(&mut reader, base)?;
|
||||
let encoding = reader.encoding();
|
||||
|
||||
Ok((elem, encoding))
|
||||
}
|
||||
|
||||
pub fn from_binary(input: Bytes) -> Result<(NodeCollection, EncodingType)> {
|
||||
let mut reader = Reader::new(input)?;
|
||||
let collection = NodeCollection::from_iter(&mut reader).ok_or(KbinErrorKind::NoNodeCollection)?;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
use minidom::Element;
|
||||
|
||||
mod node;
|
||||
|
||||
pub trait ToElement {
|
||||
fn to_element(&self) -> Element;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use minidom::Element;
|
||||
|
||||
use crate::node::Node;
|
||||
use crate::to_element::ToElement;
|
||||
use crate::value::Value;
|
||||
|
||||
impl ToElement for Node {
|
||||
fn to_element(&self) -> Element {
|
||||
let mut elem = Element::bare(self.key());
|
||||
|
||||
if let Some(value) = self.value() {
|
||||
elem.set_attr("__type", value.standard_type().name);
|
||||
|
||||
match value {
|
||||
Value::Binary(data) => {
|
||||
elem.set_attr("__size", data.len());
|
||||
|
||||
let len = data.len() * 2;
|
||||
let value = data.into_iter().fold(String::with_capacity(len), |mut val, x| {
|
||||
write!(val, "{:02x}", x).expect("Failed to append hex char");
|
||||
val
|
||||
});
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
Value::String(value) => {
|
||||
elem.append_text_node(value.as_str());
|
||||
},
|
||||
Value::Array(values) => {
|
||||
elem.set_attr("__count", values.len());
|
||||
|
||||
let value = value.to_string();
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
value => {
|
||||
let value = value.to_string();
|
||||
elem.append_text_node(value);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(attributes) = self.attributes() {
|
||||
for (key, value) in attributes {
|
||||
elem.set_attr(key.as_str(), value.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(children) = self.children() {
|
||||
for child in children {
|
||||
let child = child.to_element();
|
||||
elem.append_child(child);
|
||||
}
|
||||
}
|
||||
|
||||
elem
|
||||
}
|
||||
}
|
||||
112
src/writer.rs
112
src/writer.rs
@@ -2,8 +2,6 @@ use std::io::{Cursor, Write};
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use failure::ResultExt;
|
||||
use minidom::Element;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
use crate::byte_buffer::ByteBufferWrite;
|
||||
use crate::compression::Compression;
|
||||
@@ -60,116 +58,6 @@ pub trait Writeable {
|
||||
fn write_node(&self, options: &Options, node_buf: &mut ByteBufferWrite, data_buf: &mut ByteBufferWrite) -> Result<()>;
|
||||
}
|
||||
|
||||
impl Writeable for Element {
|
||||
fn write_node(&self, options: &Options, node_buf: &mut ByteBufferWrite, data_buf: &mut ByteBufferWrite) -> Result<()> {
|
||||
let text = self.text();
|
||||
let node_type = match self.attr("__type") {
|
||||
Some(name) => StandardType::from_name(name),
|
||||
None => {
|
||||
// Screw whitespace with pretty printed XML
|
||||
if text.trim().len() == 0 {
|
||||
StandardType::NodeStart
|
||||
} else {
|
||||
StandardType::String
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let (array_mask, count) = match self.attr("__count") {
|
||||
Some(count) => {
|
||||
let count = count.parse::<u32>().context(KbinErrorKind::StringParse("array count"))?;
|
||||
debug!("write_node => __count = {}", count);
|
||||
(ARRAY_MASK, count)
|
||||
},
|
||||
None => {
|
||||
(0, 1)
|
||||
},
|
||||
};
|
||||
|
||||
debug!("write_node => name: {}, type: {:?}, type_size: {}, type_count: {}, is_array: {}, size: {}",
|
||||
self.name(),
|
||||
node_type,
|
||||
node_type.size,
|
||||
node_type.count,
|
||||
array_mask,
|
||||
count);
|
||||
|
||||
node_buf.write_u8(node_type as u8 | array_mask).context(KbinErrorKind::DataWrite(node_type.name))?;
|
||||
match options.compression {
|
||||
Compression::Compressed => Sixbit::pack(&mut **node_buf, self.name())?,
|
||||
Compression::Uncompressed => {
|
||||
let data = options.encoding.encode_bytes(self.name())?;
|
||||
let len = (data.len() - 1) as u8;
|
||||
node_buf.write_u8(len | ARRAY_MASK).context(KbinErrorKind::DataWrite("node name length"))?;
|
||||
node_buf.write_all(&data).context(KbinErrorKind::DataWrite("node name bytes"))?;
|
||||
},
|
||||
};
|
||||
|
||||
match node_type {
|
||||
StandardType::NodeStart => {},
|
||||
|
||||
StandardType::Binary => {
|
||||
let data: Vec<u8> = text.from_hex().context(KbinErrorKind::HexError)?;
|
||||
let size = (data.len() as u32) * (node_type.size as u32);
|
||||
data_buf.write_u32::<BigEndian>(size).context(KbinErrorKind::DataWrite("binary node size"))?;
|
||||
data_buf.write_all(&data).context(KbinErrorKind::DataWrite("binary"))?;
|
||||
data_buf.realign_writes(None)?;
|
||||
},
|
||||
StandardType::String => {
|
||||
data_buf.write_str(options.encoding, &text)?;
|
||||
},
|
||||
|
||||
_ => {
|
||||
let value = Value::from_string(node_type, text.trim(), array_mask > 0, count as usize)?;
|
||||
let data = value.to_bytes()?;
|
||||
|
||||
if array_mask > 0 {
|
||||
let total_size = (count as u32) * (node_type.count as u32) * (node_type.size as u32);
|
||||
trace!("write_node data_buf array => total_size: {}, data: 0x{:02x?}", total_size, data);
|
||||
|
||||
data_buf.write_u32::<BigEndian>(total_size).context(KbinErrorKind::DataWrite("node size"))?;
|
||||
data_buf.write_all(&data).context(KbinErrorKind::DataWrite(node_type.name))?;
|
||||
data_buf.realign_writes(None)?;
|
||||
} else {
|
||||
data_buf.write_aligned(*node_type, &data)?;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
for (key, value) in self.attrs() {
|
||||
match key {
|
||||
"__count" | "__size" | "__type" => continue,
|
||||
_ => {},
|
||||
};
|
||||
|
||||
trace!("write_node => attr: {}, value: {}", key, value);
|
||||
|
||||
data_buf.write_str(options.encoding, value)?;
|
||||
|
||||
let node_type = StandardType::Attribute;
|
||||
node_buf.write_u8(node_type as u8).context(KbinErrorKind::DataWrite(node_type.name))?;
|
||||
match options.compression {
|
||||
Compression::Compressed => Sixbit::pack(&mut **node_buf, key)?,
|
||||
Compression::Uncompressed => {
|
||||
let data = options.encoding.encode_bytes(key)?;
|
||||
let len = (data.len() - 1) as u8;
|
||||
node_buf.write_u8(len | ARRAY_MASK).context(KbinErrorKind::DataWrite("attribute name length"))?;
|
||||
node_buf.write_all(&data).context(KbinErrorKind::DataWrite("node name bytes"))?;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
for child in self.children() {
|
||||
child.write_node(options, node_buf, data_buf)?;
|
||||
}
|
||||
|
||||
// node end always has the array bit set
|
||||
node_buf.write_u8(StandardType::NodeEnd as u8 | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Writeable for NodeCollection {
|
||||
fn write_node(&self, options: &Options, node_buf: &mut ByteBufferWrite, data_buf: &mut ByteBufferWrite) -> Result<()> {
|
||||
let (node_type, is_array) = self.base().node_type_tuple();
|
||||
|
||||
Reference in New Issue
Block a user