diff --git a/src/lib.rs b/src/lib.rs index 8598527..0ad83d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ mod ser; use byte_buffer::ByteBufferWrite; use node_types::StandardType; use reader::Reader; -use sixbit::pack_sixbit; +use sixbit::Sixbit; // Public exports pub use encoding_type::EncodingType; @@ -236,7 +236,7 @@ impl KbinXml { count); node_buf.write_u8(node_type.id | array_mask).context(KbinErrorKind::DataWrite(node_type.name))?; - pack_sixbit(&mut **node_buf, input.name())?; + Sixbit::pack(&mut **node_buf, input.name())?; match node_type { StandardType::NodeStart => {}, @@ -281,7 +281,7 @@ impl KbinXml { let node_type = StandardType::Attribute; node_buf.write_u8(node_type.id).context(KbinErrorKind::DataWrite(node_type.name))?; - pack_sixbit(&mut **node_buf, key)?; + Sixbit::pack(&mut **node_buf, key)?; } for child in input.children() { diff --git a/src/reader.rs b/src/reader.rs index 04b47d2..79ae2a1 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -8,7 +8,7 @@ use compression::Compression; use encoding_type::EncodingType; use error::{KbinErrorKind, Result}; use node_types::StandardType; -use sixbit::unpack_sixbit; +use sixbit::Sixbit; use super::{ARRAY_MASK, SIGNATURE, SIG_COMPRESSED}; pub struct Reader<'buf> { @@ -122,7 +122,7 @@ impl<'buf> Reader<'buf> { pub fn peek_node_identifier(&mut self) -> Result { let old_pos = self.node_buf.position(); let _raw_node_type = self.node_buf.read_u8().context(KbinErrorKind::NodeTypeRead)?; - let value = unpack_sixbit(&mut *self.node_buf)?; + let value = Sixbit::unpack(&mut *self.node_buf)?; let size = self.node_buf.position() - old_pos; self.node_buf.seek(SeekFrom::Start(old_pos)).context(KbinErrorKind::DataRead(size as usize))?; @@ -139,7 +139,7 @@ impl<'buf> Reader<'buf> { } pub fn read_node_identifier(&mut self) -> Result { - let value = unpack_sixbit(&mut *self.node_buf)?; + let value = Sixbit::unpack(&mut *self.node_buf)?; debug!("Reader::read_node_identifier() => value: {:?}", value); self.last_node_identifier = Some(value.clone()); diff --git a/src/ser/map.rs b/src/ser/map.rs index 73a5565..27347ef 100644 --- a/src/ser/map.rs +++ b/src/ser/map.rs @@ -5,7 +5,7 @@ use serde::ser::{Serialize, SerializeMap}; use error::{Error, KbinErrorKind}; use node_types::StandardType; use ser::{Result, Serializer, TypeHint, WriteMode, ARRAY_MASK}; -use sixbit::pack_sixbit; +use sixbit::Sixbit; pub struct Map<'a> { ser: &'a mut Serializer, @@ -29,7 +29,7 @@ impl<'a> Map<'a> { let node_type = StandardType::NodeStart; ser.node_buf.write_u8(node_type.id).context(KbinErrorKind::DataWrite(node_type.name))?; - pack_sixbit(&mut *ser.node_buf, name)?; + Sixbit::pack(&mut *ser.node_buf, name)?; } Ok(Self { ser }) diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 2bb8b3c..5bd10f7 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -9,7 +9,7 @@ use byte_buffer::ByteBufferWrite; use encoding_type::EncodingType; use node_types::StandardType; use error::{Error, KbinError, KbinErrorKind}; -use sixbit::pack_sixbit; +use sixbit::Sixbit; use super::{ARRAY_MASK, SIGNATURE, SIG_COMPRESSED}; mod buffer; @@ -114,7 +114,7 @@ impl Serializer { } fn write_identifier(&mut self, key: &str) -> Result<()> { - pack_sixbit(&mut *self.node_buf, key)?; + Sixbit::pack(&mut *self.node_buf, key)?; Ok(()) } } diff --git a/src/sixbit.rs b/src/sixbit.rs index aa6fdd2..79cb19f 100644 --- a/src/sixbit.rs +++ b/src/sixbit.rs @@ -21,63 +21,67 @@ lazy_static! { }; } -pub fn pack_sixbit(writer: &mut T, input: &str) -> Result<(), KbinError> - where T: Write -{ - let sixbit_chars = input - .bytes() - .map(|ch| { - *BYTE_MAP.get(&ch).expect("Character must be a valid sixbit character") - }); - let len = input.len() as usize; - let padding = 8 - len * 6 % 8; - let padding = if padding == 8 { 0 } else { padding }; - let real_len = (len * 6 + padding) / 8; - debug!("sixbit_len: {}, real_len: {}, padding: {}", len, real_len, padding); +pub struct Sixbit; - let mut bits = BigUint::new(vec![0; real_len]); - for ch in sixbit_chars { - bits <<= 6; - bits |= BigUint::from_u8(ch).unwrap(); +impl Sixbit { + pub fn pack(writer: &mut T, input: &str) -> Result<(), KbinError> + where T: Write + { + let sixbit_chars = input + .bytes() + .map(|ch| { + *BYTE_MAP.get(&ch).expect("Character must be a valid sixbit character") + }); + let len = input.len() as usize; + let padding = 8 - len * 6 % 8; + let padding = if padding == 8 { 0 } else { padding }; + let real_len = (len * 6 + padding) / 8; + debug!("sixbit_len: {}, real_len: {}, padding: {}", len, real_len, padding); + + let mut bits = BigUint::new(vec![0; real_len]); + for ch in sixbit_chars { + bits <<= 6; + bits |= BigUint::from_u8(ch).unwrap(); + } + bits <<= padding; + + let bytes = bits.to_bytes_be(); + writer.write_u8(len as u8).context(KbinErrorKind::SixbitLengthWrite)?; + writer.write(&bytes).context(KbinErrorKind::SixbitWrite)?; + + Ok(()) } - bits <<= padding; - let bytes = bits.to_bytes_be(); - writer.write_u8(len as u8).context(KbinErrorKind::SixbitLengthWrite)?; - writer.write(&bytes).context(KbinErrorKind::SixbitWrite)?; + pub fn unpack(reader: &mut T) -> Result + where T: Read + { + let len = reader.read_u8().context(KbinErrorKind::SixbitLengthRead)?; + let real_len = (f32::from(len * 6) / 8f32).ceil(); + let real_len = (real_len as u32) as usize; + let padding = (8 - ((len * 6) % 8)) as usize; + let padding = if padding == 8 { 0 } else { padding }; + debug!("sixbit_len: {}, real_len: {}, padding: {}", len, real_len, padding); - Ok(()) -} - -pub fn unpack_sixbit(reader: &mut T) -> Result - where T: Read -{ - let len = reader.read_u8().context(KbinErrorKind::SixbitLengthRead)?; - let real_len = (f32::from(len * 6) / 8f32).ceil(); - let real_len = (real_len as u32) as usize; - let padding = (8 - ((len * 6) % 8)) as usize; - let padding = if padding == 8 { 0 } else { padding }; - debug!("sixbit_len: {}, real_len: {}, padding: {}", len, real_len, padding); - - let mut buf = vec![0; real_len]; - reader.read_exact(&mut buf).context(KbinErrorKind::SixbitRead)?; - - let bits = BigUint::from_bytes_be(&buf); - let bits = bits >> padding; - debug!("bits: 0b{:b}", bits); - - let mask = BigUint::from_u8(0b111111).unwrap(); - let result = (1..=len).map(|i| { - // Get the current sixbit part starting from the the left most bit in - // big endian order - let shift = ((len - i) * 6) as usize; - let bits = bits.clone(); - let mask = mask.clone(); - let current = (bits >> shift) & mask; - - CHAR_MAP[current.to_usize().unwrap()] as char - }).collect(); - - debug!("result: {}", result); - Ok(result) + let mut buf = vec![0; real_len]; + reader.read_exact(&mut buf).context(KbinErrorKind::SixbitRead)?; + + let bits = BigUint::from_bytes_be(&buf); + let bits = bits >> padding; + debug!("bits: 0b{:b}", bits); + + let mask = BigUint::from_u8(0b111111).unwrap(); + let result = (1..=len).map(|i| { + // Get the current sixbit part starting from the the left most bit in + // big endian order + let shift = ((len - i) * 6) as usize; + let bits = bits.clone(); + let mask = mask.clone(); + let current = (bits >> shift) & mask; + + CHAR_MAP[current.to_usize().unwrap()] as char + }).collect(); + + debug!("result: {}", result); + Ok(result) + } }