use rowevents::value_type::*;
use std::io::Result;
use std::io::Cursor;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
pub fn parse_new_decimal(precision: u8, decimals: u8, data: &[u8]) -> Result<(ValueType, usize)> {
let digits_per_integer = 9;
let compressed_bytes = [0, 1, 1, 2, 2, 3, 3, 4, 4, 4];
let integral = precision - decimals;
let uncomp_integral = integral / digits_per_integer;
let uncomp_fractional = decimals / digits_per_integer;
let comp_integral = integral - (uncomp_integral * digits_per_integer);
let comp_fractional = decimals - (uncomp_fractional * digits_per_integer);
let mut data = Vec::from(data);
let (negative, mask) = {
let value = data[0];
let (negative, mask):(bool, u64) = if value & 0x80 != 0 { (false, 0) } else { (true, -1 as i64 as u64) };
data[0] = value ^ 0x80;
(negative, mask)
};
let size = compressed_bytes[comp_integral as usize];
let mut d = if size > 0 {
let mut cursor = Cursor::new(&data);
let i:u64 = cursor.read_uint::<BigEndian>(size)?;
let a = i ^ mask;
let move_bits = 64 - size * 8;
let a = a << move_bits >> move_bits;
a.to_string()
} else {
"".to_string()
};
if negative {
d = "-".to_string() + &d;
}
let mut from:usize = size;
let remain = &data[from .. ];
for i in 0 .. uncomp_integral {
let i = i as usize;
let b = &remain[i * 4 .. (i + 1) * 4];
let n = Cursor::new(b).read_u32::<LittleEndian>()? as u64 ^ mask;
d += &format!("{:09}", n);
from += (i * 4);
}
d += ".";
let remain = &data[from .. ];
for i in 0 .. uncomp_fractional {
let i = i as usize;
let b = &remain[i * 4 .. (i + 1) * 4];
let n = Cursor::new(b).read_u32::<LittleEndian>()? as u64 ^ mask;
d += &format!("{:09}", n);
from += (i * 4);
}
let size = compressed_bytes[comp_fractional as usize];
let remain = &data[from .. ];
if size > 0 {
let i = Cursor::new(remain).read_uint::<BigEndian>(size)? as u64;
let value = i ^ mask;
let move_bits = 64 - size * 8;
let value = value << move_bits >> move_bits;
d += &format!("{:0w$}", value, w=comp_fractional as usize);
from += size;
}
Ok((ValueType::Decimal(d), from))
}