waos_dev_protocol/
messages.rs1use std::fmt;
12use std::path::PathBuf;
13
14use serde::{Deserialize, Serialize};
15use waos_package::ProgramId;
16
17#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum ToWaOS {
20 Run {
24 id: ProgramId,
25 #[serde(with = "serde_bytes")]
26 component: Vec<u8>,
27 },
28 Open { id: ProgramId, files: Vec<PathBuf> },
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
36pub enum FromWaOS {
37 Started,
38 Output {
40 stream: OutputStream,
41 #[serde(with = "serde_bytes")]
42 bytes: Vec<u8>,
43 },
44 Ended(RunEnd),
45 Refused(String),
47 Opened,
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
53pub enum OutputStream {
54 Stdout,
55 Stderr,
56}
57
58#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
60pub enum RunEnd {
61 Returned { success: bool },
63 Failed(String),
65 Stopped,
67 Replaced,
69}
70
71impl fmt::Debug for ToWaOS {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 match self {
75 ToWaOS::Run { id, component } => f
76 .debug_struct("Run")
77 .field("id", &format_args!("{id}"))
78 .field("component", &format_args!("{} bytes", component.len()))
79 .finish(),
80 ToWaOS::Open { id, files } => f
81 .debug_struct("Open")
82 .field("id", &format_args!("{id}"))
83 .field("files", files)
84 .finish(),
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[derive(Debug, PartialEq, Serialize, Deserialize)]
96 enum ToWaOSAsSequence {
97 Run { id: ProgramId, component: Vec<u8> },
98 }
99
100 #[derive(Debug, PartialEq, Serialize, Deserialize)]
101 enum FromWaOSAsSequence {
102 Started,
103 Output {
104 stream: OutputStream,
105 bytes: Vec<u8>,
106 },
107 }
108
109 fn bytes() -> Vec<u8> {
111 (0..=u8::MAX).cycle().take(1000).collect()
112 }
113
114 #[test]
115 fn a_run_is_encoded_as_it_was_when_its_component_was_a_sequence() {
116 let id: ProgramId = "dev.example.triangle".parse().unwrap();
117 let run = ToWaOS::Run {
118 id: id.clone(),
119 component: bytes(),
120 };
121 let as_sequence = ToWaOSAsSequence::Run {
122 id,
123 component: bytes(),
124 };
125 let encoded = postcard::to_allocvec(&run).unwrap();
126 assert_eq!(encoded, postcard::to_allocvec(&as_sequence).unwrap());
127 assert_eq!(
128 postcard::from_bytes::<ToWaOSAsSequence>(&encoded).unwrap(),
129 as_sequence
130 );
131 }
132
133 #[test]
134 fn output_is_encoded_as_it_was_when_its_bytes_were_a_sequence() {
135 let output = FromWaOS::Output {
136 stream: OutputStream::Stderr,
137 bytes: bytes(),
138 };
139 let as_sequence = FromWaOSAsSequence::Output {
140 stream: OutputStream::Stderr,
141 bytes: bytes(),
142 };
143 let encoded = postcard::to_allocvec(&output).unwrap();
144 assert_eq!(encoded, postcard::to_allocvec(&as_sequence).unwrap());
145 assert_eq!(postcard::from_bytes::<FromWaOS>(&encoded).unwrap(), output);
146 }
147
148 #[test]
149 fn an_opening_reads_back_as_written_and_prints_its_files() {
150 let open = ToWaOS::Open {
151 id: "dev.example.notes".parse().unwrap(),
152 files: vec![PathBuf::from("/Users/me/notes.md")],
153 };
154 let encoded = postcard::to_allocvec(&open).unwrap();
155 assert_eq!(postcard::from_bytes::<ToWaOS>(&encoded).unwrap(), open);
156 assert_eq!(
157 format!("{open:?}"),
158 "Open { id: dev.example.notes, files: [\"/Users/me/notes.md\"] }"
159 );
160 let opened = postcard::to_allocvec(&FromWaOS::Opened).unwrap();
161 assert_eq!(
162 postcard::from_bytes::<FromWaOS>(&opened).unwrap(),
163 FromWaOS::Opened
164 );
165 }
166
167 #[test]
168 fn a_run_prints_its_component_as_a_count() {
169 let run = ToWaOS::Run {
170 id: "dev.example.triangle".parse().unwrap(),
171 component: vec![0; 1024],
172 };
173 assert_eq!(
174 format!("{run:?}"),
175 "Run { id: dev.example.triangle, component: 1024 bytes }"
176 );
177 }
178}