// Copyright 2020 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

// Provide host with details about funcs and views in this smart contract

use crate::context::*;
use crate::host::*;

// Note that we do not use the Wasm export symbol table on purpose
// because Wasm does not allow us to determine whether the symbols
// are meant as view or func, or meant as extra public callbacks
// generated by the compilation of the the Wasm code.
// There are only 2 symbols the ISC host will actually look for
// in the export table:
// on_load (which must be defined by the SC code) and
// on_call (which is defined here as part of WasmLib)

pub struct ScExportMap {
    pub names: &'static [&'static str],
    pub funcs: &'static [fn(&ScFuncContext)],
    pub views: &'static [fn(&ScViewContext)],
}

// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\

// context for on_load function to be able to tell host which
// funcs and views are available as entry points to the SC
pub struct ScExports {}

impl ScExports {
    // constructs the symbol export context for the on_load function
    pub fn export(export_map: &ScExportMap) {
        export_name(-1, "WASM::RUST");

        for i in 0..export_map.funcs.len() {
            export_name(i as i32, export_map.names[i]);
        }

        let offset = export_map.funcs.len();
        for i in 0..export_map.views.len() {
            export_name(i as i32 | 0x8000, export_map.names[offset + i]);
        }
    }

    // general entrypoint for the host to call any SC function
    // the host will pass the index of one of the entry points
    // that was provided by on_load during SC initialization
    pub fn call(index: i32, export_map: &ScExportMap) {
        if (index & 0x8000) == 0 {
            // mutable full function, invoke with a func context
            let func = export_map.funcs[index as usize];
            func(&ScFuncContext {});
            return;
        }
        // immutable view function, invoke with a view context
        let view = export_map.views[(index & 0x7fff) as usize];
        view(&ScViewContext {});
    }
}
