Created
November 15, 2015 19:14
-
-
Save anonymous/47360cb43ad2ca8af1b2 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::convert::From; | |
use std::str; | |
fn main() { | |
let packet = ServerInfoPacket{ | |
version: 42, | |
description: "hello", | |
}; | |
let mut bytes = encode_packet(packet); | |
println!("{:?}", bytes); | |
let mut bytes = &mut ProtocolVec(&mut bytes); | |
let packet = decode_packet(bytes); | |
println!("{:?}", packet); | |
} | |
#[derive(Debug)] | |
enum DecodedPacket<'a> { | |
ServerInfo(ServerInfoPacket<'a>) | |
} | |
fn decode_packet<'a>(src: &'a mut ProtocolVec) -> DecodedPacket<'a> { | |
let length = src.read_unsigned_short(); | |
let id = src.read_unsigned_short(); | |
let packet = match id { | |
1 => DecodedPacket::ServerInfo(ServerInfoPacket::decode(src)), | |
_ => panic!("hello"), | |
}; | |
packet | |
} | |
fn encode_packet<T: EncodeablePacket>(packet: T) -> Vec<u8> { | |
let body_length = packet.len(); | |
let mut body = Vec::with_capacity(body_length as usize); | |
let mut body = ProtocolVec(&mut body); | |
packet.encode(&mut body); | |
let packet_length = body_length + 2 + 2; | |
let mut dst: Vec<u8> = Vec::with_capacity(packet_length as usize); | |
dst.push((packet_length >> 8) as u8); | |
dst.push(packet_length as u8); | |
let id = packet.id(); | |
dst.push((id >> 8) as u8); | |
dst.push(id as u8); | |
dst.append(body.as_vec()); | |
dst | |
} | |
trait EncodeablePacket { | |
fn id(&self) -> u32; | |
fn len(&self) -> u32; | |
fn encode(&self, &mut ProtocolVec); | |
} | |
trait DecodeablePacket<'a> { | |
fn decode(&'a mut ProtocolVec) -> Self; | |
} | |
#[derive(Debug)] | |
struct ServerInfoPacket<'a> { | |
version: u16, | |
description: &'a str | |
} | |
impl<'a> EncodeablePacket for ServerInfoPacket<'a> { | |
fn id(&self) -> u32 { | |
412 | |
} | |
fn len(&self) -> u32 { | |
2 + 2 + (self.description.len() as u32) | |
} | |
fn encode(&self, dst: &mut ProtocolVec) { | |
dst.write_unsigned_short(self.version); | |
dst.write_string(self.description); | |
} | |
} | |
impl<'a> DecodeablePacket<'a> for ServerInfoPacket<'a> { | |
fn decode(src: &'a mut ProtocolVec) -> ServerInfoPacket<'a> { | |
ServerInfoPacket{ | |
version: src.read_unsigned_short(), | |
description: src.read_string(), | |
} | |
} | |
} | |
struct ProtocolVec<'a>(&'a mut Vec<u8>); | |
impl<'a> ProtocolVec<'a> { | |
fn write_unsigned_short(&mut self, num: u16) { | |
self.0.push((num >> 8) as u8); | |
self.0.push(num as u8); | |
} | |
fn write_string(&mut self, string: &str) { | |
self.write_unsigned_short(string.len() as u16); | |
self.0.append(&mut Vec::from(string)); | |
} | |
fn read_unsigned_short(&mut self) -> u16 { | |
((self.0.remove(0) as u16) << 8) | (self.0.remove(0) as u16) | |
} | |
fn read_string(&mut self) -> &str { | |
let length = self.read_unsigned_short(); | |
let (vec, bytes) = self.0.split_at(length as usize); | |
self.0 = &mut vec.to_vec(); | |
str::from_utf8(bytes).unwrap() | |
} | |
fn as_vec(&mut self) -> &mut Vec<u8> { | |
self.0 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment