1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use std::io::Cursor; use byteorder::{LittleEndian, ReadBytesExt}; use encoding::codec::utf_16::{self, Little}; use failure::{ensure, format_err, Error}; #[derive(Debug)] pub struct PackageWrapper<'a> { raw_data: &'a [u8], } impl<'a> PackageWrapper<'a> { pub fn new(raw_data: &'a [u8]) -> Self { Self { raw_data } } pub fn get_id(&self) -> Result<u32, Error> { let mut cursor = Cursor::new(self.raw_data); cursor.set_position(8); Ok(cursor.read_u32::<LittleEndian>()?) } pub fn get_name(&self) -> Result<String, Error> { let mut cursor = Cursor::new(self.raw_data); cursor.set_position(12); let initial_position = cursor.position(); ensure!( ((initial_position + 256) as usize) < self.raw_data.len(), "cursor position out of bounds" ); let final_position = self.find_end_position(initial_position as usize); ensure!( self.raw_data.len() >= (initial_position + 256) as usize, "not enough bytes to retrieve package name" ); let raw_str = &cursor.get_ref()[initial_position as usize..final_position]; let mut decoder = utf_16::UTF16Decoder::<Little>::new(); let mut o = String::new(); decoder.raw_feed(raw_str, &mut o); let decode_error = decoder.raw_finish(&mut o); match decode_error { None => Ok(o), Some(_) => Err(format_err!("error decoding UTF8 string")), } } fn find_end_position(&self, initial_position: usize) -> usize { let buffer = &self.raw_data[initial_position..initial_position + 256]; let mut zeros = 0; let mut i = 0; for c in buffer { if *c == 0 { zeros += 1; } else { zeros = 0; } if zeros > 1 { break; } i += 1; } initial_position + i } }