arcweight 0.3.0

A high-performance, modular library for weighted finite state transducers with comprehensive examples and benchmarks
Documentation
//! FST serialization and deserialization in multiple formats.
//!
//! This module provides comprehensive I/O capabilities for reading and writing
//! finite-state transducers (FSTs) in various formats. It supports interoperability
//! with other FST libraries (particularly OpenFST) and provides both human-readable
//! and efficient binary formats optimized for different use cases.
//!
//! # Supported Formats
//!
//! ## Text Format
//!
//! A human-readable, line-based format suitable for debugging and manual editing.
//!
//! - **Functions:** [`read_text()`], [`write_text()`]
//! - **Features:** Version control friendly, easy to edit, portable
//! - **Use cases:** Debugging, testing, small FSTs, manual construction
//! - **Extension:** `.txt` (conventional)
//!
//! Example text format:
//! ```text
//! START 0
//! STATE 0
//! STATE 1
//! 0 1 a b 0.5
//! FINAL 1 0.0
//! ```
//!
//! ## OpenFST Binary Format
//!
//! The de facto industry standard binary format, compatible with the OpenFST
//! C++ library and its extensive ecosystem of tools.
//!
//! - **Functions:** [`read_openfst()`], [`write_openfst()`]
//! - **Features:** Fast I/O, compact storage, broad tool compatibility
//! - **Use cases:** Production systems, interoperability with Kaldi/ESPnet
//! - **Extension:** `.fst` (standard)
//! - **Limitation:** Currently supports TropicalWeight FSTs only
//!
//! ## Native Binary Format
//!
//! A Rust-native binary format using serde/bincode for type-safe serialization.
//!
//! - **Functions:** [`read_binary()`], [`write_binary()`] (requires `serde` feature)
//! - **Features:** Type-safe, versioned, supports all semiring types
//! - **Use cases:** Caching, persistence, Rust-to-Rust communication
//! - **Extension:** `.fstb` (recommended)
//!
//! ## Zero-Copy rkyv Format
//!
//! Ultra-fast serialization using rkyv for zero-copy deserialization.
//!
//! - **Module:** [`rkyv_format`] (requires `zero-copy` feature)
//! - **Features:** Zero deserialization overhead, memory-mapped file support
//! - **Use cases:** Large models, latency-critical applications
//! - **Extension:** `.fst.rkyv` (recommended)
//!
//! ## FST Archive (FAR) Format
//!
//! Container format for storing multiple FSTs in a single file.
//!
//! - **Types:** [`FarReader`], [`FarWriter`]
//! - **Functions:** [`open_far()`], [`create_far()`]
//! - **Use cases:** Model collections, lexicons, rule sets
//! - **Extension:** `.far` (standard)
//!
//! # Format Selection Guide
//!
//! | Format | Read Speed | Write Speed | Size | Compatibility | Human-Readable |
//! |--------|------------|-------------|------|---------------|----------------|
//! | Text | Slow | Slow | Large | Universal | Yes |
//! | OpenFST | Fast | Fast | Medium | OpenFST ecosystem | No |
//! | Binary | Fast | Fast | Small | Rust only | No |
//! | rkyv | Instant | Fast | Medium | Rust only | No |
//!
//! # Examples
//!
//! ## Reading and Writing Text Format
//!
//! ```no_run
//! use arcweight::prelude::*;
//! use std::fs::File;
//! use std::io::{BufReader, BufWriter};
//!
//! // Create an FST
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let s0 = fst.add_state();
//! let s1 = fst.add_state();
//! fst.set_start(s0);
//! fst.set_final(s1, TropicalWeight::new(0.0));
//! fst.add_arc(s0, Arc::new(1, 2, TropicalWeight::new(0.5), s1));
//!
//! // Write to text file
//! let file = File::create("fst.txt").unwrap();
//! let mut writer = BufWriter::new(file);
//! write_text(&fst, &mut writer, None, None).unwrap();
//!
//! // Read from text file
//! let file = File::open("fst.txt").unwrap();
//! let mut reader = BufReader::new(file);
//! let loaded: VectorFst<TropicalWeight> = read_text(&mut reader, None, None).unwrap();
//! ```
//!
//! ## OpenFST Interoperability
//!
//! ```no_run
//! use arcweight::prelude::*;
//! use std::fs::File;
//!
//! // Read FST created by OpenFST tools (fstcompile, etc.)
//! let mut file = File::open("model.fst").unwrap();
//! let fst: VectorFst<TropicalWeight> = read_openfst(&mut file).unwrap();
//!
//! // Process with ArcWeight algorithms
//! let minimized: VectorFst<TropicalWeight> = minimize(&fst).unwrap();
//!
//! // Write back for use with OpenFST tools (fstinfo, fstdraw, etc.)
//! let mut out_file = File::create("minimized.fst").unwrap();
//! write_openfst(&minimized, &mut out_file).unwrap();
//! ```
//!
//! ## Binary Serialization
//!
//! ```
//! # #[cfg(feature = "serde")]
//! # {
//! use arcweight::prelude::*;
//! use arcweight::io::{write_binary, read_binary};
//! use std::io::Cursor;
//!
//! # fn example() -> Result<()> {
//! // Serialize FST to bytes
//! let fst = VectorFst::<LogWeight>::new();
//! let mut buffer = Vec::new();
//! write_binary(&fst, &mut buffer)?;
//!
//! // Deserialize from bytes
//! let mut cursor = Cursor::new(buffer);
//! let loaded: VectorFst<LogWeight> = read_binary(&mut cursor)?;
//! # Ok(())
//! # }
//! # }
//! ```
//!
//! ## Symbol Table Integration
//!
//! Symbol tables provide human-readable labels for arc input/output symbols.
//!
//! ```no_run
//! use arcweight::prelude::*;
//! use arcweight::utils::SymbolTable;
//! use arcweight::io::write_text;
//! use std::io::stdout;
//!
//! // Create symbol tables for input and output alphabets
//! let mut isyms = SymbolTable::new();
//! let mut osyms = SymbolTable::new();
//!
//! let cat = isyms.add_symbol("cat");
//! let chat = osyms.add_symbol("chat");
//!
//! // Build FST using symbol IDs
//! let mut fst = VectorFst::<TropicalWeight>::new();
//! let s0 = fst.add_state();
//! let s1 = fst.add_state();
//! fst.set_start(s0);
//! fst.set_final(s1, TropicalWeight::one());
//! fst.add_arc(s0, Arc::new(cat, chat, TropicalWeight::new(0.5), s1));
//!
//! // Write with symbolic labels
//! write_text(&fst, &mut stdout(), Some(&isyms), Some(&osyms)).unwrap();
//! // Output: 0 1 cat chat 0.5
//! ```
//!
//! # Error Handling
//!
//! All I/O operations return [`Result<T, Error>`](crate::Result) with descriptive
//! error types:
//!
//! - [`Error::Io`](crate::Error::Io) - Underlying I/O failures
//! - [`Error::Serialization`](crate::Error::Serialization) - Format/parsing errors
//!
//! # Performance Considerations
//!
//! - **Text format:** Best for FSTs under 10,000 states; O(n) parsing overhead
//! - **OpenFST format:** Efficient for any size; standard choice for production
//! - **Binary format:** Best for Rust-only workflows; smallest file size
//! - **rkyv format:** Best for latency-critical loading; zero parsing overhead
//!
//! For very large FSTs (millions of states), consider:
//! - Memory-mapped files with rkyv format
//! - Streaming/lazy FST implementations
//! - Sharded FST archives
//!
//! # References
//!
//! - Allauzen, C., Riley, M., Schalkwyk, J., Skut, W., & Mohri, M. (2007).
//!   OpenFst: A general and efficient weighted finite-state transducer library.
//!   In *Implementation and Application of Automata* (pp. 11-23). Springer.
//!   <https://www.openfst.org/>
//!
//! - Mohri, M. (2009). Weighted automata algorithms.
//!   In *Handbook of Weighted Automata* (pp. 213-254). Springer.

mod binary_format;
mod far;
mod openfst_compat;
mod text_format;

#[cfg(feature = "zero-copy")]
pub mod rkyv_format;

#[cfg(feature = "serde")]
pub use binary_format::{read_binary, write_binary};
pub use far::{create_far, open_far, FarReader, FarWriter};
pub use openfst_compat::{read_openfst, write_openfst};
pub use text_format::{read_text, write_text};

#[cfg(feature = "zero-copy")]
pub use rkyv_format::{
    access_archived_log_fst, access_archived_tropical_fst, deserialize_log_fst,
    deserialize_tropical_fst, read_log_rkyv, read_tropical_rkyv, serialize_log_fst,
    serialize_tropical_fst, write_log_rkyv, write_tropical_rkyv, RkyvArcF32, RkyvArcF64,
    RkyvFstF32, RkyvFstF64, RkyvStateF32, RkyvStateF64,
};

#[cfg(all(feature = "zero-copy", feature = "memmap2"))]
pub use rkyv_format::{MmapLogFst, MmapTropicalFst};