use std::convert::TryInto;
use super::line::Line;
use super::message::Message;
use super::word::Word;
use crate::util::{expect_word, parsei64};
pub(super) enum InternalReply {
Normal(Reply),
HistoryInit(i64),
HistoryMessage(i64, Message), }
#[derive(Debug, Clone)]
pub enum Reply {
Ok,
Number(i64),
Error(Box<Line>),
Name(Box<Word>),
List(Vec<Box<Word>>),
Pong,
History(Vec<Message>),
Message(Message),
}
impl Reply {
#[must_use]
pub fn ok(self) -> Option<()> {
match self {
Reply::Ok => Some(()),
_ => None,
}
}
#[must_use]
pub fn number(self) -> Option<i64> {
match self {
Reply::Number(n) => Some(n),
_ => None,
}
}
#[must_use]
pub fn error(self) -> Option<Box<Line>> {
match self {
Reply::Error(e) => Some(e),
_ => None,
}
}
#[must_use]
pub fn name(self) -> Option<Box<Word>> {
match self {
Reply::Name(n) => Some(n),
_ => None,
}
}
#[must_use]
pub fn list(self) -> Option<Vec<Box<Word>>> {
match self {
Reply::List(l) => Some(l),
_ => None,
}
}
#[must_use]
pub fn pong(self) -> Option<()> {
match self {
Reply::Pong => Some(()),
_ => None,
}
}
#[must_use]
pub fn history(self) -> Option<Vec<Message>> {
match self {
Reply::History(h) => Some(h),
_ => None,
}
}
#[must_use]
pub fn message(self) -> Option<Message> {
match self {
Reply::Message(m) => Some(m),
_ => None,
}
}
}
pub(super) fn parse(s: &str) -> (Box<Word>, InternalReply) {
let words: Vec<_> = s.split(' ').collect();
let make = |command: InternalReply| -> (Box<Word>, InternalReply) {
let tag = words[0].to_string().try_into().unwrap();
(tag, command)
};
let make_normal =
|command: Reply| -> (Box<Word>, InternalReply) { make(InternalReply::Normal(command)) };
let expect_line = |s: String| s.try_into().unwrap();
match words[1] {
"ok" => make_normal(Reply::Ok),
"number" => make_normal(Reply::Number(parsei64(words[2]))),
"error" => make_normal(Reply::Error(expect_line(words[2..].join(" ")))),
"name" => make_normal(Reply::Name(expect_word(words[2]))),
"list" => make_normal(Reply::List(words[3..].iter().map(expect_word).collect())),
"pong" => make_normal(Reply::Pong),
"message" => {
let message = Message::try_parse(&words[2..]).unwrap();
make_normal(Reply::Message(message))
}
"history" => make(InternalReply::HistoryInit(parsei64(words[2]))),
"history_message" => {
let index = parsei64(words[2]);
let message = Message::try_parse(&words[3..]).unwrap();
make(InternalReply::HistoryMessage(index, message))
}
w => panic!("unexpected response type: '{}'", w),
}
}