vibe-ready 0.2.0

Composable runtime, logging, scheduling, and storage foundations for vibe-coding Rust projects.
Documentation
use crate::api::engine_error::{VibeEngineError, VibeEngineErrorCode};
use crate::log::log_def::DESC;
use crate::{err, log_e};
use serde::{Deserialize, Serialize};
use std::backtrace::Backtrace;
use std::fmt;

#[repr(i32)]
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize, Eq, Default)]
/// Connection lifecycle state used by status integrations.
pub enum VibeConnectionStatus {
    /// No connection attempt is active.
    #[default]
    Idle,

    /// A connection attempt is in progress.
    Connecting,

    /// The connection is established.
    Connected,

    /// Disconnect is in progress.
    Disconnecting,

    /// The connection has been closed.
    Disconnected,
}

impl fmt::Display for VibeConnectionStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            VibeConnectionStatus::Idle => "Idle",
            VibeConnectionStatus::Connecting => "Connecting",
            VibeConnectionStatus::Connected => "Connected",
            VibeConnectionStatus::Disconnecting => "Disconnecting",
            VibeConnectionStatus::Disconnected => "Disconnected",
        };
        write!(f, "{}", s)
    }
}

fn trans_unreachable(
    from: VibeConnectionStatus,
    to: VibeConnectionStatus,
) -> Result<VibeConnectionStatus, VibeEngineError> {
    log_e!(
        "trans_unreachable",
        DESC,
        format!(
            "trans_unreachable_test error , from: {:?},to: {:?}, -- {:?}",
            from,
            to,
            Backtrace::capture()
        )
    );
    Err(err!(VibeEngineError::from_internal_error()))
}

impl VibeConnectionStatus {
    /// Applies a validated transition to `new_status`.
    ///
    /// # Returns
    ///
    /// `Ok(new_status)` when the transition is allowed, or [`VibeEngineError`]
    /// when the transition is invalid for the current state.
    ///
    /// # Examples
    ///
    /// ```
    /// use vibe_ready::{VibeConnectionStatus, VibeResult};
    ///
    /// # fn demo() -> VibeResult<()> {
    /// let mut status = VibeConnectionStatus::Idle;
    /// assert_eq!(status.trans(VibeConnectionStatus::Connecting)?, VibeConnectionStatus::Connecting);
    /// # Ok(())
    /// # }
    /// ```
    pub fn trans(
        &mut self,
        new_status: VibeConnectionStatus,
    ) -> Result<VibeConnectionStatus, VibeEngineError> {
        let ret = match self {
            VibeConnectionStatus::Idle => match new_status {
                VibeConnectionStatus::Idle => Ok(VibeConnectionStatus::Idle),
                VibeConnectionStatus::Connecting => Ok(VibeConnectionStatus::Connecting),
                VibeConnectionStatus::Connected => trans_unreachable(self.clone(), new_status),
                VibeConnectionStatus::Disconnecting => Err(err!(VibeEngineError::from_error_code(
                    VibeEngineErrorCode::ConnectionClosed
                ))),
                VibeConnectionStatus::Disconnected => Ok(VibeConnectionStatus::Disconnected),
            },
            VibeConnectionStatus::Connecting => match new_status {
                VibeConnectionStatus::Idle => Ok(VibeConnectionStatus::Idle),
                VibeConnectionStatus::Connecting => trans_unreachable(self.clone(), new_status),
                VibeConnectionStatus::Connected => Ok(VibeConnectionStatus::Connected),
                VibeConnectionStatus::Disconnecting => Ok(VibeConnectionStatus::Disconnecting),
                VibeConnectionStatus::Disconnected => Ok(VibeConnectionStatus::Disconnected),
            },
            VibeConnectionStatus::Connected => match new_status {
                VibeConnectionStatus::Idle => Ok(VibeConnectionStatus::Idle),
                VibeConnectionStatus::Connecting => Err(VibeEngineError::from_error_code(
                    VibeEngineErrorCode::ConnectionExists,
                )),
                VibeConnectionStatus::Connected => trans_unreachable(self.clone(), new_status),
                VibeConnectionStatus::Disconnecting => Ok(VibeConnectionStatus::Disconnecting),
                VibeConnectionStatus::Disconnected => Ok(VibeConnectionStatus::Disconnected),
            },
            VibeConnectionStatus::Disconnecting => match new_status {
                VibeConnectionStatus::Idle => Ok(VibeConnectionStatus::Idle),
                VibeConnectionStatus::Connecting => Ok(VibeConnectionStatus::Connecting),
                VibeConnectionStatus::Connected => trans_unreachable(self.clone(), new_status),
                VibeConnectionStatus::Disconnecting => Err(err!(VibeEngineError::from_error_code(
                    VibeEngineErrorCode::ConnectionClosing
                ))),
                VibeConnectionStatus::Disconnected => Ok(VibeConnectionStatus::Disconnected),
            },
            VibeConnectionStatus::Disconnected => match new_status {
                VibeConnectionStatus::Idle => Ok(VibeConnectionStatus::Idle),
                VibeConnectionStatus::Connecting => Ok(VibeConnectionStatus::Connecting),
                VibeConnectionStatus::Connected => trans_unreachable(self.clone(), new_status),
                VibeConnectionStatus::Disconnecting => Err(err!(VibeEngineError::from_error_code(
                    VibeEngineErrorCode::ConnectionClosed,
                ))),
                VibeConnectionStatus::Disconnected => Ok(VibeConnectionStatus::Disconnected),
            },
        };
        *self = ret?;
        Ok(*self)
    }
}

#[cfg(test)]
mod strict_tests {
    use super::*;
    include!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/test/unit/api/connection_status_tests.rs"
    ));
}