minecraft_client_rs/
message.rs1use std::convert::TryInto;
2use std::error::Error;
3use std::str::from_utf8;
4
5pub const HEADER_SIZE: i32 = 10;
6
7#[repr(i32)]
8pub enum MessageType {
9 Response,
10 _Unused,
11 Command,
12 Authenticate,
13}
14
15#[derive(Debug)]
16pub struct Message {
17 pub size: i32,
18 pub id: i32,
19 pub msg_type: i32,
20 pub body: String,
21}
22
23pub fn encode_message(msg: Message) -> Vec<u8> {
24 let mut bytes: Vec<u8> = vec!();
25
26 bytes.extend_from_slice(&msg.size.to_le_bytes());
27 bytes.extend_from_slice(&msg.id.to_le_bytes());
28 bytes.extend_from_slice(&msg.msg_type.to_le_bytes());
29 bytes.extend_from_slice(msg.body.as_bytes());
30 bytes.extend_from_slice(&[0, 0]);
31
32 bytes
33}
34
35pub fn decode_message(bytes: Vec<u8>) -> Result<Message, Box<dyn Error>> {
36 let size = i32::from_le_bytes(bytes[0..4].try_into()?);
37 let id = i32::from_le_bytes(bytes[4..8].try_into()?);
38 let msg_type = i32::from_le_bytes(bytes[8..12].try_into()?);
39
40 let mut body = "".to_string();
41 let body_len: usize = (size - HEADER_SIZE).try_into()?;
42 if body_len > 0 {
43 let body_bytes = from_utf8(&bytes[12..12+body_len])?;
44 body = body_bytes.to_string();
45 }
46
47 Ok(Message{
48 size: size,
49 id: id,
50 msg_type: msg_type,
51 body: body,
52 })
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_encode_message() {
61 let bytes = encode_message(Message{
62 size: 5 + HEADER_SIZE,
63 id: 1,
64 msg_type: MessageType::Command as i32,
65 body: "hello".to_string(),
66 });
67
68 let expected: Vec<u8> = vec!(15, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 104, 101, 108, 108, 111, 0, 0);
69
70 assert_eq!(bytes, expected);
71 }
72
73 #[test]
74 fn test_decode_message() {
75 let bytes: Vec<u8> = vec!(12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 104, 105);
76 let msg = decode_message(bytes).unwrap();
77
78 let expected = Message{
79 size: 2 + HEADER_SIZE,
80 id: 2,
81 msg_type: MessageType::Response as i32,
82 body: "hi".to_string(),
83 };
84
85 assert_eq!(msg.size, expected.size);
86 assert_eq!(msg.id, expected.id);
87 assert_eq!(msg.msg_type, expected.msg_type);
88 assert_eq!(msg.body, expected.body);
89 }
90}