inkpad_runtime/
util.rs

1//! Memory generator
2use crate::{Error, Result};
3use inkpad_std::Vec;
4use inkpad_support::convert::step_hex;
5use parity_wasm::elements::{External, Module};
6
7const IMPORT_MODULE_MEMORY: &str = "env";
8
9/// Parse `Vec<u8>` to `Vec<RuntimeValue>`
10pub fn parse_args(selector: &str, args: Vec<Vec<u8>>, tys: Vec<u32>) -> Result<Vec<u8>> {
11    if args.len() != tys.len() {
12        return Err(Error::InvalidArgumentLength {
13            expect: tys.len(),
14            input: args.len(),
15        });
16    }
17
18    let mut res = step_hex(selector)
19        .ok_or(Error::DecodeSelectorFailed)?
20        .to_vec();
21    for mut arg in args {
22        log::debug!("-----> {:?}", arg);
23        res.append(&mut arg);
24    }
25
26    Ok(res)
27}
28
29/// Scan an import section if any.
30///
31/// This accomplishes two tasks:
32///
33/// - checks any imported function against defined host functions set, incl.
34///   their signatures.
35/// - if there is a memory import, returns it's descriptor
36/// `import_fn_banlist`: list of function names that are disallowed to be imported
37pub fn scan_imports(module: &Module) -> core::result::Result<(u32, Option<u32>), &'static str> {
38    let import_entries = module
39        .import_section()
40        .map(|is| is.entries())
41        .unwrap_or(&[]);
42
43    let mut range = None;
44    for import in import_entries {
45        match import.external() {
46            External::Table(_) => return Err("Cannot import tables"),
47            External::Global(_) => return Err("Cannot import globals"),
48            External::Function(ref type_idx) => type_idx,
49            External::Memory(ref memory_type) => {
50                if import.module() != IMPORT_MODULE_MEMORY {
51                    return Err("Invalid module for imported memory");
52                }
53                if import.field() != "memory" {
54                    return Err("Memory import must have the field name 'memory'");
55                }
56                if range.is_some() {
57                    return Err("Multiple memory imports defined");
58                }
59
60                let limits = memory_type.limits();
61                range = Some((limits.initial() as u32, limits.maximum().map(|v| v as u32)));
62                continue;
63            }
64        };
65    }
66
67    if let Some(limit) = range {
68        Ok(limit)
69    } else {
70        Ok((0, None))
71    }
72}