use std::io::{self, Error, ErrorKind, Read, Result, Write};
pub trait ReadExt: Read {
#[inline]
fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0; 1];
self.read_exact(&mut buf)?;
Ok(buf[0])
}
#[inline]
fn read_i8(&mut self) -> Result<i8> {
Ok(self.read_u8()? as i8)
}
#[inline]
fn read_bool(&mut self) -> Result<bool> {
let mut buf = [0; 1];
self.read_exact(&mut buf)?;
Ok(buf[0] != 0)
}
#[inline]
fn read_u16(&mut self) -> Result<u16> {
let mut buf = [0; 2];
self.read_exact(&mut buf)?;
Ok(u16::from_be_bytes(buf))
}
#[inline]
fn read_u16_le(&mut self) -> Result<u16> {
let mut buf = [0; 2];
self.read_exact(&mut buf)?;
Ok(u16::from_le_bytes(buf))
}
#[inline]
fn read_u16_add(&mut self) -> Result<u16> {
Ok(((self.read_u8()? as u16) << 8) | ((self.read_u8()?.wrapping_sub(128)) as u16))
}
#[inline]
fn read_u16_add_le(&mut self) -> Result<u16> {
Ok(((self.read_u8()?.wrapping_sub(128)) as u16) | ((self.read_u8()? as u16) << 8))
}
#[inline]
fn read_i16(&mut self) -> Result<i16> {
Ok(self.read_u16()? as i16)
}
#[inline]
fn read_i16_le(&mut self) -> Result<i16> {
Ok(self.read_u16_le()? as i16)
}
#[inline]
fn read_i16_add(&mut self) -> Result<i16> {
Ok(self.read_u16_add()? as i16)
}
#[inline]
fn read_i16_add_le(&mut self) -> Result<i16> {
Ok(self.read_u16_add_le()? as i16)
}
#[inline]
fn read_u32(&mut self) -> Result<u32> {
let mut buf = [0; 4];
self.read_exact(&mut buf)?;
Ok(u32::from_be_bytes(buf))
}
#[inline]
fn read_u32_le(&mut self) -> Result<u32> {
let mut buf = [0; 4];
self.read_exact(&mut buf)?;
Ok(u32::from_le_bytes(buf))
}
#[inline]
fn read_u32_me(&mut self) -> Result<u32> {
Ok((self.read_u16_le()? as u32) << 16 | (self.read_u16_le()? as u32))
}
#[inline]
fn read_u32_ime(&mut self) -> Result<u32> {
Ok((self.read_u16()? as u32) | ((self.read_u16()? as u32) << 16))
}
#[inline]
fn read_i32(&mut self) -> Result<i32> {
Ok(self.read_u32()? as i32)
}
#[inline]
fn read_i32_le(&mut self) -> Result<i32> {
Ok(self.read_u32_le()? as i32)
}
#[inline]
fn read_i32_me(&mut self) -> Result<i32> {
Ok(self.read_u32_me()? as i32)
}
#[inline]
fn read_i32_ime(&mut self) -> Result<i32> {
Ok(self.read_u32_ime()? as i32)
}
#[inline]
fn read_u64(&mut self) -> Result<u64> {
let mut buf = [0; 8];
self.read_exact(&mut buf)?;
Ok(u64::from_be_bytes(buf))
}
#[inline]
fn read_i64(&mut self) -> Result<i64> {
Ok(self.read_u64()? as i64)
}
#[inline]
fn read_string_cp1252(&mut self) -> Result<String> {
let mut str = Vec::new();
while let Ok(x) = self.read_u8() {
if x != 0 {
str.push(x);
} else {
break;
}
}
let s = match std::str::from_utf8(&str) {
Ok(v) => v,
Err(e) => {
return Err(Error::new(
ErrorKind::Other,
format!("Invalid UTF-8 sequence: {}", e),
))
}
};
Ok(s.to_owned())
}
}
impl<R: io::Read + ?Sized> ReadExt for R {}
pub trait WriteExt: Write {
#[inline]
fn write_u8(&mut self, n: u8) -> Result<()> {
self.write_all(&[n])
}
#[inline]
fn write_i8(&mut self, n: i8) -> Result<()> {
self.write_u8(n as u8)
}
#[inline]
fn write_i8_sub(&mut self, n: i8) -> Result<()> {
self.write_u8(128 - n as u8)
}
#[inline]
fn write_i8_add(&mut self, n: i8) -> Result<()> {
self.write_u8(n as u8 + 128)
}
#[inline]
fn write_i8_neg(&mut self, n: i8) -> Result<()> {
self.write_u8(-n as u8)
}
#[inline]
fn write_bool(&mut self, b: bool) -> Result<()> {
self.write_all(&[b as u8])
}
#[inline]
fn write_u16(&mut self, n: u16) -> Result<()> {
self.write_all(&n.to_be_bytes())
}
#[inline]
fn write_u16_le(&mut self, n: u16) -> Result<()> {
self.write_all(&n.to_le_bytes())
}
#[inline]
fn write_u16_smart(&mut self, n: u16) -> Result<()> {
match n {
0..=127 => self.write_u8(n as u8),
128..=32767 => self.write_u16(n + 32768),
_ => Err(Error::new(
ErrorKind::Other,
format!("Failed writing smart, value is {}", n),
)),
}
}
#[inline]
fn write_i16(&mut self, n: i16) -> Result<()> {
self.write_u16(n as u16)
}
#[inline]
fn write_i16_le(&mut self, n: i16) -> Result<()> {
self.write_u16_le(n as u16)
}
#[inline]
fn write_i16_add(&mut self, n: i16) -> Result<()> {
self.write_i8((n >> 8) as i8)?;
self.write_i8((n + 128) as i8)
}
#[inline]
fn write_i16_le_add(&mut self, n: i16) -> Result<()> {
self.write_i8((n + 128) as i8)?;
self.write_i8((n >> 8) as i8)
}
#[inline]
fn write_u32(&mut self, n: u32) -> Result<()> {
self.write_all(&n.to_be_bytes())
}
#[inline]
fn write_u32_le(&mut self, n: u32) -> Result<()> {
self.write_all(&n.to_le_bytes())
}
#[inline]
fn write_i32(&mut self, n: i32) -> Result<()> {
self.write_u32(n as u32)
}
#[inline]
fn write_i32_le(&mut self, n: i32) -> Result<()> {
self.write_u32_le(n as u32)
}
#[inline]
fn write_i32_me(&mut self, n: i32) -> Result<()> {
self.write_i16_le((n >> 16) as i16)?;
self.write_i16_le(n as i16)
}
#[inline]
fn write_i32_ime(&mut self, n: i32) -> Result<()> {
self.write_i16(n as i16)?;
self.write_i16((n >> 16) as i16)
}
#[inline]
fn write_u64(&mut self, n: u64) -> Result<()> {
self.write_all(&n.to_be_bytes())
}
#[inline]
fn write_i64(&mut self, n: i64) -> Result<()> {
self.write_u64(n as u64)
}
#[inline]
fn write_string_cp1252(&mut self, s: &str) -> Result<()> {
for b in s.as_bytes() {
self.write_u8(*b)?;
}
self.write_i8(0)
}
#[inline]
fn write_bytes_reversed_add(&mut self, buf: &[u8]) -> Result<()> {
for b in buf.iter().rev() {
self.write_i8(b.wrapping_add((i8::MAX as u8) + 1) as i8)?;
}
Ok(())
}
}
impl<W: io::Write + ?Sized> WriteExt for W {}