runmat-execution-artifact 0.6.2

Canonical execution bundles and program artifacts for RunMat
Documentation
use runmat_execution::Digest;
use runmat_package::FrozenProjectHandoff;
use serde::{Deserialize, Serialize};

use crate::{ArtifactError, ArtifactResult};

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
pub enum BundleCodeClosure {
    SourceProject { handoff: FrozenProjectHandoff },
    Compiled { package: CompiledPackageClosure },
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CompiledPackageClosure {
    pub schema_version: u16,
    pub graph_digest: Digest,
    pub source_digest: Digest,
    pub package_instances: Vec<String>,
}

impl CompiledPackageClosure {
    pub const SCHEMA_VERSION: u16 = 1;

    pub fn validate(&self) -> ArtifactResult<()> {
        if self.schema_version != Self::SCHEMA_VERSION
            || self.package_instances.is_empty()
            || self
                .package_instances
                .windows(2)
                .any(|pair| pair[0] >= pair[1])
            || self
                .package_instances
                .iter()
                .any(|identity| !valid_identity(identity))
        {
            return Err(ArtifactError::Invalid(
                "compiled package closure is not canonical".into(),
            ));
        }
        Ok(())
    }
}

fn valid_identity(value: &str) -> bool {
    !value.is_empty()
        && value.len() <= 512
        && value.is_ascii()
        && !value.chars().any(char::is_control)
}