mod application;
mod database_capability;
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
mod http1;
mod process;
mod profusegw_http;
mod profusegw_response;
mod programming;
mod startup_candidate;
mod testing_harness;
pub use application::ProductionLauncher;
pub use application::SaddleConfig;
pub use application::{
ApprovedBundleNonceReservation, ApprovedExternalBundle,
ApprovedExternalBundleApplicabilityFailure, ApprovedExternalBundleSeal,
ApprovedExternalBundleVerification, ListenerAuthorityProvider, ListenerAuthoritySeal,
VerifiedListenerAuthority,
};
#[doc(hidden)]
pub use application::{
GeneratedApplicationBindingError, GeneratedApplicationConsumer, GeneratedApplicationOwner,
GeneratedApplicationParts, GeneratedApplicationSeal, GeneratedBoundApplicationParts,
GeneratedProductionBootstrap,
};
#[doc(hidden)]
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
pub mod internal {
pub use crate::http1::bootstrap::{
ApprovedGeneratedHttp1Facts, GeneratedApplicationBootstrap, GeneratedBootstrapError,
GeneratedBootstrapToken, GeneratedCompiledAdapter, GeneratedContextFactory,
GeneratedHttp1StaticFacts, GeneratedRoute, generated_bootstrap_type_identity,
generated_http1_framing_identity,
};
}
pub use process::{BusinessConfig, ProcessConfig};
pub use saddle_core::{ErrorKind, Result, SaddleError};
#[doc(hidden)]
pub use prost::{DecodeError, Message, alloc, bytes, encoding};
#[doc(hidden)]
pub mod __private {
pub use crate::database_capability::DatabaseRequest;
pub use crate::database_capability::TransactionSession;
pub use crate::database_capability::{GeneratedNamedQuery, GeneratedNamedWrite};
pub use crate::process::{
coordinate_profusegw_process, process_bootstrap_error, process_contract_error,
process_dispatch_error,
};
pub use crate::profusegw_http::encode_profusegw_http1;
pub use crate::profusegw_response::assert_unique_code_registries;
pub use crate::programming::{
ProfuseContractDeployment, ProfuseGwDispatchError, decode_accepted_profusegw,
ingress_matches_contract,
};
pub use crate::testing_harness::{accept_test_request, dispatch_error, execution};
pub use prost;
pub use prost::Message;
pub use saddle_boundary::ingress::{AcceptedIngress, ProfuseGwListenerAdapter};
pub use saddle_core::{BootstrapRendezvousIssuer, GeneratedApplicationFreezeSource};
pub use saddle_db::internal::{
QueryOptionalOperationProof, StaticQueryOptionalOperation, StaticWriteOperation,
WriteOperationProof,
};
pub use saddle_macros::contract_dir;
pub use saddle_macros::database_operations;
pub use serde;
pub use serde::Serializer;
pub use serde::{Deserialize, Serialize};
pub use serde_json;
}
#[macro_export]
macro_rules! database_operations {
($($declarations:tt)*) => {
$crate::__private::database_operations! { $crate; $($declarations)* }
};
}
pub mod database {
pub use saddle_db::internal::{
DbBool, DbI64, DbPair, DbU64, FixedDbBytes, GuardedQueryRow, ManagedOptionalRow,
ManagedQueryParameters, ManagedQueryRow, ManagedWriteResult, QueryOptionalExecutionError,
WriteExecutionError,
};
pub use saddle_db::internal::{
ScopeDatabaseError as DatabaseFailure, ScopeTransactionAbort as TransactionAbort,
ScopeTransactionFuture as TransactionFuture, ScopeTransactionOutcome as TransactionOutcome,
};
}
#[macro_export]
macro_rules! business_types {
($($item:item)*) => {
#[allow(unused_extern_crates)]
extern crate saddle as prost;
#[doc(hidden)]
mod serde {
pub use $crate::__private::serde::*;
}
#[allow(unused_imports)]
use $crate::__private::{Deserialize, Message, Serialize};
$($item)*
};
}
pub mod ingress {
pub use crate::profusegw_response::{
FailureMessage, FailureMessageError, MAX_FAILURE_MESSAGE_BYTES, ProfuseGwCode,
ProfuseGwFailure, ProfuseGwResponse,
};
pub use crate::programming::{
LdcInfo, MAX_PROFUSE_GW_USER_ID_BYTES, ProfuseGwContext, ProfuseGwDispatchError, TraceInfo,
};
}
pub mod testing {
pub use crate::programming::{
FakeExecutionCertainty, FakeProfuseContractBoundary, FakeStep, FakeTechnicalCode,
};
pub use crate::testing_harness::{
PROFUSEGW_MEDIA_TYPE, PROFUSEGW_METHOD, PROFUSEGW_PATH, ProfuseGwTestAttempt,
ProfuseGwTestError, ProfuseGwTestExecution, ProfuseGwTestHarness, ProfuseGwTestRequest,
TestIngressIdentity,
};
}
pub mod profusecontract {
#[doc(hidden)]
pub use crate::programming::ApplicationContractSeal;
pub use crate::programming::{
DeclaredExternalFunctionCall, ExecutionCertainty, ExternalFunctionResult, TechnicalFailure,
TechnicalFailureCode,
};
pub mod testing {
pub use crate::programming::{
FakeApplicationBinding, FakeAttempt, FakeExecutionCertainty,
FakeProfuseContractBoundary, FakeStep, FakeTechnicalCode,
};
}
}
pub mod managed {
pub use saddle_db::internal::ManagedWriteResult as WriteResult;
pub use saddle_service::internal::{
ManagedBool as Bool, ManagedPair as Pair, ManagedU64 as U64,
};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Optional<T>(Option<T>);
impl<T> Optional<T> {
#[doc(hidden)]
pub const fn from_generated(value: Option<T>) -> Self {
Self(value)
}
pub fn into_option(self) -> Option<T> {
self.0
}
pub const fn as_ref(&self) -> Option<&T> {
self.0.as_ref()
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_business_config_type {
() => {
()
};
($business_config:ty) => {
$business_config
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_route_capability {
($capability:expr, $route:ty) => {
$capability
};
($capability:expr, $route:ty, $kind:ident) => {
$capability.__for_route::<$route>()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_route_capability_type {
($route:ty) => {
()
};
($route:ty, $kind:ident) => {
$route
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_register_database_operation {
($config:expr) => {
$config
};
($config:expr, query_optional, $operation:ty, $capability:ty) => {
$config.__register_database_query::<$operation, $capability>()
};
($config:expr, write, $operation:ty, $capability:ty) => {
$config.__register_database_write::<$operation, $capability>()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_register_route_database {
($config:expr, transaction, {$($kind:ident $method:ident ($op:ty);)+}, $cap:ty) => {{
let config = $config;
$(let config = $crate::__saddle_register_scoped_operation!(config, $kind, $op, $cap);)+
config
}};
($config:expr, query_optional, ($op:ty), $cap:ty) => {{
const { assert!(!<$op as $crate::__private::GeneratedNamedQuery>::REQUIRES_TRANSACTION, "locking read requires transaction scope"); }
$crate::__saddle_register_database_operation!($config, query_optional, $op, $cap)
}};
($config:expr, write, ($op:ty), $cap:ty) => {
$crate::__saddle_register_database_operation!($config, write, $op, $cap)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_register_scoped_operation {
($config:expr, query_optional, $op:ty, $cap:ty) => {
$config.__register_scoped_query::<$op, $cap>()
};
($config:expr, write, $op:ty, $cap:ty) => {
$config.__register_scoped_write::<$op, $cap>()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_transaction_step {
($route:ty, query_optional, $method:ident, $op:ty) => {
impl DatabaseTransaction<'_, '_, '_, $route> {
pub async fn $method(
&mut self,
parameters: <$op as $crate::__private::GeneratedNamedQuery>::NamedParameters,
) -> Result<
Option<<$op as $crate::__private::GeneratedNamedQuery>::NamedRow>,
$crate::database::DatabaseFailure,
> {
let proof = $crate::__private::QueryOptionalOperationProof::<$op>::bind()
.map_err(|_| $crate::database::DatabaseFailure::Mapping)?;
let row = self
.__session
.query_optional(proof.invocation(
<$op as $crate::__private::GeneratedNamedQuery>::parameters(parameters),
))
.await?;
Ok(<$op as $crate::__private::GeneratedNamedQuery>::row(row))
}
}
};
($route:ty, write, $method:ident, $op:ty) => {
impl DatabaseTransaction<'_, '_, '_, $route> {
pub async fn $method(
&mut self,
parameters: <$op as $crate::__private::GeneratedNamedWrite>::NamedParameters,
) -> Result<$crate::database::ManagedWriteResult, $crate::database::DatabaseFailure>
{
let proof = $crate::__private::WriteOperationProof::<$op>::bind()
.map_err(|_| $crate::database::DatabaseFailure::Mapping)?;
self.__session
.write(proof.invocation(
<$op as $crate::__private::GeneratedNamedWrite>::parameters(parameters),
))
.await
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_route_database_method {
($cap:ident, $route:ty, transaction, $method:ident, {$($kind:ident $step:ident ($op:ty);)+}) => {
$($crate::__saddle_transaction_step!($route, $kind, $step, $op);)+
impl $cap<$route> {
pub async fn $method<T: Send + 'static, E: Send + 'static, B>(&mut self, body: B)
-> $crate::database::TransactionOutcome<T, E>
where B: for<'tx, 's, 'r, 'v> FnOnce(&'tx mut DatabaseTransaction<'v, 's, 'r, $route>)
-> $crate::database::TransactionFuture<'tx, T, E> + Send + 'static {
self.__database.as_mut().expect("generated transaction route carries database")
.scoped_transaction(move |session| Box::pin(async move {
let mut view = DatabaseTransaction { __session: session, __route: ::core::marker::PhantomData };
body(&mut view).await
})).await
}
}
};
($cap:ident, $route:ty, query_optional, $method:ident, ($op:ty)) => {
$crate::__saddle_database_method!($cap, $route, query_optional, $method, $op);
};
($cap:ident, $route:ty, write, $method:ident, ($op:ty)) => {
$crate::__saddle_database_method!($cap, $route, write, $method, $op);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __saddle_database_method {
($capability:ident, $route:ty, query_optional, $method:ident, $operation:ty) => {
impl $capability<$route> {
pub async fn $method(
self,
parameters: <$operation as $crate::__private::StaticQueryOptionalOperation>::Parameters,
) -> (::core::result::Result<
$crate::database::ManagedOptionalRow<<$operation as $crate::__private::StaticQueryOptionalOperation>::Row>,
$crate::database::QueryOptionalExecutionError,
>, $capability) {
let result = self.__database.expect("generated DB route carries its request capability")
.query_optional::<$operation>(parameters).await;
(result, $capability {
__seal: self.__seal,
__database: None,
__route: ::core::marker::PhantomData,
})
}
}
};
($capability:ident, $route:ty, write, $method:ident, $operation:ty) => {
impl $capability<$route> {
pub async fn $method(
self,
parameters: <$operation as $crate::__private::StaticWriteOperation>::Parameters,
) -> (::core::result::Result<$crate::database::ManagedWriteResult, $crate::database::WriteExecutionError>, $capability) {
let result = self.__database.expect("generated DB route carries its request capability")
.write::<$operation>(parameters).await;
(result, $capability {
__seal: self.__seal,
__database: None,
__route: ::core::marker::PhantomData,
})
}
}
};
}
#[macro_export]
macro_rules! application {
(
schema "saddle-application/1";
application $application:ident;
$($declaration:tt)*
) => {
pub struct $application;
};
(
schema "saddle-application/2";
application $application:ident;
deployment_app $deployment_app:literal;
business_config $business_config:ty;
profusecontract {
contract_dir $contract_dir:literal;
capability $capability:ident;
response_code $result_code:ty;
functions {
$(
$function:ident => $method:ident {
business_unit $business_unit:literal;
function $function_name:literal;
} (
$function_request:ty
) -> $function_result:ty;
)+
}
}
$(
service $service:ident {
ingress profusegw;
operation_type $operation_type:literal;
request $request:ty;
response $response:ty;
handler $handler:path;
$(uses $uses:ident;)+
$(database $db_kind:ident $db_method:ident $db_spec:tt $(;)? )?
}
)+
) => {
const __SADDLE_ONLY_APPLICATION: () = ();
$crate::__private::contract_dir!(
$contract_dir;
declarations {
$(($function, $business_unit, $function_name, $function_request, $function_result);)+
}
uses {
$($($uses;)+)+
}
);
pub struct $application;
trait __SaddleDeclaredExternalFunction {}
pub struct DatabaseTransaction<'tx, 'session, 'request, R> {
__session: &'tx mut $crate::__private::TransactionSession<'session, 'request>,
__route: ::core::marker::PhantomData<fn() -> R>,
}
$(
pub struct $function;
impl __SaddleDeclaredExternalFunction for $function {}
)+
pub struct $capability<__Route = ()> {
__seal: $crate::profusecontract::ApplicationContractSeal,
__database: ::core::option::Option<$crate::__private::DatabaseRequest>,
__route: ::core::marker::PhantomData<fn() -> __Route>,
}
impl<__Route> $capability<__Route> {
#[doc(hidden)]
pub fn __from_framework(
seal: $crate::profusecontract::ApplicationContractSeal,
) -> Self {
Self { __seal: seal, __database: None, __route: ::core::marker::PhantomData }
}
#[doc(hidden)]
pub fn __from_framework_database(
seal: $crate::profusecontract::ApplicationContractSeal,
database: $crate::__private::DatabaseRequest,
) -> Self {
Self { __seal: seal, __database: Some(database), __route: ::core::marker::PhantomData }
}
fn __for_route<__Next>(self) -> $capability<__Next> {
$capability {
__seal: self.__seal,
__database: self.__database,
__route: ::core::marker::PhantomData,
}
}
$(
pub fn $method(
&self,
request: $function_request,
) -> $crate::profusecontract::DeclaredExternalFunctionCall<
$application,
$function,
$function_request,
$function_result,
> {
$crate::profusecontract::DeclaredExternalFunctionCall::from_declared(
request,
&self.__seal,
$business_unit,
$function_name,
)
.with_database_request(self.__database.as_ref())
}
)+
}
impl $application {
pub const PROFUSECONTRACT_DIR: &'static str = $contract_dir;
#[doc(hidden)]
pub const __PROFUSECONTRACT_DESCRIPTOR: &'static [u8] =
__SADDLE_CONTRACT_DESCRIPTOR;
pub fn run() -> $crate::Result<()> {
let (application_half, listener_issuer) =
$crate::__private::BootstrapRendezvousIssuer::issue()
.freeze_application(
$crate::__private::GeneratedApplicationFreezeSource::new(
$deployment_app,
Self::__PROFUSECONTRACT_DESCRIPTOR,
&[
$(concat!(
$operation_type,
"|",
stringify!($request),
"|",
stringify!($response),
"|",
stringify!($handler)
),)+
],
),
)
.map_err(|_| $crate::__private::process_bootstrap_error())?;
let config = $crate::ProcessConfig::<$business_config>::from_args()?;
$(
$(let config = $crate::__saddle_register_route_database!(config, $db_kind, $db_spec, $capability);)?
)+
$crate::__private::coordinate_profusegw_process(
config,
Self::__profusegw_listener_adapter(),
application_half,
listener_issuer,
|authority_template| async move {
Ok($crate::__private::ProfuseContractDeployment::routed(
authority_template,
))
},
|accepted, deployment, _business, database| async move {
let capability = Self::__bind_profusecontract(&deployment, &accepted, database);
Self::__dispatch_accepted_profusegw(
accepted,
capability,
_business,
)
.await
.map_err(|_| $crate::__private::process_dispatch_error())?
.__encode_profusegw_http1()
.map_err(|_| $crate::__private::process_dispatch_error())
},
)
}
pub fn dispatch_profusegw_operation(
operation_type: &str,
) -> Option<ProfuseGwDispatch> {
match operation_type {
$(
$operation_type => Some(ProfuseGwDispatch::$service),
)+
_ => None,
}
}
#[doc(hidden)]
pub fn __profusegw_listener_adapter(
) -> $crate::__private::ProfuseGwListenerAdapter {
$crate::__private::ProfuseGwListenerAdapter::new($deployment_app)
.expect("generated deployment application identity is valid")
}
#[doc(hidden)]
pub fn __bind_profusecontract(
deployment: &$crate::__private::ProfuseContractDeployment,
accepted: &$crate::__private::AcceptedIngress,
database: $crate::__private::DatabaseRequest,
) -> $capability {
$capability::__from_framework_database(deployment.bind_accepted(accepted), database)
}
pub fn profusegw_test_harness(
fake: $crate::testing::FakeProfuseContractBoundary,
business: $crate::BusinessConfig<$business_config>,
) -> $crate::testing::ProfuseGwTestHarness<ProfuseGwResponse> {
$crate::testing::ProfuseGwTestHarness::from_executor(move |request| {
::std::boxed::Box::pin(async move {
let observed = fake.clone();
let accepted = $crate::__private::accept_test_request(
&Self::__profusegw_listener_adapter(),
request,
)?;
let binding = fake
.bind_accepted(&accepted)
.map_err($crate::__private::dispatch_error)?;
let response = Self::__dispatch_accepted_profusegw(
accepted,
$capability::__from_framework(binding.into_contract_seal()),
business.clone(),
)
.await
.map_err($crate::__private::dispatch_error)?;
Ok($crate::__private::execution(response, &observed))
})
})
}
#[doc(hidden)]
pub async fn __dispatch_accepted_profusegw(
accepted: $crate::__private::AcceptedIngress,
contract: $capability,
business: $crate::BusinessConfig<$business_config>,
) -> ::core::result::Result<ProfuseGwResponse, $crate::__private::ProfuseGwDispatchError> {
if !$crate::__private::ingress_matches_contract(&accepted, &contract.__seal) {
return Err($crate::__private::ProfuseGwDispatchError::IdentityMismatch);
}
match accepted.interface_id.as_str() {
$(
$operation_type => {
let (request, context) =
$crate::__private::decode_accepted_profusegw::<$request>(accepted)?;
let contract = $crate::__saddle_route_capability!(
contract,
$service
$(, $db_kind)?
);
Ok(ProfuseGwResponse::$service(
$handler(request, context, contract, business.clone()).await,
))
}
)+
_ => Err($crate::__private::ProfuseGwDispatchError::InterfaceNotFound),
}
}
}
pub enum ProfuseGwResponse {
$($service($crate::ingress::ProfuseGwResponse<$response, $result_code>)),+
}
impl $crate::__private::Serialize for ProfuseGwResponse {
fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
where
S: $crate::__private::Serializer,
{
match self {
$(Self::$service(response) => $crate::__private::Serialize::serialize(response, serializer)),+
}
}
}
impl ProfuseGwResponse {
#[doc(hidden)]
pub fn __encode_profusegw_http1(
&self,
) -> ::core::result::Result<
::std::vec::Vec<u8>,
$crate::__private::serde_json::Error,
> {
match self {
$(Self::$service(response) => $crate::__private::encode_profusegw_http1(response)),+
}
}
}
const _: () = $crate::__private::assert_unique_code_registries(&[
<$result_code as $crate::ingress::ProfuseGwCode>::REGISTERED_CODES,
]);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ProfuseGwDispatch {
$($service),+
}
$(
pub struct $service;
$($crate::__saddle_route_database_method!($capability, $service, $db_kind, $db_method, $db_spec);)?
impl $service {
pub const OPERATION_TYPE: &'static str = $operation_type;
}
const _: fn() = || {
fn handler_shape<F, Fut>(_: F)
where
F: Fn(
$request,
$crate::ingress::ProfuseGwContext,
$capability<$crate::__saddle_route_capability_type!($service $(, $db_kind)?)>,
$crate::BusinessConfig<$business_config>,
) -> Fut,
Fut: ::core::future::Future<
Output = $crate::ingress::ProfuseGwResponse<$response, $result_code>,
>,
{}
handler_shape($handler);
fn declared_use<F>()
where
F: __SaddleDeclaredExternalFunction,
{}
$(declared_use::<$uses>();)+
};
)+
};
($($invalid:tt)*) => {
compile_error!("skill.schema.unsupported");
};
}