From cfc1dbf50713805137d7b132e362e33e29d6cb7c Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 10 Aug 2025 16:58:44 +0800 Subject: [PATCH] Add document --- Cargo.toml | 3 + msg_tool_macro/Cargo.toml | 3 + msg_tool_macro/src/lib.rs | 2 + src/args.rs | 1 + src/lib.rs | 2 + src/scripts/artemis/ast/dump.rs | 8 ++ src/scripts/artemis/ast/mod.rs | 5 +- src/scripts/artemis/ast/parser.rs | 7 ++ src/scripts/artemis/ast/types.rs | 49 +++++++++++- src/scripts/bgi/archive/dsc.rs | 15 ++++ src/scripts/bgi/archive/mod.rs | 1 + src/scripts/bgi/archive/v1.rs | 23 ++++++ src/scripts/bgi/archive/v2.rs | 23 ++++++ src/scripts/bgi/audio/audio.rs | 8 ++ src/scripts/bgi/audio/mod.rs | 1 + src/scripts/bgi/bp.rs | 9 +++ src/scripts/bgi/bsi.rs | 10 +++ src/scripts/bgi/image/cbg.rs | 8 ++ src/scripts/bgi/image/img.rs | 8 ++ src/scripts/bgi/image/mod.rs | 1 + src/scripts/bgi/script.rs | 9 +++ src/scripts/cat_system/archive/int.rs | 10 +++ src/scripts/cat_system/archive/mod.rs | 1 + src/scripts/cat_system/cst.rs | 9 +++ src/scripts/cat_system/cstl.rs | 17 +++- src/scripts/cat_system/image/hg3.rs | 12 ++- src/scripts/cat_system/image/mod.rs | 1 + src/scripts/cat_system/mod.rs | 1 + src/scripts/circus/image/crx.rs | 6 ++ src/types.rs | 109 +++++++++++++++++++++++++- src/utils/bit_stream.rs | 20 +++++ src/utils/counter.rs | 6 ++ src/utils/crc32.rs | 7 ++ src/utils/encoding.rs | 16 ++++ src/utils/escape.rs | 7 ++ src/utils/files.rs | 9 +++ src/utils/img.rs | 56 +++++++++++++ src/utils/macros.rs | 3 + src/utils/mod.rs | 1 + src/utils/name_replacement.rs | 3 + src/utils/pcm.rs | 25 ++++-- src/utils/str.rs | 1 + src/utils/struct_pack.rs | 13 +++ 43 files changed, 516 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b11011b..1513807 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,9 @@ name = "msg_tool" version = "0.1.0" edition = "2024" +repository = "https://github.com/lifegpc/msg-tool" +description = "A command-line tool for exporting, importing, packing, and unpacking script files." +license = "MIT" [dependencies] anyhow = "1" diff --git a/msg_tool_macro/Cargo.toml b/msg_tool_macro/Cargo.toml index cb6cb77..405fdb3 100644 --- a/msg_tool_macro/Cargo.toml +++ b/msg_tool_macro/Cargo.toml @@ -2,6 +2,9 @@ name = "msg_tool_macro" version = "0.1.0" edition = "2024" +repository = "https://github.com/lifegpc/msg-tool" +description = "A procedural macro for the msg-tool project." +license = "MIT" [lib] proc-macro = true diff --git a/msg_tool_macro/src/lib.rs b/msg_tool_macro/src/lib.rs index b910ee8..6e27279 100644 --- a/msg_tool_macro/src/lib.rs +++ b/msg_tool_macro/src/lib.rs @@ -29,6 +29,7 @@ impl syn::parse::Parse for PackStruct { } #[proc_macro] +/// Implements `StructUnpack` and `StructPack` traits for numeric types. pub fn struct_unpack_impl_for_num(item: TokenStream) -> TokenStream { let i = syn::parse_macro_input!(item as syn::Ident); let output = quote::quote! { @@ -647,6 +648,7 @@ pub fn struct_unpack_derive(input: TokenStream) -> TokenStream { #[cfg(feature = "artemis-arc")] #[proc_macro] +/// Generates a list of Artemis Arc extensions for the PFS file format. pub fn gen_artemis_arc_ext(_: TokenStream) -> TokenStream { let mut exts = Vec::new(); exts.push(quote::quote! { "pfs" }); diff --git a/src/args.rs b/src/args.rs index a8d4861..89d45a2 100644 --- a/src/args.rs +++ b/src/args.rs @@ -246,6 +246,7 @@ pub struct Arg { pub zlib_compression_level: u32, #[cfg(feature = "image")] #[arg(short = 'g', long, global = true, value_enum, default_value_t = PngCompressionLevel::Fast)] + /// PNG compression level. pub png_compression_level: PngCompressionLevel, #[cfg(feature = "circus-img")] #[arg(long, global = true, action = ArgAction::SetTrue)] diff --git a/src/lib.rs b/src/lib.rs index bb27c4e..01dcf50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ //! A Rust library for exporting, importing, packing, and unpacking script files. +//! +//! For more information, please visit the [GitHub repository](https://github.com/lifegpc/msg-tool). pub mod ext; pub mod format; pub mod output_scripts; diff --git a/src/scripts/artemis/ast/dump.rs b/src/scripts/artemis/ast/dump.rs index c229912..9551d4e 100644 --- a/src/scripts/artemis/ast/dump.rs +++ b/src/scripts/artemis/ast/dump.rs @@ -73,6 +73,7 @@ impl LenChecker { } } +/// A dumper for Artemis AST scripts. pub struct Dumper<'a> { current_indent: usize, writer: Box, @@ -82,6 +83,9 @@ pub struct Dumper<'a> { } impl<'a> Dumper<'a> { + /// Creates a new Dumper with the specified writer. + /// + /// default indent size is 4 spaces, and max line width is 100 characters. pub fn new(writer: W) -> Self { Dumper { current_indent: 0, @@ -92,14 +96,17 @@ impl<'a> Dumper<'a> { } } + /// Sets the indent size for the dumper. pub fn set_indent(&mut self, indent: usize) { self.indent = Some(indent); } + /// Disables indentation for the dumper. pub fn set_no_indent(&mut self) { self.indent = None; } + /// Sets the maximum line width for the dumper. pub fn set_max_line_width(&mut self, max_line_width: usize) { self.max_line_width = max_line_width; } @@ -112,6 +119,7 @@ impl<'a> Dumper<'a> { } } + /// Dumps the AST file to the writer. pub fn dump(mut self, ast: &AstFile) -> std::io::Result<()> { if self.indent.is_none() { if let Some(astver) = ast.astver { diff --git a/src/scripts/artemis/ast/mod.rs b/src/scripts/artemis/ast/mod.rs index 2b5a67b..4b04537 100644 --- a/src/scripts/artemis/ast/mod.rs +++ b/src/scripts/artemis/ast/mod.rs @@ -9,7 +9,10 @@ use crate::types::*; use crate::utils::encoding::*; use anyhow::Result; use std::io::Write; -use types::*; + +pub use dump::Dumper; +pub use parser::Parser; +pub use types::*; #[derive(Debug)] /// The builder for Artemis AST scripts. diff --git a/src/scripts/artemis/ast/parser.rs b/src/scripts/artemis/ast/parser.rs index 8b2289a..86141a2 100644 --- a/src/scripts/artemis/ast/parser.rs +++ b/src/scripts/artemis/ast/parser.rs @@ -4,6 +4,7 @@ use crate::utils::encoding::*; use crate::utils::escape::unescape_lua_str; use anyhow::Result; +/// A parser for Artemis AST scripts. pub struct Parser<'a> { str: &'a [u8], pos: usize, @@ -14,6 +15,10 @@ pub struct Parser<'a> { } impl<'a> Parser<'a> { + /// Creates a new parser for the given string with the specified encoding. + /// + /// * `str` - The string to parse. + /// * `encoding` - The encoding of the string. pub fn new + ?Sized>(str: &'a S, encoding: Encoding) -> Self { let str = str.as_ref(); Parser { @@ -26,6 +31,7 @@ impl<'a> Parser<'a> { } } + /// Checks if input is a valid header for an AST file. pub fn try_parse_header(mut self) -> Result<()> { self.erase_whitespace(); if self.is_indent(b"astver") { @@ -44,6 +50,7 @@ impl<'a> Parser<'a> { Ok(()) } + /// Parses the AST file and returns an [AstFile] object. pub fn parse(mut self) -> Result { self.erase_whitespace(); let astver = if self.is_indent(b"astver") { diff --git a/src/scripts/artemis/ast/types.rs b/src/scripts/artemis/ast/types.rs index 0faa1de..60827c4 100644 --- a/src/scripts/artemis/ast/types.rs +++ b/src/scripts/artemis/ast/types.rs @@ -3,12 +3,19 @@ use std::convert::From; use std::ops::{Deref, Index, IndexMut}; #[derive(Clone, Debug, PartialEq)] +/// Represents a value in LUA table pub enum Value { + /// Float number Float(f64), + /// Integer number Int(i64), + /// String value Str(String), + /// Key value pair KeyVal((Box, Box)), + /// Array of values Array(Vec), + /// Null(nli) value Null, } @@ -55,8 +62,8 @@ impl<'a> Deref for Key<'a> { const NULL: Value = Value::Null; -#[allow(dead_code)] impl Value { + /// Returns a reference to the string if the value is a string, otherwise returns None. pub fn as_str(&self) -> Option<&str> { if let Value::Str(s) = self { Some(s) @@ -65,6 +72,7 @@ impl Value { } } + /// Returns a string if the value is a string, otherwise returns None. pub fn as_string(&self) -> Option { if let Value::Str(s) = self { Some(s.clone()) @@ -97,6 +105,16 @@ impl Value { } } + /// Find a nested array by key (first value of nested array). + /// If the key is not found, it creates a new array with the key and returns a mutable reference to it. + /// + /// # Example + /// ```lua + /// { + /// {"save", text="test"}, + /// } + /// ``` + /// for above array, calling `find_array_mut("save")` will return a mutable reference to the array `{"save", text="test"}`. pub fn find_array_mut(&mut self, key: &str) -> &mut Value { match &self { Value::Array(arr) => { @@ -115,22 +133,27 @@ impl Value { } } + /// Returns true if the value is an array. pub fn is_array(&self) -> bool { matches!(self, Value::Array(_)) } + /// Returns true if the value is a string. pub fn is_str(&self) -> bool { matches!(self, Value::Str(_)) } + /// Returns true if the value is a key-value pair. pub fn is_kv(&self) -> bool { matches!(self, Value::KeyVal(_)) } + /// Returns true if the value is null. pub fn is_null(&self) -> bool { matches!(self, Value::Null) } + /// Returns the key of a key-value pair if it exists, otherwise returns None. pub fn kv_key(&self) -> Option<&Value> { if let Value::KeyVal((k, _)) = self { Some(&k) @@ -139,6 +162,7 @@ impl Value { } } + /// Returns the keys in a lua table. pub fn kv_keys<'a>(&'a self) -> Box + 'a> { match self { Value::KeyVal((k, _)) => Box::new(std::iter::once(&**k)), @@ -147,6 +171,7 @@ impl Value { } } + /// Returns the last member of the array if it exists, otherwise returns a reference to `NULL`. pub fn last_member(&self) -> &Value { match self { Value::Array(arr) => arr.last().unwrap_or(&NULL), @@ -154,6 +179,10 @@ impl Value { } } + /// Returns a mutable reference to the last member of the array. + /// + /// If the array is empty, it creates a new member with `NULL` and returns it. + /// If the value is not an array, it converts it to an array with a single `NULL` member. pub fn last_member_mut(&mut self) -> &mut Value { match self { Value::Array(arr) => { @@ -169,6 +198,7 @@ impl Value { } } + /// Returns the length of the array. pub fn len(&self) -> usize { match self { Value::Array(arr) => arr.len(), @@ -176,6 +206,10 @@ impl Value { } } + /// Inserts a member at the specified index in the array. + /// + /// If the index is out of bounds, it appends the value to the end of the array. + /// If the value is not an array, it converts it to an array with a single member. pub fn insert_member(&mut self, index: usize, value: Value) { match self { Value::Array(arr) => { @@ -191,6 +225,7 @@ impl Value { } } + /// Returns an iterator over the members of the array. pub fn members<'a>(&'a self) -> Iter<'a> { match self { Value::Array(arr) => Iter { iter: arr.iter() }, @@ -198,6 +233,7 @@ impl Value { } } + /// Returns a mutable iterator over the members of the array. pub fn members_mut<'a>(&'a mut self) -> IterMut<'a> { match self { Value::Array(arr) => IterMut { @@ -207,14 +243,17 @@ impl Value { } } + /// Creates a new empty array. pub fn new_array() -> Self { Value::Array(Vec::new()) } + /// Creates a new key-value pair. pub fn new_kv, V: Into>(key: K, value: V) -> Self { Value::KeyVal((Box::new(key.into()), Box::new(value.into()))) } + /// Pushes a member to the end of the array. pub fn push_member(&mut self, value: Value) { match self { Value::Array(arr) => arr.push(value), @@ -224,10 +263,12 @@ impl Value { } } + /// Sets the value to a string. pub fn set_str + ?Sized>(&mut self, value: &S) { *self = Value::Str(value.as_ref().to_string()); } + /// Sets the value to a string. pub fn set_string>(&mut self, value: S) { *self = Value::Str(value.into()); } @@ -756,6 +797,7 @@ impl PartialOrd for Box { } #[derive(Default)] +/// An iterator over the members of an array. pub struct Iter<'a> { iter: std::slice::Iter<'a, Value>, } @@ -784,6 +826,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } #[derive(Default)] +/// A mutable iterator over the members of an array. pub struct IterMut<'a> { iter: std::slice::IterMut<'a, Value>, } @@ -812,8 +855,12 @@ impl<'a> DoubleEndedIterator for IterMut<'a> { } #[derive(Clone, Debug)] +/// Represents an AST file. pub struct AstFile { + /// The version of the AST file. pub astver: Option, + /// The name of the AST file. pub astname: Option, + /// The data of the AST file. pub ast: Value, } diff --git a/src/scripts/bgi/archive/dsc.rs b/src/scripts/bgi/archive/dsc.rs index bcb7aa1..e3e28de 100644 --- a/src/scripts/bgi/archive/dsc.rs +++ b/src/scripts/bgi/archive/dsc.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell compressed file in archive use crate::ext::io::*; use crate::ext::vec::*; use crate::scripts::base::*; @@ -52,6 +53,7 @@ struct HuffmanNode { right_index: usize, } +/// Decoder for Buriko General Interpreter/Ethornell compressed files (DSC format). pub struct DscDecoder<'a> { stream: MsbBitStream>, key: u32, @@ -61,6 +63,7 @@ pub struct DscDecoder<'a> { } impl<'a> DscDecoder<'a> { + /// Creates a new DscDecoder from the given data slice. pub fn new(data: &'a [u8]) -> Result { let mut reader = MemReaderRef::new(data); let magic = (reader.read_u16()? as u32) << 16; @@ -78,6 +81,7 @@ impl<'a> DscDecoder<'a> { }) } + /// Unpacks the DSC file and returns the decompressed data. pub fn unpack(mut self) -> Result> { self.stream.m_input.pos = 0x20; let mut codes = Vec::new(); @@ -396,6 +400,7 @@ fn generate_canonical_codes(depths: &[u8]) -> Vec> { huffman_codes } +/// Encoder for Buriko General Interpreter/Ethornell compressed files (DSC format). pub struct DscEncoder<'a, T: Write + Seek> { stream: MsbBitWriter<'a, T>, magic: u32, @@ -405,6 +410,7 @@ pub struct DscEncoder<'a, T: Write + Seek> { } impl<'a, T: Write + Seek> DscEncoder<'a, T> { + /// Creates a new DscEncoder with the given writer and minimum length for LZSS compression. pub fn new(writer: &'a mut T, min_len: usize) -> Self { let stream = MsbBitWriter::new(writer); DscEncoder { @@ -416,6 +422,7 @@ impl<'a, T: Write + Seek> DscEncoder<'a, T> { } } + /// Packs the given data into the DSC format using LZSS compression. pub fn pack(mut self, data: &[u8]) -> Result<()> { // LZSS compression let mut ops = vec![]; @@ -552,9 +559,11 @@ impl<'a, T: Write + Seek> DscEncoder<'a, T> { } #[derive(Debug)] +/// Builder for DSC scripts. pub struct DscBuilder {} impl DscBuilder { + /// Creates a new instance of `DscBuilder`. pub fn new() -> Self { DscBuilder {} } @@ -616,12 +625,17 @@ impl ScriptBuilder for DscBuilder { } #[derive(Debug)] +/// DSC script pub struct Dsc { data: Vec, min_len: usize, } impl Dsc { + /// Creates a new Dsc script + /// + /// * `buf` - The buffer containing the DSC data. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, config: &ExtraConfig) -> Result { if buf.len() < 16 || !buf.starts_with(b"DSC FORMAT 1.00\0") { return Err(anyhow::anyhow!("Invalid DSC format")); @@ -672,6 +686,7 @@ impl Script for Dsc { } } +/// Parses the minimum length for LZSS compression from a string. pub fn parse_min_length(len: &str) -> Result { clap_num::number_range(len, 2, 256) } diff --git a/src/scripts/bgi/archive/mod.rs b/src/scripts/bgi/archive/mod.rs index 717da69..c071860 100644 --- a/src/scripts/bgi/archive/mod.rs +++ b/src/scripts/bgi/archive/mod.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter / Ethornell Archive mod bse; pub mod dsc; pub mod v1; diff --git a/src/scripts/bgi/archive/v1.rs b/src/scripts/bgi/archive/v1.rs index 85947de..b004464 100644 --- a/src/scripts/bgi/archive/v1.rs +++ b/src/scripts/bgi/archive/v1.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Archive File Version 1 (.arc) use super::bse::*; use super::dsc::*; use crate::ext::io::*; @@ -12,9 +13,11 @@ use std::io::{Read, Seek, SeekFrom, Write}; use std::sync::{Arc, Mutex}; #[derive(Debug)] +/// Builder for BGI Archive Version 1 scripts. pub struct BgiArchiveBuilder {} impl BgiArchiveBuilder { + /// Creates a new instance of `BgiArchiveBuilder`. pub const fn new() -> Self { BgiArchiveBuilder {} } @@ -215,6 +218,7 @@ impl Seek for Entry { } #[derive(Debug)] +/// Buriko General Interpreter/Ethornell Archive File Version 1 (.arc) pub struct BgiArchive { reader: Arc>, entries: Vec, @@ -224,6 +228,12 @@ pub struct BgiArchive { } impl BgiArchive { + /// Creates a new BGI archive from a reader. + /// + /// * `reader` - The reader to read the archive from. + /// * `archive_encoding` - The encoding used for the archive. + /// * `config` - Extra configuration options. + /// * `filename` - The name of the archive file. pub fn new( mut reader: T, archive_encoding: Encoding, @@ -511,6 +521,7 @@ fn detect_script_type_sysgrp( Some(&ScriptType::BGIImg) } +/// BGI Archive Writer pub struct BgiArchiveWriter { writer: T, headers: HashMap, @@ -520,6 +531,12 @@ pub struct BgiArchiveWriter { } impl BgiArchiveWriter { + /// Creates a new BGI Archive Writer. + /// + /// * `writer` - The writer to write the archive to. + /// * `files` - The list of files to include in the archive. + /// * `encoding` - The encoding used for the archive. + /// * `config` - Extra configuration options. pub fn new( mut writer: T, files: &[&str], @@ -586,6 +603,7 @@ impl Archive for BgiArchiveWriter { } } +/// BGI Archive File Writer (Not compressed) pub struct BgiArchiveFile<'a, T: Write + Seek> { header: &'a mut BgiFileHeader, writer: &'a mut T, @@ -643,6 +661,7 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFile<'a, T> { } } +/// BGI Archive File Writer with DSC compression pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> { writer: BgiArchiveFile<'a, T>, buf: MemWriter, @@ -650,6 +669,10 @@ pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> { } impl<'a, T: Write + Seek> BgiArchiveFileWithDsc<'a, T> { + /// Creates a new BGI Archive File Writer with DSC compression. + /// + /// * `writer` - The writer to write the archive file to. + /// * `min_len` - The minimum length for LZSS compression. pub fn new(writer: BgiArchiveFile<'a, T>, min_len: usize) -> Self { BgiArchiveFileWithDsc { writer, diff --git a/src/scripts/bgi/archive/v2.rs b/src/scripts/bgi/archive/v2.rs index 7eef254..87f367c 100644 --- a/src/scripts/bgi/archive/v2.rs +++ b/src/scripts/bgi/archive/v2.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Archive File Version 2 (.arc) use super::bse::*; use super::dsc::*; use crate::ext::io::*; @@ -12,9 +13,11 @@ use std::io::{Read, Seek, SeekFrom, Write}; use std::sync::{Arc, Mutex}; #[derive(Debug)] +/// Builder for BGI Archive Version 2 pub struct BgiArchiveBuilder {} impl BgiArchiveBuilder { + /// Creates a new instance of `BgiArchiveBuilder`. pub const fn new() -> Self { BgiArchiveBuilder {} } @@ -247,6 +250,7 @@ impl Option<&'static ScriptType>> ArchiveContent fo } #[derive(Debug)] +/// BGI Archive Version 2 pub struct BgiArchive { reader: Arc>, entries: Vec, @@ -256,6 +260,12 @@ pub struct BgiArchive { } impl BgiArchive { + /// Creates a new BGI Archive from a reader. + /// + /// * `reader` - The reader to read the archive from. + /// * `archive_encoding` - The encoding used for the archive. + /// * `config` - Extra configuration options. + /// * `filename` - The name of the archive file (used for detecting sysgrp.arc). pub fn new( mut reader: T, archive_encoding: Encoding, @@ -513,6 +523,7 @@ fn detect_script_type_sysgrp( Some(&ScriptType::BGIImg) } +/// BGI Archive Writer for Version 2 pub struct BgiArchiveWriter { writer: T, headers: HashMap, @@ -522,6 +533,12 @@ pub struct BgiArchiveWriter { } impl BgiArchiveWriter { + /// Creates a new BGI Archive Writer. + /// + /// * `writer` - The writer to write the archive to. + /// * `files` - The list of files to include in the archive. + /// * `encoding` - The encoding used for the archive. + /// * `config` - Extra configuration options. pub fn new( mut writer: T, files: &[&str], @@ -589,6 +606,7 @@ impl Archive for BgiArchiveWriter { } } +/// BGI Archive File Writer (Not compressed) pub struct BgiArchiveFile<'a, T: Write + Seek> { header: &'a mut BgiFileHeader, writer: &'a mut T, @@ -646,6 +664,7 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFile<'a, T> { } } +/// BGI Archive File Writer with DSC compression pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> { writer: BgiArchiveFile<'a, T>, buf: MemWriter, @@ -653,6 +672,10 @@ pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> { } impl<'a, T: Write + Seek> BgiArchiveFileWithDsc<'a, T> { + /// Creates a new BGI Archive File Writer with DSC compression. + /// + /// * `writer` - The writer to write the archive file to. + /// * `min_len` - The minimum length for LZSS compression. pub fn new(writer: BgiArchiveFile<'a, T>, min_len: usize) -> Self { BgiArchiveFileWithDsc { writer, diff --git a/src/scripts/bgi/audio/audio.rs b/src/scripts/bgi/audio/audio.rs index 10e8b18..4b53dcb 100644 --- a/src/scripts/bgi/audio/audio.rs +++ b/src/scripts/bgi/audio/audio.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Audio File (Ogg/Vorbis) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -5,9 +6,11 @@ use anyhow::Result; use std::io::{Read, Seek, SeekFrom, Write}; #[derive(Debug)] +/// Builder for BGI Audio scripts. pub struct BgiAudioBuilder {} impl BgiAudioBuilder { + /// Creates a new instance of `BgiAudioBuilder`. pub fn new() -> Self { Self {} } @@ -73,11 +76,16 @@ impl ScriptBuilder for BgiAudioBuilder { } #[derive(Debug)] +/// BGI Audio script. pub struct BgiAudio { data: MemReader, } impl BgiAudio { + /// Creates a new instance of `BgiAudio` from a reader. + /// + /// * `reader` - The reader to read the audio data from. + /// * `config` - Extra configuration options. pub fn new(mut reader: R, _config: &ExtraConfig) -> Result { let offset = reader.read_u32()?; let len = reader.stream_length()?; diff --git a/src/scripts/bgi/audio/mod.rs b/src/scripts/bgi/audio/mod.rs index fa3e4e4..1fb74d6 100644 --- a/src/scripts/bgi/audio/mod.rs +++ b/src/scripts/bgi/audio/mod.rs @@ -1 +1,2 @@ +//! Buriko General Interpreter / Ethornell Audio pub mod audio; diff --git a/src/scripts/bgi/bp.rs b/src/scripts/bgi/bp.rs index 6bc902b..4a1e90e 100644 --- a/src/scripts/bgi/bp.rs +++ b/src/scripts/bgi/bp.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell BP Script (._bp) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -6,9 +7,11 @@ use anyhow::Result; use std::io::{Seek, SeekFrom}; #[derive(Debug)] +/// Builder for BGI BP scripts. pub struct BGIBpScriptBuilder {} impl BGIBpScriptBuilder { + /// Creates a new instance of `BGIBpScriptBuilder`. pub fn new() -> Self { BGIBpScriptBuilder {} } @@ -47,6 +50,7 @@ struct BpString { } #[derive(Debug)] +/// BGI BP script. pub struct BGIBpScript { data: MemReader, header_size: u32, @@ -55,6 +59,11 @@ pub struct BGIBpScript { } impl BGIBpScript { + /// Creates a new instance of `BGIBpScript` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `encoding` - The encoding of the script. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, encoding: Encoding, _config: &ExtraConfig) -> Result { let mut reader = MemReader::new(buf); let header_size = reader.read_u32()?; diff --git a/src/scripts/bgi/bsi.rs b/src/scripts/bgi/bsi.rs index 0d57ed4..1dad1d6 100644 --- a/src/scripts/bgi/bsi.rs +++ b/src/scripts/bgi/bsi.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell BSI Script (._bsi) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -7,9 +8,11 @@ use std::collections::BTreeMap; use std::ffi::CString; #[derive(Debug)] +/// Builder for BGI BSI scripts. pub struct BGIBsiScriptBuilder {} impl BGIBsiScriptBuilder { + /// Creates a new instance of `BGIBsiScriptBuilder`. pub fn new() -> Self { BGIBsiScriptBuilder {} } @@ -57,11 +60,18 @@ impl ScriptBuilder for BGIBsiScriptBuilder { } #[derive(Debug)] +/// BGI BSI script. pub struct BGIBsiScript { + /// Section name and its data map. pub data: BTreeMap>, } impl BGIBsiScript { + /// Creates a new instance of `BGIBsiScript` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `encoding` - The encoding of the script. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, encoding: Encoding, _config: &ExtraConfig) -> Result { let mut data = BTreeMap::new(); let mut reader = MemReader::new(buf); diff --git a/src/scripts/bgi/image/cbg.rs b/src/scripts/bgi/image/cbg.rs index c4ee01d..5072d12 100644 --- a/src/scripts/bgi/image/cbg.rs +++ b/src/scripts/bgi/image/cbg.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Compressed Image File use crate::ext::atomic::*; use crate::ext::io::*; use crate::scripts::base::*; @@ -12,9 +13,11 @@ use std::sync::atomic::AtomicBool; use std::sync::{Arc, Mutex}; #[derive(Debug)] +/// Builder for BGI Compressed Image scripts. pub struct BgiCBGBuilder {} impl BgiCBGBuilder { + /// Creates a new instance of `BgiCBGBuilder`. pub const fn new() -> Self { BgiCBGBuilder {} } @@ -125,6 +128,7 @@ fn convert_bgr565_to_bgr24(input: Vec, width: u16, height: u16) -> ImageData } #[derive(Debug)] +/// BGI Compressed Image script. pub struct BgiCBG { header: BgiCBGHeader, data: MemReader, @@ -132,6 +136,10 @@ pub struct BgiCBG { } impl BgiCBG { + /// Creates a new instance of `BgiCBG` from a buffer. + /// + /// * `data` - The buffer containing the script data. + /// * `config` - Extra configuration options. pub fn new(data: Vec, _config: &ExtraConfig) -> Result { let mut reader = MemReader::new(data); let mut magic = [0u8; 16]; diff --git a/src/scripts/bgi/image/img.rs b/src/scripts/bgi/image/img.rs index 07bf8f5..2b1f373 100644 --- a/src/scripts/bgi/image/img.rs +++ b/src/scripts/bgi/image/img.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Uncompressed Image File use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -31,9 +32,11 @@ fn try_parse(buf: &[u8]) -> Result { } #[derive(Debug)] +/// Builder for BGI Uncompressed Image scripts. pub struct BgiImageBuilder {} impl BgiImageBuilder { + /// Creates a new instance of `BgiImageBuilder`. pub const fn new() -> Self { BgiImageBuilder {} } @@ -90,6 +93,7 @@ impl ScriptBuilder for BgiImageBuilder { } #[derive(Debug)] +/// BGI Uncompressed Image script. pub struct BgiImage { data: MemReader, width: u32, @@ -162,6 +166,10 @@ fn create_image<'a>( } impl BgiImage { + /// Creates a new instance of `BgiImage` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, config: &ExtraConfig) -> Result { let mut reader = MemReader::new(buf); let width = reader.read_u16()? as u32; diff --git a/src/scripts/bgi/image/mod.rs b/src/scripts/bgi/image/mod.rs index fd87631..2a2dca2 100644 --- a/src/scripts/bgi/image/mod.rs +++ b/src/scripts/bgi/image/mod.rs @@ -1,2 +1,3 @@ +//! Buriko General Interpreter/Ethornell Image pub mod cbg; pub mod img; diff --git a/src/scripts/bgi/script.rs b/src/scripts/bgi/script.rs index 0b844e4..4cd1853 100644 --- a/src/scripts/bgi/script.rs +++ b/src/scripts/bgi/script.rs @@ -1,3 +1,4 @@ +//! Buriko General Interpreter/Ethornell Script use super::parser::*; use crate::ext::io::*; use crate::scripts::base::*; @@ -9,9 +10,11 @@ use lazy_static::lazy_static; use std::collections::{BTreeMap, HashMap}; #[derive(Debug)] +/// Builder for BGI scripts. pub struct BGIScriptBuilder {} impl BGIScriptBuilder { + /// Creates a new instance of `BGIScriptBuilder`. pub fn new() -> Self { BGIScriptBuilder {} } @@ -54,6 +57,7 @@ impl ScriptBuilder for BGIScriptBuilder { } } +/// BGI Script pub struct BGIScript { data: MemReader, encoding: Encoding, @@ -74,6 +78,11 @@ impl std::fmt::Debug for BGIScript { } impl BGIScript { + /// Creates a new instance of `BGIScript` from a buffer. + /// + /// * `data` - The buffer containing the script data. + /// * `encoding` - The encoding of the script. + /// * `config` - Extra configuration options. pub fn new(data: Vec, encoding: Encoding, config: &ExtraConfig) -> Result { let data = MemReader::new(data); if data.data.starts_with(b"BurikoCompiledScriptVer1.00\0") { diff --git a/src/scripts/cat_system/archive/int.rs b/src/scripts/cat_system/archive/int.rs index 511c648..dcace4d 100644 --- a/src/scripts/cat_system/archive/int.rs +++ b/src/scripts/cat_system/archive/int.rs @@ -1,3 +1,4 @@ +//! CatSystem2 Archive File (.int) use super::twister::MersenneTwister; use crate::ext::io::*; use crate::scripts::base::*; @@ -11,9 +12,11 @@ use std::io::{Read, Seek, SeekFrom}; use std::sync::{Arc, Mutex}; #[derive(Debug)] +/// Builder for CatSystem2 Archive scripts. pub struct CSIntArcBuilder {} impl CSIntArcBuilder { + /// Creates a new instance of `CSIntArcBuilder`. pub fn new() -> Self { CSIntArcBuilder {} } @@ -237,6 +240,7 @@ impl ArchiveContent for MemEntry { } #[derive(Debug)] +/// CatSystem2 Archive script. pub struct CSIntArc { reader: Arc>, encrypt: Option, @@ -246,6 +250,12 @@ pub struct CSIntArc { const NAME_SIZES: [usize; 2] = [0x20, 0x40]; impl CSIntArc { + /// Creates a new instance of `CSIntArc` from a reader. + /// + /// * `reader` - The reader to read the archive from. + /// * `archive_encoding` - The encoding used for the archive. + /// * `config` - Extra configuration options. + /// * `filename` - The name of the file. pub fn new( mut reader: T, archive_encoding: Encoding, diff --git a/src/scripts/cat_system/archive/mod.rs b/src/scripts/cat_system/archive/mod.rs index f1d7407..2d0c07c 100644 --- a/src/scripts/cat_system/archive/mod.rs +++ b/src/scripts/cat_system/archive/mod.rs @@ -1,2 +1,3 @@ +//! CatSystem2 Archive pub mod int; mod twister; diff --git a/src/scripts/cat_system/cst.rs b/src/scripts/cat_system/cst.rs index e7216ea..4f571f5 100644 --- a/src/scripts/cat_system/cst.rs +++ b/src/scripts/cat_system/cst.rs @@ -1,3 +1,4 @@ +//! CatSystem2 Scene Script File (.cst) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -8,9 +9,11 @@ use int_enum::IntEnum; use std::io::{Read, Write}; #[derive(Debug)] +/// Builder for CatSystem2 Scene Script files. pub struct CstScriptBuilder {} impl CstScriptBuilder { + /// Creates a new instance of `CstScriptBuilder`. pub fn new() -> Self { CstScriptBuilder {} } @@ -96,6 +99,7 @@ struct CstString { } #[derive(Debug)] +/// CatSystem2 Scene Script. pub struct CstScript { data: MemReader, compressed: bool, @@ -104,6 +108,11 @@ pub struct CstScript { } impl CstScript { + /// Creates a new instance of `CstScript` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `encoding` - The encoding of the script. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, encoding: Encoding, config: &ExtraConfig) -> Result { let mut reader = MemReader::new(buf); let mut magic = [0; 8]; diff --git a/src/scripts/cat_system/cstl.rs b/src/scripts/cat_system/cstl.rs index fe66e35..a5a9f8b 100644 --- a/src/scripts/cat_system/cstl.rs +++ b/src/scripts/cat_system/cstl.rs @@ -1,3 +1,4 @@ +//! CatSystem2 Scene I18N File (.cstl) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -7,9 +8,11 @@ use std::collections::BTreeMap; use std::io::{Read, Write}; #[derive(Debug)] +/// Builder for CatSystem2 Scene I18N Script files. pub struct CstlScriptBuilder {} impl CstlScriptBuilder { + /// Creates a new instance of `CstlScriptBuilder`. pub fn new() -> Self { CstlScriptBuilder {} } @@ -63,6 +66,12 @@ impl ScriptBuilder for CstlScriptBuilder { } } +/// Create a new CSTL file. +/// +/// * `custom_filename` - The path of input file. +/// * `file` - The writer to write the CSTL file to. +/// * `encoding` - The encoding of the CSTL file. +/// * `output_encoding` - The encoding to use for the input file. pub fn create_file( custom_filename: &str, mut file: T, @@ -151,13 +160,19 @@ impl CustomWriteFn for T { } #[derive(Debug)] -struct CstlScript { +/// CSTL script. +pub struct CstlScript { langs: Vec, data: Vec>, lang_index: Option, } impl CstlScript { + /// Creates a new instance of `CstlScript` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `encoding` - The encoding of the script. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, encoding: Encoding, config: &ExtraConfig) -> Result { let mut langs = Vec::new(); let mut data = Vec::new(); diff --git a/src/scripts/cat_system/image/hg3.rs b/src/scripts/cat_system/image/hg3.rs index ec37da9..928f6e4 100644 --- a/src/scripts/cat_system/image/hg3.rs +++ b/src/scripts/cat_system/image/hg3.rs @@ -1,3 +1,4 @@ +//! CatSystem2 HG3 Image File (.hg3) use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; @@ -11,9 +12,11 @@ use overf::wrapping; use std::io::{Read, Seek, Write}; #[derive(Debug)] +/// Builder for CatSystem2 HG3 Image scripts. pub struct Hg3ImageBuilder {} impl Hg3ImageBuilder { + /// Creates a new instance of `Hg3ImageBuilder`. pub const fn new() -> Self { Hg3ImageBuilder {} } @@ -66,6 +69,7 @@ struct Hg3Entry { } #[derive(Debug)] +/// CatSystem2 HG3 Image script. pub struct Hg3Image { data: MemReader, entries: Vec<(Hg3Entry, usize, usize)>, @@ -73,6 +77,10 @@ pub struct Hg3Image { } impl Hg3Image { + /// Creates a new instance of `Hg3Image` from a buffer. + /// + /// * `buf` - The buffer containing the script data. + /// * `config` - Extra configuration options. pub fn new(buf: Vec, config: &ExtraConfig) -> Result { let mut reader = MemReader::new(buf); let mut magic = [0u8; 4]; @@ -216,14 +224,14 @@ impl<'a, T: Iterator + 'a> Iterator for Hg3 } } -pub struct Hg3Reader<'a> { +struct Hg3Reader<'a> { m_input: MemReaderRef<'a>, m_info: Hg3Entry, m_pixel_size: u32, } impl<'a> Hg3Reader<'a> { - pub fn unpack_stream( + fn unpack_stream( &mut self, data_offset: usize, data_packed: usize, diff --git a/src/scripts/cat_system/image/mod.rs b/src/scripts/cat_system/image/mod.rs index 8ec74ac..3059b82 100644 --- a/src/scripts/cat_system/image/mod.rs +++ b/src/scripts/cat_system/image/mod.rs @@ -1 +1,2 @@ +//! CatSystem2 HG3 Image pub mod hg3; diff --git a/src/scripts/cat_system/mod.rs b/src/scripts/cat_system/mod.rs index 6884b6c..9b55cf2 100644 --- a/src/scripts/cat_system/mod.rs +++ b/src/scripts/cat_system/mod.rs @@ -1,3 +1,4 @@ +//! CatSystem2 Scripts #[cfg(feature = "cat-system-arc")] pub mod archive; pub mod cst; diff --git a/src/scripts/circus/image/crx.rs b/src/scripts/circus/image/crx.rs index 3bb870e..a2bcc68 100644 --- a/src/scripts/circus/image/crx.rs +++ b/src/scripts/circus/image/crx.rs @@ -18,6 +18,12 @@ pub enum CircusCrxMode { Best, } +impl Default for CircusCrxMode { + fn default() -> Self { + CircusCrxMode::Auto + } +} + impl CircusCrxMode { pub fn for_importing(&self) -> Self { match self { diff --git a/src/types.rs b/src/types.rs index 08ae3d2..f97dc0f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,3 +1,4 @@ +//! Basic types use clap::ValueEnum; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -26,6 +27,7 @@ impl Default for Encoding { } impl Encoding { + /// Returns true if the encoding is Shift-JIS (CP932). pub fn is_jis(&self) -> bool { match self { Self::Cp932 => true, @@ -37,7 +39,7 @@ impl Encoding { } #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] -/// Text Encoding +/// Text Encoding (for CLI) pub enum TextEncoding { /// Use script's default encoding Default, @@ -67,12 +69,14 @@ pub enum OutputScriptType { } impl OutputScriptType { + /// Returns true if the script type is custom. pub fn is_custom(&self) -> bool { matches!(self, OutputScriptType::Custom) } } impl AsRef for OutputScriptType { + /// Returns the extension for the script type. fn as_ref(&self) -> &str { match self { OutputScriptType::M3t => "m3t", @@ -85,6 +89,7 @@ impl AsRef for OutputScriptType { #[cfg(feature = "circus")] #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] +/// Circus MES game pub enum CircusMesType { /// fortissimo//Akkord:Bsusvier Ffexa, @@ -152,6 +157,7 @@ pub enum CircusMesType { #[cfg(feature = "circus")] impl AsRef for CircusMesType { + /// Returns the name. fn as_ref(&self) -> &str { match self { CircusMesType::Ffexa => "ffexa", @@ -189,84 +195,133 @@ impl AsRef for CircusMesType { } } +/// Extra configuration options for the script. +#[derive(Debug, Clone, Default)] pub struct ExtraConfig { #[cfg(feature = "circus")] + /// Circus Game for circus MES script. pub circus_mes_type: Option, #[cfg(feature = "escude-arc")] + /// Whether to use fake compression for Escude archive pub escude_fake_compress: bool, #[cfg(feature = "escude")] + /// The path to the Escude enum script file (enum_scr.bin) pub escude_enum_scr: Option, #[cfg(feature = "bgi")] + /// Duplicate same strings when importing into BGI scripts. + /// Enable this will cause BGI scripts to become very large. pub bgi_import_duplicate: bool, #[cfg(feature = "bgi")] + /// Disable appending new strings to the end of BGI scripts. + /// Disable may cause BGI scripts broken. pub bgi_disable_append: bool, #[cfg(feature = "image")] + /// Output image type pub image_type: Option, #[cfg(all(feature = "bgi-arc", feature = "bgi-img"))] + /// Detect all files in BGI archive as SysGrp Images. By default, only files which name is `sysgrp.arc` will enabled this. pub bgi_is_sysgrp_arc: Option, #[cfg(feature = "bgi-img")] + /// Whether to create scrambled SysGrp images. When in import mode, the default value depends on the original image. + /// When in creation mode, it is not enabled by default. pub bgi_img_scramble: Option, #[cfg(feature = "cat-system-arc")] + /// CatSystem2 engine int archive password pub cat_system_int_encrypt_password: Option, #[cfg(feature = "cat-system-img")] + /// Draw CatSystem2 image on canvas (if canvas width and height are specified in file) pub cat_system_image_canvas: bool, #[cfg(feature = "kirikiri")] + /// Kirikiri language index in script. If not specified, the first language will be used. pub kirikiri_language_index: Option, #[cfg(feature = "kirikiri")] + /// Export COMU message to extra json file. (for Kirikiri SCN script.) + /// Only CIRCUS's game have COMU message. pub kirikiri_export_comumode: bool, #[cfg(feature = "kirikiri")] + /// Kirikiri COMU message translation. key is original text, value is translated text. pub kirikiri_comumode_json: Option>>, #[cfg(feature = "kirikiri")] + /// Remove empty lines in Kirikiri KS script. pub kirikiri_remove_empty_lines: bool, #[cfg(feature = "kirikiri")] + /// Kirikiri name commands, used to extract names from ks script. pub kirikiri_name_commands: std::sync::Arc>, #[cfg(feature = "kirikiri")] + /// Kirikiri message commands, used to extract more message from ks script. pub kirikiri_message_commands: std::sync::Arc>, #[cfg(feature = "bgi-arc")] + /// Whether to compress files in BGI archive when packing BGI archive. pub bgi_compress_file: bool, #[cfg(feature = "bgi-arc")] + /// Minimum length of match size for DSC compression. Possible values are 2-256. pub bgi_compress_min_len: usize, #[cfg(feature = "kirikiri-img")] + /// Whether to overlay PIMG images. (By default, true if all layers are not group layers.) pub kirikiri_pimg_overlay: Option, #[cfg(feature = "artemis-arc")] + /// Disable Artemis archive (.pfs) XOR encryption when packing. pub artemis_arc_disable_xor: bool, #[cfg(feature = "artemis")] + /// Artemis script indent size, used to format Artemis script. + /// Default is 4 spaces. pub artemis_indent: Option, #[cfg(feature = "artemis")] + /// Disable Artemis script indent, used to format Artemis script. pub artemis_no_indent: bool, #[cfg(feature = "artemis")] + /// Max line width in Artemis script, used to format Artemis script. pub artemis_max_line_width: usize, #[cfg(feature = "artemis")] + /// Specify the language of Artemis AST script. + /// If not specified, the first language will be used. pub artemis_ast_lang: Option, #[cfg(feature = "cat-system")] + /// CatSystem2 CSTL script language, used to extract messages from CSTL script. + /// If not specified, the first language will be used. pub cat_system_cstl_lang: Option, #[cfg(feature = "flate2")] + /// Zlib compression level. 0 means no compression, 9 means best compression. pub zlib_compression_level: u32, #[cfg(feature = "image")] + /// PNG compression level. pub png_compression_level: PngCompressionLevel, #[cfg(feature = "circus-img")] + /// Keep original BPP when importing Circus CRX images. pub circus_crx_keep_original_bpp: bool, #[cfg(feature = "circus-img")] + /// Use zstd compression for Circus CRX images. (CIRCUS Engine don't support this. Hook is required.) pub circus_crx_zstd: bool, #[cfg(feature = "zstd")] + /// Zstd compression level. 0 means default compression level (3), 22 means best compression. pub zstd_compression_level: i32, #[cfg(feature = "circus-img")] + /// Circus CRX image row type mode pub circus_crx_mode: crate::scripts::circus::image::crx::CircusCrxMode, #[cfg(feature = "ex-hibit")] + /// ExHibit xor key for rld script. + /// Use [ReExHIBIT](https://github.com/ZQF-ReVN/RxExHIBIT) to find the key. pub ex_hibit_rld_xor_key: Option, #[cfg(feature = "ex-hibit")] + /// ExHibit def.rld xor key. pub ex_hibit_rld_def_xor_key: Option, #[cfg(feature = "ex-hibit")] + /// ExHibit rld xor keys. pub ex_hibit_rld_keys: Option>, #[cfg(feature = "ex-hibit")] + /// ExHibit def.rld xor keys. pub ex_hibit_rld_def_keys: Option>, #[cfg(feature = "mozjpeg")] + /// JPEG quality for output images, 0-100. 100 means best quality. pub jpeg_quality: u8, #[cfg(feature = "webp")] + /// Use WebP lossless compression for output images. pub webp_lossless: bool, #[cfg(feature = "webp")] + /// WebP quality for output images, 0-100. 100 means best quality. pub webp_quality: u8, #[cfg(feature = "circus-img")] + /// Draw Circus CRX images on canvas (if canvas width and height are specified in file) pub circus_crx_canvas: bool, } @@ -409,25 +464,33 @@ pub enum ScriptType { } #[derive(Clone, Debug, Serialize, Deserialize)] +/// Message structure for scripts pub struct Message { #[serde(skip_serializing_if = "Option::is_none")] + /// Optional name for the message, used in some scripts. pub name: Option, + /// The actual message content. pub message: String, } impl Message { + /// Creates a new `Message` instance. pub fn new(message: String, name: Option) -> Self { Message { message, name } } } +/// Result of script operation. pub enum ScriptResult { + /// Operation completed successfully. Ok, + /// Operation completed without any changes. + /// For example, no messages found in the script. Ignored, } #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] -/// Format type +/// Format type (for CLI) pub enum FormatType { /// Wrap line with fixed length Fixed, @@ -449,33 +512,46 @@ pub enum FormatOptions { } #[derive(Debug, Serialize, Deserialize)] +/// Name table cell pub struct NameTableCell { #[serde(rename = "JP_Name")] + /// Original name pub jp_name: String, #[serde(rename = "CN_Name")] + /// Translated name pub cn_name: String, #[serde(rename = "Count")] + /// Number of times this name appears in the script pub count: usize, } #[derive(Debug, Serialize, Deserialize)] +/// Replacement table for string replacements pub struct ReplacementTable { #[serde(flatten)] + /// Map of original strings to their replacements pub map: HashMap, } #[cfg(feature = "image")] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +/// Image color type pub enum ImageColorType { + /// Grayscale image Grayscale, + /// RGB image Rgb, + /// RGBA image Rgba, + /// BGR image Bgr, + /// BGRA image Bgra, } #[cfg(feature = "image")] impl ImageColorType { + /// Returns the number of bytes per pixel for the color type and depth. pub fn bpp(&self, depth: u8) -> u16 { match self { ImageColorType::Grayscale => depth as u16, @@ -489,11 +565,15 @@ impl ImageColorType { #[cfg(feature = "image")] #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] +/// Image output type pub enum ImageOutputType { + /// PNG image Png, #[cfg(feature = "image-jpg")] + /// JPEG image Jpg, #[cfg(feature = "image-webp")] + /// WebP image Webp, } @@ -532,6 +612,7 @@ impl TryFrom<&std::path::Path> for ImageOutputType { #[cfg(feature = "image")] impl AsRef for ImageOutputType { + /// Returns the extension for the image output type. fn as_ref(&self) -> &str { match self { ImageOutputType::Png => "png", @@ -545,30 +626,45 @@ impl AsRef for ImageOutputType { #[cfg(feature = "image")] #[derive(Clone, Debug)] +/// Image data pub struct ImageData { + /// Image width in pixels pub width: u32, + /// Image height in pixels pub height: u32, + /// Image color type pub color_type: ImageColorType, + /// Image depth in bits per channel pub depth: u8, + /// Image data pub data: Vec, } #[cfg(feature = "image")] #[derive(Clone, Debug)] +/// Image data with name pub struct ImageDataWithName { + /// Image name pub name: String, + /// Image data pub data: ImageData, } #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] +/// BOM type pub enum BomType { + /// No BOM None, + /// UTF-8 BOM Utf8, + /// UTF-16 Little Endian BOM Utf16LE, + /// UTF-16 Big Endian BOM Utf16BE, } impl BomType { + /// Returns the byte sequence for the BOM type. pub fn as_bytes(&self) -> &'static [u8] { match self { BomType::None => &[], @@ -581,6 +677,7 @@ impl BomType { #[cfg(feature = "image")] #[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)] +/// PNG compression level pub enum PngCompressionLevel { #[value(alias = "d")] /// Default level @@ -597,8 +694,16 @@ pub enum PngCompressionLevel { Best, } +#[cfg(feature = "image")] +impl Default for PngCompressionLevel { + fn default() -> Self { + PngCompressionLevel::Default + } +} + #[cfg(feature = "image")] impl PngCompressionLevel { + /// Converts the [PngCompressionLevel] to a [png::Compression] enum. pub fn to_compression(&self) -> png::Compression { match self { PngCompressionLevel::Default => png::Compression::Default, diff --git a/src/utils/bit_stream.rs b/src/utils/bit_stream.rs index 8dba11f..cc80412 100644 --- a/src/utils/bit_stream.rs +++ b/src/utils/bit_stream.rs @@ -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 { + /// 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 MsbBitStream { + /// Creates a new MSB bit stream reader. pub fn new(input: T) -> Self { MsbBitStream { m_input: input, @@ -17,6 +22,7 @@ impl MsbBitStream { } } + /// Reads a specified number of bits from the stream. pub fn get_bits(&mut self, count: u32) -> Result { while self.m_cached_bits < count { let byte = self.m_input.read_u8()?; @@ -29,6 +35,7 @@ impl MsbBitStream { Ok(result) } + /// Reads the next bit from the stream. pub fn get_next_bit(&mut self) -> Result { if self.m_cached_bits == 0 { let byte = self.m_input.read_u8()?; @@ -41,13 +48,16 @@ impl MsbBitStream { } } +/// 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 { + /// 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 LsbBitStream { + /// Creates a new LSB bit stream reader. pub fn new(input: T) -> Self { LsbBitStream { m_input: input, @@ -102,6 +120,7 @@ impl LsbBitStream { } } + /// Reads a specified number of bits from the stream. pub fn get_bits(&mut self, mut count: u32) -> Result { if self.m_cached_bits >= count { let mask = (1 << count) - 1; @@ -130,6 +149,7 @@ impl LsbBitStream { } } + /// Reads the next bit from the stream. pub fn get_next_bit(&mut self) -> Result { Ok(self.get_bits(1)? == 1) } diff --git a/src/utils/counter.rs b/src/utils/counter.rs index f7f367c..c79e3cc 100644 --- a/src/utils/counter.rs +++ b/src/utils/counter.rs @@ -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), diff --git a/src/utils/crc32.rs b/src/utils/crc32.rs index 68439bc..faeb237 100644 --- a/src/utils/crc32.rs +++ b/src/utils/crc32.rs @@ -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 } diff --git a/src/utils/encoding.rs b/src/utils/encoding.rs index 6e65e51..4642e5c 100644 --- a/src/utils/encoding.rs +++ b/src/utils/encoding.rs @@ -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, diff --git a/src/utils/escape.rs b/src/utils/escape.rs index 4d862a6..7f77c51 100644 --- a/src/utils/escape.rs +++ b/src/utils/escape.rs @@ -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()) } diff --git a/src/utils/files.rs b/src/utils/files.rs index 85c0e2d..a9010c8 100644 --- a/src/utils/files.rs +++ b/src/utils/files.rs @@ -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, T: AsRef>(root: P, target: T) -> PathBuf { let root = root .as_ref() @@ -40,6 +42,7 @@ pub fn relative_path, T: AsRef>(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> { 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> { 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> { 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, 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 )) } +/// Reads the content of a file or standard input if the path is "-". pub fn read_file + ?Sized>(f: &F) -> io::Result> { let mut content = Vec::new(); if f.as_ref() == Path::new("-") { @@ -158,6 +165,7 @@ pub fn read_file + ?Sized>(f: &F) -> io::Result> { Ok(content) } +/// Writes content to a file or standard output if the path is "-". pub fn write_file + ?Sized>(f: &F) -> io::Result> { Ok(if f.as_ref() == Path::new("-") { Box::new(io::stdout()) @@ -166,6 +174,7 @@ pub fn write_file + ?Sized>(f: &F) -> io::Result> }) } +/// Ensures that the parent directory for the specified path exists, creating it if necessary. pub fn make_sure_dir_exists + ?Sized>(f: &F) -> io::Result<()> { let path = f.as_ref(); if let Some(parent) = path.parent() { diff --git a/src/utils/img.rs b/src/utils/img.rs index fb1689c..a63abe4 100644 --- a/src/utils/img.rs +++ b/src/utils/img.rs @@ -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(data: R) -> Result { let decoder = png::Decoder::new(data); let mut reader = decoder.read_info()?; @@ -289,6 +321,10 @@ pub fn load_png(data: R) -> Result { }) } +/// 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 { match typ { ImageOutputType::Png => { @@ -361,6 +397,15 @@ pub fn decode_img(typ: ImageOutputType, filename: &str) -> Result { } } +/// 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, diff --git a/src/utils/macros.rs b/src/utils/macros.rs index 323c654..8cf30c6 100644 --- a/src/utils/macros.rs +++ b/src/utils/macros.rs @@ -1,4 +1,7 @@ +//! Macros Utilities + #[macro_export] +/// A macro likes `try!` but returns `Option>`. macro_rules! try_option { ($expr:expr $(,)?) => { match $expr { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 22a0e6b..77eb5d4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ +//! Utility functions and modules. #[cfg(feature = "utils-bit-stream")] pub mod bit_stream; pub mod counter; diff --git a/src/utils/name_replacement.rs b/src/utils/name_replacement.rs index 319c422..1e45c7b 100644 --- a/src/utils/name_replacement.rs +++ b/src/utils/name_replacement.rs @@ -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> { let mut reader = csv::ReaderBuilder::new() .has_headers(true) @@ -17,6 +19,7 @@ pub fn read_csv(path: &str) -> Result> { Ok(map) } +/// Replace names in the message with the given name table. pub fn replace_message(mes: &mut Vec, name_table: &HashMap) { for message in mes.iter_mut() { if let Some(name) = &message.name { diff --git a/src/utils/pcm.rs b/src/utils/pcm.rs index 1b142fd..9804535 100644 --- a/src/utils/pcm.rs +++ b/src/utils/pcm.rs @@ -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( format: &PcmFormat, mut reader: R, diff --git a/src/utils/str.rs b/src/utils/str.rs index cc6d3a8..2650639 100644 --- a/src/utils/str.rs +++ b/src/utils/str.rs @@ -1,3 +1,4 @@ +//! String Utilities use crate::types::*; use crate::utils::encoding::*; use anyhow::Result; diff --git a/src/utils/struct_pack.rs b/src/utils/struct_pack.rs index 765ccd1..680bfba 100644 --- a/src/utils/struct_pack.rs +++ b/src/utils/struct_pack.rs @@ -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(reader: R, big: bool, encoding: Encoding) -> Result; } +/// 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(&self, writer: &mut W, big: bool, encoding: Encoding) -> Result<()>; }