escvpnet/
command.rs

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}