logline_core/
status.rs

1/// Estado do lifecycle do LogLine.
2///
3/// O lifecycle é determinístico e permite apenas as seguintes transições:
4/// - `Draft → Pending` (via `freeze()`)
5/// - `Pending → Committed` (via `commit()`)
6/// - `Draft/Pending → Ghost` (via `abandon()` ou `abandon_signed()`)
7///
8/// Uma vez `Committed`, o LogLine é imutável e não pode mais ser modificado.
9///
10/// # Exemplo
11///
12/// ```rust
13/// use logline_core::Status;
14///
15/// let status = Status::Draft;
16/// assert_eq!(status.as_str(), "DRAFT");
17/// ```
18#[derive(Copy, Clone, Debug, PartialEq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub enum Status {
21    /// Estado inicial: LogLine em construção, ainda não validado.
22    Draft,
23    /// Estado intermediário: LogLine validado, pronto para commit ou abandon.
24    Pending,
25    /// Estado final: LogLine commitado e imutável.
26    Committed,
27    /// Estado forense: LogLine abandonado, preservado para análise.
28    Ghost,
29}
30
31impl Status {
32    /// Retorna a representação string do status (ex: "DRAFT", "PENDING").
33    pub fn as_str(&self) -> &'static str {
34        match self {
35            Status::Draft => "DRAFT",
36            Status::Pending => "PENDING",
37            Status::Committed => "COMMITTED",
38            Status::Ghost => "GHOST",
39        }
40    }
41}
42
43use crate::{LogLineError, Status as S};
44
45pub fn ensure(expected_from: S, to: S, current: S) -> Result<(), LogLineError> {
46    if current != expected_from {
47        return Err(LogLineError::InvalidTransition { from: current, to });
48    }
49    Ok(())
50}