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
use std::convert::TryInto; use std::error::Error; use std::str::from_utf8; pub const HEADER_SIZE: i32 = 10; #[repr(i32)] pub enum MessageType { Response, _Unused, Command, Authenticate, } #[derive(Debug)] pub struct Message { pub size: i32, pub id: i32, pub msg_type: i32, pub body: String, } pub fn encode_message(msg: Message) -> Vec<u8> { let mut bytes: Vec<u8> = vec!(); bytes.extend_from_slice(&msg.size.to_le_bytes()); bytes.extend_from_slice(&msg.id.to_le_bytes()); bytes.extend_from_slice(&msg.msg_type.to_le_bytes()); bytes.extend_from_slice(msg.body.as_bytes()); bytes.extend_from_slice(&[0, 0]); bytes } pub fn decode_message(bytes: Vec<u8>) -> Result<Message, Box<dyn Error>> { let size = i32::from_le_bytes(bytes[0..4].try_into()?); let id = i32::from_le_bytes(bytes[4..8].try_into()?); let msg_type = i32::from_le_bytes(bytes[8..12].try_into()?); let mut body = "".to_string(); let body_len: usize = (size - HEADER_SIZE).try_into()?; if body_len > 0 { let body_bytes = from_utf8(&bytes[12..12+body_len])?; body = body_bytes.to_string(); } Ok(Message{ size: size, id: id, msg_type: msg_type, body: body, }) } #[cfg(test)] mod tests { use super::*; #[test] fn test_encode_message() { let bytes = encode_message(Message{ size: 5 + HEADER_SIZE, id: 1, msg_type: MessageType::Command as i32, body: "hello".to_string(), }); let expected: Vec<u8> = vec!(15, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 104, 101, 108, 108, 111, 0, 0); assert_eq!(bytes, expected); } #[test] fn test_decode_message() { let bytes: Vec<u8> = vec!(12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 104, 105); let msg = decode_message(bytes).unwrap(); let expected = Message{ size: 2 + HEADER_SIZE, id: 2, msg_type: MessageType::Response as i32, body: "hi".to_string(), }; assert_eq!(msg.size, expected.size); assert_eq!(msg.id, expected.id); assert_eq!(msg.msg_type, expected.msg_type); assert_eq!(msg.body, expected.body); } }