use std::net::TcpStream;
use std::io::{Read, Write};
use serde_json;
use inquire::Select;
const NET_ERR: &str = "network error";
pub struct Client {
pub stream: TcpStream,
}
pub enum Message {
Text(String),
Number(usize),
Json(String),
Begin,
End,
}
impl Message {
pub fn unwrap(self) -> String {
match self {
Text(s) | Json(s) => s,
_ => panic!("can't unwrap"),
}
}
}
use Message::*;
impl Client {
pub fn new(addr: String) -> Client {
let stream = TcpStream::connect(&addr).expect(NET_ERR);
Client { stream }
}
fn read_line(stream: &mut TcpStream) -> Vec<u8> {
let mut buf: [u8; 1] = [0];
let mut res = Vec::new();
loop {
match stream.read_exact(&mut buf) {
Ok(_) => {
if buf[0] == 0x7 {
break;
}
res.push(buf[0]);
}
Err(_) => {
break;
}
}
}
res
}
pub fn rec(&mut self) -> String {
let msg = Self::read_line(&mut self.stream);
let res = String::from_utf8(msg).unwrap();
res
}
pub fn rec_number(&mut self) -> u64 {
let res = self.receive();
if let Number(x) = res {
x as u64
}
else { panic!("not a number"); }
}
pub fn send(&mut self, message: &str) {
let message = format!("{}\x07", message);
self.stream.write_all(message.as_bytes()).unwrap();
}
pub fn transimit(&mut self, x: Message) {
match x {
Text(s) => self.send(&format!("t{}", s)),
Number(n) => self.send(&format!("n{}", n)),
Json(s) => self.send(&format!("j{}", s)),
_ => panic!("can't send"),
}
}
pub fn receive(&mut self) -> Message {
let msg = self.rec();
let mut it = msg.chars();
let typ = it.next().unwrap();
let s = it.collect();
match typ {
'y' => Begin,
'o' => End,
'j' => Json(s),
'm' => Text(s),
'n' => Number(s.parse().unwrap()),
_ => panic!("received type error"),
}
}
pub fn begin(&mut self) {
let res = self.receive();
match res {
Begin => return,
_ => panic!("begin error"),
}
}
pub fn end(&mut self) {
let res = self.receive();
match res {
End => return,
_ => panic!("end error"),
}
}
}
pub fn vote(cli: &mut Client) {
let pmt = cli.receive().unwrap();
let s = cli.receive().unwrap();
let list: Vec<String> = serde_json::from_str(&s).unwrap();
println!();
let inq = Select::new(&pmt, list.clone()).prompt().unwrap();
for c in list.into_iter().enumerate() {
if c.1 == inq { cli.transimit(Number(c.0)); break; }
}
}