use napi_derive::napi;
use napi::Result;
use napi::bindgen_prelude::*;
#[napi]
pub enum Endianness {
Big,
Little,
}
#[napi]
pub struct BinaryStream {
pub binary: Vec<u8>,
pub offset: u32,
}
#[napi]
impl BinaryStream {
#[napi(constructor)]
pub fn new(buffer: Option<Buffer>, offset: Option<u32>) -> Self {
let bin = buffer.unwrap_or(Buffer::from(vec![]));
let offset = offset.unwrap_or(0);
return BinaryStream {
binary: bin.as_ref().to_vec(),
offset,
}
}
#[napi(factory)]
pub fn from(binary: Vec<u8>, offset: Option<u32>) -> Self {
let offset = offset.unwrap_or(0);
return BinaryStream {
binary,
offset,
}
}
#[napi(factory)]
pub fn from_buffer(buffer: Buffer, offset: Option<u32>) -> Self {
let offset = offset.unwrap_or(0);
return BinaryStream {
binary: buffer.as_ref().to_vec(),
offset,
}
}
#[napi]
pub fn read(&mut self, length: u32) -> Vec<u8> {
let start = self.offset as usize;
let end = (self.offset + length) as usize;
self.offset += length;
return self.binary[start..end].to_vec()
}
#[napi]
pub fn read_buffer(&mut self, length: u32) -> Buffer {
let bytes = self.read(length);
return Buffer::from(bytes)
}
#[napi]
pub fn write(&mut self, data: Vec<u8>) -> () {
self.binary.extend(data);
}
#[napi]
pub fn write_buffer(&mut self, data: Buffer) -> () {
data.as_ref().to_vec();
}
#[napi]
pub fn read_remaining(&mut self) -> Vec<u8> {
let start = self.offset as usize;
let end = self.binary.len();
self.offset = end as u32;
return self.binary[start..end].to_vec()
}
#[napi]
pub fn read_remaining_buffer(&mut self) -> Buffer {
let bytes = self.read_remaining();
return Buffer::from(bytes)
}
#[napi]
pub fn skip(&mut self, length: u32) -> u32 {
self.offset += length;
return self.offset
}
#[napi]
pub fn cursor_at_end(&self) -> bool {
return self.offset == self.binary.len() as u32
}
#[napi]
pub fn cursor_at_start(&self) -> bool {
return self.offset == 0
}
#[napi]
pub fn get_buffer(&self) -> Buffer {
return Buffer::from(self.binary.clone())
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_string(&mut self) -> String {
let len = self.read_uint16(Some(Endianness::Big));
let value = String::from_utf8_lossy(&&self.binary[self.offset as usize..self.offset as usize + len as usize]).to_string();
self.offset += len as u32;
return value
}
#[napi]
pub fn write_string(&mut self, data: String) -> () {
let len = data.len() as u16;
self.write_uint16(len, Some(Endianness::Big));
self.write(data.as_bytes().to_vec())
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_big_string(&mut self) -> String {
let length = self.read_var_int().unwrap() as usize;
let value = String::from_utf8_lossy(&&self.binary[self.offset as usize..self.offset as usize + length]).to_string();
self.offset += length as u32;
return value
}
#[napi]
pub fn write_big_string(&mut self, data: String) -> () {
let length = data.len() as u32;
let vec = data.as_bytes().to_vec();
self.write_var_int(length);
self.write(vec)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_little_string(&mut self) -> String {
let length = self.read_int32(Some(Endianness::Little)) as usize;
let value = String::from_utf8_lossy(&&self.binary[self.offset as usize..self.offset as usize + length]).to_string();
self.offset += length as u32;
return value
}
#[napi]
pub fn write_little_string(&mut self, data: String) -> () {
let length = data.len() as i32;
self.write_int32(length, Some(Endianness::Little));
self.write_string(data)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uuid(&mut self) -> String {
let bytes = self.read(16);
let mut uuid = String::new();
for byte in bytes {
uuid.push_str(&format!("{:02X}", byte));
}
return uuid
}
#[napi]
pub fn write_uuid(&mut self, data: String) -> () {
let mut data = data.replace("-", "");
data = data.to_uppercase();
let mut bytes = Vec::new();
for i in 0..16 {
let byte = u8::from_str_radix(&data[i * 2..i * 2 + 2], 16).unwrap();
bytes.push(byte);
}
self.write(bytes)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_bool(&mut self) -> bool {
let bytes = self.read(1);
return bytes[0] != 0
}
#[napi]
pub fn write_bool(&mut self, data: bool) -> () {
let value = match data {
true => 1,
false => 0,
};
self.write(vec![value])
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_byte(&mut self) -> i8 {
let bytes = self.read(1);
return bytes[0] as i8
}
#[napi]
pub fn write_byte(&mut self, data: i8) -> () {
self.write(vec![data as u8])
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uint8(&mut self) -> u8 {
let bytes = self.read(1);
return bytes[0]
}
#[napi]
pub fn write_uint8(&mut self, data: u8) -> () {
self.write(vec![data])
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_int8(&mut self) -> i8 {
let bytes = self.read(1);
return bytes[0] as i8
}
#[napi]
pub fn write_int8(&mut self, data: i8) -> () {
self.write(vec![data as u8])
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uint16(&mut self, endian: Option<Endianness>) -> u16 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(2);
match endian {
Endianness::Big => return u16::from_be_bytes([bytes[0], bytes[1]]),
Endianness::Little => return u16::from_le_bytes([bytes[0], bytes[1]]),
}
}
#[napi]
pub fn write_uint16(&mut self, data: u16, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes().to_vec()),
Endianness::Little => self.write(data.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_int16(&mut self, endian: Option<Endianness>) -> i16 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(2);
match endian {
Endianness::Big => return i16::from_be_bytes([bytes[0], bytes[1]]),
Endianness::Little => return i16::from_le_bytes([bytes[0], bytes[1]]),
}
}
#[napi]
pub fn write_int16(&mut self, data: i16, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes().to_vec()),
Endianness::Little => self.write(data.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_u_short(&mut self, endian: Option<Endianness>) -> u16 {
self.read_uint16(endian)
}
#[napi]
pub fn write_u_short(&mut self, data: u16, endian: Option<Endianness>) -> () {
self.write_uint16(data, endian)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_short(&mut self, endian: Option<Endianness>) -> i16 {
self.read_int16(endian)
}
#[napi]
pub fn write_short(&mut self, data: i16, endian: Option<Endianness>) -> () {
self.write_int16(data, endian)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uint24(&mut self, endian: Option<Endianness>) -> u32 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(3);
match endian {
Endianness::Big => return u32::from_be_bytes([0, bytes[0], bytes[1], bytes[2]]),
Endianness::Little => return u32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0]),
}
}
#[napi]
pub fn write_uint24(&mut self, data: u32, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes()[1..].to_vec()),
Endianness::Little => self.write(data.to_le_bytes()[..3].to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_int24(&mut self, endian: Option<Endianness>) -> i32 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(3);
match endian {
Endianness::Big => return i32::from_be_bytes([0, bytes[0], bytes[1], bytes[2]]),
Endianness::Little => return i32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0]),
}
}
#[napi]
pub fn write_int24(&mut self, data: i32, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes()[1..].to_vec()),
Endianness::Little => self.write(data.to_le_bytes()[..3].to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uint32(&mut self, endian: Option<Endianness>) -> u32 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(4);
match endian {
Endianness::Big => return u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
Endianness::Little => return u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
}
}
#[napi]
pub fn write_uint32(&mut self, data: u32, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes().to_vec()),
Endianness::Little => self.write(data.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_int32(&mut self, endian: Option<Endianness>) -> i32 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(4);
match endian {
Endianness::Big => return i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
Endianness::Little => return i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
}
}
#[napi]
pub fn write_int32(&mut self, data: i32, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
match endian {
Endianness::Big => self.write(data.to_be_bytes().to_vec()),
Endianness::Little => self.write(data.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_uint64(&mut self, endian: Option<Endianness>) -> BigInt {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(8);
match endian {
Endianness::Big => return BigInt::from(u64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]])),
Endianness::Little => return BigInt::from(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]])),
}
}
#[napi]
pub fn write_uint64(&mut self, data: BigInt, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
let value = data.get_u64().1;
match endian {
Endianness::Big => self.write(value.to_be_bytes().to_vec()),
Endianness::Little => self.write(value.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_int64(&mut self, endian: Option<Endianness>) -> BigInt {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(8);
match endian {
Endianness::Big => return BigInt::from(i64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]])),
Endianness::Little => return BigInt::from(i64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]])),
}
}
#[napi]
pub fn write_int64(&mut self, data: BigInt, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
let value = data.get_i64().0;
match endian {
Endianness::Big => self.write(value.to_be_bytes().to_vec()),
Endianness::Little => self.write(value.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_float32(&mut self, endian: Option<Endianness>) -> f64 {
let endian = endian.unwrap_or(Endianness::Big);
let bytes = self.read(4);
match endian {
Endianness::Big => return f32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as f64,
Endianness::Little => return f32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as f64,
}
}
#[napi]
pub fn write_float32(&mut self, data: f64, endian: Option<Endianness>) -> () {
let endian = endian.unwrap_or(Endianness::Big);
let value = data as f32;
match endian {
Endianness::Big => self.write(value.to_be_bytes().to_vec()),
Endianness::Little => self.write(value.to_le_bytes().to_vec()),
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_u_long(&mut self, endian: Option<Endianness>) -> BigInt {
self.read_uint64(endian)
}
#[napi]
pub fn write_u_long(&mut self, data: BigInt, endian: Option<Endianness>) -> () {
self.write_uint64(data, endian)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_long(&mut self, endian: Option<Endianness>) -> BigInt {
self.read_int64(endian)
}
#[napi]
pub fn write_long(&mut self, data: BigInt, endian: Option<Endianness>) -> () {
self.write_int64(data, endian)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_var_int(&mut self) -> Result<u32> {
let mut value = 0;
let mut size = 0;
loop {
let byte = self.read_uint8();
value |= (byte as u32 & 0x7F) << (size * 7);
size += 1;
if size > 5 {
return Err(Error::new(Status::GenericFailure, "VarInt is too big"));
}
if (byte & 0x80) != 0x80 {
break;
}
}
return Ok(value)
}
#[napi]
pub fn write_var_int(&mut self, data: u32) -> () {
let mut value = data;
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
self.write_uint8(byte);
if value == 0 {
break;
}
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_zig_zag(&mut self) -> i32 {
let value = self.read_var_int().unwrap();
return ((value >> 1) as i32) ^ (-((value & 1) as i32))
}
#[napi]
pub fn write_zig_zag(&mut self, data: i32) -> () {
let value = ((data << 1) ^ (data >> 31)) as u32;
self.write_var_int(value)
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_var_long(&mut self) -> Result<BigInt> {
let mut num_read = 0;
let mut result = 0;
loop {
let read = self.read_uint8() as u64;
let value = read & 0b01111111;
result |= value << (7 * num_read);
num_read += 1;
if num_read > 10 {
return Err(Error::new(Status::GenericFailure, "VarLong is too big"));
}
if (read & 0b10000000) == 0 {
break;
}
}
return Ok(BigInt::from(result))
}
#[napi]
pub fn write_var_long(&mut self, data: BigInt) -> () {
let mut value = data.get_u64().1;
loop {
let mut temp = (value & 0b01111111) as u8;
value >>= 7;
if value != 0 {
temp |= 0b10000000;
}
self.write_uint8(temp);
if value == 0 {
break;
}
}
}
}
#[napi]
impl BinaryStream {
#[napi]
pub fn read_zig_zong(&mut self) -> BigInt {
let value = self.read_var_long().unwrap();
let value = value.get_u64().1;
let value = ((value >> 1) as i64) ^ (-((value & 1) as i64));
let signed = value < 0;
let value = match signed {
true => (-value) as u64,
false => value as u64,
};
let value = napi::bindgen_prelude::BigInt {
sign_bit: signed,
words: vec![value],
};
value
}
#[napi]
pub fn write_zig_zong(&mut self, data: BigInt) -> () {
let value = data.get_i64().0;
let value = ((value << 1) ^ (value >> 63)) as u64;
let value = napi::bindgen_prelude::BigInt {
sign_bit: false,
words: vec![value],
};
self.write_var_long(value)
}
}