//! CPU-bound fixture used to verify fuel and epoch deadline interruption.
//!
//! The input's first eight bytes select a little-endian iteration count.
//! Initializing with `spin` intentionally runs without a finite loop bound.
//! This crate is a Runtime test fixture, not an application service.

mod bindings {
    // Compile the base service WIT contract into guest and export adapters.
    wit_bindgen::generate!({
        path: "wit",
        world: "spin-component",
    });
}

static mut SPIN_STATE: u64 = 0;

struct Spin;

impl bindings::Guest for Spin {
    fn init(config: Vec<u8>) -> Result<(), bindings::ServiceError> {
        if config == b"spin" {
            burn(u64::MAX);
        }

        Ok(())
    }

    fn invoke(input: Vec<u8>) -> Result<Vec<u8>, bindings::ServiceError> {
        let steps = input
            .get(..size_of::<u64>())
            .and_then(|bytes| bytes.try_into().ok())
            .map(u64::from_le_bytes)
            .unwrap_or_default();

        burn(steps);
        Ok(Vec::new())
    }
}

// The volatile write makes every loop iteration observable to the optimizer.
fn burn(steps: u64) {
    let mut state = unsafe { core::ptr::read_volatile(&raw const SPIN_STATE) };

    for _ in 0..steps {
        state = state.rotate_left(7).wrapping_add(0x9e37_79b9_7f4a_7c15);
        unsafe { core::ptr::write_volatile(&raw mut SPIN_STATE, state) };
    }
}

bindings::export!(Spin with_types_in bindings);
