use crate::errors::Result;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use sha2::{Digest, Sha256};
use std::io::{Read, Write};
pub fn double_sha256(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(data);
let hash1 = hasher.finalize();
let mut hasher = Sha256::new();
hasher.update(hash1);
hasher.finalize().into()
}
pub fn read_varint<R: Read>(reader: &mut R) -> Result<u64> {
let mut b = [0u8; 1];
reader.read_exact(&mut b)?;
let n = b[0];
match n {
0..=0xfc => Ok(n as u64),
0xfd => {
let val = reader.read_u16::<LittleEndian>()? as u64;
if val < 0xfd {
return Err(crate::errors::ShiaError::InvalidVarInt);
}
Ok(val)
}
0xfe => {
let val = reader.read_u32::<LittleEndian>()? as u64;
if val < 0x10000 {
return Err(crate::errors::ShiaError::InvalidVarInt);
}
Ok(val)
}
0xff => {
let val = reader.read_u64::<LittleEndian>()?;
if val < 0x100000000 {
return Err(crate::errors::ShiaError::InvalidVarInt);
}
if val > usize::MAX as u64 {
return Err(crate::errors::ShiaError::InvalidVarInt);
}
Ok(val)
}
}
}
pub fn write_varint<W: Write>(writer: &mut W, n: u64) -> Result<()> {
if n < 0xfd {
writer.write_u8(n as u8)?;
} else if n <= 0xffff {
writer.write_u8(0xfd)?;
writer.write_u16::<LittleEndian>(n as u16)?;
} else if n <= 0xffffffff {
writer.write_u8(0xfe)?;
writer.write_u32::<LittleEndian>(n as u32)?;
} else {
writer.write_u8(0xff)?;
writer.write_u64::<LittleEndian>(n)?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_read_varint() {
let data = vec![
0x01,
0xfd, 0xfd, 0x00,
0xfd, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
];
let mut cursor = Cursor::new(data);
assert_eq!(read_varint(&mut cursor).unwrap(), 1);
assert_eq!(read_varint(&mut cursor).unwrap(), 253);
assert_eq!(read_varint(&mut cursor).unwrap(), 65535);
assert_eq!(read_varint(&mut cursor).unwrap(), 4_294_967_296u64);
}
#[test]
fn test_write_varint() {
let mut buf = Vec::new();
write_varint(&mut buf, 1).unwrap();
write_varint(&mut buf, 253).unwrap();
write_varint(&mut buf, 65535).unwrap();
write_varint(&mut buf, 4_294_967_296u64).unwrap();
let expected = vec![
0x01,
0xfd, 0xfd, 0x00,
0xfd, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
];
assert_eq!(buf, expected);
}
}