saddle-framework 0.3.0-alpha.7

The single business-facing facade for Saddle applications
//! The only Saddle crate that business applications directly depend on.
//!
//! Pool construction and Service registry assembly remain framework-owned:
//!
//! ```compile_fail
//! let _ = saddle::db::Database::connect;
//! ```
//!
//! ```compile_fail
//! let _ = saddle::service::ServiceRegistryBuilder::new();
//! ```
//!
//! The old static/three-argument launcher is not a public surface:
//!
//! ```compile_fail
//! let _ = saddle::Saddle::run;
//! ```

mod application;
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
mod http1;
mod profusegw_http;
mod profusegw_response;
mod programming;
mod startup_candidate;

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,
};
/// Framework/Skill assembly handshake. This is not a business API.
#[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 saddle_core::{ErrorKind, Result, SaddleError};

#[doc(hidden)]
pub mod __private {
    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 saddle_boundary::ProfuseContractEndpoint;
    pub use saddle_boundary::ingress::{AcceptedIngress, ProfuseGwListenerAdapter};
    pub use saddle_macros::contract_dir;
    pub use serde::{Serialize, Serializer};
    pub use serde_json;
}

/// Fixed profusegw handler context.
pub mod ingress {
    pub use crate::profusegw_response::{
        FailureMessage, FailureMessageError, MAX_FAILURE_MESSAGE_BYTES, ProfuseGwCode,
        ProfuseGwFailure, ProfuseGwResponse,
    };
    pub use crate::programming::{
        MAX_PROFUSE_GW_USER_ID_BYTES, ProfuseGwContext, ProfuseGwDispatchError,
    };
}

/// Application-facing, strongly typed profusecontract programming surface.
pub mod profusecontract {
    #[doc(hidden)]
    pub use crate::programming::ApplicationContractSeal;
    pub use crate::programming::{
        DeclaredExternalFunctionCall, ExecutionCertainty, ExternalFunctionResult, TechnicalFailure,
        TechnicalFailureCode,
    };

    /// Deterministic alpha.1 consumer harness. Production assembly does not
    /// consume this harness, and Transport's raw boundary types remain hidden.
    pub mod testing {
        pub use crate::programming::{
            FakeApplicationBinding, FakeAttempt, FakeExecutionCertainty,
            FakeProfuseContractBoundary, FakeStep, FakeTechnicalCode,
        };
    }
}

/// The complete stable set of business-owned values accepted by generated
/// Saddle 0.2 handlers.
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,
    };

    /// A fixed optional value delivered to a `query_optional` handler.
    #[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()
        }
    }
}

/// Declares the sole generated Saddle application in a business crate.
///
/// The Skill emits a private `__saddle_generated` module beside this
/// invocation. Only the generated application marker can move that module's
/// bootstrap owner into the facade.
#[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;
        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;)+
            }
        )+
    ) => {
        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 $function;
            impl __SaddleDeclaredExternalFunction for $function {}
        )+

        pub struct $capability {
            __seal: $crate::profusecontract::ApplicationContractSeal,
        }

        impl $capability {
            #[doc(hidden)]
            pub fn __from_framework(
                seal: $crate::profusecontract::ApplicationContractSeal,
            ) -> Self {
                Self { __seal: seal }
            }

            $(
                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,
                    )
                }
            )+
        }

        impl $application {
            pub const PROFUSECONTRACT_DIR: &'static str = $contract_dir;

            #[doc(hidden)]
            pub const __PROFUSECONTRACT_DESCRIPTOR: &'static [u8] =
                __SADDLE_CONTRACT_DESCRIPTOR;

            /// Resolves the MobileGW operation name against the sole static
            /// application graph. Business handlers never perform dispatch.
            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 async fn __connect_profusecontract(
                endpoint: $crate::__private::ProfuseContractEndpoint,
            ) -> ::core::result::Result<
                $crate::__private::ProfuseContractDeployment,
                $crate::profusecontract::TechnicalFailure,
            > {
                $crate::__private::ProfuseContractDeployment::connect(endpoint).await
            }

            #[doc(hidden)]
            pub fn __bind_profusecontract(
                deployment: &$crate::__private::ProfuseContractDeployment,
                accepted: &$crate::__private::AcceptedIngress,
            ) -> $capability {
                $capability::__from_framework(deployment.bind_accepted(accepted))
            }

            #[doc(hidden)]
            pub async fn __dispatch_accepted_profusegw(
                accepted: $crate::__private::AcceptedIngress,
                contract: $capability,
            ) -> ::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)?;
                            Ok(ProfuseGwResponse::$service(
                                $handler(request, context, contract).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 {
            /// The sole production HTTP adapter projection. The core response
            /// remains transport-independent and supplies only `Serialize`.
            #[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;
            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) -> 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");
    };
}