bigml/resource/execution/
mod.rs1use serde::de;
4use serde::de::DeserializeOwned;
5use serde::ser::SerializeSeq;
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use std::fmt;
8use url::Url;
9
10use super::id::*;
11use super::status::*;
12use super::{Library, Script};
13use super::{Resource, ResourceCommon};
14use crate::client::Client;
15use crate::errors::*;
16
17mod args;
18mod execution_status;
19
20pub use self::args::*;
21pub use self::execution_status::*;
22
23#[derive(Clone, Debug, Deserialize, Resource, Serialize)]
27#[api_name = "execution"]
28#[non_exhaustive]
29pub struct Execution {
30 #[serde(flatten)]
33 pub common: ResourceCommon,
34
35 pub resource: Id<Execution>,
37
38 pub status: ExecutionStatus,
40
41 pub execution: Data,
43}
44
45#[derive(Clone, Debug, Deserialize, Serialize)]
49#[non_exhaustive]
50pub struct Data {
51 #[serde(default)]
53 pub outputs: Vec<Output>,
54
55 pub result: Option<serde_json::Value>,
58
59 #[serde(default)]
61 pub logs: Vec<LogEntry>,
62
63 #[serde(default)]
65 pub output_resources: Vec<OutputResource>,
66
67 #[serde(default)]
69 pub sources: Vec<Source>,
70}
71
72impl Data {
73 pub fn get<D: DeserializeOwned>(&self, name: &str) -> Result<D> {
75 for output in &self.outputs {
76 if output.name == name {
77 return output.get();
78 }
79 }
80 Err(Error::could_not_get_output(
81 name,
82 Error::OutputNotAvailable {},
83 ))
84 }
85}
86
87#[derive(Clone, Debug)]
89#[non_exhaustive]
90pub struct Source {
91 pub id: SourceId,
93 pub description: String,
95}
96
97impl<'de> Deserialize<'de> for Source {
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: Deserializer<'de>,
101 {
102 struct Visitor;
103
104 impl<'de> de::Visitor<'de> for Visitor {
107 type Value = Source;
108
109 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 write!(f, "a list with a source ID and a description")
111 }
112
113 fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
114 where
115 V: de::SeqAccess<'de>,
116 {
117 use serde::de::Error;
118
119 let id = visitor
120 .next_element()?
121 .ok_or_else(|| V::Error::custom("no id field in source"))?;
122 let description = visitor.next_element()?.ok_or_else(|| {
123 V::Error::custom("no description field in source")
124 })?;
125
126 Ok(Source { id, description })
127 }
128 }
129
130 deserializer.deserialize_seq(Visitor)
131 }
132}
133
134impl Serialize for Source {
135 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
136 where
137 S: Serializer,
138 {
139 let mut seq = serializer.serialize_seq(Some(2))?;
140 seq.serialize_element(&self.id)?;
141 seq.serialize_element(&self.description)?;
142 seq.end()
143 }
144}
145
146#[derive(Clone, Debug)]
148#[non_exhaustive]
149pub enum SourceId {
150 Library(Id<Library>),
152 Script(Id<Script>),
154}
155
156impl SourceId {
157 pub fn dashboard_url(&self) -> Url {
159 match self {
160 SourceId::Library(id) => id.dashboard_url(),
161 SourceId::Script(id) => id.dashboard_url(),
162 }
163 }
164
165 pub async fn fetch_source_code(&self, client: &Client) -> Result<String> {
167 match *self {
168 SourceId::Library(ref id) => Ok(client.fetch(id).await?.source_code),
169 SourceId::Script(ref id) => Ok(client.fetch(id).await?.source_code),
170 }
171 }
172}
173
174impl fmt::Display for SourceId {
175 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
176 match *self {
177 SourceId::Library(ref id) => id.fmt(fmt),
178 SourceId::Script(ref id) => id.fmt(fmt),
179 }
180 }
181}
182
183impl<'de> Deserialize<'de> for SourceId {
184 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
185 where
186 D: Deserializer<'de>,
187 {
188 struct Visitor;
189
190 impl<'de> de::Visitor<'de> for Visitor {
193 type Value = SourceId;
194
195 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 write!(f, "a script or library ID")
197 }
198
199 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
200 where
201 E: de::Error,
202 {
203 if value.starts_with(Library::id_prefix()) {
204 let id = value
205 .parse()
206 .map_err(|e| de::Error::custom(format!("{}", e)))?;
207 Ok(SourceId::Library(id))
208 } else if value.starts_with(Script::id_prefix()) {
209 let id = value
210 .parse()
211 .map_err(|e| de::Error::custom(format!("{}", e)))?;
212 Ok(SourceId::Script(id))
213 } else {
214 Err(de::Error::custom("expected script or library ID"))
215 }
216 }
217 }
218
219 deserializer.deserialize_str(Visitor)
220 }
221}
222
223impl Serialize for SourceId {
224 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
225 where
226 S: Serializer,
227 {
228 match *self {
229 SourceId::Library(ref id) => id.serialize(serializer),
230 SourceId::Script(ref id) => id.serialize(serializer),
231 }
232 }
233}