use std::fmt;
use std::vec::Vec;
use schemars::JsonSchema;
use serde::{de::DeserializeOwned, Serialize};
use crate::deps::OwnedDeps;
use crate::imports::{ExternalApi, ExternalQuerier, ExternalStorage};
use crate::memory::{alloc, consume_region, release_buffer, Region};
use crate::results::{ContractResult, QueryResponse, Reply, Response};
use crate::serde::{from_slice, to_vec};
use crate::types::Env;
use crate::{Deps, DepsMut, MessageInfo};
#[cfg(feature = "staking")]
#[no_mangle]
extern "C" fn requires_staking() -> () {}
#[cfg(feature = "stargate")]
#[no_mangle]
extern "C" fn requires_stargate() -> () {}
#[no_mangle]
extern "C" fn interface_version_5() -> () {}
#[no_mangle]
extern "C" fn allocate(size: usize) -> u32 {
alloc(size) as u32
}
#[no_mangle]
extern "C" fn deallocate(pointer: u32) {
let _ = unsafe { consume_region(pointer as *mut Region) };
}
macro_rules! r#try_into_contract_result {
($expr:expr) => {
match $expr {
Ok(val) => val,
Err(err) => {
return ContractResult::Err(err.to_string());
}
}
};
($expr:expr,) => {
$crate::try_into_contract_result!($expr)
};
}
pub fn do_init<M, C, E>(
init_fn: &dyn Fn(DepsMut, Env, MessageInfo, M) -> Result<Response<C>, E>,
env_ptr: u32,
info_ptr: u32,
msg_ptr: u32,
) -> u32
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let res = _do_init(
init_fn,
env_ptr as *mut Region,
info_ptr as *mut Region,
msg_ptr as *mut Region,
);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
pub fn do_execute<M, C, E>(
execute_fn: &dyn Fn(DepsMut, Env, MessageInfo, M) -> Result<Response<C>, E>,
env_ptr: u32,
info_ptr: u32,
msg_ptr: u32,
) -> u32
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let res = _do_execute(
execute_fn,
env_ptr as *mut Region,
info_ptr as *mut Region,
msg_ptr as *mut Region,
);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
pub fn do_migrate<M, C, E>(
migrate_fn: &dyn Fn(DepsMut, Env, M) -> Result<Response<C>, E>,
env_ptr: u32,
msg_ptr: u32,
) -> u32
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let res = _do_migrate(migrate_fn, env_ptr as *mut Region, msg_ptr as *mut Region);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
pub fn do_sudo<M, C, E>(
sudo_fn: &dyn Fn(DepsMut, Env, M) -> Result<Response<C>, E>,
env_ptr: u32,
msg_ptr: u32,
) -> u32
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let res = _do_sudo(sudo_fn, env_ptr as *mut Region, msg_ptr as *mut Region);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
pub fn do_reply<C, E>(
reply_fn: &dyn Fn(DepsMut, Env, Reply) -> Result<Response<C>, E>,
env_ptr: u32,
msg_ptr: u32,
) -> u32
where
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let res = _do_reply(reply_fn, env_ptr as *mut Region, msg_ptr as *mut Region);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
pub fn do_query<M, E>(
query_fn: &dyn Fn(Deps, Env, M) -> Result<QueryResponse, E>,
env_ptr: u32,
msg_ptr: u32,
) -> u32
where
M: DeserializeOwned + JsonSchema,
E: ToString,
{
let res = _do_query(query_fn, env_ptr as *mut Region, msg_ptr as *mut Region);
let v = to_vec(&res).unwrap();
release_buffer(v) as u32
}
fn _do_init<M, C, E>(
init_fn: &dyn Fn(DepsMut, Env, MessageInfo, M) -> Result<Response<C>, E>,
env_ptr: *mut Region,
info_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<Response<C>>
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let info: Vec<u8> = unsafe { consume_region(info_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let info: MessageInfo = try_into_contract_result!(from_slice(&info));
let msg: M = try_into_contract_result!(from_slice(&msg));
let mut deps = make_dependencies();
init_fn(deps.as_mut(), env, info, msg).into()
}
fn _do_execute<M, C, E>(
execute_fn: &dyn Fn(DepsMut, Env, MessageInfo, M) -> Result<Response<C>, E>,
env_ptr: *mut Region,
info_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<Response<C>>
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let info: Vec<u8> = unsafe { consume_region(info_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let info: MessageInfo = try_into_contract_result!(from_slice(&info));
let msg: M = try_into_contract_result!(from_slice(&msg));
let mut deps = make_dependencies();
execute_fn(deps.as_mut(), env, info, msg).into()
}
fn _do_migrate<M, C, E>(
migrate_fn: &dyn Fn(DepsMut, Env, M) -> Result<Response<C>, E>,
env_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<Response<C>>
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let msg: M = try_into_contract_result!(from_slice(&msg));
let mut deps = make_dependencies();
migrate_fn(deps.as_mut(), env, msg).into()
}
fn _do_sudo<M, C, E>(
sudo_fn: &dyn Fn(DepsMut, Env, M) -> Result<Response<C>, E>,
env_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<Response<C>>
where
M: DeserializeOwned + JsonSchema,
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let msg: M = try_into_contract_result!(from_slice(&msg));
let mut deps = make_dependencies();
sudo_fn(deps.as_mut(), env, msg).into()
}
fn _do_reply<C, E>(
reply_fn: &dyn Fn(DepsMut, Env, Reply) -> Result<Response<C>, E>,
env_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<Response<C>>
where
C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let msg: Reply = try_into_contract_result!(from_slice(&msg));
let mut deps = make_dependencies();
reply_fn(deps.as_mut(), env, msg).into()
}
fn _do_query<M, E>(
query_fn: &dyn Fn(Deps, Env, M) -> Result<QueryResponse, E>,
env_ptr: *mut Region,
msg_ptr: *mut Region,
) -> ContractResult<QueryResponse>
where
M: DeserializeOwned + JsonSchema,
E: ToString,
{
let env: Vec<u8> = unsafe { consume_region(env_ptr) };
let msg: Vec<u8> = unsafe { consume_region(msg_ptr) };
let env: Env = try_into_contract_result!(from_slice(&env));
let msg: M = try_into_contract_result!(from_slice(&msg));
let deps = make_dependencies();
query_fn(deps.as_ref(), env, msg).into()
}
pub(crate) fn make_dependencies() -> OwnedDeps<ExternalStorage, ExternalApi, ExternalQuerier> {
OwnedDeps {
storage: ExternalStorage::new(),
api: ExternalApi::new(),
querier: ExternalQuerier::new(),
}
}