#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SourceKind(&'static str);
impl SourceKind {
pub const CLI: Self = Self("cli");
pub const ENV: Self = Self("env");
pub const FILE: Self = Self("file");
pub const DEFAULTS: Self = Self("defaults");
pub const COERCED: Self = Self("coerced");
pub const fn new(name: &'static str) -> Self {
Self(name)
}
pub const fn name(self) -> &'static str {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FileScope {
Project,
Global,
System,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Trust {
Project,
Operator,
Invocation,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Origin {
pub kind: SourceKind,
pub identifier: String,
pub trust: Trust,
}
impl Origin {
pub fn new(kind: SourceKind, identifier: impl Into<String>) -> Self {
let trust = match kind {
SourceKind::CLI | SourceKind::ENV | SourceKind::DEFAULTS | SourceKind::COERCED => {
Trust::Invocation
}
_ => Trust::Project,
};
Self {
kind,
identifier: identifier.into(),
trust,
}
}
pub fn trusted_as(mut self, trust: Trust) -> Self {
self.trust = trust;
self
}
pub fn file(identifier: impl Into<String>, scope: FileScope) -> Self {
Self {
kind: SourceKind::FILE,
identifier: identifier.into(),
trust: match scope {
FileScope::Project => Trust::Project,
FileScope::Global | FileScope::System => Trust::Operator,
},
}
}
pub fn declared_default() -> Self {
Self::new(SourceKind::DEFAULTS, "the default")
}
pub fn describe(&self) -> &str {
&self.identifier
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_kind_usage_does_not_know_is_still_a_kind() {
let git = SourceKind::new("git");
assert_eq!(git.name(), "git");
assert_ne!(git, SourceKind::FILE);
assert_ne!(SourceKind::CLI, SourceKind::ENV);
assert_ne!(SourceKind::DEFAULTS, SourceKind::COERCED);
}
#[test]
fn a_kind_usage_cannot_vouch_for_is_trusted_least() {
assert_eq!(
Origin::new(SourceKind::new("pkl"), "jobs").trust,
Trust::Project
);
assert_eq!(
Origin::new(SourceKind::new("git"), "hk.jobs").trust,
Trust::Project
);
for kind in [SourceKind::CLI, SourceKind::ENV, SourceKind::COERCED] {
assert_eq!(Origin::new(kind, "x").trust, Trust::Invocation, "{kind:?}");
}
assert_eq!(Origin::declared_default().trust, Trust::Invocation);
assert_eq!(
Origin::new(SourceKind::new("git"), "hk.jobs")
.trusted_as(Trust::Operator)
.trust,
Trust::Operator
);
assert_eq!(
Origin::file("hk.toml", FileScope::Project).trust,
Trust::Project
);
for scope in [FileScope::Global, FileScope::System] {
assert_eq!(Origin::file("x", scope).trust, Trust::Operator, "{scope:?}");
}
}
}