mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-08 22:08:47 +08:00
Add library and documents
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
//!Extensions for atomic operations.
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
/// A trait to help to load and store atomic value quickly.
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
//!Extensions for fancy_regex crate.
|
||||
use anyhow::Result;
|
||||
use fancy_regex::Regex;
|
||||
|
||||
/// Extension trait for [fancy_regex::Regex] to provide more convenient methods.
|
||||
pub trait FancyRegexExt {
|
||||
/// Splits the input string by the regex pattern.
|
||||
/// Like python's `re.split()`, but returns an iterator.
|
||||
fn py_split<'a>(&'a self, input: &'a str) -> Result<PySplit<'a>>;
|
||||
}
|
||||
|
||||
/// An iterator that splits a string by a regex pattern, similar to Python's `re.split()`.
|
||||
pub struct PySplit<'a> {
|
||||
str: &'a str,
|
||||
pos: Vec<(usize, usize)>,
|
||||
|
||||
216
src/ext/io.rs
216
src/ext/io.rs
@@ -1,14 +1,26 @@
|
||||
//!Extensions for IO operations.
|
||||
use crate::utils::encoding::decode_to_string;
|
||||
use crate::{types::Encoding, utils::struct_pack::StructUnpack};
|
||||
use std::ffi::CString;
|
||||
use std::io::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// A trait to help to peek data from a reader.
|
||||
pub trait Peek {
|
||||
/// Peeks data from the reader into the provided buffer.
|
||||
/// Returns the number of bytes read.
|
||||
fn peek(&mut self, buf: &mut [u8]) -> Result<usize>;
|
||||
/// Peeks data from the reader into the provided buffer.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn peek_exact(&mut self, buf: &mut [u8]) -> Result<()>;
|
||||
/// Peeks data from the reader at a specific offset into the provided buffer.
|
||||
/// Returns the number of bytes read.
|
||||
fn peek_at(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize>;
|
||||
/// Peeks data from the reader at a specific offset into the provided buffer.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn peek_exact_at(&mut self, offset: usize, buf: &mut [u8]) -> Result<()>;
|
||||
/// Peeks data from the reader at a specific offset into a vector.
|
||||
/// Returns the vector containing the data read.
|
||||
fn peek_at_vec(&mut self, offset: usize, len: usize) -> Result<Vec<u8>> {
|
||||
let mut buf = vec![0u8; len];
|
||||
let bytes_read = self.peek_at(offset, &mut buf)?;
|
||||
@@ -17,197 +29,250 @@ pub trait Peek {
|
||||
}
|
||||
Ok(buf)
|
||||
}
|
||||
/// Peeks data from the reader at a specific offset into a vector.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn peek_exact_at_vec(&mut self, offset: usize, len: usize) -> Result<Vec<u8>> {
|
||||
let mut buf = vec![0u8; len];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Peeks a [u8] from the reader.
|
||||
fn peek_u8(&mut self) -> Result<u8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
/// Peeks a [u16] from the reader in little-endian order.
|
||||
fn peek_u16(&mut self) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u16] from the reader in big-endian order.
|
||||
fn peek_u16_be(&mut self) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] from the reader in little-endian order.
|
||||
fn peek_u32(&mut self) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] from the reader in big-endian order.
|
||||
fn peek_u32_be(&mut self) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] from the reader in little-endian order.
|
||||
fn peek_u64(&mut self) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] from the reader in big-endian order.
|
||||
fn peek_u64_be(&mut self) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] from the reader in little-endian order.
|
||||
fn peek_u128(&mut self) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] from the reader in big-endian order.
|
||||
fn peek_u128_be(&mut self) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(u128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i8] from the reader.
|
||||
fn peek_i8(&mut self) -> Result<i8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i8::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] from the reader in little-endian order.
|
||||
fn peek_i16(&mut self) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] from the reader in big-endian order.
|
||||
fn peek_i16_be(&mut self) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] from the reader in little-endian order.
|
||||
fn peek_i32(&mut self) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] from the reader in big-endian order.
|
||||
fn peek_i32_be(&mut self) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] from the reader in little-endian order.
|
||||
fn peek_i64(&mut self) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] from the reader in big-endian order.
|
||||
fn peek_i64_be(&mut self) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] from the reader in little-endian order.
|
||||
fn peek_i128(&mut self) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] from the reader in big-endian order.
|
||||
fn peek_i128_be(&mut self) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact(&mut buf)?;
|
||||
Ok(i128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u8] at a specific offset from the reader.
|
||||
fn peek_u8_at(&mut self, offset: usize) -> Result<u8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
/// Peeks a [u16] at a specific offset from the reader in little-endian order.
|
||||
fn peek_u16_at(&mut self, offset: usize) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u16] at a specific offset from the reader in big-endian order.
|
||||
fn peek_u16_be_at(&mut self, offset: usize) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] at a specific offset from the reader in little-endian order.
|
||||
fn peek_u32_at(&mut self, offset: usize) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] at a specific offset from the reader in big-endian order.
|
||||
fn peek_u32_be_at(&mut self, offset: usize) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] at a specific offset from the reader in little-endian order.
|
||||
fn peek_u64_at(&mut self, offset: usize) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] at a specific offset from the reader in big-endian order.
|
||||
fn peek_u64_be_at(&mut self, offset: usize) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] at a specific offset from the reader in little-endian order.
|
||||
fn peek_u128_at(&mut self, offset: usize) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] at a specific offset from the reader in big-endian order.
|
||||
fn peek_u128_be_at(&mut self, offset: usize) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(u128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i8] at a specific offset from the reader.
|
||||
fn peek_i8_at(&mut self, offset: usize) -> Result<i8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i8::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] at a specific offset from the reader in little-endian order.
|
||||
fn peek_i16_at(&mut self, offset: usize) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] at a specific offset from the reader in big-endian order.
|
||||
fn peek_i16_be_at(&mut self, offset: usize) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] at a specific offset from the reader in little-endian order.
|
||||
fn peek_i32_at(&mut self, offset: usize) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] at a specific offset from the reader in big-endian order.
|
||||
fn peek_i32_be_at(&mut self, offset: usize) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] at a specific offset from the reader in little-endian order.
|
||||
fn peek_i64_at(&mut self, offset: usize) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] at a specific offset from the reader in big-endian order.
|
||||
fn peek_i64_be_at(&mut self, offset: usize) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] at a specific offset from the reader in little-endian order.
|
||||
fn peek_i128_at(&mut self, offset: usize) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] at a specific offset from the reader in big-endian order.
|
||||
fn peek_i128_be_at(&mut self, offset: usize) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
Ok(i128::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
/// Peeks a C-style string (null-terminated) from the reader.
|
||||
fn peek_cstring(&mut self) -> Result<CString>;
|
||||
/// Peeks a C-style string (null-terminated) from the reader at a specific offset.
|
||||
fn peek_cstring_at(&mut self, offset: usize) -> Result<CString>;
|
||||
|
||||
/// Reads a struct from the reader.
|
||||
/// The struct must implement the `StructUnpack` trait.
|
||||
///
|
||||
/// * `big` indicates whether the struct is in big-endian format.
|
||||
/// * `encoding` specifies the encoding to use for string fields in the struct.
|
||||
/// Returns the unpacked struct.
|
||||
fn read_struct<T: StructUnpack>(&mut self, big: bool, encoding: Encoding) -> Result<T>;
|
||||
/// Reads a vector of structs from the reader.
|
||||
/// The structs must implement the `StructUnpack` trait.
|
||||
///
|
||||
/// * `count` is the number of structs to read.
|
||||
/// * `big` indicates whether the structs are in big-endian format.
|
||||
/// * `encoding` specifies the encoding to use for string fields in the structs.
|
||||
/// Returns a vector of unpacked structs.
|
||||
fn read_struct_vec<T: StructUnpack>(
|
||||
&mut self,
|
||||
count: usize,
|
||||
@@ -221,6 +286,7 @@ pub trait Peek {
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
/// Peeks data and checks if it matches the provided data.
|
||||
fn peek_and_equal(&mut self, data: &[u8]) -> Result<()> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
self.peek_exact(&mut buf)?;
|
||||
@@ -232,6 +298,7 @@ pub trait Peek {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Peeks data at a specific offset and checks if it matches the provided data.
|
||||
fn peek_and_equal_at(&mut self, offset: usize, data: &[u8]) -> Result<()> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
self.peek_exact_at(offset, &mut buf)?;
|
||||
@@ -313,8 +380,13 @@ impl<T: Read + Seek> Peek for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to help to peek data from a reader in a thread-safe manner.
|
||||
pub trait CPeek {
|
||||
/// Peeks data from the reader into the provided buffer.
|
||||
/// Returns the number of bytes read.
|
||||
fn cpeek(&self, buf: &mut [u8]) -> Result<usize>;
|
||||
/// Peeks data from the reader into the provided buffer.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn cpeek_exact(&self, buf: &mut [u8]) -> Result<()> {
|
||||
let bytes_read = self.cpeek(buf)?;
|
||||
if bytes_read < buf.len() {
|
||||
@@ -325,7 +397,11 @@ pub trait CPeek {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Peeks data from the reader at a specific offset into the provided buffer.
|
||||
/// Returns the number of bytes read.
|
||||
fn cpeek_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
|
||||
/// Peeks data from the reader at a specific offset into the provided buffer.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn cpeek_exact_at(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
|
||||
let bytes_read = self.cpeek_at(offset, buf)?;
|
||||
if bytes_read < buf.len() {
|
||||
@@ -336,6 +412,8 @@ pub trait CPeek {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Peeks data from the reader at a specific offset into a vector.
|
||||
/// Returns the vector containing the data read.
|
||||
fn cpeek_at_vec(&self, offset: usize, len: usize) -> Result<Vec<u8>> {
|
||||
let mut buf = vec![0u8; len];
|
||||
let bytes_read = self.cpeek_at(offset, &mut buf)?;
|
||||
@@ -344,195 +422,235 @@ pub trait CPeek {
|
||||
}
|
||||
Ok(buf)
|
||||
}
|
||||
/// Peeks data from the reader at a specific offset into a vector.
|
||||
/// Returns an error if the buffer is not filled completely.
|
||||
fn cpeek_exact_at_vec(&self, offset: usize, len: usize) -> Result<Vec<u8>> {
|
||||
let mut buf = vec![0u8; len];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Peeks a [u8] from the reader.
|
||||
fn cpeek_u8(&self) -> Result<u8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
/// Peeks a [u16] from the reader in little-endian order.
|
||||
fn cpeek_u16(&self) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u16] from the reader in big-endian order.
|
||||
fn cpeek_u16_be(&self) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] from the reader in little-endian order.
|
||||
fn cpeek_u32(&self) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] from the reader in big-endian order.
|
||||
fn cpeek_u32_be(&self) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] from the reader in little-endian order.
|
||||
fn cpeek_u64(&self) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] from the reader in big-endian order.
|
||||
fn cpeek_u64_be(&self) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] from the reader in little-endian order.
|
||||
fn cpeek_u128(&self) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] from the reader in big-endian order.
|
||||
fn cpeek_u128_be(&self) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(u128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i8] from the reader.
|
||||
fn cpeek_i8(&self) -> Result<i8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i8::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] from the reader in little-endian order.
|
||||
fn cpeek_i16(&self) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] from the reader in big-endian order.
|
||||
fn cpeek_i16_be(&self) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] from the reader in little-endian order.
|
||||
fn cpeek_i32(&self) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] from the reader in big-endian order.
|
||||
fn cpeek_i32_be(&self) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] from the reader in little-endian order.
|
||||
fn cpeek_i64(&self) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] from the reader in big-endian order.
|
||||
fn cpeek_i64_be(&self) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] from the reader in little-endian order.
|
||||
fn cpeek_i128(&self) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] from the reader in big-endian order.
|
||||
fn cpeek_i128_be(&self) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
Ok(i128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u8] at a specific offset from the reader.
|
||||
fn cpeek_u8_at(&self, offset: usize) -> Result<u8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
/// Peeks a [u16] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_u16_at(&self, offset: usize) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u16] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_u16_be_at(&self, offset: usize) -> Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_u32_at(&self, offset: usize) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u32] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_u32_be_at(&self, offset: usize) -> Result<u32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_u64_at(&self, offset: usize) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u64] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_u64_be_at(&self, offset: usize) -> Result<u64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_u128_at(&self, offset: usize) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks a [u128] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_u128_be_at(&self, offset: usize) -> Result<u128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(u128::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i8] at a specific offset from the reader.
|
||||
fn cpeek_i8_at(&self, offset: usize) -> Result<i8> {
|
||||
let mut buf = [0u8; 1];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i8::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_i16_at(&self, offset: usize) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i16::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i16] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_i16_be_at(&self, offset: usize) -> Result<i16> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i16::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_i32_at(&self, offset: usize) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i32::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i32] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_i32_be_at(&self, offset: usize) -> Result<i32> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i32::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_i64_at(&self, offset: usize) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i64::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i64] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_i64_be_at(&self, offset: usize) -> Result<i64> {
|
||||
let mut buf = [0u8; 8];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i64::from_be_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] at a specific offset from the reader in little-endian order.
|
||||
fn cpeek_i128_at(&self, offset: usize) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i128::from_le_bytes(buf))
|
||||
}
|
||||
/// Peeks an [i128] at a specific offset from the reader in big-endian order.
|
||||
fn cpeek_i128_be_at(&self, offset: usize) -> Result<i128> {
|
||||
let mut buf = [0u8; 16];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
Ok(i128::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
/// Peeks a C-style string (null-terminated) from the reader.
|
||||
fn cpeek_cstring(&self) -> Result<CString>;
|
||||
|
||||
/// Peeks a C-style string (null-terminated) from the reader at a specific offset.
|
||||
fn cpeek_cstring_at(&self, offset: usize) -> Result<CString> {
|
||||
let mut buf = Vec::new();
|
||||
let mut byte = [0u8; 1];
|
||||
@@ -544,6 +662,7 @@ pub trait CPeek {
|
||||
CString::new(buf).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
|
||||
}
|
||||
|
||||
/// Peeks data and checks if it matches the provided data.
|
||||
fn cpeek_and_equal(&self, data: &[u8]) -> Result<()> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
self.cpeek_exact(&mut buf)?;
|
||||
@@ -555,6 +674,7 @@ pub trait CPeek {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Peeks data at a specific offset and checks if it matches the provided data.
|
||||
fn cpeek_and_equal_at(&self, offset: usize, data: &[u8]) -> Result<()> {
|
||||
let mut buf = vec![0u8; data.len()];
|
||||
self.cpeek_exact_at(offset, &mut buf)?;
|
||||
@@ -591,31 +711,57 @@ impl<T: Peek> CPeek for Mutex<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to help to read data from a reader.
|
||||
pub trait ReadExt {
|
||||
/// Reads a [u8] from the reader.
|
||||
fn read_u8(&mut self) -> Result<u8>;
|
||||
/// Reads a [u16] from the reader in little-endian order.
|
||||
fn read_u16(&mut self) -> Result<u16>;
|
||||
/// Reads a [u16] from the reader in big-endian order.
|
||||
fn read_u16_be(&mut self) -> Result<u16>;
|
||||
/// Reads a [u32] from the reader in little-endian order.
|
||||
fn read_u32(&mut self) -> Result<u32>;
|
||||
/// Reads a [u32] from the reader in big-endian order.
|
||||
fn read_u32_be(&mut self) -> Result<u32>;
|
||||
/// Reads a [u64] from the reader in little-endian order.
|
||||
fn read_u64(&mut self) -> Result<u64>;
|
||||
/// Reads a [u64] from the reader in big-endian order.
|
||||
fn read_u64_be(&mut self) -> Result<u64>;
|
||||
/// Reads a [u128] from the reader in little-endian order.
|
||||
fn read_u128(&mut self) -> Result<u128>;
|
||||
/// Reads a [u128] from the reader in big-endian order.
|
||||
fn read_u128_be(&mut self) -> Result<u128>;
|
||||
/// Reads an [i8] from the reader.
|
||||
fn read_i8(&mut self) -> Result<i8>;
|
||||
/// Reads an [i16] from the reader in little-endian order.
|
||||
fn read_i16(&mut self) -> Result<i16>;
|
||||
/// Reads an [i16] from the reader in big-endian order.
|
||||
fn read_i16_be(&mut self) -> Result<i16>;
|
||||
/// Reads an [i32] from the reader in little-endian order.
|
||||
fn read_i32(&mut self) -> Result<i32>;
|
||||
/// Reads an [i32] from the reader in big-endian order.
|
||||
fn read_i32_be(&mut self) -> Result<i32>;
|
||||
/// Reads an [i64] from the reader in little-endian order.
|
||||
fn read_i64(&mut self) -> Result<i64>;
|
||||
/// Reads an [i64] from the reader in big-endian order.
|
||||
fn read_i64_be(&mut self) -> Result<i64>;
|
||||
/// Reads an [i128] from the reader in little-endian order.
|
||||
fn read_i128(&mut self) -> Result<i128>;
|
||||
/// Reads an [i128] from the reader in big-endian order.
|
||||
fn read_i128_be(&mut self) -> Result<i128>;
|
||||
|
||||
/// Reads a C-style string (null-terminated) from the reader.
|
||||
fn read_cstring(&mut self) -> Result<CString>;
|
||||
/// Reads a C-style string (null-terminated) from the reader with maximum length.
|
||||
/// * `len` is the maximum length of the string to read.
|
||||
/// * `encoding` specifies the encoding to use for the string.
|
||||
/// * `trim` indicates whether to trim the string after the first null byte.
|
||||
fn read_fstring(&mut self, len: usize, encoding: Encoding, trim: bool) -> Result<String>;
|
||||
|
||||
/// Reads some data from the reader into a vector.
|
||||
fn read_exact_vec(&mut self, len: usize) -> Result<Vec<u8>>;
|
||||
|
||||
/// Reads data and checks if it matches the provided data.
|
||||
fn read_and_equal(&mut self, data: &[u8]) -> Result<()>;
|
||||
}
|
||||
|
||||
@@ -756,26 +902,46 @@ impl<T: Read> ReadExt for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to help to write data to a writer.
|
||||
pub trait WriteExt {
|
||||
/// Writes a [u8] to the writer.
|
||||
fn write_u8(&mut self, value: u8) -> Result<()>;
|
||||
/// Writes a [u16] to the writer in little-endian order.
|
||||
fn write_u16(&mut self, value: u16) -> Result<()>;
|
||||
/// Writes a [u16] to the writer in big-endian order.
|
||||
fn write_u16_be(&mut self, value: u16) -> Result<()>;
|
||||
/// Writes a [u32] to the writer in little-endian order.
|
||||
fn write_u32(&mut self, value: u32) -> Result<()>;
|
||||
/// Writes a [u32] to the writer in big-endian order.
|
||||
fn write_u32_be(&mut self, value: u32) -> Result<()>;
|
||||
/// Writes a [u64] to the writer in little-endian order.
|
||||
fn write_u64(&mut self, value: u64) -> Result<()>;
|
||||
/// Writes a [u64] to the writer in big-endian order.
|
||||
fn write_u64_be(&mut self, value: u64) -> Result<()>;
|
||||
/// Writes a [u128] to the writer in little-endian order.
|
||||
fn write_u128(&mut self, value: u128) -> Result<()>;
|
||||
/// Writes a [u128] to the writer in big-endian order.
|
||||
fn write_u128_be(&mut self, value: u128) -> Result<()>;
|
||||
/// Writes an [i8] to the writer.
|
||||
fn write_i8(&mut self, value: i8) -> Result<()>;
|
||||
/// Writes an [i16] to the writer in little-endian order.
|
||||
fn write_i16(&mut self, value: i16) -> Result<()>;
|
||||
/// Writes an [i16] to the writer in big-endian order.
|
||||
fn write_i16_be(&mut self, value: i16) -> Result<()>;
|
||||
/// Writes an [i32] to the writer in little-endian order.
|
||||
fn write_i32(&mut self, value: i32) -> Result<()>;
|
||||
/// Writes an [i32] to the writer in big-endian order.
|
||||
fn write_i32_be(&mut self, value: i32) -> Result<()>;
|
||||
/// Writes an [i64] to the writer in little-endian order.
|
||||
fn write_i64(&mut self, value: i64) -> Result<()>;
|
||||
/// Writes an [i64] to the writer in big-endian order.
|
||||
fn write_i64_be(&mut self, value: i64) -> Result<()>;
|
||||
/// Writes an [i128] to the writer in little-endian order.
|
||||
fn write_i128(&mut self, value: i128) -> Result<()>;
|
||||
/// Writes an [i128] to the writer in big-endian order.
|
||||
fn write_i128_be(&mut self, value: i128) -> Result<()>;
|
||||
|
||||
/// Writes a C-style string (null-terminated) to the writer.
|
||||
fn write_cstring(&mut self, value: &CString) -> Result<()>;
|
||||
}
|
||||
|
||||
@@ -840,65 +1006,89 @@ impl<T: Write> WriteExt for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to help to write data to a writer at a specific offset.
|
||||
pub trait WriteAt {
|
||||
/// Writes data to the writer at a specific offset.
|
||||
/// Returns the number of bytes written.
|
||||
fn write_at(&mut self, offset: usize, buf: &[u8]) -> Result<usize>;
|
||||
/// Writes all data to the writer at a specific offset.
|
||||
/// Returns an error if the write fails.
|
||||
fn write_all_at(&mut self, offset: usize, buf: &[u8]) -> Result<()>;
|
||||
|
||||
/// Writes a [u8] at a specific offset.
|
||||
fn write_u8_at(&mut self, offset: usize, value: u8) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes a [u16] at a specific offset in little-endian order.
|
||||
fn write_u16_at(&mut self, offset: usize, value: u16) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes a [u16] at a specific offset in big-endian order.
|
||||
fn write_u16_be_at(&mut self, offset: usize, value: u16) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes a [u32] at a specific offset in little-endian order.
|
||||
fn write_u32_at(&mut self, offset: usize, value: u32) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes a [u32] at a specific offset in big-endian order.
|
||||
fn write_u32_be_at(&mut self, offset: usize, value: u32) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes a [u64] at a specific offset in little-endian order.
|
||||
fn write_u64_at(&mut self, offset: usize, value: u64) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes a [u64] at a specific offset in big-endian order.
|
||||
fn write_u64_be_at(&mut self, offset: usize, value: u64) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes a [u128] at a specific offset in little-endian order.
|
||||
fn write_u128_at(&mut self, offset: usize, value: u128) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes a [u128] at a specific offset in big-endian order.
|
||||
fn write_u128_be_at(&mut self, offset: usize, value: u128) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes an [i8] at a specific offset.
|
||||
fn write_i8_at(&mut self, offset: usize, value: i8) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes an [i16] at a specific offset in little-endian order.
|
||||
fn write_i16_at(&mut self, offset: usize, value: i16) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes an [i16] at a specific offset in big-endian order.
|
||||
fn write_i16_be_at(&mut self, offset: usize, value: i16) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes an [i32] at a specific offset in little-endian order.
|
||||
fn write_i32_at(&mut self, offset: usize, value: i32) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes an [i32] at a specific offset in big-endian order.
|
||||
fn write_i32_be_at(&mut self, offset: usize, value: i32) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes an [i64] at a specific offset in little-endian order.
|
||||
fn write_i64_at(&mut self, offset: usize, value: i64) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes an [i64] at a specific offset in big-endian order.
|
||||
fn write_i64_be_at(&mut self, offset: usize, value: i64) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
/// Writes an [i128] at a specific offset in little-endian order.
|
||||
fn write_i128_at(&mut self, offset: usize, value: i128) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_le_bytes())
|
||||
}
|
||||
/// Writes an [i128] at a specific offset in big-endian order.
|
||||
fn write_i128_be_at(&mut self, offset: usize, value: i128) -> Result<()> {
|
||||
self.write_all_at(offset, &value.to_be_bytes())
|
||||
}
|
||||
|
||||
/// Writes a C-style string (null-terminated) at a specific offset.
|
||||
fn write_cstring_at(&mut self, offset: usize, value: &CString) -> Result<()> {
|
||||
self.write_all_at(offset, value.as_bytes_with_nul())
|
||||
}
|
||||
@@ -922,7 +1112,9 @@ impl<T: Write + Seek> WriteAt for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to help to seek in a stream.
|
||||
pub trait SeekExt {
|
||||
/// Returns the length of the stream.
|
||||
fn stream_length(&mut self) -> Result<u64>;
|
||||
}
|
||||
|
||||
@@ -935,14 +1127,20 @@ impl<T: Seek> SeekExt for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A memory reader that can read data from a vector of bytes.
|
||||
pub struct MemReader {
|
||||
/// The data to read from.
|
||||
pub data: Vec<u8>,
|
||||
/// The current position in the data.
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
/// A memory reader that can read data from a slice of bytes.
|
||||
#[derive(Clone)]
|
||||
pub struct MemReaderRef<'a> {
|
||||
/// The data to read from.
|
||||
pub data: &'a [u8],
|
||||
/// The current position in the data.
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
@@ -965,10 +1163,12 @@ impl<'a> std::fmt::Debug for MemReaderRef<'a> {
|
||||
}
|
||||
|
||||
impl MemReader {
|
||||
/// Creates a new `MemReader` with the given data.
|
||||
pub fn new(data: Vec<u8>) -> Self {
|
||||
MemReader { data, pos: 0 }
|
||||
}
|
||||
|
||||
/// Creates a new [MemReaderRef] from the current data and position.
|
||||
pub fn to_ref<'a>(&'a self) -> MemReaderRef<'a> {
|
||||
MemReaderRef {
|
||||
data: &self.data,
|
||||
@@ -976,20 +1176,24 @@ impl MemReader {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the reader has reached the end of the data.
|
||||
pub fn is_eof(&self) -> bool {
|
||||
self.pos >= self.data.len()
|
||||
}
|
||||
|
||||
/// Returns the inner data of the reader.
|
||||
pub fn inner(self) -> Vec<u8> {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MemReaderRef<'a> {
|
||||
/// Creates a new `MemReaderRef` with the given data.
|
||||
pub fn new(data: &'a [u8]) -> Self {
|
||||
MemReaderRef { data, pos: 0 }
|
||||
}
|
||||
|
||||
/// Checks if the reader has reached the end of the data.
|
||||
pub fn is_eof(&self) -> bool {
|
||||
self.pos >= self.data.len()
|
||||
}
|
||||
@@ -1157,12 +1361,16 @@ impl<'a> CPeek for MemReaderRef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A memory writer that can write data to a vector of bytes.
|
||||
pub struct MemWriter {
|
||||
/// The data to write to.
|
||||
pub data: Vec<u8>,
|
||||
/// The current position in the data.
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
impl MemWriter {
|
||||
/// Creates a new `MemWriter` with an empty data vector.
|
||||
pub fn new() -> Self {
|
||||
MemWriter {
|
||||
data: Vec::new(),
|
||||
@@ -1170,18 +1378,22 @@ impl MemWriter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `MemWriter` with the given data.
|
||||
pub fn from_vec(data: Vec<u8>) -> Self {
|
||||
MemWriter { data, pos: 0 }
|
||||
}
|
||||
|
||||
/// Returns the inner data of the writer.
|
||||
pub fn into_inner(self) -> Vec<u8> {
|
||||
self.data
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner data of the writer.
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
/// Returns a new `MemReaderRef` that references the current data and position.
|
||||
pub fn to_ref<'a>(&'a self) -> MemReaderRef<'a> {
|
||||
MemReaderRef {
|
||||
data: &self.data,
|
||||
@@ -1269,6 +1481,7 @@ impl CPeek for MemWriter {
|
||||
}
|
||||
}
|
||||
|
||||
/// A region of a stream that can be read/write and seeked within a specified range.
|
||||
pub struct StreamRegion<T: Seek> {
|
||||
stream: T,
|
||||
start_pos: u64,
|
||||
@@ -1277,6 +1490,7 @@ pub struct StreamRegion<T: Seek> {
|
||||
}
|
||||
|
||||
impl<T: Seek> StreamRegion<T> {
|
||||
/// Creates a new `StreamRegion` with the specified stream and position range.
|
||||
pub fn new(stream: T, start_pos: u64, end_pos: u64) -> Result<Self> {
|
||||
if start_pos > end_pos {
|
||||
return Err(std::io::Error::new(
|
||||
@@ -1292,6 +1506,8 @@ impl<T: Seek> StreamRegion<T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `StreamRegion` with the specified stream and start position.
|
||||
/// The end position is determined by the length of the stream.
|
||||
pub fn with_start_pos(mut stream: T, start_pos: u64) -> Result<Self> {
|
||||
let end_pos = stream.stream_length()?;
|
||||
Self::new(stream, start_pos, end_pos)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! Extensions for other crates.
|
||||
pub mod atomic;
|
||||
#[cfg(feature = "fancy-regex")]
|
||||
pub mod fancy_regex;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//!Extensions for emote_psb crate.
|
||||
use emote_psb::VirtualPsb;
|
||||
use emote_psb::header::PsbHeader;
|
||||
use emote_psb::types::collection::*;
|
||||
@@ -14,27 +15,46 @@ use std::ops::{Index, IndexMut};
|
||||
const NONE: PsbValueFixed = PsbValueFixed::None;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Represents of a PSB value.
|
||||
pub enum PsbValueFixed {
|
||||
/// No value.
|
||||
None,
|
||||
/// Represents a null value.
|
||||
Null,
|
||||
/// Represents a boolean value.
|
||||
Bool(bool),
|
||||
/// Represents a number value.
|
||||
Number(PsbNumber),
|
||||
/// Represents an array of integers.
|
||||
IntArray(PsbUintArray),
|
||||
/// Represents a string value.
|
||||
String(PsbString),
|
||||
/// Represents a list of PSB values.
|
||||
List(PsbListFixed),
|
||||
/// Represents an object with key-value pairs.
|
||||
Object(PsbObjectFixed),
|
||||
/// Represents a resource reference.
|
||||
Resource(PsbResourceRef),
|
||||
/// Represents an extra resource reference.
|
||||
ExtraResource(PsbExtraRef),
|
||||
/// Represents a compiler number.
|
||||
CompilerNumber,
|
||||
/// Represents a compiler string.
|
||||
CompilerString,
|
||||
/// Represents a compiler resource.
|
||||
CompilerResource,
|
||||
/// Represents a compiler decimal.
|
||||
CompilerDecimal,
|
||||
/// Represents a compiler array.
|
||||
CompilerArray,
|
||||
/// Represents a compiler boolean.
|
||||
CompilerBool,
|
||||
/// Represents a compiler binary tree.
|
||||
CompilerBinaryTree,
|
||||
}
|
||||
|
||||
impl PsbValueFixed {
|
||||
/// Converts this value to original PSB value type.
|
||||
pub fn to_psb(self) -> PsbValue {
|
||||
match self {
|
||||
PsbValueFixed::None => PsbValue::None,
|
||||
@@ -57,30 +77,37 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this value is a list.
|
||||
pub fn is_list(&self) -> bool {
|
||||
matches!(self, PsbValueFixed::List(_))
|
||||
}
|
||||
|
||||
/// Returns true if this value is an object.
|
||||
pub fn is_object(&self) -> bool {
|
||||
matches!(self, PsbValueFixed::Object(_))
|
||||
}
|
||||
|
||||
/// Returns true if this value is a string or null.
|
||||
pub fn is_string_or_null(&self) -> bool {
|
||||
self.is_string() || self.is_null()
|
||||
}
|
||||
|
||||
/// Returns true if this value is a string.
|
||||
pub fn is_string(&self) -> bool {
|
||||
matches!(self, PsbValueFixed::String(_))
|
||||
}
|
||||
|
||||
/// Returns true if this value is none.
|
||||
pub fn is_none(&self) -> bool {
|
||||
matches!(self, PsbValueFixed::None)
|
||||
}
|
||||
|
||||
/// Returns true if this value is null.
|
||||
pub fn is_null(&self) -> bool {
|
||||
matches!(self, PsbValueFixed::Null)
|
||||
}
|
||||
|
||||
/// Sets the value of this PSB value to a new string.
|
||||
pub fn set_str(&mut self, value: &str) {
|
||||
match self {
|
||||
PsbValueFixed::String(s) => {
|
||||
@@ -94,18 +121,22 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the value of this PSB value to a new string.
|
||||
pub fn set_string(&mut self, value: String) {
|
||||
self.set_str(&value);
|
||||
}
|
||||
|
||||
/// Returns the value as a boolean, if it is a boolean.
|
||||
pub fn as_u8(&self) -> Option<u8> {
|
||||
self.as_i64().map(|n| n.try_into().ok()).flatten()
|
||||
}
|
||||
|
||||
/// Returns the value as a [u32], if it is a number.
|
||||
pub fn as_u32(&self) -> Option<u32> {
|
||||
self.as_i64().map(|n| n as u32)
|
||||
}
|
||||
|
||||
/// Returns the value as a [i64], if it is a number.
|
||||
pub fn as_i64(&self) -> Option<i64> {
|
||||
match self {
|
||||
PsbValueFixed::Number(n) => match n {
|
||||
@@ -116,6 +147,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value as a string, if it is a string.
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
PsbValueFixed::String(s) => Some(s.string()),
|
||||
@@ -123,6 +155,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the lengtho of a list or object.
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
PsbValueFixed::List(l) => l.len(),
|
||||
@@ -131,6 +164,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a iterator over the entries of an object.
|
||||
pub fn entries(&self) -> ObjectIter<'_> {
|
||||
match self {
|
||||
PsbValueFixed::Object(o) => o.iter(),
|
||||
@@ -138,6 +172,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the entries of an object.
|
||||
pub fn entries_mut(&mut self) -> ObjectIterMut<'_> {
|
||||
match self {
|
||||
PsbValueFixed::Object(o) => o.iter_mut(),
|
||||
@@ -145,6 +180,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a iterator over the members of a list.
|
||||
pub fn members(&self) -> ListIter<'_> {
|
||||
match self {
|
||||
PsbValueFixed::List(l) => l.iter(),
|
||||
@@ -152,6 +188,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the members of a list.
|
||||
pub fn members_mut(&mut self) -> ListIterMut<'_> {
|
||||
match self {
|
||||
PsbValueFixed::List(l) => l.iter_mut(),
|
||||
@@ -159,6 +196,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the resource ID if this value is a resource reference.
|
||||
pub fn resource_id(&self) -> Option<u64> {
|
||||
match self {
|
||||
PsbValueFixed::Resource(r) => Some(r.resource_ref),
|
||||
@@ -166,6 +204,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this value to a JSON value, if possible.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn to_json(&self) -> Option<JsonValue> {
|
||||
match self {
|
||||
@@ -193,6 +232,7 @@ impl PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a JSON value to a PSB value.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn from_json(obj: &JsonValue) -> Self {
|
||||
match obj {
|
||||
@@ -378,7 +418,9 @@ impl<'a> PartialEq<&'a str> for PsbValueFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to convert a PSB value to a fixed PSB value.
|
||||
pub trait PsbValueExt {
|
||||
/// Converts this PSB value to a fixed PSB value.
|
||||
fn to_psb_fixed(self) -> PsbValueFixed;
|
||||
}
|
||||
|
||||
@@ -407,36 +449,44 @@ impl PsbValueExt for PsbValue {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Represents a PSB list of PSB values.
|
||||
pub struct PsbListFixed {
|
||||
/// The values in the list.
|
||||
pub values: Vec<PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl PsbListFixed {
|
||||
/// Converts this PSB list to a original PSB list.
|
||||
pub fn to_psb(self) -> PsbList {
|
||||
let v: Vec<_> = self.values.into_iter().map(|v| v.to_psb()).collect();
|
||||
PsbList::from(v)
|
||||
}
|
||||
|
||||
/// Returns a iterator over the values in the list.
|
||||
pub fn iter(&self) -> ListIter<'_> {
|
||||
ListIter {
|
||||
inner: self.values.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the values in the list.
|
||||
pub fn iter_mut(&mut self) -> ListIterMut<'_> {
|
||||
ListIterMut {
|
||||
inner: self.values.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the values in the list.
|
||||
pub fn values(&self) -> &Vec<PsbValueFixed> {
|
||||
&self.values
|
||||
}
|
||||
|
||||
/// Returns the length of the list.
|
||||
pub fn len(&self) -> usize {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
/// Converts this PSB list to a JSON value.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn to_json(&self) -> JsonValue {
|
||||
let data: Vec<_> = self.values.iter().filter_map(|v| v.to_json()).collect();
|
||||
@@ -463,11 +513,13 @@ impl IndexMut<usize> for PsbListFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator for a slice of PSB values in a list.
|
||||
pub struct ListIter<'a> {
|
||||
inner: std::slice::Iter<'a, PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl<'a> ListIter<'a> {
|
||||
/// Creates an empty iterator.
|
||||
pub fn empty() -> Self {
|
||||
ListIter {
|
||||
inner: Default::default(),
|
||||
@@ -497,11 +549,13 @@ impl<'a> DoubleEndedIterator for ListIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable iterator for a slice of PSB values in a list.
|
||||
pub struct ListIterMut<'a> {
|
||||
inner: std::slice::IterMut<'a, PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl<'a> ListIterMut<'a> {
|
||||
/// Creates an empty mutable iterator.
|
||||
pub fn empty() -> Self {
|
||||
ListIterMut {
|
||||
inner: Default::default(),
|
||||
@@ -531,7 +585,9 @@ impl<'a> DoubleEndedIterator for ListIterMut<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to convert a PSB list to a fixed PSB list.
|
||||
pub trait PsbListExt {
|
||||
/// Converts this PSB list to a fixed PSB list.
|
||||
fn to_psb_fixed(self) -> PsbListFixed;
|
||||
}
|
||||
|
||||
@@ -547,11 +603,14 @@ impl PsbListExt for PsbList {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Represents a PSB object with key-value pairs.
|
||||
pub struct PsbObjectFixed {
|
||||
/// The key-value pairs in the object.
|
||||
pub values: HashMap<String, PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl PsbObjectFixed {
|
||||
/// Creates a new empty PSB object.
|
||||
pub fn to_psb(self) -> PsbObject {
|
||||
let mut hash_map = HashMap::new();
|
||||
for (key, value) in self.values {
|
||||
@@ -560,22 +619,26 @@ impl PsbObjectFixed {
|
||||
PsbObject::from(hash_map)
|
||||
}
|
||||
|
||||
/// Gets a reference of value in the object by key.
|
||||
pub fn get_value(&self, key: &str) -> Option<&PsbValueFixed> {
|
||||
self.values.get(key)
|
||||
}
|
||||
|
||||
/// Returns a iterator over the entries of the object.
|
||||
pub fn iter(&self) -> ObjectIter<'_> {
|
||||
ObjectIter {
|
||||
inner: self.values.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the entries of the object.
|
||||
pub fn iter_mut(&mut self) -> ObjectIterMut<'_> {
|
||||
ObjectIterMut {
|
||||
inner: self.values.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this PSB object to a JSON value.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn to_json(&self) -> JsonValue {
|
||||
let mut obj = json::object::Object::new();
|
||||
@@ -587,6 +650,7 @@ impl PsbObjectFixed {
|
||||
JsonValue::Object(obj)
|
||||
}
|
||||
|
||||
/// Converts a JSON object to a PSB object.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn from_json(obj: &JsonValue) -> Self {
|
||||
let mut values = HashMap::new();
|
||||
@@ -639,7 +703,9 @@ impl IndexMut<String> for PsbObjectFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to convert a PSB object to a fixed PSB object.
|
||||
pub trait PsbObjectExt {
|
||||
/// Converts this PSB object to a fixed PSB object.
|
||||
fn to_psb_fixed(self) -> PsbObjectFixed;
|
||||
}
|
||||
|
||||
@@ -653,11 +719,13 @@ impl PsbObjectExt for PsbObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator for a slice of PSB values in an object.
|
||||
pub struct ObjectIter<'a> {
|
||||
inner: std::collections::hash_map::Iter<'a, String, PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl<'a> ObjectIter<'a> {
|
||||
/// Creates an empty iterator.
|
||||
pub fn empty() -> Self {
|
||||
ObjectIter {
|
||||
inner: Default::default(),
|
||||
@@ -679,11 +747,13 @@ impl<'a> ExactSizeIterator for ObjectIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable iterator for a slice of PSB values in an object.
|
||||
pub struct ObjectIterMut<'a> {
|
||||
inner: std::collections::hash_map::IterMut<'a, String, PsbValueFixed>,
|
||||
}
|
||||
|
||||
impl<'a> ObjectIterMut<'a> {
|
||||
/// Creates an empty mutable iterator.
|
||||
pub fn empty() -> Self {
|
||||
ObjectIterMut {
|
||||
inner: Default::default(),
|
||||
@@ -706,6 +776,7 @@ impl<'a> ExactSizeIterator for ObjectIterMut<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a fixed version of a virtual PSB.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VirtualPsbFixed {
|
||||
header: PsbHeader,
|
||||
@@ -715,6 +786,7 @@ pub struct VirtualPsbFixed {
|
||||
}
|
||||
|
||||
impl VirtualPsbFixed {
|
||||
/// Creates a new fixed virtual PSB.
|
||||
pub fn new(
|
||||
header: PsbHeader,
|
||||
resources: Vec<Vec<u8>>,
|
||||
@@ -729,47 +801,58 @@ impl VirtualPsbFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the header of the PSB.
|
||||
pub fn header(&self) -> PsbHeader {
|
||||
self.header
|
||||
}
|
||||
|
||||
/// Returns a reference to the resources of the PSB.
|
||||
pub fn resources(&self) -> &Vec<Vec<u8>> {
|
||||
&self.resources
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the resources of the PSB.
|
||||
pub fn resources_mut(&mut self) -> &mut Vec<Vec<u8>> {
|
||||
&mut self.resources
|
||||
}
|
||||
|
||||
/// Returns a reference to the extra resources of the PSB.
|
||||
pub fn extra(&self) -> &Vec<Vec<u8>> {
|
||||
&self.extra
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the extra resources of the PSB.
|
||||
pub fn extra_mut(&mut self) -> &mut Vec<Vec<u8>> {
|
||||
&mut self.extra
|
||||
}
|
||||
|
||||
/// Returns a reference to the root object of the PSB.
|
||||
pub fn root(&self) -> &PsbObjectFixed {
|
||||
&self.root
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the root object of the PSB.
|
||||
pub fn root_mut(&mut self) -> &mut PsbObjectFixed {
|
||||
&mut self.root
|
||||
}
|
||||
|
||||
/// Sets the root of the PSB.
|
||||
pub fn set_root(&mut self, root: PsbObjectFixed) {
|
||||
self.root = root;
|
||||
}
|
||||
|
||||
/// Unwraps the PSB into its components.
|
||||
pub fn unwrap(self) -> (PsbHeader, Vec<Vec<u8>>, Vec<Vec<u8>>, PsbObjectFixed) {
|
||||
(self.header, self.resources, self.extra, self.root)
|
||||
}
|
||||
|
||||
/// Converts this fixed PSB to a virtual PSB.
|
||||
pub fn to_psb(self) -> VirtualPsb {
|
||||
let (header, resources, extra, root) = self.unwrap();
|
||||
VirtualPsb::new(header, resources, extra, root.to_psb())
|
||||
}
|
||||
|
||||
/// Converts json object to a fixed PSB.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn from_json(&mut self, obj: &JsonValue) -> Result<(), anyhow::Error> {
|
||||
let version = obj["version"]
|
||||
@@ -784,6 +867,7 @@ impl VirtualPsbFixed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts this fixed PSB to a JSON object.
|
||||
#[cfg(feature = "json")]
|
||||
pub fn to_json(&self) -> JsonValue {
|
||||
json::object! {
|
||||
@@ -794,7 +878,9 @@ impl VirtualPsbFixed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to convert a virtual PSB to a fixed PSB.
|
||||
pub trait VirtualPsbExt {
|
||||
/// Converts this virtual PSB to a fixed PSB.
|
||||
fn to_psb_fixed(self) -> VirtualPsbFixed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//!Extensions for vector operations.
|
||||
/// Extensions for vector operations.
|
||||
pub trait VecExt<T> {
|
||||
/// Copy potentially overlapping sequence of elements from `src` to `dst`.
|
||||
fn copy_overlapped(&mut self, src: usize, dst: usize, len: usize);
|
||||
|
||||
Reference in New Issue
Block a user