├── .gitignore ├── README.md ├── Cargo.toml ├── LICENSE ├── benches └── rw.rs └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | *.iml 5 | .idea/ 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # minecaft-varint 2 | Minecraft VarInt and VarLong implemetation in Rust, providing minimum memory usage and maximum performance. 3 | 4 | [![Crates.io][crates-badge]][crates-url] 5 | [![WTFPL licensed][pl-badge]][pl-url] 6 | 7 | [crates-badge]: https://img.shields.io/crates/v/minecraft-varint.svg 8 | [crates-url]: https://crates.io/crates/minecraft-varint 9 | [pl-badge]: https://img.shields.io/badge/license-WTFPL-blue.svg 10 | [pl-url]: LICENSE 11 | 12 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "minecraft-varint" 3 | version = "0.2.0" 4 | authors = ["luojia65 ", "belohnung "] 5 | description = "Minecraft's VarInt and VarLong implemetation in Rust, providing minimum memory usage and maximum performance." 6 | license = "WTFPL" 7 | readme = "README.md" 8 | repository = "https://github.com/belohnung/minecraft-varint" 9 | documentation = "https://docs.rs/minecraft-varint" 10 | keywords = ["minecraft"] 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar ; 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /benches/rw.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | extern crate mc_varint; 4 | 5 | use std::io; 6 | use mc_varint::{VarIntRead, VarIntWrite}; 7 | 8 | // FF*8 [0, 7], 7F [8] 9 | 10 | struct VarI64Gen { 11 | state: u8 12 | } 13 | 14 | impl VarI64Gen { 15 | fn new() -> Self { 16 | Self { state: 0 } 17 | } 18 | } 19 | 20 | impl io::Read for VarI64Gen { 21 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 22 | buf[0] = if self.state != 8 { 0xff } else { 0x7f }; 23 | self.state = (self.state + 1) % 9; 24 | Ok(1) 25 | } 26 | } 27 | // FF*4 [0, 3], 7F [4] 28 | 29 | struct VarI32Gen { 30 | state: u8 31 | } 32 | 33 | impl VarI32Gen { 34 | fn new() -> Self { 35 | Self { state: 0 } 36 | } 37 | } 38 | 39 | impl io::Read for VarI32Gen { 40 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 41 | buf[0] = if self.state != 4 { 0xff } else { 0x7f }; 42 | self.state = (self.state + 1) % 5; 43 | Ok(1) 44 | } 45 | } 46 | 47 | #[bench] 48 | fn read_i64(b: &mut test::Bencher) { 49 | b.iter(|| { 50 | let mut src = VarI64Gen::new(); 51 | let _ = test::black_box(src.read_var_i64()).unwrap(); 52 | }) 53 | } 54 | 55 | #[bench] 56 | fn read_u64(b: &mut test::Bencher) { 57 | b.iter(|| { 58 | let mut src = VarI64Gen::new(); 59 | let _ = test::black_box(src.read_var_u64()).unwrap(); 60 | }) 61 | } 62 | 63 | #[bench] 64 | fn read_i32(b: &mut test::Bencher) { 65 | b.iter(|| { 66 | let mut src = VarI32Gen::new(); 67 | let _ = test::black_box(src.read_var_i32()).unwrap(); 68 | }) 69 | } 70 | 71 | #[bench] 72 | fn read_u32(b: &mut test::Bencher) { 73 | b.iter(|| { 74 | let mut src = VarI32Gen::new(); 75 | let _ = test::black_box(src.read_var_u32()).unwrap(); 76 | }) 77 | } 78 | 79 | struct Blackhole; 80 | 81 | impl io::Write for Blackhole { 82 | fn write(&mut self, buf: &[u8]) -> io::Result { 83 | Ok(buf.len()) 84 | } 85 | 86 | fn flush(&mut self) -> io::Result<()> { 87 | Ok(()) 88 | } 89 | } 90 | 91 | #[bench] 92 | fn write_i64(b: &mut test::Bencher) { 93 | b.iter(|| { 94 | let mut dst = Blackhole; 95 | let _ = test::black_box(dst.write_var_i64(i64::min_value())).unwrap(); 96 | }) 97 | } 98 | 99 | #[bench] 100 | fn write_u64(b: &mut test::Bencher) { 101 | b.iter(|| { 102 | let mut dst = Blackhole; 103 | let _ = test::black_box(dst.write_var_u64(u64::min_value())).unwrap(); 104 | }) 105 | } 106 | 107 | #[bench] 108 | fn write_i32(b: &mut test::Bencher) { 109 | b.iter(|| { 110 | let mut dst = Blackhole; 111 | let _ = test::black_box(dst.write_var_i32(i32::min_value())).unwrap(); 112 | }) 113 | } 114 | 115 | #[bench] 116 | fn write_u32(b: &mut test::Bencher) { 117 | b.iter(|| { 118 | let mut dst = Blackhole; 119 | let _ = test::black_box(dst.write_var_u32(u32::min_value())).unwrap(); 120 | }) 121 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | type Result = std::io::Result; 2 | 3 | fn zigzag_encode_32(src: i32) -> u32 { 4 | if src >= 0 { 5 | (src as u32) << 1 6 | } else { 7 | (((-src) as u32) << 1) - 1 8 | } 9 | } 10 | 11 | fn zigzag_decode_32(src: u32) -> i32 { 12 | if src & 1 != 0 { 13 | -((src >> 1) as i32) - 1 14 | } else { 15 | (src >> 1) as i32 16 | } 17 | } 18 | 19 | fn zigzag_encode_64(src: i64) -> u64 { 20 | if src >= 0 { 21 | (src as u64) << 1 22 | } else { 23 | (((-src) as u64) << 1) - 1 24 | } 25 | } 26 | 27 | fn zigzag_decode_64(src: u64) -> i64 { 28 | if src & 1 != 0 { 29 | -((src >> 1) as i64) - 1 30 | } else { 31 | (src >> 1) as i64 32 | } 33 | } 34 | 35 | pub trait VarIntRead { 36 | fn read_var_i64(&mut self) -> Result { 37 | self.read_var_u64().map(|x| zigzag_decode_64(x)) 38 | } 39 | 40 | fn read_var_i32(&mut self) -> Result { 41 | self.read_var_u32().map(|x| zigzag_decode_32(x)) 42 | } 43 | 44 | fn read_var_u64(&mut self) -> Result; 45 | 46 | fn read_var_u32(&mut self) -> Result; 47 | } 48 | 49 | pub trait VarIntWrite { 50 | fn write_var_i32(&mut self, value: i32) -> Result { 51 | self.write_var_u32(zigzag_encode_32(value)) 52 | } 53 | 54 | fn write_var_i64(&mut self, value: i64) -> Result { 55 | self.write_var_u64(zigzag_encode_64(value)) 56 | } 57 | 58 | fn write_var_u32(&mut self, value: u32) -> Result; 59 | 60 | fn write_var_u64(&mut self, value: u64) -> Result; 61 | } 62 | 63 | impl VarIntRead for R 64 | where 65 | R: std::io::Read, 66 | { 67 | fn read_var_u64(&mut self) -> Result { 68 | let mut buf = [0]; 69 | let mut ans = 0; 70 | for i in 0..9 { 71 | self.read_exact(&mut buf)?; 72 | 73 | ans |= (buf[0] as u64 & 0x7F) << 7 * i; 74 | 75 | if buf[0] & 0x80 == 0 { 76 | break; 77 | } 78 | } 79 | Ok(ans) 80 | } 81 | 82 | fn read_var_u32(&mut self) -> Result { 83 | let mut buf = [0]; 84 | let mut ans = 0; 85 | for i in 0..5 { 86 | self.read_exact(&mut buf)?; 87 | 88 | ans |= (buf[0] as u32 & 0x7F) << 7 * i; 89 | 90 | if buf[0] & 0x80 == 0 { 91 | break; 92 | } 93 | } 94 | Ok(ans) 95 | } 96 | } 97 | 98 | impl VarIntWrite for W 99 | where 100 | W: std::io::Write, 101 | { 102 | fn write_var_u32(&mut self, mut value: u32) -> Result { 103 | let mut buf = [0; (u32::BITS as usize + 6) / 7]; 104 | let mut i = 0; 105 | 106 | loop { 107 | buf[i] = (value & 0b0111_1111) as u8; 108 | value >>= 7; 109 | if value != 0 { 110 | buf[i] |= 0b1000_0000; 111 | } 112 | i += 1; 113 | 114 | if value == 0 { 115 | break; 116 | } 117 | } 118 | 119 | self.write_all(&buf[..i])?; 120 | Ok(i) 121 | } 122 | 123 | fn write_var_u64(&mut self, mut value: u64) -> Result { 124 | let mut buf = [0; (u64::BITS as usize + 6) / 7]; 125 | let mut i = 0; 126 | 127 | loop { 128 | buf[i] = (value & 0b0111_1111) as u8; 129 | value >>= 7; 130 | if value != 0 { 131 | buf[i] |= 0b1000_0000; 132 | } 133 | i += 1; 134 | 135 | if value == 0 { 136 | break; 137 | } 138 | } 139 | 140 | self.write_all(&buf[..i])?; 141 | Ok(i) 142 | } 143 | } 144 | --------------------------------------------------------------------------------