1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! 实现底层通讯。

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 {
    /// 方便从消息中获得原始信息和 json 字符串。
    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 }
    }

    /// 接收一条消息。TcpStream 是流式的,没有消息分隔。这里以蜂鸣器控制字符分隔。
    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();
        // #[cfg(debug_assertions)]
        // println!("{}: {}", "Received", res);
        res
    }

    /// 接收数字,收到的不是数字说明服务端出了大问题,直接 panic。
    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();
        // #[cfg(debug_assertions)]
        // println!("{}: {}", "Sended", message);
    }

    /// 发送 [`Message`] 封装好的信息。
    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"),
        }
    }

    /// 接收消息,用 [`Message`] 封装好。
    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; }
    }
}