greentic-component 0.5.2

High-level component loader and store for Greentic components
Documentation
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use time::OffsetDateTime;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Provenance {
    pub builder: String,
    pub git_commit: String,
    pub toolchain: String,
    #[serde(with = "time::serde::rfc3339")]
    pub built_at_utc: OffsetDateTime,
}

impl Provenance {
    pub fn validate(&self) -> Result<(), ProvenanceError> {
        if self.builder.trim().is_empty() {
            return Err(ProvenanceError::EmptyField("builder"));
        }
        if self.toolchain.trim().is_empty() {
            return Err(ProvenanceError::EmptyField("toolchain"));
        }
        if !GIT_COMMIT_RE.is_match(&self.git_commit) {
            return Err(ProvenanceError::InvalidGit(self.git_commit.clone()));
        }
        Ok(())
    }
}

#[derive(Debug, Error)]
pub enum ProvenanceError {
    #[error("provenance field `{0}` cannot be empty")]
    EmptyField(&'static str),
    #[error("git commit `{0}` must be lowercase hex (min 7 chars)")]
    InvalidGit(String),
}

static GIT_COMMIT_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"^[0-9a-f]{7,40}$").expect("git commit regex compile should never fail")
});