crankshaft_engine/task/
input.rs

1//! Task inputs.
2
3use anyhow::Context;
4use anyhow::Result;
5use bon::Builder;
6
7mod contents;
8
9pub use contents::Contents;
10
11/// A type of input.
12#[derive(Clone, Debug)]
13pub enum Type {
14    /// A file.
15    File,
16
17    /// A directory.
18    Directory,
19}
20
21/// An input to a task.
22#[derive(Builder, Clone, Debug)]
23#[builder(builder_type = Builder)]
24pub struct Input {
25    /// An optional name to give the input.
26    #[builder(into)]
27    pub(crate) name: Option<String>,
28
29    /// A description of the input.
30    #[builder(into)]
31    pub(crate) description: Option<String>,
32
33    /// The contents of the input.
34    #[builder(into)]
35    pub(crate) contents: Contents,
36
37    /// The expected guest path of the input.
38    #[builder(into)]
39    pub(crate) path: String,
40
41    /// The type of the input.
42    #[builder(into)]
43    pub(crate) ty: Type,
44
45    /// Whether or not the input should be treated as read-only.
46    ///
47    /// Defaults to `true`.
48    #[builder(default = true)]
49    pub(crate) read_only: bool,
50}
51
52impl Input {
53    /// The name of the input (if it exists).
54    pub fn name(&self) -> Option<&str> {
55        self.name.as_deref()
56    }
57
58    /// The description of the input (if it exists).
59    pub fn description(&self) -> Option<&str> {
60        self.description.as_deref()
61    }
62
63    /// The contents of the input.
64    pub fn contents(&self) -> &Contents {
65        &self.contents
66    }
67
68    /// The path where the input should be placed within the container.
69    pub fn path(&self) -> &str {
70        &self.path
71    }
72
73    /// The type of the container.
74    pub fn ty(&self) -> &Type {
75        &self.ty
76    }
77
78    /// Gets whether or not the input is read-only.
79    ///
80    /// Inputs are read-only by default.
81    pub fn read_only(&self) -> bool {
82        self.read_only
83    }
84}
85
86impl TryFrom<Input> for tes::v1::types::task::Input {
87    type Error = anyhow::Error;
88
89    fn try_from(input: Input) -> Result<Self, Self::Error> {
90        let Input {
91            name,
92            description,
93            contents,
94            path,
95            ty,
96            read_only: _,
97        } = input;
98
99        let (url, content) = contents.one_hot()?;
100
101        let ty = match ty {
102            Type::File => tes::v1::types::task::IoType::File,
103            Type::Directory => tes::v1::types::task::IoType::Directory,
104        };
105
106        Ok(tes::v1::types::task::Input {
107            name,
108            description,
109            url: url.map(|url| url.to_string()),
110            path,
111            ty,
112            content: content
113                .map(|v| String::from_utf8(v).context("TES requires file content to be UTF-8"))
114                .transpose()?,
115            streamable: None,
116        })
117    }
118}