use crate::error::{ZomeApiError, ZomeApiResult};
use bitflags::bitflags;
use holochain_json_api::json::{default_to_json, JsonString, RawString};
use holochain_persistence_api::{cas::content::Address, hash::HashString};
use lazy_static::lazy_static;
use holochain_core_types::{
dna::capabilities::CapabilityRequest,
error::{RibosomeEncodedAllocation, RibosomeEncodingBits, ZomeApiInternalResult},
};
pub use holochain_wasm_utils::api_serialization::validation::*;
use holochain_wasm_utils::{
api_serialization::ZomeApiGlobals,
memory::{ribosome::load_ribosome_encoded_json, stack::WasmStack},
};
use crate::init_globals::init_globals;
use std::convert::{TryFrom, TryInto};
mod bundle;
mod call;
mod capability;
mod commit_entry;
mod debug;
mod decrypt;
mod emit_signal;
mod encrypt;
mod entry_address;
mod entry_type_properties;
mod get_entry;
mod get_links;
mod keystore;
mod link_entries;
mod property;
mod query;
mod remove_link;
mod send;
mod sign;
mod sleep;
mod update_remove;
mod version;
pub use self::{
bundle::{close_bundle, start_bundle},
call::call,
capability::{commit_capability_claim, commit_capability_grant},
commit_entry::{commit_entry, commit_entry_result},
debug::debug,
decrypt::decrypt,
emit_signal::emit_signal,
encrypt::encrypt,
entry_address::entry_address,
entry_type_properties::entry_type_properties,
get_entry::{get_entry, get_entry_history, get_entry_initial, get_entry_result},
get_links::{
get_links, get_links_and_load, get_links_count, get_links_count_with_options,
get_links_result, get_links_with_options,
},
keystore::{
keystore_derive_key, keystore_derive_seed, keystore_get_public_key, keystore_list,
keystore_new_random, keystore_sign,
},
link_entries::link_entries,
property::property,
query::{query, query_result},
remove_link::remove_link,
send::send,
sign::{sign, sign_one_time, verify_signature},
sleep::sleep,
update_remove::{remove_entry, update_agent, update_entry},
version::version,
};
macro_rules! def_api_fns {
(
$(
$function_name:ident, $enum_variant:ident ;
)*
) => {
pub enum Dispatch {
$( $enum_variant ),*
}
impl Dispatch {
pub fn without_input<O: TryFrom<JsonString> + Into<JsonString>>(
&self,
) -> ZomeApiResult<O> {
self.with_input(JsonString::empty_object())
}
pub fn with_input<I: TryInto<JsonString>, O: TryFrom<JsonString>>(
&self,
input: I,
) -> ZomeApiResult<O> {
let mut mem_stack = unsafe { G_MEM_STACK }
.ok_or_else(|| ZomeApiError::Internal("debug failed to load mem_stack".to_string()))?;
let wasm_allocation = mem_stack.write_json(input)?;
let encoded_input: RibosomeEncodingBits =
RibosomeEncodedAllocation::from(wasm_allocation).into();
let encoded_output: RibosomeEncodingBits = unsafe {
(match self {
$(Dispatch::$enum_variant => $function_name),*
})(encoded_input)
};
let result: ZomeApiInternalResult =
load_ribosome_encoded_json(encoded_output).or_else(|e| {
mem_stack.deallocate(wasm_allocation)?;
Err(ZomeApiError::from(e))
})?;
mem_stack.deallocate(wasm_allocation)?;
if result.ok {
JsonString::from_json(&result.value)
.try_into()
.map_err(|_| ZomeApiError::from(format!("Failed to deserialize return value: {}", result.value)))
} else {
Err(ZomeApiError::from(result.error))
}
}
}
#[allow(dead_code)]
extern "C" {
pub(crate) fn hc_property(_: RibosomeEncodingBits) -> RibosomeEncodingBits;
pub(crate) fn hc_start_bundle(_: RibosomeEncodingBits) -> RibosomeEncodingBits;
pub(crate) fn hc_close_bundle(_: RibosomeEncodingBits) -> RibosomeEncodingBits;
$( pub(crate) fn $function_name (_: RibosomeEncodingBits) -> RibosomeEncodingBits;) *
}
#[cfg(test)]
mod tests {
use crate::holochain_core_types::error::{RibosomeEncodedValue, RibosomeEncodingBits};
$( #[no_mangle]
pub fn $function_name(_: RibosomeEncodingBits) -> RibosomeEncodingBits {
RibosomeEncodedValue::Success.into()
}) *
}
};
}
def_api_fns! {
hc_init_globals, InitGlobals;
hc_commit_entry, CommitEntry;
hc_get_entry, GetEntry;
hc_entry_address, EntryAddress;
hc_query, Query;
hc_update_entry, UpdateEntry;
hc_remove_entry, RemoveEntry;
hc_send, Send;
hc_debug, Debug;
hc_call, Call;
hc_crypto,Crypto;
hc_sign_one_time, SignOneTime;
hc_verify_signature, VerifySignature;
hc_link_entries, LinkEntries;
hc_remove_link, RemoveLink;
hc_get_links, GetLinks;
hc_get_links_count,GetLinksCount;
hc_sleep, Sleep;
hc_meta,Meta;
hc_keystore_list, KeystoreList;
hc_keystore_new_random, KeystoreNewRandom;
hc_keystore_derive_seed, KeystoreDeriveSeed;
hc_keystore_derive_key, KeystoreDeriveKey;
hc_keystore_sign, KeystoreSign;
hc_keystore_get_public_key, KeystoreGetPublicKey;
hc_commit_capability_grant, CommitCapabilityGrant;
hc_commit_capability_claim, CommitCapabilityClaim;
hc_emit_signal, EmitSignal;
}
pub static mut G_MEM_STACK: Option<WasmStack> = None;
lazy_static! {
pub(crate) static ref GLOBALS: ZomeApiGlobals = init_globals().unwrap();
pub static ref DNA_NAME: &'static str = &GLOBALS.dna_name;
pub static ref DNA_ADDRESS: &'static Address = &GLOBALS.dna_address;
pub static ref AGENT_ID_STR: &'static str = &GLOBALS.agent_id_str;
pub static ref AGENT_ADDRESS: &'static Address = &GLOBALS.agent_address;
pub static ref AGENT_INITIAL_HASH: &'static HashString = &GLOBALS.agent_initial_hash;
#[doc(hidden)]
pub static ref AGENT_LATEST_HASH: &'static HashString = &GLOBALS.agent_latest_hash;
pub static ref PUBLIC_TOKEN: &'static Address = &GLOBALS.public_token;
pub static ref CAPABILITY_REQ: &'static Option<CapabilityRequest> = &GLOBALS.cap_request;
pub static ref PROPERTIES: &'static JsonString = &GLOBALS.properties;
}
impl From<DNA_NAME> for JsonString {
fn from(dna_name: DNA_NAME) -> JsonString {
JsonString::from(RawString::from(dna_name.to_string()))
}
}
impl From<DNA_ADDRESS> for JsonString {
fn from(dna_address: DNA_ADDRESS) -> JsonString {
JsonString::from(HashString::from(dna_address.to_string()))
}
}
impl From<AGENT_ID_STR> for JsonString {
fn from(agent_id: AGENT_ID_STR) -> JsonString {
JsonString::from(RawString::from(agent_id.to_string()))
}
}
impl From<AGENT_ADDRESS> for JsonString {
fn from(agent_address: AGENT_ADDRESS) -> JsonString {
JsonString::from(Address::from(agent_address.to_string()))
}
}
impl From<AGENT_INITIAL_HASH> for JsonString {
fn from(agent_initial_hash: AGENT_INITIAL_HASH) -> JsonString {
JsonString::from(HashString::from(agent_initial_hash.to_string()))
}
}
impl From<AGENT_LATEST_HASH> for JsonString {
fn from(agent_latest_hash: AGENT_LATEST_HASH) -> JsonString {
JsonString::from(HashString::from(agent_latest_hash.to_string()))
}
}
impl From<PUBLIC_TOKEN> for JsonString {
fn from(public_token: PUBLIC_TOKEN) -> JsonString {
JsonString::from(Address::from(public_token.to_string()))
}
}
impl From<CAPABILITY_REQ> for JsonString {
fn from(cap_request: CAPABILITY_REQ) -> JsonString {
default_to_json(*cap_request)
}
}
bitflags! {
pub struct GetEntryMask: u8 {
const ENTRY = 1;
const ENTRY_TYPE = 1 << 1;
const SOURCES = 1 << 2;
}
}
impl Default for GetEntryMask {
fn default() -> GetEntryMask {
GetEntryMask::ENTRY
}
}
pub enum BundleOnClose {
Commit,
Discard,
}