zingen/codegen/
constructor.rsuse crate::{wasm::ToLSBytes, Buffer, MacroAssembler, Result};
use smallvec::SmallVec;
use std::collections::HashMap;
pub type InitStorage = HashMap<SmallVec<[u8; 32]>, SmallVec<[u8; 32]>>;
#[derive(Default, Debug, Clone)]
pub struct Constructor {
masm: MacroAssembler,
}
impl Constructor {
pub fn storage(&mut self, mapping: InitStorage) -> Result<()> {
tracing::debug!("Building storage in constructor ...");
for (key, value) in mapping.into_iter() {
self.masm.push(&value)?;
self.masm.push(&key)?;
self.masm._sstore()?;
}
Ok(())
}
pub fn finish(&self, runtime_bytecode: Buffer) -> Result<Buffer> {
let init_code = self.masm.buffer();
let init_code_len = init_code.len();
let runtime_bytecode_len = runtime_bytecode.len();
let runtime_bytecode_size = runtime_bytecode_len.to_ls_bytes();
let runtime_bytecode_offset =
Self::runtime_bytcode_offset(init_code_len, runtime_bytecode_size.len());
tracing::trace!("length of bytecode: {:?}", runtime_bytecode_len);
tracing::trace!(
"length of bytecode in hex: {:?}",
hex::encode(&runtime_bytecode_size)
);
let mut masm = self.masm.clone();
masm.push(&runtime_bytecode_size)?; masm.push(&runtime_bytecode_offset.to_ls_bytes())?; masm._push0()?; masm._codecopy()?;
masm.push(&runtime_bytecode_size)?; masm._push0()?; masm.asm._return()?;
masm.buffer_mut().extend_from_slice(&runtime_bytecode);
Ok(masm.buffer().into())
}
fn runtime_bytcode_offset(init_code_len: usize, runtime_bytecode_size_len: usize) -> usize {
let mut offset = init_code_len + runtime_bytecode_size_len * 2 + 8;
if (offset <= 0xff) && (offset + offset.to_ls_bytes().len() > 0xff) {
offset += 1;
}
offset
}
}