use crate::osm_io::error::{Error, ErrorKind, Result};
use std::io::{Read, Write};
#[derive(Debug)]
pub struct VarInt {
bytes: Vec<u8>,
}
impl VarInt {
pub fn new(bytes: Vec<u8>) -> Self {
VarInt { bytes }
}
pub fn create_bytes<T: Into<VarInt>>(value: T) -> Vec<u8> {
let varint: VarInt = value.into();
varint.into_bytes()
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
pub trait ReadVarInt: Read {
fn read_varint(&mut self) -> Result<VarInt> {
let mut bytes = Vec::new();
for i in 0..10 {
if i == 9 {
return Err(Error::new(
ErrorKind::ParseError,
Some("Varint overflow, read 9 bytes.".to_owned()),
));
}
let mut buf = [0u8; 1];
self.read_exact(&mut buf)?;
let byte = buf[0];
bytes.push(byte);
if byte & 0x80 == 0 {
break;
}
}
Ok(VarInt { bytes })
}
}
impl<R: Read + ?Sized> ReadVarInt for R {}
pub trait WriteVarInt: Write {
fn write_varint<T: Into<VarInt>>(&mut self, i: T) -> Result<()> {
let varint: VarInt = i.into();
self.write_all(&varint.bytes)?;
Ok(())
}
}
impl<W: Write + ?Sized> WriteVarInt for W {}
impl From<VarInt> for i64 {
fn from(mut vi: VarInt) -> Self {
let (first, rest) = vi.bytes.split_first().unwrap();
let byte = *first as u64;
let negative = (byte & 0x01) != 0x00;
let mut value = (byte & 0x7E) >> 1;
if (byte & 0x80) != 0x00 {
vi.bytes = rest.to_vec();
value |= (Into::<u64>::into(vi)) << 6;
}
let value = value as i64;
if negative {
-value - 1
} else {
value
}
}
}
impl From<VarInt> for u64 {
fn from(vi: VarInt) -> Self {
let mut value = 0;
for (n, _) in vi.bytes.iter().enumerate() {
let byte = vi.bytes[n] as u64;
value |= (byte & 0x7F) << (7 * (n as u64));
if byte & 0x80 == 0 {
break;
}
}
value
}
}
impl From<u32> for VarInt {
fn from(value: u32) -> Self {
VarInt::from(value as u64)
}
}
impl From<u64> for VarInt {
fn from(mut value: u64) -> Self {
let mut bytes = Vec::new();
while value > 0x7F {
bytes.push(((value & 0x7F) | 0x80) as u8);
value >>= 7;
}
if value > 0 {
bytes.push(value as u8);
}
VarInt::new(bytes)
}
}
impl From<i32> for VarInt {
fn from(value: i32) -> Self {
VarInt::from(value as i64)
}
}
impl From<i64> for VarInt {
fn from(mut value: i64) -> Self {
let mut sign_bit = 0x00;
if value < 0 {
sign_bit = 0x01;
value = -value - 1;
}
let value = value as u64;
let least_significant = (((value << 1) & 0x7F) | sign_bit) as u8;
let mut bytes = Vec::new();
if value > 0x3F {
bytes.push(least_significant | 0x80);
let mut rest = Self::from((value >> 6) as u64);
bytes.append(&mut rest.bytes);
} else {
bytes.push(least_significant);
}
VarInt::new(bytes)
}
}
#[cfg(test)]
mod test_from_bytes {
use crate::osm_io::o5m::varint::ReadVarInt;
use crate::osm_io::o5m::varint::VarInt;
#[test]
fn max_one_byte_uvarint() {
let varint = VarInt::new(vec![0x7F]);
assert_eq!(Into::<u64>::into(varint), 127);
}
#[test]
fn read_two_bytes_uvarint() {
let data = vec![0xC3, 0x02];
let varint = data.as_slice().read_varint().unwrap();
assert_eq!(Into::<u64>::into(varint), 323);
}
#[test]
fn three_byte_uvarint() {
let varint = VarInt::new(vec![0x80, 0x80, 0x01]);
assert_eq!(Into::<u64>::into(varint), 16384);
}
#[test]
fn read_one_byte_positive_varint() {
let data = vec![0x08];
let varint = data.as_slice().read_varint().unwrap();
assert_eq!(Into::<i64>::into(varint), 4);
}
#[test]
fn one_byte_negative_varint() {
let varint = VarInt::new(vec![0x03]);
assert_eq!(Into::<i64>::into(varint), -2);
}
#[test]
fn read_four_byte_positive_varint() {
let data = vec![0x94, 0xfe, 0xd2, 0x05];
let varint = data.as_slice().read_varint().unwrap();
assert_eq!(Into::<i64>::into(varint), 5922698);
}
#[test]
fn two_byte_negative_varint() {
let varint = VarInt::new(vec![0x81, 0x01]);
assert_eq!(Into::<i64>::into(varint), -65);
}
#[test]
fn too_many_bytes() {
let data = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let error = data.as_slice().read_varint().unwrap_err();
assert_eq!(error.to_string(), "Varint overflow, read 9 bytes.")
}
}
#[cfg(test)]
mod test_to_bytes {
use crate::osm_io::o5m::varint::VarInt;
#[test]
fn one_byte_uvarint() {
let varint = VarInt::from(5 as u64);
assert_eq!(varint.bytes, vec![0x05]);
}
#[test]
fn max_one_byte_uvarint() {
let varint = VarInt::from(127 as u64);
assert_eq!(varint.bytes, vec![0x7F]);
}
#[test]
fn two_byte_uvarint() {
let varint = VarInt::from(323 as u64);
assert_eq!(varint.bytes, vec![0xC3, 0x02]);
}
#[test]
fn three_byte_uvarint() {
let varint = VarInt::from(16384 as u64);
assert_eq!(varint.bytes, vec![0x80, 0x80, 0x01]);
}
#[test]
fn one_byte_positive_varint() {
let varint = VarInt::from(4 as i64);
assert_eq!(varint.bytes, vec![0x08]);
}
#[test]
fn one_byte_negative_varint() {
let varint = VarInt::from(-3 as i64);
assert_eq!(varint.bytes, vec![0x05]);
}
#[test]
fn two_byte_positive_varint() {
let varint = VarInt::from(64 as i64);
assert_eq!(varint.bytes, vec![0x80, 0x01]);
}
#[test]
fn two_byte_negative_varint() {
let varint = VarInt::from(-65 as i64);
assert_eq!(varint.bytes, vec![0x81, 0x01]);
}
}