forge_primitives/call_output.rs
1//! A call's own output, as the read answers it.
2
3use serde::{Deserialize, Serialize};
4
5/// The answer to a read of a call's own output file: the tail of the file
6/// the CLI streamed a backgrounded task's output to, or the reason there is
7/// nothing to draw - never a blank.
8///
9/// The two reasons are named apart because a reader can act on the
10/// difference: a call the conversation no longer names is not a file that
11/// went away, and a view saying which of the two it met is the whole of what
12/// this carries.
13#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum CallOutput {
16 /// The tail, oldest first, as the command wrote it - escape sequences
17 /// and all. What a renderer drops is the renderer's rule: a terminal and
18 /// a page drop different bytes.
19 Lines(Vec<String>),
20 /// The file the read was pointed at is gone, or would not open.
21 FileGone,
22 /// No output file is recorded for this call: the frame that named one is
23 /// not in the conversation the task carries.
24 NoPath,
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 /// The wire shape the client narrows, held from the Rust side: a name for
32 /// the lines and a bare word for each reason. No compiler links the two
33 /// sides, so this is what keeps serde's output and the client's
34 /// `callOutputOf` together - the `draftEndingLine` precedent.
35 #[test]
36 fn a_call_output_serialises_as_the_client_narrows_it() {
37 assert_eq!(
38 serde_json::to_value(CallOutput::Lines(vec!["one".to_owned()])).expect("encodes"),
39 serde_json::json!({ "lines": ["one"] }),
40 );
41 assert_eq!(
42 serde_json::to_value(CallOutput::FileGone).expect("encodes"),
43 serde_json::json!("file_gone"),
44 );
45 assert_eq!(
46 serde_json::to_value(CallOutput::NoPath).expect("encodes"),
47 serde_json::json!("no_path"),
48 );
49 }
50}