Rust Unicode精确字符串处理库precis-core的使用,支持PRECIS框架和国际化文本规范化

Rust Unicode精确字符串处理库precis-core的使用,支持PRECIS框架和国际化文本规范化

precis-core是一个实现了PRECIS框架(Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols)的Rust库,基于RFC 8264标准。该库提供了IdentifierClassFreeFormClass两个基础字符串类,以及实现PRECIS Profiles所需的API。

特性

  • 实现RFC 8264定义的PRECIS框架
  • 提供基础字符串类:IdentifierClassFreeFormClass
  • 支持国际化文本的规范化处理
  • 为应用程序协议提供字符串准备、强制和比较功能

安装

在Cargo.toml中添加依赖:

precis-core = "0.1.11"

或者运行命令:

cargo add precis-core

示例代码

use precis_core::{Profile, FreeFormClass};

fn main() {
    // 使用FreeFormClass处理自由格式字符串
    let input = "My C00l Us3rN4m3";
    
    // 准备字符串
    let prepared = FreeFormClass::prepare(input).unwrap();
    println!("Prepared string: {}", prepared);
    
    // 强制执行PRECIS规则
    let enforced = FreeFormClass::enforce(input).unwrap();
    println!("Enforced string: {}", enforced);
    
    // 比较两个字符串
    let other_input = "my c00l us3rn4m3";
    let comparison = FreeFormClass::compare(input, other_input).unwrap();
    println!("Comparison result: {}", comparison);
}

更完整的示例,展示如何处理国际化文本:

use precis_core::{Profile, IdentifierClass};

fn main() {
    // 国际化用户名示例
    let username = "USER"; // 全角字符示例
    
    // 准备国际化的用户名
    match IdentifierClass::prepare(username) {
        Ok(prepared) => {
            println!("准备后的用户名: {}", prepared);
            
            // 强制执行PRECIS规则
            let enforced = IdentifierClass::enforce(username).unwrap();
            println!("强制后的用户名: {}", enforced);
            
            // 比较两个国际化用户名
            let other_username = "user"; // 半角字符
            let comparison = IdentifierClass::compare(username, other_username).unwrap();
            println!("用户名比较结果(是否等效): {}", comparison);
        }
        Err(e) => {
            println!("用户名准备失败: {:?}", e);
        }
    }
    
    // 处理可能包含特殊字符的自由格式文本
    let freetext = "Hello 世界! 123";
    match FreeFormClass::prepare(freetext) {
        Ok(prepared) => {
            println!("准备后的自由文本: {}", prepared);
            
            // 强制执行规则
            let enforced = FreeFormClass::enforce(freetext).unwrap();
            println!("强制后的自由文本: {}", enforced);
        }
        Err(e) => {
            println!("自由文本准备失败: {:?}", e);
        }
    }
}

完整示例说明

  1. FreeFormClass示例:

    • 处理自由格式字符串,如用户名、标签等
    • 自动进行大小写转换和规范化处理
    • 提供字符串比较功能,自动处理大小写差异
  2. IdentifierClass示例:

    • 专门用于处理国际化标识符
    • 正确处理全角/半角字符转换
    • 确保字符串符合PRECIS框架的标识符规范
  3. 错误处理:

    • 所有操作都返回Result类型,可以捕获处理错误
    • 常见错误包括包含非法字符或不符合PRECIS规范
  4. 比较功能:

    • 自动处理不同字符形式的等效性比较
    • 对于国际化文本特别有用

这个库特别适合需要处理国际化用户输入、网络协议字符串处理等场景,确保不同系统间的字符串能够正确比较和处理。


1 回复

Rust Unicode精确字符串处理库precis-core的使用指南

概述

precis-core是一个Rust库,实现了PRECIS框架(Prepared Representation of Internationalized Strings),用于Unicode字符串的精确处理和规范化。它特别适用于需要处理国际化文本的应用程序,如用户名、密码、标识符等需要严格规范的场景。

主要功能

  • 实现RFC 8264、RFC 8265和RFC 8266定义的PRECIS框架
  • 支持多种字符串处理规则(Profiles)
  • 提供Unicode规范化功能
  • 支持ASCII兼容性检查
  • 支持宽度映射和大小写处理

安装

在Cargo.toml中添加依赖:

[dependencies]
precis-core = "0.4"

基本使用方法

1. 使用预定义的Profile

use precis_core::profile::{Nickname, OpaqueString, UsernameCaseMapped, UsernameCasePreserved};

fn main() {
    // 处理昵称(根据RFC 8266)
    let nickname = "Rustacean🦀";
    let processed = Nickname::prepare(nickname).unwrap();
    println!("Processed nickname: {}", processed);
    
    // 处理用户名(大小写保留)
    let username = "Alice_123";
    let processed = UsernameCasePreserved::prepare(username).unwrap();
    println!("Processed username: {}", processed);
    
    // 处理密码(不透明字符串)
    let password = "MyP@ssw0rd💻";
    let processed = OpaqueString::prepare(password).unwrap();
    println!("Processed password: {}", processed);
}

2. 自定义Profile

use precis_core::{Profile, DerivedPropertyValue, Error};
use precis_core::properties::derive;

struct MyCustomProfile;

impl Profile for MyCustomProfile {
    fn prepare(&self, s: &str) -> Result<String, Error> {
        // 应用自定义规则
        let derived = derive(s)?;
        
        // 检查不允许的字符
        if derived.allow_unassigned != DerivedPropertyValue::True {
            return Err(Error::InvalidCodePoint);
        }
        
        // 应用宽度映射和大小写处理
        let s = precis_core::width::map(s);
        let s = precis_core::case::fold(s);
        
        Ok(s.to_string())
    }
}

fn main() {
    let profile = MyCustomProfile;
    let result = profile.ppprepare("自定义文本CustomText");
    println!("{:?}", result);
}

3. 验证字符串

use precis_core::profile::UsernameCaseMapped;

fn validate_username(username: &str) -> bool {
    UsernameCaseMapped::validate(username).is_ok()
}

fn main() {
    let usernames = ["Alice", "ALICE", "Alice123", "Alice@123"];
    
    for username in &usernames {
        println!(
            "{} is {}valid", 
            username, 
            if validate_username(username) { "" } else { "in" }
        );
    }
}

高级用法

处理错误

use precis_core::profile::UsernameCaseMapped;
use precis_core::Error;

fn process_username(username: &str) -> Result<String, String> {
    match UsernameCaseMapped::prepare(username) {
        Ok(s) => Ok(s),
        Err(Error::InvalidCodePoint) => Err("包含无效字符".to_string()),
        Err(Error::ProhibitedCharacter) => Err("包含禁止字符".to_string()),
        Err(Error::ContextRuleViolation) => Err("违反上下文规则".to_string()),
        Err(e) => Err(format!("其他错误: {:?}", e)),
    }
}

fn main() {
    let result = process_username("Admin@123");
    match result {
        Ok(s) => println!("有效用户名: {}", s),
        Err(e) => println!("错误: {}", e),
    }
}

比较规范化后的字符串

use precis_core::profile::UsernameCaseMapped;

fn compare_usernames(a: &str, b: &str) -> bool {
    let a_normalized = UsernameCaseMapped::prepare(a).unwrap();
    let b_normalized = UsernameCaseMapped::prepare(b).unwrap();
    a_normalized == b_normalized
}

fn main() {
    let username1 = "Alice";
    let username2 = "ALICE";
    
    println!(
        "'{}' and '{}' are {}",
        username1,
        username2,
        if compare_usernames(username1, username2) {
            "the same"
        } else {
            "different"
        }
    );
}

注意事项

  1. PRECIS框架定义了不同的字符串类型处理规则,选择正确的Profile很重要
  2. 处理用户输入时应始终检查错误
  3. 密码等敏感信息应使用OpaqueString Profile
  4. 用户名等标识符通常使用UsernameCaseMapped或UsernameCasePreserved

precis-core库为Rust开发者提供了强大的国际化文本处理能力,特别适合需要遵循RFC规范的网络应用程序开发。

完整示例

下面是一个完整的用户注册系统示例,展示如何使用precis-core处理用户名、昵称和密码:

use precis_core::profile::{
    Nickname, 
    OpaqueString, 
    UsernameCaseMapped,
    UsernameCasePreserved
};
use precis_core::Error;

struct UserRegistration {
    username: String,
    nickname: String,
    password: String,
}

impl UserRegistration {
    pub fn new(
        raw_username: &str,
        raw_nickname: &str,
        raw_password: &str
    ) -> Result<Self, String> {
        // 处理用户名(使用大小写映射)
        let username = match UsernameCaseMapped::prepare(raw_username) {
            Ok(u) => u,
            Err(e) => return Err(format!("用户名无效: {:?}", e)),
        };
        
        // 处理昵称
        let nickname = match Nickname::prepare(raw_nickname) {
            Ok(n) => n,
            Err(e) => return Err(format!("昵称无效: {:?}", e)),
        };
        
        // 处理密码
        let password = match OpaqueString::prepare(raw_password) {
            Ok(p) => p,
            Err(e) => return Err(format!("密码无效: {:?}", e)),
        };
        
        Ok(Self {
            username,
            nickname,
            password,
        })
    }
    
    pub fn compare_usernames(&self, other_username: &str) -> bool {
        match UsernameCaseMapped::prepare(other_username) {
            Ok(u) => u == self.username,
            Err(_) => false,
        }
    }
}

fn main() {
    // 模拟用户注册
    let registration = UserRegistration::new(
        "Alice_123",
        "Rust爱好者🦀",
        "SecureP@ssw0rd!"
    );
    
    match registration {
        Ok(user) => {
            println!("用户注册成功:");
            println!("用户名: {}", user.username);
            println!("昵称: {}", user.nickname);
            
            // 比较用户名
            println!(
                "用户名 'Alice_123' 和 'alice_123' 是否相同: {}",
                user.compare_usernames("alice_123")
            );
        },
        Err(e) => println!("注册失败: {}", e),
    }
}

这个完整示例展示了:

  1. 使用预定义的Profile处理不同类型的字符串
  2. 错误处理的完整流程
  3. 用户名比较功能
  4. 完整的用户注册流程实现

在实际应用中,您可以根据需求扩展这个基础结构,添加更多验证规则和业务逻辑。

回到顶部