Replace some helper functions with Parse trait instances

This commit is contained in:
Brian Carroll 2022-05-22 10:17:09 +01:00
parent 8114ec60c1
commit 66c78ceed5
No known key found for this signature in database
GPG key ID: 9CF4E3BF9C4722C7
3 changed files with 35 additions and 54 deletions

View file

@ -2,7 +2,7 @@ use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use super::opcodes::OpCode;
use super::parse::{parse_u32_or_panic, SkipBytes};
use super::parse::{Parse, SkipBytes};
use super::serialize::{SerialBuffer, Serialize};
use super::CodeBuilder;
@ -92,13 +92,13 @@ pub fn parse_preloads_call_graph<'a>(
call_graph.code_offsets.push(cursor as u32);
call_graph.calls_offsets.push(call_graph.calls.len() as u32);
let func_size = parse_u32_or_panic(code_section_body, &mut cursor);
let func_size = u32::parse((), code_section_body, &mut cursor).unwrap();
let func_end = cursor + func_size as usize;
// Skip over local variable declarations
let local_groups_count = parse_u32_or_panic(code_section_body, &mut cursor);
let local_groups_count = u32::parse((), code_section_body, &mut cursor).unwrap();
for _ in 0..local_groups_count {
parse_u32_or_panic(code_section_body, &mut cursor);
u32::parse((), code_section_body, &mut cursor).unwrap();
cursor += 1; // ValueType
}
@ -107,12 +107,12 @@ pub fn parse_preloads_call_graph<'a>(
let opcode_byte: u8 = code_section_body[cursor];
if opcode_byte == OpCode::CALL as u8 {
cursor += 1;
let call_index = parse_u32_or_panic(code_section_body, &mut cursor);
let call_index = u32::parse((), code_section_body, &mut cursor).unwrap();
call_graph.calls.push(call_index as u32);
} else if opcode_byte == OpCode::CALLINDIRECT as u8 {
cursor += 1;
// Insert all indirect callees with a matching type signature
let sig = parse_u32_or_panic(code_section_body, &mut cursor);
let sig = u32::parse((), code_section_body, &mut cursor).unwrap();
call_graph.calls.extend(
indirect_callees
.iter()

View file

@ -1,7 +1,5 @@
use super::serialize::MAX_SIZE_ENCODED_U32;
use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use roc_error_macros::internal_error;
/// Parse serialized bytes into a data structure
/// Specific parsers may need contextual data from other parts of the .wasm file
@ -41,32 +39,16 @@ impl Parse<()> for u32 {
}
}
// Parse a vector of bytes (used for strings, but we don't bother with utf8 validation)
impl<'a> Parse<&'a Bump> for Vec<'a, u8> {
// Parse string bytes without utf8 validation
impl<'a> Parse<&'a Bump> for &'a [u8] {
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, String> {
let len = parse_u32_or_panic(bytes, cursor);
let end = *cursor + len as usize;
let bytes: &[u8] = &bytes[*cursor..end];
let mut copy = Vec::with_capacity_in(bytes.len(), arena);
copy.extend_from_slice(bytes);
*cursor = end;
Ok(copy)
}
}
pub fn parse_u32_or_panic(bytes: &[u8], cursor: &mut usize) -> u32 {
let (value, len) = decode_u32(&bytes[*cursor..]).unwrap_or_else(|e| internal_error!("{}", e));
*cursor += len;
value
}
pub fn parse_string_bytes<'a>(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> &'a [u8] {
let len = parse_u32_or_panic(bytes, cursor);
let len = u32::parse((), bytes, cursor)?;
let end = *cursor + len as usize;
let bytes: &[u8] = &bytes[*cursor..end];
let copy = arena.alloc_slice_copy(bytes);
*cursor = end;
copy
Ok(copy)
}
}
impl SkipBytes for u32 {
@ -105,7 +87,7 @@ impl SkipBytes for u8 {
/// Note: This is just for skipping over Wasm bytes. We don't actually care about String vs str!
impl SkipBytes for String {
fn skip_bytes(bytes: &[u8], cursor: &mut usize) -> Result<(), String> {
let len = parse_u32_or_panic(bytes, cursor);
let len = u32::parse((), bytes, cursor)?;
if false {
let str_bytes = &bytes[*cursor..(*cursor + len as usize)];
@ -123,7 +105,7 @@ impl SkipBytes for String {
#[cfg(test)]
mod tests {
use super::*;
use crate::wasm_module::parse::{decode_u32, parse_u32_or_panic};
use crate::wasm_module::parse::decode_u32;
#[test]
fn test_decode_u32() {
@ -148,13 +130,13 @@ mod tests {
let expected = [0, 128, u32::MAX];
let mut cursor = 0;
assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[0]);
assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[0]);
assert_eq!(cursor, 1);
assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[1]);
assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[1]);
assert_eq!(cursor, 3);
assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[2]);
assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[2]);
assert_eq!(cursor, 8);
}
}

View file

@ -11,7 +11,7 @@ use super::dead_code::{
};
use super::linking::RelocationEntry;
use super::opcodes::OpCode;
use super::parse::{parse_string_bytes, parse_u32_or_panic, Parse, SkipBytes};
use super::parse::{Parse, SkipBytes};
use super::serialize::{SerialBuffer, Serialize, MAX_SIZE_ENCODED_U32};
use super::{CodeBuilder, ValueType};
@ -118,9 +118,9 @@ fn parse_section<'a>(id: SectionId, module_bytes: &'a [u8], cursor: &mut usize)
}
*cursor += 1;
let section_size = parse_u32_or_panic(module_bytes, cursor);
let section_size = u32::parse((), module_bytes, cursor).unwrap();
let count_start = *cursor;
let count = parse_u32_or_panic(module_bytes, cursor);
let count = u32::parse((), module_bytes, cursor).unwrap();
let body_start = *cursor;
let next_section_start = count_start + section_size as usize;
@ -237,7 +237,7 @@ impl<'a> TypeSection<'a> {
debug_assert!(self.bytes[i] == Signature::SEPARATOR);
i += 1;
let n_params = parse_u32_or_panic(&self.bytes, &mut i);
let n_params = u32::parse((), &self.bytes, &mut i).unwrap();
i += n_params as usize; // skip over one byte per param type
let n_return_values = self.bytes[i];
@ -421,7 +421,7 @@ impl<'a> FunctionSection<'a> {
let mut signatures = Vec::with_capacity_in(count, arena);
let mut cursor = 0;
for _ in 0..count {
signatures.push(parse_u32_or_panic(&self.bytes, &mut cursor));
signatures.push(u32::parse((), &self.bytes, &mut cursor).unwrap());
}
signatures
}
@ -579,9 +579,9 @@ impl Limits {
let variant_id = bytes[*cursor];
*cursor += 1;
let min = parse_u32_or_panic(bytes, cursor);
let min = u32::parse((), bytes, cursor).unwrap();
if variant_id == LimitsId::MinMax as u8 {
let max = parse_u32_or_panic(bytes, cursor);
let max = u32::parse((), bytes, cursor).unwrap();
Limits::MinMax(min, max)
} else {
Limits::Min(min)
@ -663,7 +663,7 @@ impl ConstExpr {
}
*cursor += 1;
let value = parse_u32_or_panic(bytes, cursor);
let value = u32::parse((), bytes, cursor).unwrap();
if bytes[*cursor] != OpCode::END as u8 {
return err;
@ -791,12 +791,12 @@ pub struct Export<'a> {
impl<'a> Export<'a> {
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Self {
let name = parse_string_bytes(arena, bytes, cursor);
let name = <&'a [u8]>::parse(arena, bytes, cursor).unwrap();
let ty = ExportType::from(bytes[*cursor]);
*cursor += 1;
let index = parse_u32_or_panic(bytes, cursor);
let index = u32::parse((), bytes, cursor).unwrap();
Export { name, ty, index }
}
@ -895,14 +895,14 @@ impl<'a> ElementSegment<'a> {
let const_expr_opcode = bytes[*cursor];
debug_assert!(const_expr_opcode == OpCode::I32CONST as u8);
*cursor += 1;
let offset = parse_u32_or_panic(bytes, cursor);
let offset = u32::parse((), bytes, cursor).unwrap();
debug_assert!(bytes[*cursor] == OpCode::END as u8);
*cursor += 1;
let num_elems = parse_u32_or_panic(bytes, cursor);
let num_elems = u32::parse((), bytes, cursor).unwrap();
let mut fn_indices = Vec::with_capacity_in(num_elems as usize, arena);
for _ in 0..num_elems {
let fn_idx = parse_u32_or_panic(bytes, cursor);
let fn_idx = u32::parse((), bytes, cursor).unwrap();
fn_indices.push(fn_idx);
}
@ -1219,7 +1219,7 @@ impl<'a> OpaqueSection<'a> {
} else {
let section_start = *cursor;
*cursor += 1;
let section_size = parse_u32_or_panic(module_bytes, cursor);
let section_size = u32::parse((), module_bytes, cursor).unwrap();
let next_section_start = *cursor + section_size as usize;
bytes = &module_bytes[section_start..next_section_start];
*cursor = next_section_start;
@ -1293,7 +1293,7 @@ impl<'a> NameSection<'a> {
*cursor += 1;
// Section size
let section_size = parse_u32_or_panic(module_bytes, cursor) as usize;
let section_size = u32::parse((), module_bytes, cursor).unwrap() as usize;
let section_end = *cursor + section_size;
let mut section = NameSection {
@ -1312,7 +1312,7 @@ impl<'a> NameSection<'a> {
cursor: &mut usize,
section_end: usize,
) {
let section_name = parse_string_bytes(arena, module_bytes, cursor);
let section_name = <&'a [u8]>::parse(arena, module_bytes, cursor).unwrap();
if section_name != Self::NAME.as_bytes() {
internal_error!(
"Expected Custom section {:?}, found {:?}",
@ -1326,7 +1326,7 @@ impl<'a> NameSection<'a> {
for _possible_subsection_id in 0..2 {
let subsection_id = module_bytes[*cursor];
*cursor += 1;
let subsection_size = parse_u32_or_panic(module_bytes, cursor);
let subsection_size = u32::parse((), module_bytes, cursor).unwrap();
if subsection_id == NameSubSections::FunctionNames as u8 {
found_function_names = true;
break;
@ -1341,12 +1341,11 @@ impl<'a> NameSection<'a> {
}
// Function names
let num_entries = parse_u32_or_panic(module_bytes, cursor) as usize;
let num_entries = u32::parse((), module_bytes, cursor).unwrap() as usize;
let fn_names_start = *cursor;
for _ in 0..num_entries {
let fn_index = parse_u32_or_panic(module_bytes, cursor);
let name_bytes = parse_string_bytes(arena, module_bytes, cursor);
let fn_index = u32::parse((), module_bytes, cursor).unwrap();
let name_bytes = <&'a [u8]>::parse(arena, module_bytes, cursor).unwrap();
self.functions
.insert(arena.alloc_slice_copy(name_bytes), fn_index);
}