minecraft_client_rs/
message.rs

1use 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}