makepad_hub/
wasmstrip.rs

1 
2use std::{mem};
3
4#[derive(Clone, Debug)]
5struct Reader<'a> {
6    bytes: &'a [u8],
7    offset: usize
8}
9
10#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
11pub struct WasmParseError;
12
13impl<'a> Reader<'a> {
14    fn new(bytes: &'a [u8]) -> Reader<'a> {
15        Reader { bytes, offset:0 }
16    }
17
18    fn skip(&mut self, count: usize) -> Result<(),WasmParseError> {
19        if count > self.bytes.len() {
20            return Err(WasmParseError);
21        }
22        self.offset += count;
23        self.bytes = &self.bytes[count..];
24        Ok(())
25    }
26
27    fn read(&mut self, bytes: &mut [u8]) -> Result<(),WasmParseError> {
28        if bytes.len() > self.bytes.len() {
29            return Err(WasmParseError);
30        }
31        bytes.copy_from_slice(&self.bytes[..bytes.len()]);
32        self.bytes = &self.bytes[bytes.len()..];
33        self.offset += bytes.len();
34        Ok(())
35    }
36    
37    fn read_u8(&mut self) -> Result<u8,WasmParseError> {
38        let mut bytes = [0; mem::size_of::<u8>()];
39        self.read(&mut bytes)?;
40        Ok(u8::from_le_bytes(bytes))
41    }
42
43    fn read_u32(&mut self) -> Result<u32,WasmParseError> {
44        let mut bytes = [0; mem::size_of::<u32>()];
45        self.read(&mut bytes)?;
46        Ok(u32::from_le_bytes(bytes))
47    }
48    
49    fn read_var_u32(&mut self) -> Result<u32,WasmParseError>{
50        let byte = self.read_u8()? as  u32;
51        if byte&0x80 == 0{
52            return Ok(byte)
53        }
54        
55        let mut result = byte & 0x7F;
56        let mut shift = 7;
57        loop {
58            let byte = self.read_u8()?;
59            result |= ((byte & 0x7F) as u32) << shift;
60            if shift >= 25 && (byte >> (32 - shift)) != 0 {
61                // The continuation bit or unused bits are set.
62                return Err(WasmParseError);
63            }
64            shift += 7;
65            if (byte & 0x80) == 0 {
66                break;
67            }
68        }
69        Ok(result)
70    }
71
72}
73
74struct WasmSection{
75    pub type_id: u8,
76    pub start: usize,
77    pub end: usize,
78    pub name: String
79}
80
81fn read_wasm_sections(buf:&[u8])->Result<Vec<WasmSection>,WasmParseError>{
82    let mut sections = Vec::new();
83    let mut reader = Reader::new(&buf);
84    if reader.read_u32()? != 0x6d736100{
85        println!("Not a wasm file!");
86        return Err(WasmParseError);
87    }
88    if reader.read_u32()? != 0x1{
89        println!("Wrong version");
90        return Err(WasmParseError);
91    }
92    loop{
93        let offset = reader.offset;
94        if let Ok(type_id) = reader.read_u8(){
95            let payload_len = reader.read_var_u32()? as usize;
96            let start = reader.offset;
97            if type_id == 0{
98                let name_len = reader.read_var_u32()? as usize;
99                if let Ok(name) = std::str::from_utf8(&reader.bytes[0..name_len]){
100                    sections.push(WasmSection{
101                        start: offset,
102                        type_id: type_id,
103                        end: offset + payload_len + (start-offset),
104                        name: name.to_string()
105                    })
106                }
107                else{
108                    return Err(WasmParseError);
109                }
110                let end = reader.offset;
111                reader.skip(payload_len - (end-start))?;
112            }
113            else{
114                sections.push(WasmSection{
115                    start: offset,
116                    type_id: type_id,
117                    end: offset + payload_len + (start-offset),
118                    name: "".to_string()
119                });
120                reader.skip(payload_len)?;
121            }
122        } 
123        else{
124            break;
125        }
126    }
127    return Ok(sections);
128}
129
130pub fn wasm_strip_debug(buf: &[u8])->Result<Vec<u8>,WasmParseError>{
131    let mut strip = Vec::new();
132    strip.extend_from_slice(&[0, 97, 115, 109, 1, 0, 0, 0]);
133    let sections = read_wasm_sections(&buf)?;
134    // lets rewrite it
135    for section in &sections{
136        if section.type_id != 0{// !section.name.starts_with(".debug"){
137            strip.extend_from_slice(&buf[section.start..section.end]);
138        }
139        
140    }
141    Ok(strip)
142}