2 个版本
0.1.1 | 2019年2月14日 |
---|---|
0.1.0 | 2019年2月14日 |
#2291 in 编码
用于 otkeep
18KB
160 行
paths_as_strings
一个Rust crate,用于无歧义且普遍地将 Paths 编码为 UTF-8 字符串。
Rust的paths不总是可以转换为UTF-8字符串,因为它们是操作系统兼容的,Unix和Windows都不使用UTF-8来表示路径。如果你想要将路径转换为字符串形式,例如将其存储在 MRU.txt
文件中,这会引发问题。我编写了这个crate来解决这个问题。
这个crate导出两个函数,encode_path
将路径转换为UTF-8,以及它的逆函数 decode_path
,可用于进行逆编码。
用法
use std::borrow::Cow;
use std::path::PathBuf;
fn main() {
let the_path = PathBuf::from("some/path");
let encoded: Cow<str> = paths_as_strings::encode_path(&the_path);
println!("encoded = {:?}", encoded);
let decoded: PathBuf = paths_as_strings::decode_path(&encoded).unwrap();
println!("decoded = {:?}", decoded);
}
在(非常、非常)常见的情况下,路径实际上是一个UTF-8字符串,这相当于调用 Path.to_str() 进行编码,以及调用 PathBuf::from() 进行解码。换句话说,它的开销并不比调用你通常会使用的两个方法更高。
在(非常、非常)罕见的情况下,路径不是有效的UTF-8字符串——或者包含控制字符,如 \n
——那么路径将被编码为base64,并在前面添加一个特殊的前缀,表示路径已被编码。
如果编码字符串被篡改,解码可能会失败,因此 decode_path
返回一个 Result<PathBuf, base64::DecodeError>
。
巧妙之处
巧妙之处在于 decode_path
如何能够识别一个经过base64编码的路径和一个未编码的路径。例如,字符串 'b478dn3hgi' 可能代表一个编码的文件名,也可能是一个实际的合法文件名。因此,必须找到一种方法来在非编码路径的命名空间中区分编码路径。这是通过在编码需要时让 encode_path
返回一个不能是有效文件名的字符串来实现的。
在Windows上,有很多字符不能用于文件名,而且在使用类似于"A:"的驱动器字母语法时,第一个字符只能是A-Z。这个crate采用的方案是在base64编码的路径前加上"::\_"。
在Linux上,这比较困难,因为除了'/'和'\0'之外的所有字符都可以在文件名的任何地方使用,这意味着base64编码所使用的所有字符在真实文件名中也是有效的。然而,POSIX 规范指出/dev/null
是一个文件名
,而不是一个目录
,因此你永远不能有如/dev/null/xyz
这样的文件。这个crate采用的方案是在base64编码的路径前加上"/dev/null/b64_"。
运行工具
paths_as_strings
包含两个工具程序。
第一个是名为make_awkward_dir
,可以通过命令cargo run --example make_awkward_dir
运行。它将创建一个名为'awkward'的目录,其中包含所有可能的1字节文件名(Unix)或2字节文件名(Windows)。这对于测试编码/解码是否正常工作很有用。
第二个程序扫描目录以查找无法表示为UTF-8的文件,因此需要进行编码。你可以使用命令cargo run --example path_analyzer
运行它。它接受一个参数,即开始扫描的目录,默认为当前工作目录。它将打印出需要编码的所有文件名,并在最后打印总数。例如
Counting paths below /home/phil/repos/paths_as_strings according to encoding needs.
Counting complete. Totals follow:
num_not_encoded = 451, num_encoded = 0
这意味着在该目录下找到的451个路径中,有451个可以直接表示为UTF-8字符串,并且它们都不需要编码。
在我Linux Mint 19系统的整个文件系统上运行时,它打印出
num_not_encoded = 8668563, num_encoded = 3
3 out of 8,668,566 paths needed encoding (and were successfully round-tripped).
This represents 0.000034607800182867614% of the total path count.
我告诉过你这是很少见的。3个无效的文件名都是来自互联网下载的文件,它们不是标准操作系统文件负载的一部分。
依赖关系
~375KB