Add library and documents

This commit is contained in:
2025-08-10 15:11:24 +08:00
parent 808c5acd2b
commit f602ddb4b5
23 changed files with 584 additions and 41 deletions

View File

@@ -1,3 +1,4 @@
//!Extensions for atomic operations.
use std::sync::atomic::Ordering;
/// A trait to help to load and store atomic value quickly.

View File

@@ -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)>,

View File

@@ -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)

View File

@@ -1,3 +1,4 @@
//! Extensions for other crates.
pub mod atomic;
#[cfg(feature = "fancy-regex")]
pub mod fancy_regex;

View File

@@ -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;
}

View File

@@ -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);