Skip to content

Instantly share code, notes, and snippets.

Created November 15, 2015 19:14
Show Gist options
  • Save anonymous/47360cb43ad2ca8af1b2 to your computer and use it in GitHub Desktop.
Save anonymous/47360cb43ad2ca8af1b2 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
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