Skip to main content

usage/spec/
mount.rs

1use std::fmt::Display;
2
3use kdl::KdlNode;
4use serde::Serialize;
5
6use crate::error::Result;
7use crate::spec::context::ParsingContext;
8use crate::spec::helpers::{string_entry, NodeHelper};
9
10#[derive(Debug, Default, Clone, Serialize)]
11#[non_exhaustive]
12pub struct SpecMount {
13    pub run: String,
14}
15
16impl SpecMount {
17    /// A mount that runs `run` to produce a spec for the subcommands here.
18    pub fn new(run: impl Into<String>) -> Self {
19        Self { run: run.into() }
20    }
21}
22
23impl SpecMount {
24    pub(crate) fn parse(ctx: &ParsingContext, node: &NodeHelper) -> Result<Self> {
25        let mut mount = SpecMount::default();
26        for (k, v) in node.props() {
27            match k {
28                "run" => mount.run = v.ensure_string()?,
29                k => bail_parse!(ctx, v.entry.span(), "unsupported mount key {k}"),
30            }
31        }
32        for child in node.children() {
33            match child.name() {
34                "run" => mount.run = child.arg(0)?.ensure_string()?,
35                k => bail_parse!(
36                    ctx,
37                    child.node.name().span(),
38                    "unsupported mount value key {k}"
39                ),
40            }
41        }
42        if mount.run.is_empty() {
43            bail_parse!(ctx, node.span(), "mount run is required")
44        }
45        Ok(mount)
46    }
47    pub fn usage(&self) -> String {
48        format!("mount:{}", self.run)
49    }
50}
51
52impl From<&SpecMount> for KdlNode {
53    fn from(mount: &SpecMount) -> KdlNode {
54        let mut node = KdlNode::new("mount");
55        node.push(string_entry(Some("run"), &mount.run));
56        node
57    }
58}
59
60impl Display for SpecMount {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        write!(f, "{}", self.usage())
63    }
64}