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 在 开发工具
33,536 每月下载量
用于 44 个 crate(直接使用10个)
44KB
617 行(不包括注释)
STFU-8:UTF-8 的类似文本格式
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]) -> String
和decode_u8(&str) -> Vec<u8>
:将u8
值数组编码或解码为 STFU-8,主要用于与几乎为 UTF-8 的二进制/不可见数据进行接口。encode_u16(&[u16]) -> String
和decode_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 代码点,因此重新编码时会成为'þ'
字符。故事的教训是:不要混合u8
和u16
函数的输入/输出。
制表符、换行符和换行符字符是“可见”的,因此带有这些字符的“美观形式”的编码是可选的。
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,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由您选择。
除非您明确说明,否则,根据Apache-2.0许可证定义,您有意提交的任何旨在包含在本作品中的贡献,均应按上述方式双许可,不得附加任何其他条款或条件。
STFU-8协议/规范本身(包括名称)根据CC0社区通用许可授权,任何人都可以为任何目的重新实现或修改它,无需归因。然而,为了完全不同的协议使用相同的名称可能会让人困惑,所以请不要这样做。