use std::io::*;
#[derive(Clone, Debug, Default, Hash, Eq, PartialEq)]
pub struct Response {
pub control: Vec<(char, String)>,
pub message: Option<String>,
}
impl Response {
pub fn get_code(&self, code: char) -> Option<&str> {
for (key, value) in &self.control {
if *key == code {
return Some(value);
}
}
None
}
pub fn get_code_character(&self, code: char) -> Option<char> {
self.get_code(code).and_then(|value| value.chars().next())
}
pub fn get_code_integer(&self, code: char) -> Option<i32> {
self.get_code(code).and_then(|value| value.parse().ok())
}
pub fn is_ok(&self) -> bool {
self.message.as_ref().map(|message| message == "OK").unwrap_or_default()
}
}
impl TryFrom<&[u8]> for Response {
type Error = Error;
fn try_from(response: &[u8]) -> Result<Self> {
let response = str::from_utf8(response).map_err(Error::other)?;
if !response.is_ascii() {
return Err(Error::other("Kitty response is not ASCII"));
}
let (control, message) = match response.split_once(';') {
Some((control, message)) => (control, Some(message.into())),
None => (response, None),
};
let control: Vec<_> = control
.split(',')
.into_iter()
.filter_map(|control| control.split_once('='))
.filter_map(|(key, value)| key.chars().next().map(|key| (key, String::from(value))))
.collect();
Ok(Self { control, message })
}
}