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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::io;
use std::slice;

pub trait Read7BitEncodedI32Ext {
	fn read_7_bit_encoded_i32(&mut self) -> io::Result<i32>;
}

impl<T: io::Read> Read7BitEncodedI32Ext for T {
	fn read_7_bit_encoded_i32(&mut self) -> io::Result<i32> {
		let mut buf = 0u8;
		let mut result = 0u64;
		for i in 0..5 {
			self.read_exact(slice::from_mut(&mut buf))?;
			result |= ((buf & 127) as u64) << (i * 7);

			if buf & 128 == 0 {
				break;
			}
		}

		if result > u32::MAX as u64 {
			return Err(io::Error::new(
				io::ErrorKind::InvalidData,
				"Input data can't fit into i32",
			));
		}

		Ok(result as u32 as i32)
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use crate::read_byte_arr::ReadByteArr;
	#[test]
	fn reading_ints() {
		let encoded_7_bit_ints: [u8; 40] = [
			0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x08, 0x01, 0xff, 0xff, 0xff,
			0xff, 0x07, 0x00, 0x02, 0x05, 0x80, 0xa4, 0xe8, 0x03, 0x80, 0xd0, 0xa5, 0x4c, 0xb0,
			0xea, 0x01, 0xe0, 0x99, 0xf2, 0xfe, 0x0f, 0xc0, 0xca, 0xfe, 0xff, 0x0f,
		];

		let mut reader = ReadByteArr::new(&encoded_7_bit_ints);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -1);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -2147483648);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 1);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 2147483647);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 0);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 2);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 5);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 8000000);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 160000000);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), 30000);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -2323232);
		assert_eq!(reader.read_7_bit_encoded_i32().unwrap(), -23232);
	}

	#[test]
	fn too_short() {
		let encoded_7_bit_int: [u8; 1] = [0xFF];
		let mut reader = ReadByteArr::new(&encoded_7_bit_int);
		assert_eq!(
			reader.read_7_bit_encoded_i32().map_err(|e| e.kind()),
			Err(io::ErrorKind::UnexpectedEof)
		);
	}

	#[test]
	fn invalid_data() {
		let encoded_7_bit_int: [u8; 5] = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
		let mut reader = ReadByteArr::new(&encoded_7_bit_int);
		assert_eq!(
			reader.read_7_bit_encoded_i32().map_err(|e| e.kind()),
			Err(io::ErrorKind::InvalidData)
		);
	}
}