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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use std::collections::VecDeque;

use crate::packet::{self, Packet, Opcode};

pub(crate) struct Parser {
    state: State,
    buffer: Vec<u8>,
    packet_size: u32,
    opcode: Opcode,
    user_count: u32,
    nickname_size: u32,
    users: Vec<Vec<u8>>,
    current_byte: u32,
    body: Vec<u8>,
    packet_queue: VecDeque<Packet>,
}

impl Parser {
    pub(crate) fn new() -> Self {
        Self {
            state: State::Magic,
            buffer: Vec::new(),
            packet_size: 0,
            opcode: Opcode::ChangeNicknameRequest,
            user_count: 0,
            nickname_size: 0,
            users: Vec::new(),
            current_byte: 0,
            body: Vec::new(),
            packet_queue: VecDeque::new(),
        }
    }

    pub(crate) fn parse(&mut self, bytes: &[u8]) -> Result<(), Error> {
        fn parse_number(buffer: &mut Vec<u8>, byte: u8) -> Result<Option<u32>, Error> {
            if byte != packet::TERMINATOR {
                buffer.push(byte);
                Ok(None)
            } else {
                let result = std::str::from_utf8(&buffer).ok().and_then(|s| s.parse().ok()).ok_or(Error::CountIsNotANumber)?;
                buffer.clear();
                Ok(Some(result))
            }
        }

        for byte in bytes {
            let mut new_state = match self.state {
                State::Magic => {
                    if *byte == packet::MAGIC {
                        State::PacketSize
                    } else {
                        return Err(Error::InvalidMagic);
                    }
                },
                State::PacketSize => parse_number(&mut self.buffer, *byte)?
                    .map_or(State::PacketSize, |n| { self.packet_size = n; State::Opcode }),
                State::Opcode => {
                    self.opcode = (*byte).try_into()?;
                    State::UserCount
                },
                State::UserCount => parse_number(&mut self.buffer, *byte)?
                    .map_or(State::UserCount, |n| { self.user_count = n; State::UserNicknameSize }),
                State::UserNicknameSize => parse_number(&mut self.buffer, *byte)?
                    .map_or(State::UserNicknameSize, |n| { self.nickname_size = n; State::UserNickname }),
                State::UserNickname => {
                    let in_size_limit = |size| size < (self.nickname_size as usize);

                    if in_size_limit(self.buffer.len()) {
                        self.buffer.push(*byte);
                    }

                    if in_size_limit(self.buffer.len()) {
                        State::UserNickname
                    } else {
                        self.users.push(self.buffer.clone());
                        self.buffer.clear();
                        State::UserNicknameSize
                    }
                },
                State::Body => {
                    self.body.push(*byte);
                    State::Body
                },
            };

            if matches!(new_state, State::UserNicknameSize) && self.users.len() >= self.user_count as usize {
                self.body.clear();
                new_state = State::Body;
            }

            if self.state.counts_to_size() {
                self.current_byte += 1;
            }

            if self.current_byte >= self.packet_size && matches!(new_state, State::Body) {
                let mut body = Vec::new();
                body.append(&mut self.body);
                let body_to_list = || body.split(|a| *a == packet::SEPARATOR).map(|s| s.to_vec()).collect();
                let mut users = Vec::new();
                users.append(&mut self.users);

                self.packet_queue.push_back(match self.opcode {
                    Opcode::SetNicknameRequest => Packet::SetNicknameRequest(body),
                    Opcode::SetNickname => Packet::SetNickname(body),
                    Opcode::ChangeNicknameRequest => Packet::ChangeNicknameRequest(body),
                    Opcode::ChangeNickname => Packet::ChangeNickname(body),
                    Opcode::UserListRequest => Packet::UserListRequest,
                    Opcode::UserListResponse => Packet::UserListResponse(users),
                    Opcode::SendWord => Packet::SendWord { sender: users.remove(0), recipients: users, word: body },
                    Opcode::DeliverWord => Packet::DeliverWord { sender: users.swap_remove(0), word: body },
                    Opcode::SendInstructions => Packet::SendInstructions { sender: users.remove(0), recipients: users, instructions: body },
                    Opcode::DeliverInstructions => Packet::DeliverInstructions { sender: users.swap_remove(0), instructions: body },
                    Opcode::SendList => Packet::SendList { sender: users.remove(0), recipients: users, list: body_to_list() },
                    Opcode::DeliverList => Packet::DeliverList { sender: users.swap_remove(0), list: body_to_list() },
                    Opcode::SendImage => Packet::SendImage { sender: users.remove(0), recipients: users, bytes: body },
                    Opcode::DeliverImage => Packet::DeliverImage { sender: users.swap_remove(0), bytes: body },
                    Opcode::SendObject => Packet::SendObject { sender: users.remove(0), recipients: users, bytes: body },
                    Opcode::DeliverObject => Packet::DeliverObject { sender: users.swap_remove(0), bytes: body },
                });

                self.current_byte = 0;
                self.buffer.clear();
                new_state = State::Magic;
            }

            self.state = new_state;
        }

        Ok(())
    }

    pub fn get_packet(&mut self) -> Option<Packet> {
        self.packet_queue.pop_front()
    }
}

#[derive(Debug)]
pub enum Error {
    InvalidMagic,
    CountIsNotANumber,
    PacketError(packet::Error)
}

impl From<packet::Error> for Error {
    fn from(e: packet::Error) -> Self {
        Self::PacketError(e)
    }
}

#[derive(Debug)]
enum State {
    Magic,
    PacketSize,
    Opcode,
    UserCount,
    UserNicknameSize,
    UserNickname,
    Body,
}

impl State {
    fn counts_to_size(&self) -> bool {
        match self {
            Self::Magic | Self::PacketSize => false,
            _ => true,
        }
    }
}