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标准。该库提供了IdentifierClass
和FreeFormClass
两个基础字符串类,以及实现PRECIS Profiles所需的API。
特性
- 实现RFC 8264定义的PRECIS框架
- 提供基础字符串类:
IdentifierClass
和FreeFormClass
- 支持国际化文本的规范化处理
- 为应用程序协议提供字符串准备、强制和比较功能
安装
在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);
}
}
}
完整示例说明
-
FreeFormClass
示例:- 处理自由格式字符串,如用户名、标签等
- 自动进行大小写转换和规范化处理
- 提供字符串比较功能,自动处理大小写差异
-
IdentifierClass
示例:- 专门用于处理国际化标识符
- 正确处理全角/半角字符转换
- 确保字符串符合PRECIS框架的标识符规范
-
错误处理:
- 所有操作都返回Result类型,可以捕获处理错误
- 常见错误包括包含非法字符或不符合PRECIS规范
-
比较功能:
- 自动处理不同字符形式的等效性比较
- 对于国际化文本特别有用
这个库特别适合需要处理国际化用户输入、网络协议字符串处理等场景,确保不同系统间的字符串能够正确比较和处理。
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"
}
);
}
注意事项
- PRECIS框架定义了不同的字符串类型处理规则,选择正确的Profile很重要
- 处理用户输入时应始终检查错误
- 密码等敏感信息应使用OpaqueString Profile
- 用户名等标识符通常使用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),
}
}
这个完整示例展示了:
- 使用预定义的Profile处理不同类型的字符串
- 错误处理的完整流程
- 用户名比较功能
- 完整的用户注册流程实现
在实际应用中,您可以根据需求扩展这个基础结构,添加更多验证规则和业务逻辑。