1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
extern crate byteorder;

use std::io::{Read, Write, Error, ErrorKind, self};

use byteorder::{ReadBytesExt, WriteBytesExt};

pub trait VarIntRead: Read {
    fn read_varint_u32(&mut self) -> io::Result<u32> {
        const PART: u32 = 0x7F;
        let mut size = 0;
        let mut val = 0u32;
        loop {
            let b = self.read_u8()? as u32;
            val |= (b & PART) << (size * 7);
            size += 1;
            if size > 5{
                return Err(Error::from(ErrorKind::InvalidInput));
            }
            if (b & 0x80) == 0 {
                break;
            }
        }
        Ok(val)
    }
}

pub trait VarIntWrite: Write {
    fn write_varint_u32(&mut self, val: u32) -> io::Result<()> {
        const PART: u32 = 0x7F;
        let mut val = val;
        loop {
            if (val & !PART) == 0 {
                self.write_u8(val as u8)?;
                return Ok(());
            }
            self.write_u8(((val & PART) | 0x80) as u8)?;
            val >>= 7;
        }
    }
}

impl <R: Read + Sized> VarIntRead for R {
}

impl <W: Write + Sized> VarIntWrite for W {
}