use serde::Deserialize;
use crate::verdict::SafetyLevel;
#[derive(Debug, Deserialize)]
pub(super) struct TomlFile {
#[serde(default)]
pub command: Vec<TomlCommand>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlCommand {
pub name: String,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub candidate: Option<bool>,
#[serde(default)]
pub aliases: Vec<String>,
#[serde(default)]
pub url: String,
#[serde(default)]
pub level: Option<TomlLevel>,
#[serde(default)]
pub bare: Option<bool>,
#[serde(default)]
pub max_positional: Option<usize>,
#[serde(default)]
pub positional_style: Option<bool>,
#[serde(default)]
pub tolerate_unknown_short: Option<bool>,
#[serde(default)]
pub tolerate_unknown_long: Option<bool>,
#[serde(default)]
pub numeric_dash: Option<bool>,
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub bare_flags: Vec<String>,
#[serde(default)]
pub sub: Vec<TomlSub>,
#[serde(default)]
pub handler: Option<String>,
#[serde(default)]
pub doc_body: Option<String>,
#[serde(default)]
pub require_any: Vec<String>,
#[serde(default)]
pub first_arg: Vec<String>,
#[serde(default)]
pub credential_first_arg: Vec<String>,
#[serde(default)]
pub flag: Vec<TomlSubFlag>,
#[serde(default)]
pub wrapper: Option<TomlWrapper>,
#[serde(default)]
pub write_flags: Vec<String>,
#[serde(default)]
pub path_gate: Option<crate::pathgate::RoleSpec>,
#[serde(default)]
pub researched_version: Option<String>,
#[serde(default)]
pub examples_safe: Vec<String>,
#[serde(default)]
pub examples_denied: Vec<String>,
#[serde(default)]
pub eval_safe: Option<bool>,
#[serde(default)]
pub eval_safe_flags: Vec<String>,
#[serde(default)]
pub eval_safe_flag_values: std::collections::HashMap<String, Vec<String>>,
#[serde(default)]
pub eval_safe_required_flags: Vec<String>,
#[serde(default)]
pub deny: Option<bool>,
#[serde(default)]
pub fallback: Option<TomlFallback>,
#[serde(default)]
pub handler_policy: std::collections::HashMap<String, TomlHandlerPolicy>,
#[serde(default)]
pub matrix: Vec<TomlMatrix>,
#[serde(default)]
pub verb_chain: Option<TomlVerbChain>,
#[serde(default)]
pub behavior: Option<TomlBehavior>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlBehavior {
pub operation: String,
pub positionals: String,
#[serde(default)]
pub scale: Option<String>,
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub numeric_shorthand: Option<bool>,
#[serde(default)]
pub flags: std::collections::HashMap<String, TomlBehaviorFlag>,
#[serde(default)]
pub hook: Option<String>,
#[serde(default)]
pub transfer: Option<TomlTransfer>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlTransfer {
pub source: String,
#[serde(default)]
pub no_clobber_flags: Vec<String>,
#[serde(default)]
pub clobber_flags: Vec<String>,
#[serde(default)]
pub recursive_flags: Vec<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlBehaviorFlag {
#[serde(default)]
pub scale: Option<String>,
#[serde(default)]
pub kind: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlVerbChain {
#[serde(default)]
pub level: Option<TomlLevel>,
#[serde(default)]
pub separator: Option<String>,
#[serde(default)]
pub main_standalone: Vec<String>,
#[serde(default)]
pub main_valued: Vec<String>,
#[serde(default)]
pub main_variadic: Vec<String>,
#[serde(default)]
pub verbs: Vec<String>,
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlMatrix {
pub parents: Vec<String>,
pub level: TomlLevel,
pub actions: std::collections::HashMap<String, TomlMatrixAction>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub(super) enum TomlMatrixAction {
Policy(String),
Detailed(TomlMatrixActionDetailed),
}
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct TomlMatrixActionDetailed {
pub policy: String,
#[serde(default)]
pub guard: Option<String>,
#[serde(default)]
pub guard_short: Option<String>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlHandlerPolicy {
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub bare: Option<bool>,
#[serde(default)]
pub max_positional: Option<usize>,
#[serde(default)]
pub tolerate_unknown_short: Option<bool>,
#[serde(default)]
pub tolerate_unknown_long: Option<bool>,
#[serde(default)]
pub numeric_dash: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlFallback {
#[serde(default)]
pub level: Option<TomlLevel>,
#[serde(default)]
pub bare: Option<bool>,
#[serde(default)]
pub max_positional: Option<usize>,
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub tolerate_unknown_short: Option<bool>,
#[serde(default)]
pub tolerate_unknown_long: Option<bool>,
#[serde(default)]
pub numeric_dash: Option<bool>,
#[serde(default)]
pub positional_shape: Option<String>,
#[serde(default)]
pub executor: Option<String>,
#[serde(default)]
pub executor_redirect_flag: Option<String>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlWrapper {
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub positional_skip: Option<usize>,
#[serde(default)]
pub separator: Option<String>,
#[serde(default)]
pub bare_ok: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlSubFlag {
pub name: String,
pub classifies: String,
#[serde(default)]
pub value_prefix: Option<String>,
#[serde(default)]
pub when_absent: Option<bool>,
#[serde(default)]
pub fact: Option<String>,
#[serde(default)]
pub source: Option<String>,
#[serde(default)]
pub judgment: Option<String>,
}
#[derive(Debug, Deserialize)]
pub(super) struct TomlSub {
pub name: String,
#[serde(default)]
pub candidate: Option<bool>,
#[serde(default)]
pub profile: Option<String>,
#[serde(default)]
pub fact: Option<String>,
#[serde(default)]
pub source: Option<String>,
#[serde(default)]
pub judgment: Option<String>,
#[serde(default)]
pub aliases: Vec<String>,
#[serde(default)]
pub level: Option<TomlLevel>,
#[serde(default)]
pub bare: Option<bool>,
#[serde(default)]
pub max_positional: Option<usize>,
#[serde(default)]
pub positional_style: Option<bool>,
#[serde(default)]
pub tolerate_unknown_short: Option<bool>,
#[serde(default)]
pub tolerate_unknown_long: Option<bool>,
#[serde(default)]
pub numeric_dash: Option<bool>,
#[serde(default)]
pub standalone: Vec<String>,
#[serde(default)]
pub valued: Vec<String>,
#[serde(default)]
pub guard: Option<String>,
#[serde(default)]
pub guard_short: Option<String>,
#[serde(default)]
pub allow_all: Option<bool>,
#[serde(default)]
pub policy: Option<String>,
#[serde(default)]
pub sub: Vec<TomlSub>,
#[serde(default)]
pub flag: Vec<TomlSubFlag>,
#[serde(default)]
pub network_destination: Option<bool>,
#[serde(default)]
pub destination_flag: Option<String>,
#[serde(default)]
pub output_path_flags: Vec<String>,
#[serde(default)]
pub nested_bare: Option<bool>,
#[serde(default)]
pub require_any: Vec<String>,
#[serde(default)]
pub first_arg: Vec<String>,
#[serde(default)]
pub credential_first_arg: Vec<String>,
#[serde(default)]
pub write_flags: Vec<String>,
#[serde(default)]
pub delegate_after: Option<String>,
#[serde(default)]
pub delegate_skip: Option<usize>,
#[serde(default)]
pub executor: Option<String>,
#[serde(default)]
pub executor_redirect_flag: Option<String>,
#[serde(default)]
pub positional_shape: Option<String>,
#[serde(default)]
pub handler: Option<String>,
#[serde(default)]
pub doc_body: Option<String>,
#[serde(default)]
pub eval_safe: Option<bool>,
#[serde(default)]
pub eval_safe_flags: Vec<String>,
#[serde(default)]
pub eval_safe_flag_values: std::collections::HashMap<String, Vec<String>>,
#[serde(default)]
pub eval_safe_required_flags: Vec<String>,
}
#[derive(Debug, Clone, Copy, Deserialize)]
pub(super) enum TomlLevel {
Inert,
SafeRead,
SafeWrite,
}
impl From<TomlLevel> for SafetyLevel {
fn from(l: TomlLevel) -> Self {
match l {
TomlLevel::Inert => SafetyLevel::Inert,
TomlLevel::SafeRead => SafetyLevel::SafeRead,
TomlLevel::SafeWrite => SafetyLevel::SafeWrite,
}
}
}
#[derive(Debug)]
pub struct CommandSpec {
pub name: String,
pub description: String,
pub aliases: Vec<String>,
pub url: String,
pub category: String,
pub researched_version: Option<String>,
pub examples_safe: Vec<String>,
pub examples_denied: Vec<String>,
pub eval_safe: bool,
pub eval_safe_flags: Vec<String>,
pub eval_safe_flag_values: std::collections::HashMap<String, Vec<String>>,
pub eval_safe_required_flags: Vec<String>,
pub(super) path_gate: Option<crate::pathgate::RoleSpec>,
pub(super) archetype_flags: Vec<FlagProvenance>,
pub(super) behavior: Option<BehaviorSpec>,
pub(super) kind: DispatchKind,
}
#[derive(Debug, Clone)]
pub(crate) struct BehaviorSpec {
pub operation: crate::engine::facet::Operation,
pub positionals: PositionalRole,
pub scale: ScaleModel,
pub short: Vec<u8>,
pub valued_short: Vec<u8>,
pub long: Vec<String>,
pub valued_long: Vec<String>,
pub numeric_shorthand: bool,
pub unbounded_flags: Vec<String>,
pub path_flags: Vec<PathFlag>,
pub hook: Option<BehaviorHook>,
pub transfer: Option<TransferSpec>,
}
#[derive(Debug, Clone)]
pub(crate) struct PathFlag {
pub short: Option<u8>,
pub long: Option<String>,
pub role: PathRole,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PathRole {
Read,
Write,
}
#[derive(Debug, Clone)]
pub(crate) struct TransferSpec {
pub source: TransferSource,
pub no_clobber_flags: Vec<String>,
pub clobber_flags: Vec<String>,
pub recursive_flags: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TransferSource {
Observe,
Relocate,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PositionalRole {
None,
Read,
Write,
PatternThenRead,
Transfer,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ScaleModel {
Single,
Breadth,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum BehaviorHook {
Grep,
Dd,
Tar,
Sed,
}
#[derive(Debug, Clone)]
pub(super) struct FlagProvenance {
pub name: String,
pub classifies: String,
pub value_prefix: Option<String>,
pub when_absent: bool,
}
#[derive(Debug, Clone)]
pub(super) struct SubSpec {
pub name: String,
pub kind: DispatchKind,
pub profile: Option<String>,
pub flags: Vec<FlagProvenance>,
pub policy_ref: Option<String>,
pub eval_safe: bool,
pub eval_safe_flags: Vec<String>,
pub eval_safe_flag_values: std::collections::HashMap<String, Vec<String>>,
pub eval_safe_required_flags: Vec<String>,
pub network_destination: bool,
pub destination_flag: Option<String>,
pub output_path_flags: Vec<String>,
}
#[derive(Debug, Clone)]
pub(super) enum DispatchKind {
Policy {
policy: OwnedPolicy,
level: SafetyLevel,
},
FirstArg {
patterns: Vec<String>,
level: SafetyLevel,
},
RequireAny {
require_any: Vec<String>,
policy: OwnedPolicy,
level: SafetyLevel,
accept_bare_help: bool,
},
Branching {
subs: Vec<SubSpec>,
bare_flags: Vec<String>,
bare_ok: bool,
pre_standalone: Vec<String>,
pre_valued: Vec<String>,
first_arg: Vec<String>,
first_arg_level: SafetyLevel,
credential_first_arg: Vec<String>,
},
WriteFlagged {
policy: OwnedPolicy,
base_level: SafetyLevel,
write_flags: Vec<String>,
},
DelegateAfterSeparator {
separator: String,
},
DelegateSkip {
skip: usize,
},
Wrapper {
standalone: Vec<String>,
valued: Vec<String>,
positional_skip: usize,
separator: Option<String>,
bare_ok: bool,
},
VerbChain(VerbChainSpec),
Executor {
policy: OwnedPolicy,
level: SafetyLevel,
kind: ExecutorKind,
redirect_flag: Option<String>,
shape: Option<crate::policy::PositionalShape>,
},
Custom {
#[allow(dead_code)]
handler_name: String,
doc_body: Option<String>,
subs: Vec<SubSpec>,
fallback: Option<FallbackSpec>,
handler_policies: std::collections::HashMap<String, OwnedPolicy>,
matrices: Vec<MatrixSpec>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ExecutorKind {
File,
Project,
}
impl ExecutorKind {
pub(super) fn from_name(name: &str) -> Option<Self> {
match name {
"file" => Some(Self::File),
"project" => Some(Self::Project),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct OwnedPolicy {
pub standalone: Vec<String>,
pub valued: Vec<String>,
pub bare: bool,
pub max_positional: Option<usize>,
pub tolerance: crate::policy::FlagTolerance,
}
#[derive(Debug, Clone)]
pub(super) struct MatrixSpec {
pub parents: Vec<String>,
pub level: SafetyLevel,
pub actions: std::collections::HashMap<String, MatrixAction>,
}
#[derive(Debug, Clone)]
pub(super) struct MatrixAction {
pub policy_key: String,
pub guard: Option<String>,
pub guard_short: Option<String>,
}
#[derive(Debug, Clone)]
pub(super) struct VerbChainSpec {
pub level: SafetyLevel,
pub separator: String,
pub main_standalone: Vec<String>,
pub main_valued: Vec<String>,
pub main_variadic: Vec<String>,
pub verbs: std::collections::HashSet<String>,
}
#[derive(Debug, Clone)]
pub(super) struct FallbackSpec {
pub policy: OwnedPolicy,
pub level: SafetyLevel,
pub positional_shape: Option<crate::policy::PositionalShape>,
pub executor: Option<ExecutorKind>,
pub executor_redirect_flag: Option<String>,
}