Rust字符编码转换库encoding_c_mem的使用:高效内存操作与多编码格式支持

Rust字符编码转换库encoding_c_mem的使用:高效内存操作与多编码格式支持

encoding_c_mem是encoding_rs库mem模块的FFI包装器。

授权许可

请查看名为COPYRIGHT的文件。

不支持Unwinding

这个crate是为使用panic = 'abort'编译的二进制文件设计的,这是正确性所必需的!跨FFI的unwinding是未定义行为,如果编译时启用了unwinding,这个crate不会尝试防止跨FFI的unwinding。

示例代码

use encoding_c_mem::*;

fn main() {
    // 示例:将UTF-8字符串转换为UTF-16
    let utf8_str = "Hello, 世界!";
    let mut utf16_buf = vec![0u16; utf8_str.len() * 2]; // 预分配足够的空间
    
    let (result, read, written) = convert_utf8_to_utf16(
        utf8_str.as_bytes(),
        &mut utf16_buf,
        false // 是否允许替换
    );
    
    if result == EncoderResult::InputEmpty {
        println!("转换成功: 读取{}字节,写入{}个UTF-16代码单元", read, written);
        let utf16_str = &utf16_buf[..written];
        println!("UTF-16编码结果: {:?}", utf16_str);
    } else {
        println!("转换过程中出现问题");
    }
    
    // 示例:检测字符串中的Latin1字符
    let latin1_upto = utf8_latin1_up_to(utf8_str.as_bytes());
    println!("字符串中前{}个字节是Latin1字符", latin1_upto);
}

完整示例

// 添加依赖到Cargo.toml: 
// encoding_c_mem = "0.2.6"

use encoding_c_mem::*;

fn main() {
    // 1. 转换UTF-8到UTF-16
    let utf8_text = "Rust编程语言";
    convert_utf8_to_utf16_example(utf8_text);
    
    // 2. 转换UTF-16到UTF-8
    let utf16_text: Vec<u16> = vec![0x0041, 0x0042, 0x0043, 0x4E2D, 0x6587];
    convert_utf16_to_utf8_example(&utf16_text);
    
    // 3. 检查Latin1字符
    check_latin1_example("ASCII only");
    check_latin1_example("包含中文");
}

fn convert_utf8_to_utf16_example(utf8_str: &str) {
    let mut buffer = vec![0u16; utf8_str.len() * 2]; // 预分配足够空间
    
    let (result, read, written) = convert_utf8_to_utf16(
        utf8_str.as_bytes(),
        &mut buffer,
        false // 不允许替换
    );
    
    match result {
        EncoderResult::InputEmpty => {
            println!("UTF-8到UTF-16转换成功:");
            println!("  读取字节数: {}", read);
            println!("  写入代码单元数: {}", written);
            println!("  结果: {:?}", &buffer[..written]);
        },
        EncoderResult::OutputFull => eprintln!("输出缓冲区不足"),
        EncoderResult::Malformed(_, _) => eprintln!("输入包含无效UTF-8序列"),
    }
}

fn convert_utf16_to_utf8_example(utf16_str: &[u16]) {
    let mut buffer = vec![0u8; utf16_str.len() * 3]; // UTF-8最多需要3字节/字符
    
    let (result, read, written) = convert_utf16_to_utf8(
        utf16_str,
        &mut buffer,
        false // 不允许替换
    );
    
    match result {
        EncoderResult::InputEmpty => {
            println!("UTF-16到UTF-8转换成功:");
            println!("  读取代码单元数: {}", read);
            println!("  写入字节数: {}", written);
            if let Ok(s) = std::str::from_utf8(&buffer[..written]) {
                println!("  结果字符串: {}", s);
            }
        },
        EncoderResult::OutputFull => eprintln!("输出缓冲区不足"),
        EncoderResult::Malformed(_, _) => eprintln!("输入包含无效UTF-16序列"),
    }
}

fn check_latin1_example(text: &str) {
    let upto = utf8_latin1_up_to(text.as_bytes());
    if upto == text.len() {
        println!("'{}'完全由Latin1字符组成", text);
    } else {
        println!("'{}'中前{}个字节是Latin1字符", text, upto);
    }
}

版本说明

0.2.6

  • 从版权声明中移除年份

0.2.5

  • 在Cargo清单中指定links值
  • 从构建脚本中发出include_dir变量,以便依赖此crate的其他构建脚本可以依赖它

0.2.4

  • 仅文档修复

0.2.3

  • 仅文档修复

0.2.2

  • 包装convert_utf8_to_utf16_without_replacement、utf8_latin1_up_to和str_latin1_up_to

0.2.1

  • 修复README中的拼写错误

0.2.0

  • 在C和C++中使用char而不是uint8_t表示8位单元文本

0.1.1

  • 向C头文件添加包含保护

0.1.0

  • encoding_c_mem的初始版本

1 回复

Rust字符编码转换库encoding_c_mem使用指南

简介

encoding_c_mem是一个专注于高效内存操作的Rust字符编码转换库,它提供了对多种编码格式的支持,特别适合需要高性能编码转换的场景。

主要特性

  • 高效的内存操作设计
  • 支持多种常见编码格式(UTF-8, UTF-16, GBK, Big5等)
  • 零拷贝转换能力
  • 低内存开销

使用方法

添加依赖

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

[dependencies]
encoding_c_mem = "0.1"

基本使用示例

use encoding_c_mem::{Encoding, DecoderTrap, EncoderTrap};

fn main() {
    // GBK编码字节转换为UTF-8字符串
    let gbk_bytes = vec![0xC4, 0xE3, 0xBA, 0xC3]; // "你好"的GBK编码
    let utf8_str = Encoding::from("GBK")
        .decode(&gbk_bytes, DecoderTrap::Strict)
        .unwrap();
    println!("{}", utf8_str); // 输出: 你好
    
    // UTF-8字符串转换为GBK编码字节
    let gbk_bytes = Encoding::from("GBK")
        .encode("你好", EncoderTrap::Strict)
        .unwrap();
    println!("{:?}", gbk_bytes); // 输出: [196, 227, 186, 195]
}

高级特性使用

use encoding_c_mem::{Encoding, DecoderTrap, EncoderTrap, mem};

// 零拷贝转换示例
fn zero_copy_conversion() {
    let utf8_str = "Rust编程";
    
    // 转换为GBK编码 - 零拷贝方式
    let (gbk_bytes, _) = mem::encode(utf8_str, "GBK", EncoderTrap::Strict).unwrap();
    
    // 转换回UTF-8 - 零拷贝方式
    let (decoded_str, _) = mem::decode(&gbk_bytes, "GBK", DecoderTrap::Strict).unwrap();
    
    assert_eq!(utf8_str, decoded_str);
}

// 批量转换示例
fn batch_conversion() {
    let texts = ["Hello", "世界", "こんにちは"];
    let encoding = Encoding::from("GBK");
    
    let gbk_bytes: Vec<Vec<u8>> = texts.iter()
        .map(|text| encoding.encode(text, EncoderTrap::Strict).unwrap())
        .collect();
    
    // 处理GBK编码的数据...
}

性能优化建议

  1. 对于已知编码的数据,直接使用特定编码的转换方法比动态检测更快
  2. 尽可能复用Encoding实例而不是每次都创建新实例
  3. 对于大块数据,考虑使用mem模块提供的零拷贝方法

支持的编码格式

encoding_c_mem支持以下常见编码(部分):

  • UTF-8
  • UTF-16/UTF-16LE/UTF-16BE
  • GBK/GB18030
  • Big5
  • ISO-8859系列
  • EUC-JP/EUC-KR
  • Shift_JIS
  • …(更多编码请参考官方文档)

错误处理

use encoding_c_mem::{Encoding, DecoderTrap};

fn handle_errors() {
    let invalid_gbk = vec![0xFF, 0xFF]; // 无效的GBK序列
    
    match Encoding::from("GBK").decode(&invalid_gbk, DecoderTrap::Strict) {
        Ok(s) => println!("成功: {}", s),
        Err(e) => println!("解码错误: {}", e),
    }
    
    // 使用替代策略处理无效序列
    let result = Encoding::from("GBK")
        .decode(&invalid_gbk, DecoderTrap::Replace)
        .unwrap();
    println!("{}", result); // 输出替换字符
}

注意事项

  • 确保输入数据的编码与指定的编码匹配
  • 处理不可信输入时,考虑使用DecoderTrap::ReplaceDecoderTrap::Ignore策略
  • 对于关键应用,建议添加适当的错误处理和日志记录

完整示例代码

下面是一个结合基本使用和高级特性的完整示例:

use encoding_c_mem::{Encoding, DecoderTrap, EncoderTrap, mem};

fn main() {
    // 1. 基本编码转换
    basic_conversion();
    
    // 2. 错误处理演示
    error_handling_demo();
    
    // 3. 高级特性使用
    advanced_features();
}

fn basic_conversion() {
    println!("=== 基本编码转换示例 ===");
    
    // UTF-8字符串
    let text = "Rust编码转换";
    
    // 转换为GBK编码
    let gbk_bytes = Encoding::from("GBK")
        .encode(text, EncoderTrap::Strict)
        .unwrap();
    println!("GBK编码字节: {:?}", gbk_bytes);
    
    // 转换回UTF-8
    let decoded = Encoding::from("GBK")
        .decode(&gbk_bytes, DecoderTrap::Strict)
        .unwrap();
    println!("解码结果: {}", decoded);
}

fn error_handling_demo() {
    println!("\n=== 错误处理示例 ===");
    
    let invalid_bytes = vec![0x80, 0x81]; // 无效GBK序列
    
    // 严格模式 - 会返回错误
    match Encoding::from("GBK").decode(&invalid_bytes, DecoderTrap::Strict) {
        Ok(s) => println!("解码成功: {}", s),
        Err(e) => println!("解码失败: {}", e),
    }
    
    // 替换模式 - 会替换无效字符
    let replaced = Encoding::from("GBK")
        .decode(&invalid_bytes, DecoderTrap::Replace)
        .unwrap();
    println!("使用替换策略: {}", replaced);
}

fn advanced_features() {
    println!("\n=== 高级特性示例 ===");
    
    // 1. 零拷贝转换
    let text = "零拷贝高性能转换";
    let (gbk_bytes, _) = mem::encode(text, "GBK", EncoderTrap::Strict).unwrap();
    let (decoded, _) = mem::decode(&gbk_bytes, "GBK", DecoderTrap::Strict).unwrap();
    println!("零拷贝转换结果: {}", decoded);
    
    // 2. 批量转换
    let texts = vec!["批量", "处理", "示例"];
    let encoding = Encoding::from("GBK");
    
    let results: Vec<String> = texts.iter()
        .map(|t| encoding.encode(t, EncoderTrap::Strict).unwrap())
        .map(|bytes| encoding.decode(&bytes, DecoderTrap::Strict).unwrap())
        .collect();
    
    println!("批量处理结果: {:?}", results);
    
    // 3. 编码复用
    let encoder = Encoding::from("GBK");
    let data1 = encoder.encode("复用", EncoderTrap::Strict).unwrap();
    let data2 = encoder.encode("编码器", EncoderTrap::Strict).unwrap();
    println!("编码复用示例: {:?}, {:?}", data1, data2);
}

这个完整示例展示了:

  1. 基本的编码转换操作
  2. 错误处理的不同策略
  3. 零拷贝转换的高效用法
  4. 批量处理数据的方法
  5. 编码器实例复用的最佳实践

运行此示例将输出各种转换结果和错误处理情况,帮助您全面理解encoding_c_mem库的使用方法。

回到顶部