1use std::{ pin::Pin, str::FromStr};
2
3use async_trait::async_trait;
4use tokio::io::{AsyncReadExt, AsyncBufReadExt, BufReader, AsyncWriteExt};
5
6use crate::{
7 error::ErrorKind,
8 io::{DecodeFrom, EncodeTo},
9};
10#[derive(Debug, Clone, PartialEq)]
11pub enum Command {
12 Get { name: String },
13 Set { name: String, value: String },
14}
15
16impl FromStr for Command {
17 type Err = crate::Error;
18 fn from_str(s: &str) -> Result<Self, Self::Err> {
19 let s = s.trim_end();
20 if s.contains("?") {
21 let mut parts = s.split('?');
22 let name = parts.next().ok_or(crate::Error::new(
23 ErrorKind::Decoding,
24 "Failed to decode command".to_string(),
25 ))?;
26 Ok(Self::Get {
27 name: name.to_string(),
28 })
29 } else {
30 let mut parts = s.split(' ');
31 let name = parts.next().ok_or(crate::Error::new(
32 ErrorKind::Decoding,
33 "Failed to decode command".to_string(),
34 ))?;
35 let value = parts.next().ok_or(crate::Error::new(
36 ErrorKind::Decoding,
37 "Failed to decode command".to_string(),
38 ))?;
39 Ok(Self::Set {
40 name: name.to_string(),
41 value: value.to_string(),
42 })
43 }
44 }
45}
46#[async_trait]
47impl<R: AsyncReadExt+Send> DecodeFrom<R> for Command {
48 type Error = crate::Error;
49 async fn decode_from(reader: &mut Pin<&mut R>) -> Result<Self, Self::Error> {
50 let mut reader = BufReader::new(reader);
51 let mut buf = String::new();
52 reader.read_line(&mut buf).await?;
53 buf.parse()
54
55 }
56}
57#[async_trait]
58impl<W: AsyncWriteExt+Send> EncodeTo<W> for Command {
59 type Error = crate::Error;
60 async fn encode_to(self, writer: &mut Pin<&mut W>) -> Result<usize, Self::Error> {
61 let command = match self {
62 Self::Get { name } => {
63 format!("{name}?\n")
64 }
65 Self::Set { name, value } => {
66 format!("{name} {value}\n")
67 }
68 };
69 writer.write_all(command.as_bytes()).await?;
70 Ok(command.len())
71 }
72}
73
74pub struct Response {
75 name: String,
76 value: String,
77}
78
79impl Response {
80 pub fn name(&self) -> &str {
81 self.name.as_ref()
82 }
83
84 pub fn value(&self) -> &str {
85 self.value.as_ref()
86 }
87}
88#[async_trait]
89impl<R: AsyncReadExt+ Send> DecodeFrom<R> for Response {
90 type Error = crate::Error;
91 async fn decode_from(reader: &mut Pin<&mut R>) -> Result<Self, Self::Error> {
92 let mut buf_reader = BufReader::new(reader);
93 let mut buf = String::new();
94 buf_reader.read_line(&mut buf).await?;
95 let mut parts = buf.split("=");
96 let name = parts
97 .next()
98 .ok_or(crate::Error::new(
99 ErrorKind::Decoding,
100 "Failed to decode response".to_string(),
101 ))?
102 .to_string();
103 let value = parts
104 .next()
105 .ok_or(crate::Error::new(
106 ErrorKind::Decoding,
107 "Failed to decode response".to_string(),
108 ))?
109 .to_string();
110
111 Ok(Self { name, value })
112 }
113}
114#[cfg(test)]
115mod tests {
116use super::*;
117 #[test]
118 fn command() {
119 let data = "PWR?\n";
120 let command = Command::Get { name: "PWR".to_string() };
121 let decoded_command:Command = data.parse().unwrap();
122 assert_eq!(decoded_command, command);
123
124 let data = "PWR ON\n";
125 let command = Command::Set { name: "PWR".to_string(), value: "ON".to_string() } ;
126 let decoded_command:Command = data.parse().unwrap();
127 assert_eq!(decoded_command, command)
128
129 }
130}