Rust动态格式化库dyn-fmt的使用,dyn-fmt提供运行时字符串格式化与模板渲染功能

maintenance: passively maintained

dyn-fmt

提供动态字符串格式化功能。

use dyn_fmt::AsStrFormatExt;

fn main() {
    assert_eq!("{}a{}b{}c".format(&[1, 2, 3]), "1a2b3c");
    assert_eq!("{}a{}b{}c".format(&[1, 2, 3, 4]), "1a2b3c");
    assert_eq!("{}a{}b{}c".format(&[1, 2]), "1a2bc");
    assert_eq!("{{}}{}".format(&[1, 2]), "{}1");
}

比较

dyn-fmt strfmt dynfmt
no_std + - -
简单但强大的API,使用愉快 + +/- -
良好的许可证 + +/- +/-

完整示例代码:

// 引入dyn-fmt库
use dyn_fmt::AsStrFormatExt;

fn main() {
    // 基本格式化示例
    let formatted = "Hello, {}! Today is {}.".format(&["World", "Monday"]);
    println!("{}", formatted); // 输出: Hello, World! Today is Monday.
    
    // 处理多余参数
    let result = "Numbers: {}, {}, {}".format(&[1, 2, 3, 4, 5]);
    println!("{}", result); // 输出: Numbers: 1, 2, 3
    
    // 处理参数不足
    let partial = "Values: {}, {}, {}".format(&[10, 20]);
    println!("{}", partial); // 输出: Values: 10, 20, 
    
    // 转义大括号
    let escaped = "Escaped: {{}} and {}".format(&["replacement"]);
    println!("{}", escaped); // 输出: Escaped: {} and replacement
    
    // 使用不同类型的值
    let mixed = "Int: {}, Float: {}, Str: {}".format(&[42, 3.14, "test"]);
    println!("{}", mixed); // 输出: Int: 42, Float: 3.14, Str: test
}

1 回复

Rust动态格式化库dyn-fmt的使用指南

概述

dyn-fmt是一个Rust动态格式化库,提供运行时字符串格式化和模板渲染功能。与Rust标准库的format!宏不同,dyn-fmt允许在运行时动态指定格式化模板和参数,特别适合需要从配置文件、用户输入或其他外部源加载模板的场景。

主要特性

  • 运行时模板解析和格式化
  • 支持位置参数和命名参数
  • 轻量级且无依赖
  • 与标准库格式化语法兼容

安装方法

在Cargo.toml中添加依赖:

[dependencies]
dyn-fmt = "0.3"

基本用法

1. 使用位置参数

use dyn_fmt::AsStrFormatExt;

fn main() {
    let template = "Hello, {}! Today is {}.";
    let formatted = template.format(&["World", "Monday"]);
    println!("{}", formatted); // 输出: Hello, World! Today is Monday.
}

2. 使用命名参数

use dyn_fmt::AsStrFormatExt;

fn main() {
    let template = "User: {name}, Age: {age}, City: {city}";
    let params = [
        ("name", "Alice"),
        ("age", "25"),
        ("city", "New York")
    ];
    
    let formatted = template.format(&params);
    println!("{}", formatted); // 输出: User: Alice, Age: 25, City: New York
}

3. 混合使用位置和命名参数

use dyn_fmt::AsStrFormatExt;

fn main() {
    let template = "{}: {name} scored {score} points";
    let params = [
        ("0", "Game1"),        // 位置参数
        ("name", "PlayerA"),   // 命名参数
        ("score", "100")       // 命名参数
    ];
    
    let formatted = template.format(&params);
    println!("{}", formatted); // 输出: Game1: PlayerA scored 100 points
}

高级用法

1. 从文件加载模板

use dyn_fmt::AsStrFormatExt;
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let template = fs::read_to_string("template.txt")?;
    let data = [
        ("title", "Rust Programming"),
        ("author", "Mozilla"),
        ("year", "2023")
    ];
    
    let content = template.format(&data);
    println!("{}", content);
    Ok(())
}

2. 动态构建参数列表

use dyn_fmt::AsStrFormatExt;

fn format_user_data(name: &str, email: &str, age: u32) -> String {
    let template = "Name: {name}\nEmail: {email}\nAge: {age}";
    let params = [
        ("name", name),
        ("email", email),
        ("age", &age.to_string())
    ];
    
    template.format(&params)
}

fn main() {
    let result = format_user_data("Bob", "bob@example.com", 30);
    println!("{}", result);
}

错误处理

dyn-fmt会在格式化失败时返回错误而不是panic:

use dyn_fmt::AsStrFormatExt;

fn safe_format(template: &str, params: &[(&str, &str)]) -> Result<String, dyn_fmt::FormatError> {
    template.try_format(params)
}

fn main() {
    let result = safe_format("Hello {name}", &[("wrong_key", "value")]);
    match result {
        Ok(s) => println!("Success: {}", s),
        Err(e) => println!("Error: {}", e),
    }
}

性能提示

  • 对于需要重复使用的模板,考虑缓存格式化结果
  • 在性能关键路径上,尽量避免频繁的字符串分配
  • 使用try_format进行错误检查而不是直接使用format

这个库为需要运行时格式化的场景提供了灵活的解决方案,特别适合Web模板、日志格式化和配置驱动的文本生成等应用场景。

完整示例demo

// 完整示例:演示dyn-fmt库的各种用法
use dyn_fmt::AsStrFormatExt;
use std::fs;
use std::collections::HashMap;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1:基本位置参数
    println!("=== 基本位置参数示例 ===");
    let template1 = "欢迎来到{},今天是{},天气{}";
    let result1 = template1.format(&["北京", "星期一", "晴朗"]);
    println!("{}", result1);
    
    // 示例2:命名参数
    println!("\n=== 命名参数示例 ===");
    let template2 = "产品名称:{name},价格:{price}元,库存:{stock}件";
    let params2 = [
        ("name", "Rust编程书"),
        ("price", "99"),
        ("stock", "50")
    ];
    let result2 = template2.format(&params2);
    println!("{}", result2);
    
    // 示例3:混合参数
    println!("\n=== 混合参数示例 ===");
    let template3 = "订单{}:客户{name}购买了{product},总价{price}元";
    let params3 = [
        ("0", "20231001"),         // 位置参数
        ("name", "张三"),          // 命名参数
        ("product", "笔记本电脑"),  // 命名参数
        ("price", "5999")          // 命名参数
    ];
    let result3 = template3.format(&params3);
    println!("{}", result3);
    
    // 示例4:从文件读取模板
    println!("\n=== 文件模板示例 ===");
    // 假设template.txt内容为:"文章标题:{title}\n作者:{author}\n发布时间:{date}"
    let template_content = "文章标题:{title}\n作者:{author}\n发布时间:{date}";
    let article_data = [
        ("title", "Rust语言入门指南"),
        ("author", "技术社区"),
        ("date", "2023-10-01")
    ];
    let article_content = template_content.format(&article_data);
    println!("{}", article_content);
    
    // 示例5:错误处理
    println!("\n=== 错误处理示例 ===");
    let error_template = "Hello {username}";
    let error_params = [("wrong_key", "value")];
    match error_template.try_format(&error_params) {
        Ok(s) => println!("成功: {}", s),
        Err(e) => println!("错误: {}", e),
    }
    
    // 示例6:动态构建复杂参数
    println!("\n=== 动态参数构建示例 ===");
    let user_info = format_user_profile("李四", "lisi@example.com", 28, "上海");
    println!("{}", user_info);
    
    Ok(())
}

// 动态构建用户信息
fn format_user_profile(name: &str, email: &str, age: u32, city: &str) -> String {
    let template = "用户信息:\n姓名:{name}\n邮箱:{email}\n年龄:{age}\n城市:{city}";
    
    // 动态构建参数数组
    let params = [
        ("name", name),
        ("email", email),
        ("age", &age.to_string()),
        ("city", city)
    ];
    
    template.format(&params)
}

// 使用HashMap构建参数的替代方法
fn format_with_hashmap() -> String {
    let template = "配置信息:\n服务器:{host}\n端口:{port}\n数据库:{db}";
    
    let mut params_map = HashMap::new();
    params_map.insert("host", "localhost");
    params_map.insert("port", "5432");
    params_map.insert("db", "postgres");
    
    // 将HashMap转换为数组切片
    let params: Vec<(&str, &str)> = params_map.iter()
        .map(|(k, v)| (k.as_str(), *v))
        .collect();
    
    template.format(&params)
}

这个完整示例演示了dyn-fmt库的主要功能,包括基本的位置参数和命名参数使用、混合参数、错误处理以及动态参数构建。示例代码包含了详细的注释,帮助理解每个功能的使用方法。

回到顶部