saddle-framework 0.3.24

The single business-facing facade for Saddle applications
//! Negative input evidence for S: the current PUBLIC callback return erases
//! the concrete allocation before the generated transaction wrapper sees it.
//! This is not a replacement executor or a production fit assertion.
use saddle::database::TransactionFuture;
use std::{
    alloc::Layout,
    future::Future,
    sync::atomic::{AtomicUsize, Ordering},
};

static CALLS: AtomicUsize = AtomicUsize::new(0);

fn body<const N: usize>()
-> impl Future<Output = Result<(), saddle::database::TransactionAbort<()>>> + Send {
    async move {
        let bytes = [7_u8; N];
        std::future::pending::<()>().await;
        std::hint::black_box(bytes);
        Ok(())
    }
}

fn callback<const N: usize>() -> TransactionFuture<'static, (), ()> {
    CALLS.fetch_add(1, Ordering::SeqCst);
    Box::pin(body::<N>())
}

fn output_layout<F, T>(_: F) -> Layout
where
    F: FnOnce() -> T,
{
    Layout::new::<T>()
}

fn main() {
    // Type witnesses only: no callback invocation or Box allocation.
    let small_body = output_layout(body::<8>);
    let large_body = output_layout(body::<8192>);
    let small_return = output_layout(callback::<8>);
    let large_return = output_layout(callback::<8192>);
    assert!(large_body.size() >= small_body.size() + 8184);
    assert_eq!(small_return, large_return);
    assert_eq!(CALLS.load(Ordering::SeqCst), 0);
    println!(
        "concrete_small={} concrete_large={} erased_small={} erased_large={} callback_calls=0",
        small_body.size(),
        large_body.size(),
        small_return.size(),
        large_return.size()
    );
}