Rust动态字符串格式化库dynfmt的使用,dynfmt提供灵活高效的运行时字符串模板渲染功能

Rust动态字符串格式化库dynfmt的使用,dynfmt提供灵活高效的运行时字符串模板渲染功能

简介

dynfmt是一个用于动态格式化字符串的Rust库。它提供了几种实现格式化的方式,这些实现都支持std::fmt功能的一个子集。格式字符串的解析和参数检查都在运行时进行,同时还支持创建新的自定义格式。

基本用法

use dynfmt::{Format, NoopFormat};

let formatted = NoopFormat.format("hello, world", &["unused"]);
assert_eq!("hello, world", formatted.expect("formatting failed"));

特性

该库提供以下特性(可通过Cargo features启用):

  1. json (默认启用): 通过JSON实现复杂结构的序列化
  2. python: 实现类似Python 2的printf风格字符串格式化
  3. curly: 使用花括号的简单格式字符串语法,类似于.NET和Rust

扩展性

可以通过实现Format trait来创建新的格式。唯一必须实现的方法是iter_args,它需要返回一个迭代ArgumentSpec结构的迭代器。

示例代码展示了如何创建一个自定义的HashFormat格式:

use std::str::MatchIndices;
use dynfmt::{ArgumentSpec, Format, Error};

struct HashFormat;

impl<'f> Format<'f> for HashFormat {
    type Iter = HashIter<'f>;

    fn iter_args(&self, format: &'f str) -> Result<Self::Iter, Error<'f>> {
        Ok(HashIter(format.match_indices('#')))
    }
}

struct HashIter<'f>(MatchIndices<'f, char>);

impl<'f> Iterator for HashIter<'f> {
    type Item = Result<ArgumentSpec<'f>, Error<'f>>;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|(index, _)| Ok(ArgumentSpec::new(index, index + 1)))
    }
}

let formatted = HashFormat.format("hello, #", &["world"]);
assert_eq!("hello, world", formatted.expect("formatting failed"));

完整示例

下面是一个使用dynfmt库的完整示例,展示了如何使用Python风格的格式化:

use dynfmt::{Format, PythonFormat};

fn main() {
    // 使用Python风格的格式化
    let python_fmt = PythonFormat;
    
    // 格式化字符串
    let formatted = python_fmt.format(
        "Hello, %s! Today is %02d/%02d/%04d", 
        &["Rust", 3, 17, 2023]
    ).expect("Formatting failed");
    
    println!("{}", formatted); // 输出: "Hello, Rust! Today is 03/17/2023"
}

要使用这个示例,需要在Cargo.toml中添加以下依赖:

[dependencies]
dynfmt = { version = "0.1.5", features = ["python"] }

完整示例代码

下面是一个更完整的示例,展示了dynfmt库的多种用法:

// 引入必要的模块
use dynfmt::{Format, PythonFormat, CurlyFormat, NoopFormat};

fn main() {
    // 示例1: 使用NoopFormat基本格式化
    let noop_formatted = NoopFormat.format("静态文本,无需参数", &[]).unwrap();
    println!("NoopFormat示例: {}", noop_formatted);
    
    // 示例2: 使用Python风格的格式化
    let python_fmt = PythonFormat;
    let python_formatted = python_fmt.format(
        "Python风格: 姓名: %s, 年龄: %d, 余额: %.2f",
        &["张三", 25, 1234.5678]
    ).unwrap();
    println!("{}", python_formatted);
    
    // 示例3: 使用花括号风格的格式化
    let curly_fmt = CurlyFormat;
    let curly_formatted = curly_fmt.format(
        "花括号风格: 姓名: {}, 年龄: {}, 余额: {:.2}",
        &["李四", 30, 5678.1234]
    ).unwrap();
    println!("{}", curly_formatted);
    
    // 示例4: 自定义HashFormat
    struct HashFormat;
    impl<'f> Format<'f> for HashFormat {
        type Iter = std::iter::Map<
            std::str::MatchIndices<'f, char>,
            fn((usize, char)) -> Result<ArgumentSpec<'f>, Error<'f>>
        >;
        
        fn iter_args(&self, format: &'f str) -> Result<Self::Iter, Error<'f>> {
            Ok(format.match_indices('#').map(|(i, _)| 
                Ok(ArgumentSpec::new(i, i + 1))
            ))
        }
    }
    
    let hash_fmt = HashFormat;
    let hash_formatted = hash_fmt.format(
        "自定义格式: 姓名: #, 年龄: #",
        &["王五", 35]
    ).unwrap();
    println!("{}", hash_formatted);
}

对应的Cargo.toml依赖配置:

[dependencies]
dynfmt = { version = "0.1.5", features = ["python", "curly"] }

许可证

MIT License


1 回复

Rust动态字符串格式化库dynfmt使用指南

dynfmt是一个Rust库,提供了运行时字符串模板渲染功能,相比标准库的格式化功能更加灵活高效。

主要特性

  • 运行时解析和渲染字符串模板
  • 支持多种格式化语法
  • 高性能的模板渲染
  • 支持自定义格式化函数

基本用法

首先在Cargo.toml中添加依赖:

[dependencies]
dynfmt = "0.3"

简单示例

use dynfmt::{Format, SimpleCurlyFormat};

fn main() {
    let formatted = SimpleCurlyFormat.format("Hello, {}!", &["Rust"]);
    assert_eq!(formatted.expect("formatting failed"), "Hello, Rust!");
}

使用命名参数

use dynfmt::{Format, SimpleCurlyFormat};

fn main() {
    let formatted = SimpleCurlyFormat.format(
        "Hello, {name}! You have {count} new messages.",
        &[("name", "Alice"), ("count", "5")]
    );
    assert_eq!(formatted.unwrap(), "Hello, Alice! You have 5 new messages.");
}

支持的格式化语法

dynfmt支持多种格式化语法风格:

  1. 花括号语法 (默认)

    SimpleCurlyFormat.format("{} {}", &["Hello", "world"]);
    
  2. Python风格语法

    use dynfmt::PythonFormat;
    
    PythonFormat.format("{0} {1}", &["Hello", "world"]);
    
  3. Shell风格语法

    use dynfmt::ShellFormat;
    
    ShellFormat.format("$0 $1", &["Hello", "world"]);
    

高级用法

自定义格式化器

use dynfmt::{Format, Formatter, SimpleCurlyFormat};

struct UppercaseFormatter;

impl Formatter for UppercaseFormatter {
    fn format(&self, value: &dyn std::fmt::Display) -> Result<String, dynfmt::Error> {
        Ok(value.to_string().to_uppercase())
    }
}

fn main() {
    let formatted = SimpleCurlyFormat.format_with(
        "Hello, {name}!",
        &[("name", &"rust")],
        &UppercaseFormatter
    );
    assert_eq!(formatted.unwrap(), "Hello, RUST!");
}

性能优化

对于需要重复使用的模板,可以先编译模板:

use dynfmt::{CompiledFormat, SimpleCurlyFormat};

fn main() {
    let template = SimpleCurlyFormat.compile("Hello, {name}!").unwrap();
    let formatted = template.format(&[("name", "World")]).unwrap();
    assert_eq!(formatted, "Hello, World!");
}

错误处理

dynfmt提供了详细的错误信息:

use dynfmt::{Format, SimpleCurlyFormat};

match SimpleCurlyFormat.format("Hello, {name}", &[]) {
    Ok(result) => println!("{}", result),
    Err(e) => eprintln!("Formatting error: {}", e),
}

完整示例

下面是一个结合多种功能的完整示例:

use dynfmt::{Format, SimpleCurlyFormat, PythonFormat, ShellFormat, Formatter, CompiledFormat};

// 自定义格式化器 - 将值转换为大写
struct UppercaseFormatter;

impl Formatter for UppercaseFormatter {
    fn format(&self, value: &dyn std::fmt::Display) -> Result<String, dynfmt::Error> {
        Ok(value.to_string().to_uppercase())
    }
}

fn main() {
    // 1. 简单格式化示例
    let simple_result = SimpleCurlyFormat.format("Hello, {}!", &["Rust"])
        .expect("简单格式化失败");
    println!("简单格式化结果: {}", simple_result);

    // 2. 命名参数示例
    let named_result = SimpleCurlyFormat.format(
        "Hello, {name}! Age: {age}", 
        &[("name", "Bob"), ("age", "30")]
    ).unwrap();
    println!("命名参数结果: {}", named_result);

    // 3. Python风格格式化
    let python_result = PythonFormat.format("{0} {1} {0}", &["Repeat", "me"])
        .unwrap();
    println!("Python风格结果: {}", python_result);

    // 4. Shell风格格式化
    let shell_result = ShellFormat.format("$1 $0", &["World", "Hello"])
        .unwrap();
    println!("Shell风格结果: {}", shell_result);

    // 5. 使用自定义格式化器
    let custom_result = SimpleCurlyFormat.format_with(
        "Shout: {msg}", 
        &[("msg", &"hello world")],
        &UppercaseFormatter
    ).unwrap();
    println!("自定义格式化器结果: {}", custom_result);

    // 6. 编译模板重用
    let template = SimpleCurlyFormat.compile("重用的模板: {data}")
        .unwrap();
    for i in 1..=3 {
        let result = template.format(&[("data", &i.to_string())]).unwrap();
        println!("编译模板结果 {}: {}", i, result);
    }

    // 7. 错误处理示例
    match SimpleCurlyFormat.format("Missing {parameter}", &[]) {
        Ok(r) => println!("成功: {}", r),
        Err(e) => println!("错误处理示例 - 预期错误: {}", e),
    }
}

这个完整示例展示了:

  1. 基本格式化功能
  2. 命名参数使用
  3. 不同语法风格
  4. 自定义格式化器
  5. 模板编译和重用
  6. 错误处理

dynfmt是处理运行时字符串格式化的强大工具,特别适合模板内容在运行时确定或需要从外部加载的场景。

回到顶部