mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-08 05:48:46 +08:00
Add document
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
//! Bit stream utilities.
|
||||
use crate::ext::io::*;
|
||||
use anyhow::Result;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
/// A most significant bit (MSB) bit stream reader.
|
||||
pub struct MsbBitStream<T: Read> {
|
||||
/// The input stream to read from.
|
||||
pub m_input: T,
|
||||
m_bits: u32,
|
||||
/// The number of bits currently cached.
|
||||
pub m_cached_bits: u32,
|
||||
}
|
||||
|
||||
impl<T: Read> MsbBitStream<T> {
|
||||
/// Creates a new MSB bit stream reader.
|
||||
pub fn new(input: T) -> Self {
|
||||
MsbBitStream {
|
||||
m_input: input,
|
||||
@@ -17,6 +22,7 @@ impl<T: Read> MsbBitStream<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a specified number of bits from the stream.
|
||||
pub fn get_bits(&mut self, count: u32) -> Result<u32> {
|
||||
while self.m_cached_bits < count {
|
||||
let byte = self.m_input.read_u8()?;
|
||||
@@ -29,6 +35,7 @@ impl<T: Read> MsbBitStream<T> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Reads the next bit from the stream.
|
||||
pub fn get_next_bit(&mut self) -> Result<bool> {
|
||||
if self.m_cached_bits == 0 {
|
||||
let byte = self.m_input.read_u8()?;
|
||||
@@ -41,13 +48,16 @@ impl<T: Read> MsbBitStream<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A most significant bit (MSB) bit writer.
|
||||
pub struct MsbBitWriter<'a, T: Write> {
|
||||
/// The output stream to write to.
|
||||
pub writer: &'a mut T,
|
||||
buffer: u32,
|
||||
buffer_size: u32,
|
||||
}
|
||||
|
||||
impl<'a, T: Write> MsbBitWriter<'a, T> {
|
||||
/// Creates a new MSB bit writer.
|
||||
pub fn new(writer: &'a mut T) -> Self {
|
||||
MsbBitWriter {
|
||||
writer,
|
||||
@@ -56,6 +66,8 @@ impl<'a, T: Write> MsbBitWriter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Flushes the buffer to the output stream.
|
||||
/// This writes any remaining bits in the buffer to the stream.
|
||||
pub fn flush(&mut self) -> Result<()> {
|
||||
if self.buffer_size > 0 {
|
||||
self.writer
|
||||
@@ -66,6 +78,7 @@ impl<'a, T: Write> MsbBitWriter<'a, T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Puts a byte into the bit stream with a specified token width.
|
||||
pub fn put_bits(&mut self, byte: u32, token_width: u8) -> Result<()> {
|
||||
for i in 0..token_width {
|
||||
self.put_bit((byte & (1 << (token_width - 1 - i))) != 0)?;
|
||||
@@ -73,6 +86,7 @@ impl<'a, T: Write> MsbBitWriter<'a, T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Puts a single bit into the bit stream.
|
||||
pub fn put_bit(&mut self, bit: bool) -> Result<()> {
|
||||
self.buffer <<= 1;
|
||||
if bit {
|
||||
@@ -87,13 +101,17 @@ impl<'a, T: Write> MsbBitWriter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A least significant bit (LSB) bit stream reader.
|
||||
pub struct LsbBitStream<T: Read> {
|
||||
/// The input stream to read from.
|
||||
pub m_input: T,
|
||||
m_bits: u32,
|
||||
/// The number of bits currently cached.
|
||||
pub m_cached_bits: u32,
|
||||
}
|
||||
|
||||
impl<T: Read> LsbBitStream<T> {
|
||||
/// Creates a new LSB bit stream reader.
|
||||
pub fn new(input: T) -> Self {
|
||||
LsbBitStream {
|
||||
m_input: input,
|
||||
@@ -102,6 +120,7 @@ impl<T: Read> LsbBitStream<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a specified number of bits from the stream.
|
||||
pub fn get_bits(&mut self, mut count: u32) -> Result<u32> {
|
||||
if self.m_cached_bits >= count {
|
||||
let mask = (1 << count) - 1;
|
||||
@@ -130,6 +149,7 @@ impl<T: Read> LsbBitStream<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the next bit from the stream.
|
||||
pub fn get_next_bit(&mut self) -> Result<bool> {
|
||||
Ok(self.get_bits(1)? == 1)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//! A simple counter for tracking script execution results.
|
||||
use crate::types::*;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
/// A counter for tracking script execution results.
|
||||
pub struct Counter {
|
||||
ok: AtomicUsize,
|
||||
ignored: AtomicUsize,
|
||||
@@ -10,6 +12,7 @@ pub struct Counter {
|
||||
}
|
||||
|
||||
impl Counter {
|
||||
/// Creates a new Counter instance.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ok: AtomicUsize::new(0),
|
||||
@@ -19,14 +22,17 @@ impl Counter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Increments the count of errors.
|
||||
pub fn inc_error(&self) {
|
||||
self.error.fetch_add(1, SeqCst);
|
||||
}
|
||||
|
||||
/// Increments the count of warnings.
|
||||
pub fn inc_warning(&self) {
|
||||
self.warning.fetch_add(1, SeqCst);
|
||||
}
|
||||
|
||||
/// Increments the count of script executions.
|
||||
pub fn inc(&self, result: ScriptResult) {
|
||||
match result {
|
||||
ScriptResult::Ok => self.ok.fetch_add(1, SeqCst),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! Crc32 Utility
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
fn get_crc32normal_table() -> [u32; 256] {
|
||||
@@ -17,18 +18,22 @@ fn get_crc32normal_table() -> [u32; 256] {
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// CRC32 Normal Table
|
||||
pub static ref CRC32NORMAL_TABLE: [u32; 256] = get_crc32normal_table();
|
||||
}
|
||||
|
||||
/// A CRC32 Normal implementation.
|
||||
pub struct Crc32Normal {
|
||||
crc: u32,
|
||||
}
|
||||
|
||||
impl Crc32Normal {
|
||||
/// Creates a new Crc32Normal instance with an initial CRC value.
|
||||
pub fn new() -> Self {
|
||||
Crc32Normal { crc: 0xFFFFFFFF }
|
||||
}
|
||||
|
||||
/// Creates a new Crc32Normal instance with a specified initial CRC value.
|
||||
pub fn update_crc(init_crc: u32, data: &[u8]) -> u32 {
|
||||
let mut crc = init_crc;
|
||||
for &byte in data {
|
||||
@@ -38,10 +43,12 @@ impl Crc32Normal {
|
||||
crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
/// Updates the CRC value with new data.
|
||||
pub fn update(&mut self, data: &[u8]) {
|
||||
self.crc = Self::update_crc(self.crc, data);
|
||||
}
|
||||
|
||||
/// Returns the current CRC value.
|
||||
pub fn value(&self) -> u32 {
|
||||
self.crc
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
//! Encoding Utilities
|
||||
use crate::types::*;
|
||||
|
||||
/// Decodes a byte slice to a string using the specified encoding with BOM detection.
|
||||
///
|
||||
/// * `check` - If true, checks for decoding errors and returns an error if any.
|
||||
///
|
||||
/// Returns the decoded string and the detected BOM type.
|
||||
pub fn decode_with_bom_detect(
|
||||
encoding: Encoding,
|
||||
data: &[u8],
|
||||
@@ -53,6 +59,9 @@ pub fn decode_with_bom_detect(
|
||||
decode_to_string(encoding, data, check).map(|s| (s, BomType::None))
|
||||
}
|
||||
|
||||
/// Decodes a byte slice to a string using the specified encoding.
|
||||
///
|
||||
/// * `check` - If true, checks for decoding errors and returns an error if any.
|
||||
pub fn decode_to_string(
|
||||
encoding: Encoding,
|
||||
data: &[u8],
|
||||
@@ -98,6 +107,9 @@ pub fn decode_to_string(
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes a string to a byte vector using the specified encoding.
|
||||
///
|
||||
/// * `check` - If true, checks for encoding errors and returns an error if any.
|
||||
pub fn encode_string(
|
||||
encoding: Encoding,
|
||||
data: &str,
|
||||
@@ -141,6 +153,10 @@ pub fn encode_string(
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes a string to a byte vector using the specified encoding with BOM.
|
||||
///
|
||||
/// * `bom` - The BOM type to use.
|
||||
/// * `check` - If true, checks for encoding errors and returns an error if any
|
||||
pub fn encode_string_with_bom(
|
||||
encoding: Encoding,
|
||||
data: &str,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Escape and Unescape Utilities
|
||||
use fancy_regex::Regex;
|
||||
|
||||
/// Escapes special characters in XML attribute values.
|
||||
pub fn escape_xml_attr_value(s: &str) -> String {
|
||||
let mut escaped = String::with_capacity(s.len());
|
||||
for c in s.chars() {
|
||||
@@ -14,6 +16,7 @@ pub fn escape_xml_attr_value(s: &str) -> String {
|
||||
escaped
|
||||
}
|
||||
|
||||
/// Escapes special characters in XML text values.
|
||||
pub fn escape_xml_text_value(s: &str) -> String {
|
||||
let mut escaped = String::with_capacity(s.len());
|
||||
for c in s.chars() {
|
||||
@@ -37,6 +40,7 @@ lazy_static::lazy_static! {
|
||||
static ref LUA_NCR_BASE16_U_REGEX: Regex = Regex::new(r"\\u([0-9a-fA-F]{4})").unwrap();
|
||||
}
|
||||
|
||||
/// Unescapes XML character references and entities.
|
||||
pub fn unescape_xml(s: &str) -> String {
|
||||
let mut s = s.to_owned();
|
||||
s = XML_NCR_BASE10_REGEX
|
||||
@@ -58,6 +62,7 @@ pub fn unescape_xml(s: &str) -> String {
|
||||
.replace("'", "'")
|
||||
}
|
||||
|
||||
/// Unescapes Lua string escape sequences.
|
||||
pub fn unescape_lua_str(s: &str) -> String {
|
||||
let mut s = s.to_owned();
|
||||
s = s
|
||||
@@ -91,6 +96,7 @@ pub fn unescape_lua_str(s: &str) -> String {
|
||||
s.replace("\\\\", "\\")
|
||||
}
|
||||
|
||||
/// Checks if a string contains characters that need to be escaped in Lua strings.
|
||||
pub fn lua_str_contains_need_escape(s: &str) -> bool {
|
||||
s.contains('\\')
|
||||
|| s.contains('\n')
|
||||
@@ -103,6 +109,7 @@ pub fn lua_str_contains_need_escape(s: &str) -> bool {
|
||||
|| s.contains('"')
|
||||
}
|
||||
|
||||
/// Checks if a string contains characters that need to be escaped in Lua keys.
|
||||
pub fn lua_key_contains_need_escape(s: &str) -> bool {
|
||||
s.chars().next().map_or(false, |c| c.is_ascii_digit())
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
//! Utilities for File Operations
|
||||
use crate::scripts::{ALL_EXTS, ARCHIVE_EXTS};
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Returns the relative path from `root` to `target`.
|
||||
pub fn relative_path<P: AsRef<Path>, T: AsRef<Path>>(root: P, target: T) -> PathBuf {
|
||||
let root = root
|
||||
.as_ref()
|
||||
@@ -40,6 +42,7 @@ pub fn relative_path<P: AsRef<Path>, T: AsRef<Path>>(root: P, target: T) -> Path
|
||||
result
|
||||
}
|
||||
|
||||
/// Finds all files in the specified directory and its subdirectories.
|
||||
pub fn find_files(path: &str, recursive: bool, no_ext_filter: bool) -> io::Result<Vec<String>> {
|
||||
let mut result = Vec::new();
|
||||
let dir_path = Path::new(&path);
|
||||
@@ -79,6 +82,7 @@ pub fn find_files(path: &str, recursive: bool, no_ext_filter: bool) -> io::Resul
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Finds all archive files in the specified directory and its subdirectories.
|
||||
pub fn find_arc_files(path: &str, recursive: bool) -> io::Result<Vec<String>> {
|
||||
let mut result = Vec::new();
|
||||
let dir_path = Path::new(&path);
|
||||
@@ -116,6 +120,7 @@ pub fn find_arc_files(path: &str, recursive: bool) -> io::Result<Vec<String>> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Collects files from the specified path, either as a directory or a single file.
|
||||
pub fn collect_files(
|
||||
path: &str,
|
||||
recursive: bool,
|
||||
@@ -134,6 +139,7 @@ pub fn collect_files(
|
||||
))
|
||||
}
|
||||
|
||||
/// Collects archive files from the specified path, either as a directory or a single file.
|
||||
pub fn collect_arc_files(path: &str, recursive: bool) -> io::Result<(Vec<String>, bool)> {
|
||||
let pa = Path::new(path);
|
||||
if pa.is_dir() {
|
||||
@@ -148,6 +154,7 @@ pub fn collect_arc_files(path: &str, recursive: bool) -> io::Result<(Vec<String>
|
||||
))
|
||||
}
|
||||
|
||||
/// Reads the content of a file or standard input if the path is "-".
|
||||
pub fn read_file<F: AsRef<Path> + ?Sized>(f: &F) -> io::Result<Vec<u8>> {
|
||||
let mut content = Vec::new();
|
||||
if f.as_ref() == Path::new("-") {
|
||||
@@ -158,6 +165,7 @@ pub fn read_file<F: AsRef<Path> + ?Sized>(f: &F) -> io::Result<Vec<u8>> {
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
/// Writes content to a file or standard output if the path is "-".
|
||||
pub fn write_file<F: AsRef<Path> + ?Sized>(f: &F) -> io::Result<Box<dyn Write>> {
|
||||
Ok(if f.as_ref() == Path::new("-") {
|
||||
Box::new(io::stdout())
|
||||
@@ -166,6 +174,7 @@ pub fn write_file<F: AsRef<Path> + ?Sized>(f: &F) -> io::Result<Box<dyn Write>>
|
||||
})
|
||||
}
|
||||
|
||||
/// Ensures that the parent directory for the specified path exists, creating it if necessary.
|
||||
pub fn make_sure_dir_exists<F: AsRef<Path> + ?Sized>(f: &F) -> io::Result<()> {
|
||||
let path = f.as_ref();
|
||||
if let Some(parent) = path.parent() {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
//! Image Utilities
|
||||
use crate::types::*;
|
||||
use anyhow::Result;
|
||||
|
||||
/// Reverses the alpha values of an image.
|
||||
///
|
||||
/// Only supports RGBA or BGRA images with 8-bit depth.
|
||||
pub fn reverse_alpha_values(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Rgba && data.color_type != ImageColorType::Bgra {
|
||||
return Err(anyhow::anyhow!("Image is not RGBA or BGRA"));
|
||||
@@ -16,6 +20,9 @@ pub fn reverse_alpha_values(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts a BGR image to BGRA format.
|
||||
///
|
||||
/// Only supports BGR images with 8-bit depth.
|
||||
pub fn convert_bgr_to_bgra(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Bgr {
|
||||
return Err(anyhow::anyhow!("Image is not BGR"));
|
||||
@@ -37,6 +44,9 @@ pub fn convert_bgr_to_bgra(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts a BGR image to RGB format.
|
||||
///
|
||||
/// Only supports BGR images with 8-bit depth.
|
||||
pub fn convert_bgr_to_rgb(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Bgr {
|
||||
return Err(anyhow::anyhow!("Image is not BGR"));
|
||||
@@ -55,6 +65,9 @@ pub fn convert_bgr_to_rgb(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts a BGRA image to BGR format.
|
||||
///
|
||||
/// Only supports BGRA images with 8-bit depth.
|
||||
pub fn convert_bgra_to_bgr(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Bgra {
|
||||
return Err(anyhow::anyhow!("Image is not BGRA"));
|
||||
@@ -75,6 +88,9 @@ pub fn convert_bgra_to_bgr(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts a BGRA image to RGBA format.
|
||||
///
|
||||
/// Only supports BGRA images with 8-bit depth.
|
||||
pub fn convert_bgra_to_rgba(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Bgra {
|
||||
return Err(anyhow::anyhow!("Image is not BGRA"));
|
||||
@@ -93,6 +109,9 @@ pub fn convert_bgra_to_rgba(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts an RGB image to RGBA format.
|
||||
///
|
||||
/// Only supports RGB images with 8-bit depth.
|
||||
pub fn convert_rgb_to_rgba(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Rgb {
|
||||
return Err(anyhow::anyhow!("Image is not RGB"));
|
||||
@@ -114,6 +133,9 @@ pub fn convert_rgb_to_rgba(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts an RGB image to BGR format.
|
||||
///
|
||||
/// Only supports RGB images with 8-bit depth.
|
||||
pub fn convert_rgb_to_bgr(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Rgb {
|
||||
return Err(anyhow::anyhow!("Image is not RGB"));
|
||||
@@ -132,6 +154,9 @@ pub fn convert_rgb_to_bgr(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Converts an RGBA image to BGRA format.
|
||||
///
|
||||
/// Only supports RGBA images with 8-bit depth.
|
||||
pub fn convert_rgba_to_bgra(data: &mut ImageData) -> Result<()> {
|
||||
if data.color_type != ImageColorType::Rgba {
|
||||
return Err(anyhow::anyhow!("Image is not RGBA"));
|
||||
@@ -150,6 +175,12 @@ pub fn convert_rgba_to_bgra(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encodes an image to the specified format and writes it to a file.
|
||||
///
|
||||
/// * `data` - The image data to encode.
|
||||
/// * `typ` - The output image format.
|
||||
/// * `filename` - The path of the file to write the encoded image to.
|
||||
/// * `config` - Extra configuration.
|
||||
pub fn encode_img(
|
||||
mut data: ImageData,
|
||||
typ: ImageOutputType,
|
||||
@@ -256,6 +287,7 @@ pub fn encode_img(
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a PNG image from the given reader and returns its data.
|
||||
pub fn load_png<R: std::io::Read>(data: R) -> Result<ImageData> {
|
||||
let decoder = png::Decoder::new(data);
|
||||
let mut reader = decoder.read_info()?;
|
||||
@@ -289,6 +321,10 @@ pub fn load_png<R: std::io::Read>(data: R) -> Result<ImageData> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Decodes an image from the specified file path and returns its data.
|
||||
///
|
||||
/// * `typ` - The type of the image to decode.
|
||||
/// * `filename` - The path of the file to decode.
|
||||
pub fn decode_img(typ: ImageOutputType, filename: &str) -> Result<ImageData> {
|
||||
match typ {
|
||||
ImageOutputType::Png => {
|
||||
@@ -361,6 +397,15 @@ pub fn decode_img(typ: ImageOutputType, filename: &str) -> Result<ImageData> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws an image on a canvas with specified offsets.
|
||||
///
|
||||
/// * `img` - The image data to draw.
|
||||
/// * `canvas_width` - The width of the canvas.
|
||||
/// * `canvas_height` - The height of the canvas.
|
||||
/// * `offset_x` - The horizontal offset to start drawing the image.
|
||||
/// * `offset_y` - The vertical offset to start drawing the image.
|
||||
///
|
||||
/// Returns the canvas image data.
|
||||
pub fn draw_on_canvas(
|
||||
img: ImageData,
|
||||
canvas_width: u32,
|
||||
@@ -397,6 +442,7 @@ pub fn draw_on_canvas(
|
||||
})
|
||||
}
|
||||
|
||||
/// Flips an image vertically.
|
||||
pub fn flip_image(data: &mut ImageData) -> Result<()> {
|
||||
if data.height <= 1 {
|
||||
return Ok(());
|
||||
@@ -420,6 +466,9 @@ pub fn flip_image(data: &mut ImageData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Applies opacity to an image.
|
||||
///
|
||||
/// Only supports RGBA or BGRA images with 8-bit depth.
|
||||
pub fn apply_opacity(img: &mut ImageData, opacity: u8) -> Result<()> {
|
||||
if img.color_type != ImageColorType::Rgba && img.color_type != ImageColorType::Bgra {
|
||||
return Err(anyhow::anyhow!("Image is not RGBA or BGRA"));
|
||||
@@ -435,6 +484,13 @@ pub fn apply_opacity(img: &mut ImageData, opacity: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draws an image on another image with specified opacity.
|
||||
///
|
||||
/// * `base` - The base image to draw on.
|
||||
/// * `diff` - The image to draw with opacity.
|
||||
/// * `left` - The horizontal offset to start drawing the image.
|
||||
/// * `top` - The vertical offset to start drawing the image.
|
||||
/// * `opacity` - The opacity level to apply to the drawn image (0-255
|
||||
pub fn draw_on_img_with_opacity(
|
||||
base: &mut ImageData,
|
||||
diff: &ImageData,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
//! Macros Utilities
|
||||
|
||||
#[macro_export]
|
||||
/// A macro likes `try!` but returns `Option<Result<T, E>>`.
|
||||
macro_rules! try_option {
|
||||
($expr:expr $(,)?) => {
|
||||
match $expr {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! Utility functions and modules.
|
||||
#[cfg(feature = "utils-bit-stream")]
|
||||
pub mod bit_stream;
|
||||
pub mod counter;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//! Name Replacement Utilities
|
||||
use crate::types::*;
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Read Name Replacement Table from CSV
|
||||
pub fn read_csv(path: &str) -> Result<HashMap<String, String>> {
|
||||
let mut reader = csv::ReaderBuilder::new()
|
||||
.has_headers(true)
|
||||
@@ -17,6 +19,7 @@ pub fn read_csv(path: &str) -> Result<HashMap<String, String>> {
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
/// Replace names in the message with the given name table.
|
||||
pub fn replace_message(mes: &mut Vec<Message>, name_table: &HashMap<String, String>) {
|
||||
for message in mes.iter_mut() {
|
||||
if let Some(name) = &message.name {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! PCM Utilities
|
||||
use crate::ext::io::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::struct_pack::*;
|
||||
@@ -6,15 +7,27 @@ use msg_tool_macro::*;
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
#[derive(Debug, StructPack, StructUnpack)]
|
||||
/// PCM Audio Format
|
||||
pub struct PcmFormat {
|
||||
format_tag: u16,
|
||||
channels: u16,
|
||||
sample_rate: u32,
|
||||
average_bytes_per_second: u32,
|
||||
block_align: u16,
|
||||
bits_per_sample: u16,
|
||||
/// The format tag
|
||||
pub format_tag: u16,
|
||||
/// The number of channels
|
||||
pub channels: u16,
|
||||
/// The sample rate
|
||||
pub sample_rate: u32,
|
||||
/// The average bytes per second
|
||||
pub average_bytes_per_second: u32,
|
||||
/// The block alignment
|
||||
pub block_align: u16,
|
||||
/// The bits per sample
|
||||
pub bits_per_sample: u16,
|
||||
}
|
||||
|
||||
/// Writes PCM data to a file.
|
||||
///
|
||||
/// * `format` - The PCM format to write.
|
||||
/// * `reader` - The reader to read PCM data from.
|
||||
/// * `writer` - The writer to write PCM data to.
|
||||
pub fn write_pcm<W: Write + Seek, R: Read>(
|
||||
format: &PcmFormat,
|
||||
mut reader: R,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! String Utilities
|
||||
use crate::types::*;
|
||||
use crate::utils::encoding::*;
|
||||
use anyhow::Result;
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
//! Binary Struct Packing and Unpacking Utilities
|
||||
use crate::types::Encoding;
|
||||
use anyhow::Result;
|
||||
use msg_tool_macro::struct_unpack_impl_for_num;
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
/// Trait for unpacking a struct from a binary stream.
|
||||
pub trait StructUnpack: Sized {
|
||||
/// Unpacks a struct from a binary stream.
|
||||
///
|
||||
/// * `reader` - The reader to read the binary data from.
|
||||
/// * `big` - Whether the data is in big-endian format.
|
||||
/// * `encoding` - The encoding to use for string fields.
|
||||
fn unpack<R: Read + Seek>(reader: R, big: bool, encoding: Encoding) -> Result<Self>;
|
||||
}
|
||||
|
||||
/// Trait for packing a struct into a binary stream.
|
||||
pub trait StructPack: Sized {
|
||||
/// Packs a struct into a binary stream.
|
||||
///
|
||||
/// * `writer` - The writer to write the binary data to.
|
||||
/// * `big` - Whether to use big-endian format.
|
||||
/// * `encoding` - The encoding to use for string fields.
|
||||
fn pack<W: Write>(&self, writer: &mut W, big: bool, encoding: Encoding) -> Result<()>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user