Skip to main content

quanttide_work/
outcome.rs

1//! 结果:一次动作的答复。
2//!
3//! 规范(`docs/specification/process/outcome.md`):一次动作一份,命令行与窗口都从它取,
4//! 推进任务的动作还记进流水。这一份是它的不变部分——四样(`ok` 通不通、`lines` 话、
5//! `columns` 与 `rows` 同一份表格、`data` 给界面的那一栏)与编解码;话怎么拼、
6//! 路径怎么显示、退出码怎么定,留各自的平台。
7
8use serde_json::{Value as Json, json};
9
10/// 一次动作的答复。四样:通不通、话、表格、给界面的那一栏。
11#[derive(Debug, Clone, Default, PartialEq)]
12pub struct Outcome {
13    pub ok: bool,
14    /// 给人看的话,一行一句。
15    pub lines: Vec<String>,
16    /// 同一份表格:表头与行,命令行与窗口共用。
17    pub columns: Vec<String>,
18    pub rows: Vec<Vec<String>>,
19    /// 给窗口与脚本的那一栏(要交原文就托在这里);没有就不写。
20    pub data: Option<Json>,
21}
22
23impl Outcome {
24    pub fn new(ok: bool) -> Self {
25        Outcome {
26            ok,
27            ..Default::default()
28        }
29    }
30
31    /// 只有话的结果。
32    pub fn lines(ok: bool, lines: Vec<String>) -> Self {
33        Outcome {
34            ok,
35            lines,
36            ..Default::default()
37        }
38    }
39
40    /// 往话的开头添一句。
41    pub fn with_first(mut self, line: String) -> Self {
42        self.lines.insert(0, line);
43        self
44    }
45
46    /// 托上给界面的那一栏。
47    pub fn with_data(mut self, data: Json) -> Self {
48        self.data = Some(data);
49        self
50    }
51
52    /// 信封:四样,`data` 有才写。
53    pub fn to_json(&self) -> Json {
54        let mut envelope = serde_json::Map::new();
55        envelope.insert("ok".to_string(), json!(self.ok));
56        envelope.insert("lines".to_string(), json!(self.lines));
57        envelope.insert("columns".to_string(), json!(self.columns));
58        envelope.insert("rows".to_string(), json!(self.rows));
59        if let Some(data) = &self.data {
60            envelope.insert("data".to_string(), data.clone());
61        }
62        Json::Object(envelope)
63    }
64
65    /// 原文那一栏(`--out` 落的就是它);没托东西就给信封。
66    pub fn data_json(&self) -> Json {
67        match &self.data {
68            Some(data) => data.clone(),
69            None => self.to_json(),
70        }
71    }
72
73    /// 从信封装回来。缺样按空算。
74    pub fn from_json(value: &Json) -> Self {
75        Outcome {
76            ok: value.get("ok").and_then(Json::as_bool).unwrap_or(false),
77            lines: strings(value.get("lines")),
78            columns: strings(value.get("columns")),
79            rows: value
80                .get("rows")
81                .and_then(Json::as_array)
82                .map(|rows| rows.iter().map(|row| strings(Some(row))).collect())
83                .unwrap_or_default(),
84            data: value.get("data").cloned(),
85        }
86    }
87}
88
89/// 一栏字符串:不是数组按空算,元素照原样写成文字。
90fn strings(value: Option<&Json>) -> Vec<String> {
91    value
92        .and_then(Json::as_array)
93        .map(|items| {
94            items
95                .iter()
96                .map(|item| match item {
97                    Json::String(text) => text.clone(),
98                    other => other.to_string(),
99                })
100                .collect()
101        })
102        .unwrap_or_default()
103}