mirror of
https://github.com/mbilker/kbinxml-rs.git
synced 2026-09-08 10:35:32 -05:00
lib: general cleanup and added some convenience methods for Value
- split out the kbin wrapper from node_types.rs
This commit is contained in:
@@ -55,6 +55,12 @@ impl<'de> Deserializer<'de> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn node_stack_last(&self) -> Result<&(StandardType, bool)> {
|
||||
self.node_stack.last()
|
||||
.ok_or(KbinErrorKind::InvalidState.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_read_mode(&mut self, read_mode: ReadMode) -> ReadMode {
|
||||
let old_read_mode = self.read_mode;
|
||||
@@ -70,11 +76,6 @@ impl<'de> Deserializer<'de> {
|
||||
|
||||
Ok((node_type, is_array, name))
|
||||
}
|
||||
|
||||
fn node_stack_last(&self) -> Result<&(StandardType, bool)> {
|
||||
self.node_stack.last()
|
||||
.ok_or(KbinErrorKind::InvalidState.into())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! de_type {
|
||||
@@ -397,7 +398,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
where V: Visitor<'de>
|
||||
{
|
||||
trace!("Deserializer::deserialize_enum(name: {:?}, variants: {:?})", name, variants);
|
||||
unimplemented!();
|
||||
|
||||
Err(Error::StaticMessage("enum deserialization not supported"))
|
||||
}
|
||||
|
||||
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
|
||||
|
||||
145
src/kbin_wrapper.rs
Normal file
145
src/kbin_wrapper.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use byteorder::WriteBytesExt;
|
||||
use failure::ResultExt;
|
||||
|
||||
use error::{KbinError, KbinErrorKind};
|
||||
|
||||
pub(crate) trait KbinWrapperType<T> {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError>;
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError>;
|
||||
}
|
||||
|
||||
macro_rules! number_impl {
|
||||
(int; $($inner_type:ident),*) => {
|
||||
$(
|
||||
impl KbinWrapperType<$inner_type> for $inner_type {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<{}> from bytes => input: {:02x?}", stringify!($inner_type), input);
|
||||
|
||||
let mut data = [0; ::std::mem::size_of::<$inner_type>()];
|
||||
data.clone_from_slice(input);
|
||||
write!(output, "{}", $inner_type::from_be_bytes(data))
|
||||
.context(KbinErrorKind::ByteParse(stringify!($inner_type)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?;
|
||||
trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num);
|
||||
|
||||
let data = $inner_type::to_be_bytes(num);
|
||||
output.extend_from_slice(&data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
(float; $($intermediate:ident => $inner_type:ident),*) => {
|
||||
$(
|
||||
impl KbinWrapperType<$inner_type> for $inner_type {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<{}> from bytes => input: {:02x?}", stringify!($inner_type), input);
|
||||
|
||||
let mut data = [0; ::std::mem::size_of::<$inner_type>()];
|
||||
data.clone_from_slice(input);
|
||||
let bits = $intermediate::from_be_bytes(data);
|
||||
|
||||
write!(output, "{:.6}", $inner_type::from_bits(bits))
|
||||
.context(KbinErrorKind::ByteParse(stringify!($inner_type)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?;
|
||||
trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num);
|
||||
|
||||
let data = $intermediate::to_be_bytes(num.to_bits());
|
||||
output.extend_from_slice(&data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
number_impl!(int; u8, u16, u32, u64);
|
||||
number_impl!(int; i8, i16, i32, i64);
|
||||
number_impl!(float; u32 => f32, u64 => f64);
|
||||
|
||||
impl KbinWrapperType<bool> for bool {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<bool> from bytes => input: {:02x?}", input);
|
||||
|
||||
let value = match input[0] {
|
||||
0x00 => "0",
|
||||
0x01 => "1",
|
||||
v => panic!("Unsupported value for boolean: {}", v),
|
||||
};
|
||||
output.push_str(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let value = match input {
|
||||
"0" => 0x00,
|
||||
"1" => 0x01,
|
||||
v => panic!("Unsupported value for boolean: {}", v),
|
||||
};
|
||||
|
||||
trace!("KbinWrapperType<bool> to bytes => input: '{}', output: {}", input, value);
|
||||
output.write_u8(value).context(KbinErrorKind::DataWrite("bool"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Ip4;
|
||||
pub(crate) struct DummyConverter;
|
||||
pub(crate) struct InvalidConverter;
|
||||
|
||||
impl KbinWrapperType<Ip4> for Ip4 {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<Ip4> from bytes => input: {:02x?}", input);
|
||||
|
||||
if input.len() != 4 {
|
||||
panic!("Ip4 type requires exactly 4 bytes of data, input: {:02x?}", input);
|
||||
}
|
||||
|
||||
write!(output, "{}.{}.{}.{}", input[0], input[1], input[2], input[3])
|
||||
.context(KbinErrorKind::ByteParse("Ip4"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<Ip4> to bytes => input: '{}'", input);
|
||||
|
||||
for part in input.split('.') {
|
||||
let num = part.parse::<u8>().context(KbinErrorKind::StringParse("ip4 segment"))?;
|
||||
output.write_u8(num).context(KbinErrorKind::DataWrite("ip4"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl KbinWrapperType<DummyConverter> for DummyConverter {
|
||||
fn from_kbin_bytes(_output: &mut String, _input: &[u8]) -> Result<(), KbinError> { Ok(()) }
|
||||
fn to_kbin_bytes(_output: &mut Vec<u8>, _input: &str) -> Result<(), KbinError> { Ok(()) }
|
||||
}
|
||||
|
||||
impl KbinWrapperType<InvalidConverter> for InvalidConverter {
|
||||
fn from_kbin_bytes(_output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
panic!("Invalid kbin type converter called for input: {:02x?}", input);
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(_output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
panic!("Invalid kbin type converter called for input: {}", input);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ mod compression;
|
||||
mod encoding_type;
|
||||
mod error;
|
||||
mod ip4;
|
||||
mod kbin_wrapper;
|
||||
mod node;
|
||||
mod node_types;
|
||||
mod options;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::fmt;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use value::Value;
|
||||
@@ -8,7 +10,7 @@ mod ser;
|
||||
|
||||
pub use self::extra::ExtraNodes;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
#[derive(Clone, Default, PartialEq)]
|
||||
pub struct Node {
|
||||
key: String,
|
||||
attributes: Option<IndexMap<String, String>>,
|
||||
@@ -16,6 +18,25 @@ pub struct Node {
|
||||
value: Option<Value>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Node {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut d = f.debug_struct("Node");
|
||||
d.field("key", &self.key);
|
||||
|
||||
if let Some(ref attributes) = self.attributes {
|
||||
d.field("attributes", attributes);
|
||||
}
|
||||
|
||||
if let Some(ref children) = self.children {
|
||||
d.field("children", children);
|
||||
} else if let Some(ref value) = self.value {
|
||||
d.field("value", value);
|
||||
}
|
||||
|
||||
d.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new(key: String, value: Option<Value>) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1,149 +1,8 @@
|
||||
use std::fmt::{self, Write};
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
use byteorder::WriteBytesExt;
|
||||
use failure::ResultExt;
|
||||
|
||||
use error::{KbinError, KbinErrorKind};
|
||||
|
||||
trait KbinWrapperType<T> {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError>;
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError>;
|
||||
}
|
||||
|
||||
macro_rules! number_impl {
|
||||
(int; $($inner_type:ident),*) => {
|
||||
$(
|
||||
impl KbinWrapperType<$inner_type> for $inner_type {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<{}> from bytes => input: {:02x?}", stringify!($inner_type), input);
|
||||
|
||||
let mut data = [0; ::std::mem::size_of::<$inner_type>()];
|
||||
data.clone_from_slice(input);
|
||||
write!(output, "{}", $inner_type::from_be_bytes(data))
|
||||
.context(KbinErrorKind::ByteParse(stringify!($inner_type)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?;
|
||||
trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num);
|
||||
|
||||
let data = $inner_type::to_be_bytes(num);
|
||||
output.extend_from_slice(&data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
(float; $($intermediate:ident => $inner_type:ident),*) => {
|
||||
$(
|
||||
impl KbinWrapperType<$inner_type> for $inner_type {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<{}> from bytes => input: {:02x?}", stringify!($inner_type), input);
|
||||
|
||||
let mut data = [0; ::std::mem::size_of::<$inner_type>()];
|
||||
data.clone_from_slice(input);
|
||||
let bits = $intermediate::from_be_bytes(data);
|
||||
|
||||
write!(output, "{:.6}", $inner_type::from_bits(bits))
|
||||
.context(KbinErrorKind::ByteParse(stringify!($inner_type)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?;
|
||||
trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num);
|
||||
|
||||
let data = $intermediate::to_be_bytes(num.to_bits());
|
||||
output.extend_from_slice(&data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
number_impl!(int; u8, u16, u32, u64);
|
||||
number_impl!(int; i8, i16, i32, i64);
|
||||
number_impl!(float; u32 => f32, u64 => f64);
|
||||
|
||||
impl KbinWrapperType<bool> for bool {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<bool> from bytes => input: {:02x?}", input);
|
||||
|
||||
let value = match input[0] {
|
||||
0x00 => "0",
|
||||
0x01 => "1",
|
||||
v => panic!("Unsupported value for boolean: {}", v),
|
||||
};
|
||||
output.push_str(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
let value = match input {
|
||||
"0" => 0x00,
|
||||
"1" => 0x01,
|
||||
v => panic!("Unsupported value for boolean: {}", v),
|
||||
};
|
||||
|
||||
trace!("KbinWrapperType<bool> to bytes => input: '{}', output: {}", input, value);
|
||||
output.write_u8(value).context(KbinErrorKind::DataWrite("bool"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct Ip4;
|
||||
struct DummyConverter;
|
||||
struct InvalidConverter;
|
||||
|
||||
impl KbinWrapperType<Ip4> for Ip4 {
|
||||
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<Ip4> from bytes => input: {:02x?}", input);
|
||||
|
||||
if input.len() != 4 {
|
||||
panic!("Ip4 type requires exactly 4 bytes of data, input: {:02x?}", input);
|
||||
}
|
||||
|
||||
write!(output, "{}.{}.{}.{}", input[0], input[1], input[2], input[3])
|
||||
.context(KbinErrorKind::ByteParse("Ip4"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
trace!("KbinWrapperType<Ip4> to bytes => input: '{}'", input);
|
||||
|
||||
for part in input.split('.') {
|
||||
let num = part.parse::<u8>().context(KbinErrorKind::StringParse("ip4 segment"))?;
|
||||
output.write_u8(num).context(KbinErrorKind::DataWrite("ip4"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl KbinWrapperType<DummyConverter> for DummyConverter {
|
||||
fn from_kbin_bytes(_output: &mut String, _input: &[u8]) -> Result<(), KbinError> { Ok(()) }
|
||||
fn to_kbin_bytes(_output: &mut Vec<u8>, _input: &str) -> Result<(), KbinError> { Ok(()) }
|
||||
}
|
||||
|
||||
impl KbinWrapperType<InvalidConverter> for InvalidConverter {
|
||||
fn from_kbin_bytes(_output: &mut String, input: &[u8]) -> Result<(), KbinError> {
|
||||
panic!("Invalid kbin type converter called for input: {:02x?}", input);
|
||||
}
|
||||
|
||||
fn to_kbin_bytes(_output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
|
||||
panic!("Invalid kbin type converter called for input: {}", input);
|
||||
}
|
||||
}
|
||||
use kbin_wrapper::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct KbinType {
|
||||
|
||||
@@ -30,7 +30,20 @@ impl<'de> Deserialize<'de> for Value {
|
||||
type Value = Value;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("any valid kbin value")
|
||||
formatter.write_str("any valid kbin value (for Value)")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
{
|
||||
trace!("ValueVisitor::visit_string(value: {:?})", value);
|
||||
|
||||
if value.starts_with("attr_") {
|
||||
Ok(Value::Attribute(String::from(&value["attr_".len()..])))
|
||||
} else {
|
||||
Ok(Value::String(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -38,7 +51,12 @@ impl<'de> Deserialize<'de> for Value {
|
||||
where E: de::Error
|
||||
{
|
||||
trace!("ValueVisitor::visit_str(value: {:?})", value);
|
||||
self.visit_string(String::from(value))
|
||||
|
||||
if value.starts_with("attr_") {
|
||||
Ok(Value::Attribute(String::from(&value["attr_".len()..])))
|
||||
} else {
|
||||
Ok(Value::String(String::from(value)))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -47,6 +47,20 @@ macro_rules! construct_types {
|
||||
Value::Node(_) => StandardType::NodeStart,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_i8(&self) -> Option<i8> {
|
||||
match self {
|
||||
Value::S8(ref n) => Some(*n),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_u8(&self) -> Option<u8> {
|
||||
match self {
|
||||
Value::U8(ref n) => Some(*n),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeSeed<'de> for StandardType {
|
||||
|
||||
Reference in New Issue
Block a user