#![doc(html_logo_url = "https://avatars2.githubusercontent.com/u/52050279?s=200&v=4")]
pub type Result<T> = ::std::result::Result<T, crate::errors::Error>;
pub type ReceiveResult = ::std::result::Result<Vec<u8>, Box<dyn std::error::Error>>;
extern crate log;
pub extern crate wapc_guest as wapc;
use crate::kv::DefaultKeyValueStore;
use crate::logger::AutomaticLogger;
use crate::msg::DefaultMessageBroker;
use crate::objectstore::DefaultObjectStore;
use crate::raw::DefaultRawCapability;
use events::DefaultEventStreams;
use extras::DefaultExtras;
use std::collections::HashMap;
use wapc_guest::console_log;
use wascc_codec::blobstore::{Blob, BlobList, Container, Transfer};
use wascc_codec::eventstreams::Event;
#[macro_export]
macro_rules! actor_handlers(
{ $($key:path => $user_handler:ident),* } => {
use $crate::wapc::prelude::*;
wapc_handler!(handle_wapc);
fn handle_wapc(operation: &str, msg: &[u8]) -> CallResult {
let ctx = $crate::CapabilitiesContext::new();
match operation {
$( $key => $user_handler(&ctx, deserialize(msg)?).map_err(|e| e.into()), )*
_ => Err("bad dispatch".into())
}
}
};
);
pub trait KeyValueStore {
fn get(&self, key: &str) -> Result<Option<String>>;
fn set(&self, key: &str, value: &str, expires: Option<u32>) -> Result<()>;
fn atomic_add(&self, key: &str, value: i32) -> Result<i32>;
fn list_add(&self, key: &str, item: &str) -> Result<usize>;
fn list_del_item(&self, key: &str, item: &str) -> Result<usize>;
fn del_key(&self, key: &str) -> Result<()>;
fn list_range(&self, key: &str, start: isize, stop_inclusive: isize) -> Result<Vec<String>>;
fn list_clear(&self, key: &str) -> Result<()>;
fn set_add(&self, key: &str, value: &str) -> Result<usize>;
fn set_remove(&self, key: &str, value: &str) -> Result<usize>;
fn set_union(&self, keys: Vec<String>) -> Result<Vec<String>>;
fn set_intersect(&self, keys: Vec<String>) -> Result<Vec<String>>;
fn set_members(&self, key: &str) -> Result<Vec<String>>;
fn exists(&self, key: &str) -> Result<bool>;
}
pub trait Extras {
fn get_random(&self, min: u32, max: u32) -> Result<u32>;
fn get_guid(&self) -> Result<String>;
fn get_sequence_number(&self) -> Result<u64>;
}
pub trait EventStreams {
fn write_event(&self, stream: &str, values: HashMap<String, String>) -> Result<String>;
fn read_all(&self, stream: &str) -> Result<Vec<Event>>;
}
pub trait MessageBroker {
fn publish(&self, subject: &str, reply_to: Option<&str>, payload: &[u8]) -> Result<()>;
fn request(&self, subject: &str, payload: &[u8], timeout_ms: u64) -> Result<Vec<u8>>;
}
pub trait ObjectStore {
fn create_container(&self, name: &str) -> Result<Container>;
fn remove_container(&self, name: &str) -> Result<()>;
fn remove_object(&self, id: &str, container: &str) -> Result<()>;
fn list_objects(&self, container: &str) -> Result<BlobList>;
fn get_blob_info(&self, container: &str, id: &str) -> Result<Option<Blob>>;
fn start_upload(&self, blob: &Blob, chunk_size: u64, total_bytes: u64) -> Result<Transfer>;
fn upload_chunk(&self, transfer: &Transfer, offset: u64, bytes: &[u8]) -> Result<()>;
fn start_download(&self, blob: &Blob, chunk_size: u64) -> Result<Transfer>;
}
pub trait Logger {
fn log(&self, level: usize, body: &str) -> Result<()>;
fn error(&self, body: &str) -> Result<()>;
fn warn(&self, body: &str) -> Result<()>;
fn info(&self, body: &str) -> Result<()>;
fn debug(&self, body: &str) -> Result<()>;
fn trace(&self, body: &str) -> Result<()>;
}
pub trait RawCapability {
fn call(&self, capid: &str, operation: &str, msg: &[u8]) -> Result<Vec<u8>>;
}
pub struct CapabilitiesContext {
kv: Box<dyn KeyValueStore>,
msg: Box<dyn MessageBroker>,
raw: Box<dyn RawCapability>,
blob: Box<dyn ObjectStore>,
extras: Box<dyn Extras>,
events: Box<dyn EventStreams>,
log: Box<dyn Logger>,
}
impl Default for CapabilitiesContext {
fn default() -> CapabilitiesContext {
CapabilitiesContext {
kv: Box::new(DefaultKeyValueStore::new()),
msg: Box::new(DefaultMessageBroker::new()),
raw: Box::new(DefaultRawCapability::new()),
blob: Box::new(DefaultObjectStore::new()),
extras: Box::new(DefaultExtras::new()),
events: Box::new(DefaultEventStreams::new()),
log: Box::new(AutomaticLogger::new()),
}
}
}
static LOGGER: AutomaticLogger = AutomaticLogger {};
impl CapabilitiesContext {
pub fn new() -> CapabilitiesContext {
match log::set_logger(&LOGGER) {
std::result::Result::Ok(_) => console_log("Set Logger: OK"),
_ => console_log("Set Logger: not ok"),
}
log::set_max_level(log::LevelFilter::Trace);
CapabilitiesContext {
kv: Box::new(DefaultKeyValueStore::new()),
msg: Box::new(DefaultMessageBroker::new()),
raw: Box::new(DefaultRawCapability::new()),
blob: Box::new(DefaultObjectStore::new()),
extras: Box::new(DefaultExtras::new()),
events: Box::new(DefaultEventStreams::new()),
log: Box::new(AutomaticLogger::new()),
}
}
pub fn custom(
kv: impl KeyValueStore + 'static,
msg: impl MessageBroker + 'static,
raw: impl RawCapability + 'static,
blob: impl ObjectStore + 'static,
extras: impl Extras + 'static,
events: impl EventStreams + 'static,
log: impl Logger + 'static,
) -> Self {
CapabilitiesContext {
kv: Box::new(kv),
msg: Box::new(msg),
raw: Box::new(raw),
blob: Box::new(blob),
extras: Box::new(extras),
events: Box::new(events),
log: Box::new(log),
}
}
pub fn kv(&self) -> &dyn KeyValueStore {
self.kv.as_ref()
}
pub fn msg(&self) -> &dyn MessageBroker {
self.msg.as_ref()
}
pub fn raw(&self) -> &dyn RawCapability {
self.raw.as_ref()
}
pub fn objectstore(&self) -> &dyn ObjectStore {
self.blob.as_ref()
}
pub fn extras(&self) -> &dyn Extras {
self.extras.as_ref()
}
pub fn events(&self) -> &dyn EventStreams {
self.events.as_ref()
}
pub fn log(&self) -> &dyn Logger {
self.log.as_ref()
}
pub fn println(&self, msg: &str) {
console_log(msg);
}
}
pub mod errors;
pub mod events;
pub mod extras;
pub mod kv;
pub mod logger;
pub mod msg;
pub mod objectstore;
pub mod prelude;
pub mod raw;