1use std::io::{BufRead, BufReader, Read, Stdin, Stdout, Write};
6
7use serde::{Deserialize, Serialize};
8
9pub enum WifiStatus {
11 Enabled,
13 Disabled,
15}
16
17impl From<WifiStatus> for bool {
18 fn from(f: WifiStatus) -> bool {
19 match f {
20 WifiStatus::Enabled => true,
21 WifiStatus::Disabled => false,
22 }
23 }
24}
25
26#[derive(Serialize, Deserialize)]
28struct NotificationEvent {
29 r#type: String,
30 message: String,
31}
32
33#[derive(Serialize, Deserialize)]
35struct WifiEvent {
36 r#type: String,
37 enable: bool,
38}
39
40#[derive(Serialize, Deserialize, PartialEq, Debug)]
42pub struct NetworkEvent {
43 r#type: String,
44 status: String,
45}
46
47pub struct PlatoHelper<W: Write, R: Read> {
50 writer: W,
51 reader: R,
52}
53
54impl Default for PlatoHelper<Stdout, Stdin> {
55 fn default() -> Self {
56 PlatoHelper {
57 writer: std::io::stdout(),
58 reader: std::io::stdin(),
59 }
60 }
61}
62
63impl<W: Write, R: Read> PlatoHelper<W, R> {
64 pub fn new(writer: W, reader: R) -> Self {
65 PlatoHelper { writer, reader }
66 }
67
68 fn write_json<T: Serialize>(&mut self, value: &T) -> std::io::Result<()> {
70 let json = serde_json::to_string(value)
71 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
72 self.writer.write_all(json.as_bytes())?;
73 Ok(())
74 }
75
76 fn read_json_blocking<J>(&mut self) -> Result<J, std::io::Error>
79 where
80 J: for<'de> Deserialize<'de>,
81 {
82 let mut reader = BufReader::new(&mut self.reader);
83 let mut input = String::new();
84 loop {
85 input.clear();
86 reader.read_line(&mut input)?;
87 if let Ok(json) = serde_json::from_str(&input) {
88 return Ok(json);
89 }
90 }
91 }
92
93 pub fn display_notification(&mut self, message: &str) -> std::io::Result<()> {
95 let event = NotificationEvent {
96 r#type: "notify".to_string(),
97 message: message.to_string(),
98 };
99 self.write_json(&event)
100 }
101
102 pub fn set_wifi(&mut self, status: WifiStatus) -> std::io::Result<()> {
104 let event = WifiEvent {
105 r#type: "setWifi".to_string(),
106 enable: status.into(),
107 };
108 self.write_json(&event)
109 }
110
111 pub fn wait_for_network_blocking(&mut self) -> Result<NetworkEvent, std::io::Error> {
114 self.read_json_blocking()
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use std::io::{BufWriter, Cursor};
121
122 use super::*;
123
124 #[test]
125 fn notification_formatting() {
126 let mut buffer = Vec::new();
127 let writer = BufWriter::new(&mut buffer);
128 {
129 let mut plato = PlatoHelper::new(writer, std::io::stdin());
130 plato.display_notification("Hello, World!").unwrap();
131 }
132
133 let notification = NotificationEvent {
134 r#type: "notify".to_string(),
135 message: "Hello, World!".to_string(),
136 };
137
138 let event = serde_json::to_string(¬ification).unwrap();
139 let output = String::from_utf8(buffer).unwrap();
140
141 assert_eq!(event, output);
142 }
143
144 #[test]
145 fn wait_for_network_blocking_deserializes_correctly() {
146 let json = r#"{"type": "network", "status": "up"}"#;
147 let reader = Cursor::new(json);
148 let mut plato = PlatoHelper::new(Vec::new(), reader);
149 let result: Result<NetworkEvent, std::io::Error> = plato.wait_for_network_blocking();
150
151 assert_eq!(
152 result.unwrap(),
153 NetworkEvent {
154 r#type: "network".to_string(),
155 status: "up".to_string()
156 }
157 );
158 }
159}