zingen/codegen/
constructor.rs1use crate::{wasm::ToLSBytes, Buffer, MacroAssembler, Result};
4use smallvec::SmallVec;
5use std::collections::HashMap;
6
7pub type InitStorage = HashMap<SmallVec<[u8; 32]>, SmallVec<[u8; 32]>>;
9
10#[derive(Default, Debug, Clone)]
12pub struct Constructor {
13 masm: MacroAssembler,
15}
16
17impl Constructor {
18 pub fn storage(&mut self, mapping: InitStorage) -> Result<()> {
20 tracing::debug!("Building storage in constructor ...");
21 for (key, value) in mapping.into_iter() {
22 self.masm.push(&value)?;
23 self.masm.push(&key)?;
24 self.masm._sstore()?;
25 }
26
27 Ok(())
28 }
29
30 pub fn finish(&self, runtime_bytecode: Buffer) -> Result<Buffer> {
35 let init_code = self.masm.buffer();
36 let init_code_len = init_code.len();
37 let runtime_bytecode_len = runtime_bytecode.len();
38 let runtime_bytecode_size = runtime_bytecode_len.to_ls_bytes();
39 let runtime_bytecode_offset =
40 Self::runtime_bytcode_offset(init_code_len, runtime_bytecode_size.len());
41
42 tracing::trace!("length of bytecode: {:?}", runtime_bytecode_len);
43 tracing::trace!(
44 "length of bytecode in hex: {:?}",
45 hex::encode(&runtime_bytecode_size)
46 );
47 let mut masm = self.masm.clone();
48
49 masm.push(&runtime_bytecode_size)?; masm.push(&runtime_bytecode_offset.to_ls_bytes())?; masm._push0()?; masm._codecopy()?;
54
55 masm.push(&runtime_bytecode_size)?; masm._push0()?; masm.asm._return()?;
59 masm.buffer_mut().extend_from_slice(&runtime_bytecode);
60
61 Ok(masm.buffer().into())
62 }
63
64 fn runtime_bytcode_offset(init_code_len: usize, runtime_bytecode_size_len: usize) -> usize {
73 let mut offset = init_code_len + runtime_bytecode_size_len * 2 + 8;
74 if (offset <= 0xff) && (offset + offset.to_ls_bytes().len() > 0xff) {
75 offset += 1;
76 }
77
78 offset
79 }
80}