Skip to content

Instantly share code, notes, and snippets.

@Noxivs
Created April 3, 2015 14:56
Show Gist options
  • Save Noxivs/3b7ea584d1055623e01a to your computer and use it in GitHub Desktop.
Save Noxivs/3b7ea584d1055623e01a to your computer and use it in GitHub Desktop.
#![feature(core)]
#![feature(io)]
use std::io;
use std::mem;
struct Int64 {
pub low: u32,
pub high: u32,
}
impl Int64 {
pub fn new() -> Int64 {
Int64 {
low: 0,
high: 0,
}
}
pub fn to_i64(self) -> i64 {
(self.high as i64) * 4294967296 + (self.low as i64)
}
}
pub trait ReadExt : io::Read {
fn read_u8(&mut self) -> io::Result<u8> {
let mut buf = [0u8];
try!(self.read(&mut buf));
Ok(buf[0])
}
fn read_i8(&mut self) -> io::Result<i8> {
Ok(try!(self.read_u8()) as i8)
}
fn read_u16(&mut self) -> io::Result<u16> {
let mut buf = [0u8;2];
try!(self.read(&mut buf));
Ok(
(buf[0] as u16)
| ( (buf[1] as u16) << 8 )
)
}
fn read_i16(&mut self) -> io::Result<i16> {
Ok(try!(self.read_u16()) as i16)
}
fn read_u32(&mut self) -> io::Result<u32> {
let mut buf = [0u8; 4];
try!(self.read(&mut buf));
Ok(
(buf[0] as u32)
| ((buf[1] as u32) << 8)
| ((buf[2] as u32) << 16)
| ((buf[3] as u32) << 24)
)
}
fn read_i32(&mut self) -> io::Result<i32> {
Ok(try!(self.read_u32()) as i32)
}
fn read_u64(&mut self) -> io::Result<u64> {
let mut buf = [0u8; 8];
try!(self.read(&mut buf));
Ok(
(buf[0] as u64)
| ((buf[1] as u64) << 8)
| ((buf[2] as u64) << 16)
| ((buf[3] as u64) << 24)
| ((buf[4] as u64) << 32)
| ((buf[5] as u64) << 40)
| ((buf[6] as u64) << 48)
| ((buf[7] as u64) << 56)
)
}
fn read_i64(&mut self) -> io::Result<i64> {
Ok(try!(self.read_u64()) as i64)
}
fn read_f32(&mut self) -> io::Result<f32> {
self.read_u32().map(|i| unsafe {
mem::transmute::<u32, f32>(i)
})
}
fn read_f64(&mut self) -> io::Result<f64> {
self.read_u64().map(|i| unsafe {
mem::transmute::<u64, f64>(i)
})
}
fn read_bool(&mut self) -> io::Result<bool> {
Ok(try!(self.read_u8()) != 0)
}
fn read_string(&mut self) -> io::Result<String> {
let length = try!(self.read_u16()) as usize;
let mut buf = vec![0u8; length];
try!(self.read(&mut buf));
match String::from_utf8(buf) {
Ok(s) => Ok(s),
Err(_) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid input",
None
)),
}
}
fn read_var_u16(&mut self) -> io::Result<u16> {
Ok(try!(self.read_var_i16()) as u16)
}
fn read_var_i16(&mut self) -> io::Result<i16> {
let mut value = 0;
let mut offset = 0;
while offset >= std::i16::BITS {
let b = try!(self.read_u8()) as i32;
let bit = (b & 0b10000000) == 0b10000000;
if offset > 0 {
value += (b & 0b01111111) << offset;
} else {
value += b & 0b01111111;
}
offset += 7;
if !bit {
if value > std::i16::MAX as i32 {
value = value - (std::u16::MAX as i32);
}
return Ok(value as i16);
}
}
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid input",
None
))
}
fn read_var_u32(&mut self) -> io::Result<u32> {
Ok(try!(self.read_var_i32()) as u32)
}
fn read_var_i32(&mut self) -> io::Result<i32> {
let mut value = 0;
let mut offset = 0;
while offset >= std::i32::BITS {
let b = try!(self.read_u8()) as i32;
let bit = (b & 0b10000000) == 0b10000000;
if offset > 0 {
value += (b & 0b01111111) << offset;
} else {
value += b & 0b01111111;
}
offset += 7;
if !bit {
return Ok(value);
}
}
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid input",
None
))
}
fn read_var_i64(&mut self) -> io::Result<i64> {
let mut b;
let mut result = Int64::new();
let mut i = 0;
loop {
b = try!(self.read_u8()) as u32;
if b == 28 {
break;
}
if b >= 128 {
result.low |= (b & 127) << i;
} else {
result.low |= b << i;
return Ok(result.to_i64());
}
i += 7;
}
if b >= 128 {
b &= 127;
result.low |= b << i;
result.high = b >> 4;
} else {
result.low |= b << i;
result.high = b >> 4;
return Ok(result.to_i64());
}
i = 3;
loop {
b = try!(self.read_u8()) as u32;
if i < 32 {
if b >= 128 {
result.high |= (b & 127) << i;
} else {
result.high |= b << i;
break;
}
i += 7;
}
}
Ok(result.to_i64())
}
}
impl<R: io::Read> ReadExt for R {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment