diff --git a/src/error.rs b/src/error.rs index 5b83770..f4b92c7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,7 +12,7 @@ use snafu::Snafu; use crate::byte_buffer::ByteBufferError; use crate::encoding_type::EncodingError; -use crate::node_types::StandardType; +use crate::node_types::{StandardType, UnknownKbinType}; use crate::reader::ReaderError; use crate::sixbit::SixbitError; use crate::value::Value; @@ -52,6 +52,9 @@ pub enum KbinError { #[snafu(display("Failed to interpret slice as UTF-8"))] Utf8Slice { source: Utf8Error }, + // TODO(felix): remove when text reader has own error type + #[snafu(display("Invalid kbin type read"))] + InvalidKbinType { source: UnknownKbinType }, #[snafu(display( "Size Mismatch, type: {}, expected size: {}, actual size: {}", diff --git a/src/node_types.rs b/src/node_types.rs index ecec8a6..b87bd1c 100644 --- a/src/node_types.rs +++ b/src/node_types.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::fmt; use std::ops::Deref; @@ -11,12 +12,29 @@ pub struct KbinType { pub count: usize, } +#[derive(Debug)] +pub enum UnknownKbinType { + Byte(u8), + Name(String), +} + impl fmt::Display for KbinType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} ({})", self.konst, self.name) } } +impl fmt::Display for UnknownKbinType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Byte(byte) => write!(f, "Unknown or not implemented type: {}", byte), + Self::Name(name) => write!(f, "Unknown or not implemented name: {}", name), + } + } +} + +impl Error for UnknownKbinType {} + macro_rules! construct_types { ( $( @@ -43,21 +61,21 @@ macro_rules! construct_types { )+ impl StandardType { - pub fn from_u8(input: u8) -> StandardType { + pub fn from_u8(input: u8) -> Result { match input { $( - $id => StandardType::$konst, + $id => Ok(StandardType::$konst), )+ - _ => panic!("Node type {} not implemented", input), + _ => Err(UnknownKbinType::Byte(input)), } } - pub fn from_name(input: &str) -> StandardType { + pub fn from_name(input: &str) -> Result { match input { $( - $name => StandardType::$konst, + $name => Ok(StandardType::$konst), )+ - _ => panic!("Node name {} not implemented", input), + _ => Err(UnknownKbinType::Name(String::from(input))), } } } diff --git a/src/reader.rs b/src/reader.rs index 4310fb8..2bc3630 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -9,7 +9,7 @@ use crate::compression_type::{CompressionType, UnknownCompression}; use crate::encoding_type::EncodingType; use crate::error::KbinError; use crate::node::{Key, NodeData, NodeDefinition}; -use crate::node_types::StandardType; +use crate::node_types::{StandardType, UnknownKbinType}; use crate::sixbit::Sixbit; use crate::{ARRAY_MASK, SIGNATURE}; @@ -42,6 +42,9 @@ pub enum ReaderError { #[snafu(display("Failed to read node type"))] NodeType { source: io::Error }, + #[snafu(display("Invalid node type read"))] + InvalidNodeType { source: UnknownKbinType }, + #[snafu(display("Failed to read array node length"))] ArrayLength { source: io::Error }, @@ -112,11 +115,11 @@ impl Reader { }) } - fn parse_node_type(raw_node_type: u8) -> Result<(StandardType, bool), KbinError> { + fn parse_node_type(raw_node_type: u8) -> Result<(StandardType, bool), ReaderError> { let is_array = raw_node_type & ARRAY_MASK == ARRAY_MASK; let node_type = raw_node_type & !ARRAY_MASK; - let xml_type = StandardType::from_u8(node_type); + let xml_type = StandardType::from_u8(node_type).context(InvalidNodeType)?; debug!( "Reader::parse_node_type() => raw_node_type: {}, node_type: {:?} ({}), is_array: {}", raw_node_type, xml_type, node_type, is_array @@ -138,7 +141,7 @@ impl Reader { } } - pub fn read_node_type(&mut self) -> Result<(StandardType, bool), KbinError> { + pub fn read_node_type(&mut self) -> Result<(StandardType, bool), ReaderError> { self.check_if_node_buffer_end()?; let raw_node_type = self.node_buf.read_u8().context(NodeType)?; @@ -147,7 +150,10 @@ impl Reader { Ok(value) } - pub fn read_node_data(&mut self, node_type: (StandardType, bool)) -> Result { + pub fn read_node_data( + &mut self, + node_type: (StandardType, bool), + ) -> Result { let (node_type, is_array) = node_type; trace!( "Reader::read_node_data(node_type: {:?}, is_array: {})", @@ -178,7 +184,7 @@ impl Reader { Ok(value) } - pub fn read_node_definition(&mut self) -> Result { + pub fn read_node_definition(&mut self) -> Result { let node_type = self.read_node_type()?; match node_type.0 { StandardType::NodeEnd | StandardType::FileEnd => { diff --git a/src/text_reader.rs b/src/text_reader.rs index 138c427..a3d3465 100644 --- a/src/text_reader.rs +++ b/src/text_reader.rs @@ -84,7 +84,7 @@ impl<'a> TextXmlReader<'a> { if attr.key == b"__type" { let value = str::from_utf8(&*value)?; - node_type = Some(StandardType::from_name(value)); + node_type = Some(StandardType::from_name(value).context(InvalidKbinType)?); } else if attr.key == b"__count" { let value = str::from_utf8(&*value)?; let num_count = value.parse::().context(StringParseInt {