10 个版本

使用旧 Rust 2015

0.2.7 2024年1月9日
0.2.6 2022年11月8日
0.2.5 2022年2月15日
0.2.4 2018年1月24日
0.1.1 2018年1月15日

#104开发工具

Download history 10951/week @ 2024-04-09 14397/week @ 2024-04-16 14497/week @ 2024-04-23 13019/week @ 2024-04-30 11419/week @ 2024-05-07 13320/week @ 2024-05-14 11110/week @ 2024-05-21 11642/week @ 2024-05-28 13325/week @ 2024-06-04 12227/week @ 2024-06-11 12496/week @ 2024-06-18 12338/week @ 2024-06-25 7663/week @ 2024-07-02 7508/week @ 2024-07-09 9186/week @ 2024-07-16 7624/week @ 2024-07-23

33,536 每月下载量
用于 44 crate(直接使用10个)

MIT/Apache 协议

44KB
617 行(不包括注释)

STFU-8:UTF-8 的类似文本格式

Build Status

STFU-8 是一种用于可能“不完全”是 UTF-8 但基本上是 UTF-8 的数据的编码/解码协议。它基于在 Rust、Python、C 或其他常见编程语言中写入(或打印)二进制文本时创建的 repr 语法。

其主要目的是能够允许人类可视化并编辑主要是(或全部)可见的 UTF-8 文本“数据”。它将所有不可见或非 UTF-8 兼容的字节编码为长文本(例如,ESC 编码为完整字符串 r"\x1B")。它还可以编码/解码不规则的 UTF-16。

与其他格式的比较

  • UTF-8(例如,std::str):UTF-8 是一种标准化的格式,用于在地球上任何语言的文本中进行编码。这是互联网几乎可以由任何人理解的原因,也应该是文本编码的主要方式。然而,并非所有“类似 UTF-8”的东西都完全遵循该标准。例如
    • Linux 命令行定义了 ANSI 转义码,用于提供颜色、粗体、斜体等样式。尽管几乎打印到终端的所有内容都是 UTF-8 文本,但这些“转义码”可能不是,即使它们是 UTF-8,它们也不是可见字符。
    • Windows 路径不一定是 UTF-8 兼容的,因为它们可以有 [不规则文本][utf-16-ill-formed-text]。
    • 可能还有其他您能想到或想要创建的情况。通常,如果不需要,请尽量不创建更多用例。
  • Rust的OsStr:OsStr是处理系统特定字符串的“跨平台”类型,主要用于文件路径。与STFU-8不同,它不能(总是)强制转换为UTF-8,因此不能序列化为JSON或其他格式。
  • WTF-8 (rust-wtf8):非常适合与其他UTF标准进行互操作,但不能用于在互联网上传输数据。《规范声明》:“WTF-8不得用于表示文件格式中的文本或通过互联网传输。”
  • base64 (base64):也用于将二进制数据编码为UTF-8。如果您的数据实际上是二进制数据(即不是文本),则使用base64。但是,如果您的数据之前是文本(或主要是文本),则编码为base64将使其完全不可读。
  • Array[u8]:如果您的数据实际上是二进制数据(即不是文本)并且您不需要将其放入UTF-8编码中,那么这显然很棒。然而,一个字节数组(即[0x72, 0x65, 0x61, 0x64, 0x20, 0x69, 0x74])是不可读的。即使它是纯ASCII,也只有那些从未弄清楚如何调试打印它们的ASCII的低级编程神才能高效地读取它。
  • STFU-8 (此包):当您只想有可打印/可手工编辑的文本(且您的数据主要是 UTF-8)但数据可能包含一些二进制/非打印/格式不良的部分时,“很好”。但如果您的数据实际上是二进制数据,则需要(平均)进行4/1的映射。

规范

简单来说,编码的STFU-8本身就是始终有效的Unicode,解码为二进制(二进制不一定是UTF-8)。它与Unicode的不同之处在于单个\项是不合法的。以下模式是合法的

  • \\:解码为反斜杠字节(\x5c
  • \t:解码为制表符字节(\x09
  • \n:解码为换行字节(\x0A
  • \r:解码为回车字节(\x0D
  • \xXX 其中 XX 是恰好两个不区分大小写的十六进制数字:解码为 \xXX 字节,其中 XX 是一个十六进制数(例如:\x9F\xaB\x05)。这个值永远不会解析为一个码点,该值直接推入解码器流中。
  • \uXXXXXX 其中 XXXXXX 是恰好六个不区分大小写的十六进制数字,解码为一个24位数字,该数字通常代表一个Unicode码点。如果该值是Unicode码点,它将始终被解码为这样的码点。否则,stfu8将尝试将该值存储到解码器中(如果该值对于解码类型太大,将是一个错误)。

stfu8为编码/解码数据提供了两种不同的函数类别,这些函数类别不一定是互操作的(不要用decode_u16解码encode_u8创建的输出)。

  • encode_u8(&[u8]) -> Stringdecode_u8(&str) -> Vec<u8>:将 u8 值数组编码或解码为 STFU-8,主要用于与几乎为 UTF-8 的二进制/不可见数据进行接口。
  • encode_u16(&[u16]) -> Stringdecode_u16(&str) -> Vec<u16>:将 u16 值数组编码或解码为 STFU-8,主要用于与可能包含 [格式不正确的文本][utf-16-ill-formed-text] 的旧式 UTF-16 格式进行接口,同时也转换不可打印的字符。

编码和解码有一些通用规则。

  • 如果 \u... 无法解析为有效的 UTF 代码点,它必须适合解码器。例如,尝试使用 decode_u8 解码 "\u00DEED"(这是一个 UTF-16 跟随代理)将失败,但使用 decode_u16 将成功。
  • 从未有转义值是 连接 的。例如,"\x01\x02" 将被转换为 [0x01, 0x02] 而不是 [0x0102] -- 即使您使用 decode_u16
  • 使用 \x... 转义的值总是逐字逐句地复制到解码器中。即 \xFF 是一个有效的 UTF-32 代码点,但如果使用 decode_u8 解码,它将在缓冲区中为 0xFE,而不是作为 UTF-8 字符 'þ' 的两个字节数据。请注意,使用 decode_u16 时,0xFE 是一个有效的 UTF-16 代码点,因此重新编码时会成为 'þ' 字符。故事的教训是:不要混合 u8u16 函数的输入/输出

制表符、换行符和换行符字符是“可见”的,因此带有这些字符的“美观形式”的编码是可选的。

UTF-16 格式不正确的文本

问题在这里简洁地陈述

http://unicode.org/faq/utf_bom.html

问题:如何将未配对的 UTF-16 代理转换为 UTF-8?

在将不正确的UTF-16数据转换为UTF-8时,如果遇到未配对的代理字符,则会引发不同的问题。将这样一个未配对的代理字符单独表示为一个3字节序列,会导致生成的UTF-8数据流不正确。虽然它忠实地反映了输入的性质,但Unicode一致性要求编码形式转换始终生成有效数据流。因此,转换器必须将其视为错误。[AF]

此外,请参阅WTF-8规范

因此,[未配对的]代理字符在实践中确实存在,并且需要保留。例如

在ECMAScript(即JavaScript)中,字符串值被定义为16位整数的序列,通常表示UTF-16文本,但可能是或可能不是正确的。Windows应用程序通常使用UTF-16,但文件系统将路径和文件名视为不可见的WCHAR(16位代码单元)序列。

我们称这些系统中的字符串是以可能不正确的UTF-16或WTF-16编码的。

基本上:你不能(总是)从UTF-16转换为UTF-8,这真的很令人沮丧。WTF-8虽然可以说是这个问题的解决方案,但无法将UTF-16序列化为UTF-8格式,发送到我的Web应用程序,编辑它(作为人类),然后发送回来。这就是STFU-8的作用。

许可证

本存储库中的源代码的许可协议为以下之一:

由您选择。

除非您明确说明,否则,根据Apache-2.0许可证定义,您有意提交的任何旨在包含在本作品中的贡献,均应按上述方式双许可,不得附加任何其他条款或条件。

STFU-8协议/规范本身(包括名称)根据CC0社区通用许可授权,任何人都可以为任何目的重新实现或修改它,无需归因。然而,为了完全不同的协议使用相同的名称可能会让人困惑,所以请不要这样做。

无运行时依赖