#![allow(dead_code)]
#![allow(unexpected_cfgs)]
use prost::Message;
use saddle::ingress::{ProfuseGwCode, ProfuseGwContext, ProfuseGwResponse as Response};
use saddle::{BusinessConfig, application};
use serde::{Deserialize, Serialize};
use std::cell::Cell;
#[path = "cf_transaction/lifecycle.rs"]
mod lifecycle;
#[derive(Clone, PartialEq, Message, Deserialize)]
struct Input {}
#[derive(Clone, PartialEq, Message, Serialize)]
struct Output {
#[prost(uint64, tag = "1")]
value: u64,
}
enum Code {
Failure,
}
impl ProfuseGwCode for Code {
const REGISTERED_CODES: &'static [&'static str] = &["FAILURE"];
fn stable_code(&self) -> &'static str {
"FAILURE"
}
}
saddle::database_operations! {
relational;
pub mod ops {
namespace "cf.account";
schema { account { id:u64, value:u64 } }
query Read { parameters ReadParams { id:u64 } from account as a;
where a.id==bind(id);result optional Row {value:a.value} }
update Write {parameters WriteParams {id:u64,value:u64} table account;
values {value:bind(value)} where account.id==bind(id);}
}
}
application! {
schema "saddle-application/2";
application App;
deployment_app "cf-app";
business_config ();
profusecontract { contract_dir "examples/contracts"; capability Cap; response_code Code; functions {} }
database_modules { Accounts {optional read(ops::Read);write store(ops::Write);} }
service ViaModule { ingress profusegw; operation_type "cf.module"; request Input; response Output;
handler module_handler; database module db(Accounts); }
service ViaRoute { ingress profusegw; operation_type "cf.route"; request Input; response Output;
handler route_handler; database transaction transfer { optional read(ops::Read);write store(ops::Write); } }
}
saddle::transaction_logic! {
fn module_logic(tx: Accounts; start:u64, state:Cell<u64>) -> (u64,()) {
for id in start..start+2 {
let step=tx.read(ops::ReadParams {id});
let row=step.await.map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
if let Some(row)=row {state.set(row.value);}
tokio::task::yield_now().await;
tx.store(ops::WriteParams{id,value:state.get()+1}).await
.map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
}
Ok(state.get())
}
}
saddle::transaction_logic! {
fn route_logic(tx: ViaRoute; state:Cell<u64>) -> (u64,()) {
let row=tx.read(ops::ReadParams{id:1}).await
.map_err(|e| saddle::database::TransactionAbort::Technical(e.into_failure()))?;
tokio::task::yield_now().await;
if let Some(row)=row {state.set(row.value);}
Ok(state.get())
}
}
fn accepts_actual_d<
B: saddle::transaction_construction::ReservedTransactionBody<
saddle::transaction_construction::Cancel,
>,
>(
_: B,
) {
}
async fn module_handler(
_: Input,
_: ProfuseGwContext,
mut cap: Cap<ViaModule>,
_: BusinessConfig<()>,
) -> Response<Output, Code> {
let db = cap.db();
accepts_actual_d(db.prepare_transaction(module_logic(1, Cell::new(0))));
Response::success(Output { value: 0 })
}
async fn route_handler(
_: Input,
_: ProfuseGwContext,
cap: Cap<ViaRoute>,
_: BusinessConfig<()>,
) -> Response<Output, Code> {
accepts_actual_d(cap.prepare_transaction(route_logic(Cell::new(0))));
Response::success(Output { value: 0 })
}
fn main() {
if std::env::var_os("SADDLE_CF_LIVE").is_some() {
lifecycle::run();
return;
}
let module = module_logic(1, Cell::new(0));
let route = route_logic(Cell::new(0));
let small = small_layout([0; 8]);
let large = large_layout([0; 4096]);
assert!(
__saddle_cf::body_layout::<Accounts, _>(&large).size()
> __saddle_cf::body_layout::<Accounts, _>(&small).size() + 4000
);
println!("CF_LAYOUT_VARIATION_PASS before_execute no_session");
println!(
"CF actual D body module={:?} route={:?}",
__saddle_cf::body_layout::<Accounts, _>(&module),
__saddle_cf::body_layout::<ViaRoute, _>(&route)
);
println!(
"CF generated route/module concrete D body compiles; execution/permit/cancellation NOT_RUN"
);
}
saddle::transaction_logic! {
fn small_layout(_tx:Accounts; bytes:[u8;8])->(u64,()) {
tokio::task::yield_now().await;
Ok(std::hint::black_box(bytes)[0] as u64)
}
}
saddle::transaction_logic! {
fn large_layout(_tx:Accounts; bytes:[u8;4096])->(u64,()) {
tokio::task::yield_now().await;
Ok(std::hint::black_box(bytes)[0] as u64)
}
}
#[cfg(cf_non_send)]
saddle::transaction_logic! {
fn forbidden_send(_tx:Accounts; value:std::rc::Rc<u64>)->(u64,()) {
tokio::task::yield_now().await; Ok(*value)
}
}
#[cfg(cf_undeclared)]
saddle::transaction_logic! {
fn forbidden_operation(tx:Accounts;)->(u64,()) {
tx.not_declared().await; Ok(0)
}
}
#[cfg(cf_escape)]
saddle::transaction_logic! {
fn forbidden_escape(tx:Accounts;)->(&'static str,()) {
tokio::spawn(async move {tx.read(ops::ReadParams{id:1}).await}); Ok("no")
}
}