Skip to content

Instantly share code, notes, and snippets.

@kimhyunkang
Created April 4, 2013 02:37
Show Gist options
  • Save kimhyunkang/5307274 to your computer and use it in GitHub Desktop.
Save kimhyunkang/5307274 to your computer and use it in GitHub Desktop.
This source code fails to compile in rust-0.6
mod protobuf;
#[deriving(Eq)]
pub enum ProtoValue {
Variant(u64),
Fixed64(u64),
Bytes(~[u8]),
Fixed32(u32),
}
pub struct Decoder {
priv rdr: @io::Reader,
}
pub fn Decoder(rdr: @io::Reader) -> Decoder {
Decoder {
rdr: rdr,
}
}
pub impl Decoder {
fn decode(&self) -> Result<(int, ProtoValue), ~str> {
let tag = self.decode_var();
let r_val = match(tag & 0b111) {
0 => Ok(Variant(self.decode_var())),
1 => Ok(Fixed64(self.rdr.read_le_u64())),
2 => Ok(Bytes(self.decode_bytes())),
5 => Ok(Fixed32(self.rdr.read_le_u32())),
_ => Err(~"bad wire type"),
};
do result::chain(r_val) |val| {
let field_num = (tag >> 3) as int;
Ok((field_num, val))
}
}
}
priv impl Decoder {
fn decode_bytes(&self) -> ~[u8] {
let length = self.decode_var() as uint;
self.rdr.read_bytes(length)
}
fn decode_var(&self) -> u64 {
let mut buffer: u64 = 0;
let mut shift = 0;
do self.rdr.each_byte |byte| {
buffer |= (byte as u64 & 0b01111111) << shift;
shift += 7;
byte & 0b10000000 != 0
}
buffer
}
}
pub struct Encoder {
priv wr: @io::Writer,
}
pub fn Encoder(wr: @io::Writer) -> Encoder {
Encoder {
wr: wr,
}
}
pub impl Encoder {
fn encode(&self, field_number: int, val: ProtoValue) {
let wire_type = match(val) {
Variant(_) => 0,
Fixed64(_) => 1,
Bytes(_) => 2,
Fixed32(_) => 5,
};
let tag = (field_number as u64 << 3) | wire_type;
self.encode_var(tag);
match(val) {
Variant(x) => self.encode_var(x),
Fixed64(x) => self.wr.write_le_u64(x),
Bytes(b) => self.encode_bytes(b),
Fixed32(x) => self.wr.write_le_u32(x),
};
}
}
priv impl Encoder {
fn encode_bytes(&self, bytes: &[u8]) {
self.encode_var(bytes.len() as u64);
self.wr.write(bytes);
}
fn encode_var(&self, val: u64) {
let mut buffer = val;
let bot_mask: u64 = 0b01111111;
let top_mask: u8 = 0b10000000;
while(buffer > bot_mask) {
let byte = (buffer & bot_mask) as u8 | top_mask;
self.wr.write_u8(byte);
buffer >>= 7;
}
self.wr.write_u8((buffer & bot_mask) as u8);
}
}
#[test]
fn test_decoder() {
let test_vector: ~[u8] = ~[0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x08, 0x96, 0x01];
do io::with_bytes_reader(test_vector) |rdr| {
let decoder = Decoder(rdr);
let bytes = "testing".to_bytes();
assert_eq!(decoder.decode(), Ok((2, Bytes(bytes))));
assert_eq!(decoder.decode(), Ok((1, Variant(150))));
}
}
#[test]
fn test_encoder() {
let test_vector: ~[u8] = ~[0x08, 0x96, 0x01];
let encoded = do io::with_bytes_writer() |wr| {
let encoder = Encoder(wr);
encoder.encode(1, Variant(150));
};
assert_eq!(test_vector, encoded);
let test_vector: ~[u8] = ~[0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67];
let encoded = do io::with_bytes_writer() |wr| {
let encoder = Encoder(wr);
let bytes = "testing".to_bytes();
encoder.encode(2, Bytes(bytes));
};
assert_eq!(test_vector, encoded);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment