@@ -54,89 +54,70 @@ pub struct StructureError;
5454/// ```
5555pub fn parse (
5656 data : & [ u8 ] ,
57- structure : & Vec < ( & str , & str ) > ,
57+ structure : & [ ( & str , & str ) ] ,
5858 endianness : & str ,
5959) -> Result < HashMap < String , usize > , StructureError > {
60+ const U8_SIZE : usize = std:: mem:: size_of :: < u8 > ( ) ;
61+ const U16_SIZE : usize = std:: mem:: size_of :: < u16 > ( ) ;
62+ const U32_SIZE : usize = std:: mem:: size_of :: < u32 > ( ) ;
63+ const U64_SIZE : usize = std:: mem:: size_of :: < u64 > ( ) ;
6064 const U24_SIZE : usize = 3 ;
6165
62- let mut value: usize ;
63- let mut offset: usize = 0 ;
64- let mut parsed_structure = HashMap :: new ( ) ;
65-
66- // Get the size of the defined structure
67- let structure_size = size ( structure) ;
68-
69- if let Some ( raw_data) = data. get ( 0 ..structure_size) {
70- for ( name, ctype) in structure {
71- let data_type: String = ctype. to_string ( ) ;
72-
73- match type_to_size ( ctype) {
74- None => return Err ( StructureError ) ,
75- Some ( csize) => {
76- if csize == std:: mem:: size_of :: < u8 > ( ) {
77- // u8, endianness doesn't matter
78- value =
79- u8:: from_be_bytes ( raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) )
80- as usize ;
81- } else if csize == std:: mem:: size_of :: < u16 > ( ) {
82- if endianness == "big" {
83- value = u16:: from_be_bytes (
84- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
85- ) as usize ;
86- } else {
87- value = u16:: from_le_bytes (
88- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
89- ) as usize ;
90- }
91-
92- // Yes Virginia, u24's are real
93- } else if csize == U24_SIZE {
94- if endianness == "big" {
95- value = ( ( raw_data[ offset] as usize ) << 16 )
96- + ( ( raw_data[ offset + 1 ] as usize ) << 8 )
97- + ( raw_data[ offset + 2 ] as usize ) ;
98- } else {
99- value = ( ( raw_data[ offset + 2 ] as usize ) << 16 )
100- + ( ( raw_data[ offset + 1 ] as usize ) << 8 )
101- + ( raw_data[ offset] as usize ) ;
102- }
103- } else if csize == std:: mem:: size_of :: < u32 > ( ) {
104- if endianness == "big" {
105- value = u32:: from_be_bytes (
106- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
107- ) as usize ;
108- } else {
109- value = u32:: from_le_bytes (
110- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
111- ) as usize ;
112- }
113- } else if csize == std:: mem:: size_of :: < u64 > ( ) {
114- if endianness == "big" {
115- value = u64:: from_be_bytes (
116- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
117- ) as usize ;
118- } else {
119- value = u64:: from_le_bytes (
120- raw_data[ offset..offset + csize] . try_into ( ) . unwrap ( ) ,
121- ) as usize ;
122- }
123- } else {
124- error ! (
125- "Cannot parse structure element with unknown data type '{data_type}'"
126- ) ;
127- return Err ( StructureError ) ;
128- }
129-
130- offset += csize;
131- parsed_structure. insert ( name. to_string ( ) , value) ;
66+ let mut parsed_structure = HashMap :: with_capacity ( structure. len ( ) ) ;
67+
68+ let mut remaining_data = data;
69+ for & ( name, ctype) in structure {
70+ let csize = type_to_size ( ctype) . ok_or ( StructureError ) ?;
71+ let raw_bytes = remaining_data. split_off ( ..csize) . ok_or ( StructureError ) ?;
72+ let value = match csize {
73+ // u8, endianness doesn't matter
74+ U8_SIZE => usize:: from ( raw_bytes[ 0 ] ) ,
75+ U16_SIZE => {
76+ let f = if endianness == "big" {
77+ u16:: from_be_bytes
78+ } else {
79+ u16:: from_le_bytes
80+ } ;
81+ usize:: from ( f ( raw_bytes. try_into ( ) . unwrap ( ) ) )
82+ }
83+ U32_SIZE => {
84+ let f = if endianness == "big" {
85+ u32:: from_be_bytes
86+ } else {
87+ u32:: from_le_bytes
88+ } ;
89+ f ( raw_bytes. try_into ( ) . unwrap ( ) ) as usize
90+ }
91+ U64_SIZE => {
92+ let f = if endianness == "big" {
93+ u64:: from_be_bytes
94+ } else {
95+ u64:: from_le_bytes
96+ } ;
97+ f ( raw_bytes. try_into ( ) . unwrap ( ) ) as usize // TODO: this will truncate on 32 bit
98+ }
99+ // Yes Virginia, u24's are real
100+ U24_SIZE => {
101+ if endianness == "big" {
102+ usize:: from ( raw_bytes[ 0 ] ) << 16
103+ | usize:: from ( raw_bytes[ 1 ] ) << 8
104+ | usize:: from ( raw_bytes[ 2 ] )
105+ } else {
106+ usize:: from ( raw_bytes[ 2 ] ) << 16
107+ | usize:: from ( raw_bytes[ 1 ] ) << 8
108+ | usize:: from ( raw_bytes[ 0 ] )
132109 }
133110 }
134- }
111+ _ => {
112+ error ! ( "Cannot parse structure element with unknown data type '{ctype}'" ) ;
113+ return Err ( StructureError ) ;
114+ }
115+ } ;
135116
136- return Ok ( parsed_structure) ;
117+ parsed_structure. insert ( name . to_string ( ) , value ) ;
137118 }
138119
139- Err ( StructureError )
120+ Ok ( parsed_structure )
140121}
141122
142123/// Returns the size of a given structure definition.
@@ -157,7 +138,7 @@ pub fn parse(
157138///
158139/// assert_eq!(struct_size, 17);
159140/// ```
160- pub fn size ( structure : & Vec < ( & str , & str ) > ) -> usize {
141+ pub fn size ( structure : & [ ( & str , & str ) ] ) -> usize {
161142 let mut struct_size: usize = 0 ;
162143
163144 for ( _name, ctype) in structure {
0 commit comments