Overview#
A high-performance Rust implementation of the ICU MessageFormat parser, providing native parsing capabilities for Rust applications.
Features#
- ๐ High Performance: Native Rust implementation optimized for speed
- ๐ Full ICU MessageFormat Support: Complete syntax support including plurals, selects, and formatting
- ๐ Type Safe: Strongly-typed AST with comprehensive error handling
- ๐ฏ Zero-Copy Parsing: Efficient parsing with minimal allocations where possible
- ๐งช Well Tested: Comprehensive test suite ensuring correctness
Installation#
Add to your Cargo.toml:
[dependencies]
formatjs_icu_messageformat_parser = "0.2.4"
Usage#
use formatjs_icu_messageformat_parser::{Parser, ParserOptions};
fn main() {
let message = "Hello {name}! You have {count, plural, one{# message} other{# messages}}.";
let options = ParserOptions::default();
let parser = Parser::new(message, options);
match parser.parse() {
Ok(ast) => {
println!("Parsed AST: {:?}", ast);
}
Err(e) => {
eprintln!("Parse error: {}", e);
}
}
}
API Reference#
Parser::new(message: &str, options: ParserOptions) -> Parser#
Creates a new parser instance.
Parameters:
message: The ICU MessageFormat string to parseoptions: Parser configuration options
Parser::parse(&self) -> Result<Vec<MessageFormatElement>, ParserError>#
Parses the message and returns an AST.
Returns:
Ok(Vec<MessageFormatElement>): Parsed AST on successErr(ParserError): Detailed error information on failure
ParserOptions#
Configuration options for the parser:
pub struct ParserOptions {
pub ignore_tag: bool, // Treat HTML-like tags as literals
pub should_parse_skeletons: bool, // Parse number/date skeletons
pub capture_location: bool, // Include location info in AST
}
AST Types#
The parser produces a strongly-typed AST with the following element types:
LiteralElement: Plain textArgumentElement: Simple variable reference{name}NumberElement: Number formatting{price, number, ::currency/USD}DateElement: Date formatting{today, date, short}TimeElement: Time formatting{now, time, short}PluralElement: Plural rules{count, plural, one{#} other{#}}SelectElement: Select choices{gender, select, male{he} female{she}}TagElement: HTML-like tags<b>text</b>PoundElement: Pound symbol#(placeholder in plural rules)
Utility Functions#
AST Manipulation#
use formatjs_icu_messageformat_parser::{hoist_selectors, is_structurally_same};
// Hoist nested selectors to top level
let hoisted_ast = hoist_selectors(ast);
// Compare two ASTs for structural equivalence
let are_same = is_structurally_same(
&source_ast,
&target_ast,
"message.id".to_string()
);
AST Printing#
use formatjs_icu_messageformat_parser::print_ast;
// Convert AST back to ICU MessageFormat string
let message = print_ast(&ast);
println!("{}", message);
Examples#
Parsing Plurals#
use formatjs_icu_messageformat_parser::{Parser, ParserOptions, MessageFormatElement};
let message = "I have {count, plural, one{# dog} other{# dogs}}.";
let parser = Parser::new(message, ParserOptions::default());
let ast = parser.parse().unwrap();
// Process plural element
if let MessageFormatElement::Plural(plural) = &ast[1] {
println!("Variable: {}", plural.value);
println!("Options: {:?}", plural.options.keys());
}
Parsing with Skeletons#
use formatjs_icu_messageformat_parser::{Parser, ParserOptions};
let message = "Price: {price, number, ::currency/USD}";
let options = ParserOptions {
should_parse_skeletons: true,
..Default::default()
};
let parser = Parser::new(message, options);
let ast = parser.parse().unwrap();
Error Handling#
use formatjs_icu_messageformat_parser::{Parser, ParserOptions, ErrorKind};
let invalid_message = "{unclosed";
let parser = Parser::new(invalid_message, ParserOptions::default());
match parser.parse() {
Ok(_) => println!("Parsed successfully"),
Err(e) => {
println!("Error: {}", e);
println!("Location: {:?}", e.location);
match e.kind {
ErrorKind::Expect(expected) => {
println!("Expected: {}", expected);
}
_ => {}
}
}
}
Performance#
The Rust parser provides significant performance improvements over JavaScript implementations:
- Parsing Speed: 10-20x faster than JS implementations
- Memory Usage: Lower memory footprint due to efficient allocation
Building from Source#
# Run tests
cargo test --package formatjs_icu_messageformat_parser
# Run benchmarks
cargo bench --package formatjs_icu_messageformat_parser
Documentation#
Related Packages#
formatjs_cli- Native Rust CLI for message extractionformatjs_icu_skeleton_parser- Number and date skeleton parser@formatjs/icu-messageformat-parser- JavaScript implementation