Change schemes for encoding custom type names

Store JSON a utf-32, map hashes of names to a `char` and store that name
in the map, and then do a reverse mapping when generating JS
This commit is contained in:
Alex Crichton
2018-02-06 16:06:21 -08:00
parent 8312f3ae9f
commit 43ee52bcbf
8 changed files with 124 additions and 57 deletions

View File

@ -1,4 +1,5 @@
use std::collections::HashSet;
use std::char;
use std::collections::{HashSet, HashMap};
use shared;
use parity_wasm::elements::*;
@ -14,6 +15,7 @@ pub struct Context<'a> {
pub config: &'a Bindgen,
pub module: &'a mut Module,
pub imports_to_rewrite: HashSet<String>,
pub custom_type_names: HashMap<char, String>,
}
pub struct SubContext<'a, 'b: 'a> {
@ -22,6 +24,18 @@ pub struct SubContext<'a, 'b: 'a> {
}
impl<'a> Context<'a> {
pub fn add_custom_type_names(&mut self, program: &shared::Program) {
for custom in program.custom_type_names.iter() {
assert!(self.custom_type_names.insert(custom.descriptor,
custom.name.clone()).is_none());
let val = custom.descriptor as u32;
assert!(val & 1 == 0);
let descriptor = char::from_u32(val | 1).unwrap();
assert!(self.custom_type_names.insert(descriptor,
custom.name.clone()).is_none());
}
}
pub fn finalize(&mut self, module_name: &str) -> (String, String) {
{
let mut bind = |name: &str, f: &Fn(&mut Self) -> String| {
@ -756,9 +770,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
pass(&format!("idx{}", i));
}
custom if (custom as u32) & shared::TYPE_CUSTOM_REF_FLAG != 0 => {
let custom = ((custom as u32) & !shared::TYPE_CUSTOM_REF_FLAG) -
shared::TYPE_CUSTOM_START;
let s = &self.program.custom_type_names[custom as usize / 2];
let s = self.cx.custom_type_names[&custom].clone();
dst_ts.push_str(&format!(": {}", s));
if self.cx.config.debug {
self.cx.expose_assert_class();
@ -769,8 +781,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
pass(&format!("{}.ptr", name));
}
custom => {
let custom = (custom as u32) - shared::TYPE_CUSTOM_START;
let s = &self.program.custom_type_names[custom as usize / 2];
let s = self.cx.custom_type_names[&custom].clone();
dst_ts.push_str(&format!(": {}", s));
if self.cx.config.debug {
self.cx.expose_assert_class();
@ -823,9 +834,8 @@ impl<'a, 'b> SubContext<'a, 'b> {
Some(&shared::TYPE_JS_REF) |
Some(&shared::TYPE_BORROWED_STR) => panic!(),
Some(&t) if (t as u32) & shared::TYPE_CUSTOM_REF_FLAG != 0 => panic!(),
Some(&custom) => {
let custom = (custom as u32) - shared::TYPE_CUSTOM_START;
let name = &self.program.custom_type_names[custom as usize / 2];
Some(custom) => {
let name = &self.cx.custom_type_names[custom];
dst_ts.push_str(": ");
dst_ts.push_str(name);
if self.cx.config.debug {

View File

@ -5,9 +5,11 @@ extern crate wasm_bindgen_shared as shared;
extern crate serde_json;
extern crate wasm_gc;
use std::char;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::slice;
use failure::Error;
use parity_wasm::elements::*;
@ -75,9 +77,13 @@ impl Bindgen {
exposed_globals: Default::default(),
required_internal_exports: Default::default(),
imports_to_rewrite: Default::default(),
custom_type_names: Default::default(),
config: &self,
module: &mut module,
};
for program in programs.iter() {
cx.add_custom_type_names(program);
}
for program in programs.iter() {
js::SubContext {
program,
@ -126,14 +132,34 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
None => return ret,
};
'outer:
for i in (0..data.entries().len()).rev() {
{
let value = data.entries()[i].value();
if !value.starts_with(b"wbg:") {
continue
let mut value = bytes_to_u32(data.entries()[i].value());
loop {
match value.iter().position(|i| i.0 == (b'w' as u32)) {
Some(i) => value = &value[i + 1..],
None => continue 'outer,
}
match value.iter().position(|i| i.0 == (b'b' as u32)) {
Some(i) => value = &value[i + 1..],
None => continue 'outer,
}
match value.iter().position(|i| i.0 == (b'g' as u32)) {
Some(i) => value = &value[i + 1..],
None => continue 'outer,
}
match value.iter().position(|i| i.0 == (b':' as u32)) {
Some(i) => value = &value[i + 1..],
None => continue 'outer,
}
break
}
let json = &value[4..];
let p = match serde_json::from_slice(json) {
// TODO: shouldn't take the rest of the value
let json = value.iter()
.map(|i| char::from_u32(i.0).unwrap())
.collect::<String>();
let p = match serde_json::from_str(&json) {
Ok(f) => f,
Err(e) => {
panic!("failed to decode what looked like wasm-bindgen data: {}", e)
@ -145,3 +171,12 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
}
return ret
}
#[repr(packed)]
struct Unaligned(u32);
fn bytes_to_u32(a: &[u8]) -> &[Unaligned] {
unsafe {
slice::from_raw_parts(a.as_ptr() as *const Unaligned, a.len() / 4)
}
}