use std::sync::{Arc, Mutex};
use parity_scale_codec::{Decode, Encode};
use crate::{
errors::MessageResult,
pallet_contracts::{chain_extension::ReturnFlags, debug::ExecResult, ExecReturnValue},
pallet_contracts_debugging::InterceptingExtT,
session::mock::{MockRegistry, Selector},
};
pub(crate) struct MockingExtension<AccountId: Ord> {
pub mock_registry: Arc<Mutex<MockRegistry<AccountId>>>,
}
impl<AccountId: Ord + Decode> InterceptingExtT for MockingExtension<AccountId> {
fn intercept_call(
&self,
contract_address: Vec<u8>,
_is_call: bool,
input_data: Vec<u8>,
) -> Vec<u8> {
let contract_address = Decode::decode(&mut &contract_address[..])
.expect("Contract address should be decodable");
match self
.mock_registry
.lock()
.expect("Should be able to acquire registry")
.get(&contract_address)
{
None => None::<()>.encode(),
Some(mock) => {
let (selector, call_data) = input_data.split_at(4);
let selector: Selector = selector
.try_into()
.expect("Input data should contain at least selector bytes");
let result = mock
.call(selector, call_data.to_vec())
.expect("TODO: let the user define the fallback mechanism");
let decoded_result: MessageResult<()> =
Decode::decode(&mut &result[..]).expect("Mock result should be decodable");
let flags = match decoded_result {
Ok(_) => ReturnFlags::empty(),
Err(_) => ReturnFlags::REVERT,
};
let result: ExecResult = Ok(ExecReturnValue {
flags,
data: result,
});
Some(result).encode()
}
}
}
}