auditlog 0.1.0

Audit trail for your data models — an ORM-agnostic core with a pluggable, async sqlx backend (SQLite & Postgres).
Documentation
//! The audited action.

use std::fmt;
use std::str::FromStr;

use serde::{Deserialize, Serialize};

/// One audited lifecycle action.
///
/// This is the value stored in the `action` column. A no-op touch is recorded as
/// [`Action::Update`] — there is no distinct `touch` action string. The value stored and
/// queried for deletions is `"destroy"`; this enum reflects that behavior.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Action {
    /// A record was created.
    Create,
    /// A record was updated (this also covers `touch`).
    Update,
    /// A record was destroyed.
    Destroy,
}

impl Action {
    /// The lowercase string stored in the `action` column.
    pub fn as_str(self) -> &'static str {
        match self {
            Action::Create => "create",
            Action::Update => "update",
            Action::Destroy => "destroy",
        }
    }

    /// Whether this is an update (the only action whose `audited_changes` are `[old, new]` pairs).
    pub fn is_update(self) -> bool {
        matches!(self, Action::Update)
    }
}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl FromStr for Action {
    type Err = ParseActionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "create" => Ok(Action::Create),
            "update" | "touch" => Ok(Action::Update),
            "destroy" | "delete" => Ok(Action::Destroy),
            other => Err(ParseActionError(other.to_owned())),
        }
    }
}

/// Returned when a string cannot be parsed into an [`Action`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseActionError(pub String);

impl fmt::Display for ParseActionError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "invalid action `{}`", self.0)
    }
}

impl std::error::Error for ParseActionError {}