makepad_wasm_bridge/
to_wasm.rs1use makepad_live_id::*;
2use crate::from_wasm::*;
3
4pub struct WasmJSOutputFn{
5 pub name: String,
6 pub body: String,
7 pub temp: usize
8}
9
10pub struct WasmJSOutput{
11 pub temp_alloc: usize,
12 pub fns: Vec<WasmJSOutputFn>,
13}
14
15impl WasmJSOutput{
16 pub fn alloc_temp(&mut self)->usize{
17 self.temp_alloc += 1;
18 self.temp_alloc
19 }
20
21 pub fn check_slot(&mut self, slot:usize, is_recur:bool, prop:&str, temp:usize, name:&str)->Option<usize>{
22 if is_recur{ self.push_ln(slot, &format!("{}({});", name, prop));
25 if self.fns.iter().any(|p| p.name == name){
27 return None
28 }
29 self.fns.push(WasmJSOutputFn{name: name.to_string(), body:String::new(), temp});
30 Some(self.fns.len() - 1)
31 }
32 else{
33 self.push_ln(slot, &format!("let t{} = {};", temp, prop));
34 Some(slot)
35 }
36 }
37
38 pub fn push_ln(&mut self, slot:usize, s:&str){
39 self.fns[slot].body.push_str(s);
40 self.fns[slot].body.push('\n');
41 }
42}
43
44pub trait ToWasm {
45 fn u32_size() -> usize;
46
47 fn type_name()->&'static str{panic!()}
48 fn live_id()->LiveId{panic!()}
49
50 fn read_to_wasm(inp: &mut ToWasmMsgRef) -> Self;
51
52 fn to_wasm_js_body(out: &mut WasmJSOutput, slot:usize, is_recur: bool, prop:&str, temp:usize);
53
54 fn to_js_code()->String{
55 let mut wrapper = String::new();
56 let id = Self::live_id();
57 wrapper.push_str(&format!("{}(t0){{\n", Self::type_name()));
58 wrapper.push_str("let app = this.app;\n");
59 wrapper.push_str(&format!("this.reserve_u32({});\n", 4 + Self::u32_size()));
60 wrapper.push_str(&format!("app.u32[this.u32_offset ++] = {};\n", id.0 & 0xffff_ffff));
61 wrapper.push_str(&format!("app.u32[this.u32_offset ++] = {};\n", (id.0 >> 32)));
62 wrapper.push_str("let block_len_offset = this.u32_offset ++;\n\n");
63
64 let mut out = WasmJSOutput{temp_alloc:0, fns:vec![WasmJSOutputFn{name:String::new(), body:String::new(), temp:0}]};
65
66 let new_temp = out.alloc_temp();
67 Self::to_wasm_js_body(&mut out, 0, false, "t0", new_temp);
68
69 for p in out.fns.iter().rev(){
70 if p.name.is_empty(){
71 wrapper.push_str(&p.body);
72 }
73 else{
74 wrapper.push_str(&format!("let {} = (t{})=>{{\n{}}}\n", p.name, p.temp, p.body))
75 }
76 }
77
78 wrapper.push_str("if( (this.u32_offset & 1) != 0){ app.u32[this.u32_offset ++] = 0;}\n");
79 wrapper.push_str("let new_len = (this.u32_offset - this.u32_ptr) >> 1;\n");
80 wrapper.push_str("app.u32[block_len_offset] = new_len - app.u32[this.u32_ptr + 1];\n");
81 wrapper.push_str("app.u32[this.u32_ptr + 1] = new_len;\n");
82 wrapper.push_str("}\n");
83 wrapper
84 }
85}
86
87#[derive(Clone, Default, Debug)]
88pub struct ToWasmMsg {
89 data: Vec<u64>,
90}
91
92pub struct ToWasmBlockSkip{
93 len:usize,
94 base:usize
95}
96
97#[derive(Clone, Default, Debug)]
98pub struct ToWasmMsgRef<'a> {
99 data: &'a[u64],
100 pub u32_offset: usize
101}
102
103impl ToWasmMsg {
104
105 pub fn take_ownership(val: u32) -> Self {
106 unsafe {
107 let ptr = val as *mut u64;
108 let head = ptr.offset(0).read();
109 let len = (head >> 32) as usize;
110 let cap = (head & 0xffff_ffff) as usize;
111
112 Self {
113 data: Vec::from_raw_parts(ptr, len, cap),
114 }
116 }
117 }
118
119 pub fn into_from_wasm(self) -> FromWasmMsg {
120 FromWasmMsg {
121 data: self.data,
122 odd: false
123 }
124 }
125
126 pub fn as_ref(&self) ->ToWasmMsgRef{
127 ToWasmMsgRef{
128 data: &self.data,
129 u32_offset: 2
130 }
131 }
132
133 pub fn as_ref_at(&self, offset:usize) ->ToWasmMsgRef{
134 ToWasmMsgRef{
135 data: &self.data,
136 u32_offset: offset
137 }
138 }
139}
140
141impl<'a> ToWasmMsgRef<'a> {
142
143 pub fn read_u32(&mut self) -> u32 {
144 let ret = if self.u32_offset & 1 != 0 {
145 (self.data[self.u32_offset >> 1] >> 32) as u32
146 }
147 else {
148 (self.data[self.u32_offset >> 1] & 0xffff_ffff) as u32
149 };
150 self.u32_offset += 1;
151 ret
152 }
153
154 pub fn read_block_skip(&mut self)->ToWasmBlockSkip{
155 ToWasmBlockSkip{
156 base: self.u32_offset >> 1,
157 len: self.read_u32() as usize,
158 }
159 }
160
161 pub fn block_skip(&mut self, block_skip:ToWasmBlockSkip){
162 self.u32_offset = (block_skip.base + block_skip.len - 1)<<1
163 }
164
165 pub fn read_f32(&mut self) -> f32 {
166 f32::from_bits(self.read_u32())
167 }
168
169 pub fn read_u64(&mut self) -> u64 {
170 self.u32_offset += self.u32_offset & 1;
171 let ret = self.data[self.u32_offset >> 1];
172 self.u32_offset += 2;
173 ret
174 }
175
176 pub fn read_f64(&mut self) -> f64 {
177 f64::from_bits(self.read_u64())
178 }
179
180 pub fn read_string(&mut self) -> String {
181 let chars = self.read_u32();
182 let mut out = String::new();
183 for _ in 0..chars {
184 out.push(char::from_u32(self.read_u32()).unwrap_or('?'));
185 }
186 out
187 }
188
189 pub fn was_last_block(&mut self)->bool{
190 self.u32_offset += self.u32_offset & 1;
191 self.u32_offset>>1 >= self.data.len()
192 }
193}