Created
April 4, 2013 02:37
-
-
Save kimhyunkang/5307274 to your computer and use it in GitHub Desktop.
This source code fails to compile in rust-0.6
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
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