dar*_*que 7 string utf-16 rust
对于大多数程序,最好在内部使用UTF-8,并在必要时转换为其他编码.但在我的情况下,我想编写一个Javascript解释器,并且只存储UTF-16字符串(或数组u16)更简单,因为
我需要单独处理16位代码单元(这通常是一个坏主意,但Javascript需要这个).这意味着我需要它来实现Index<usize>.
我需要存储不成对代理人,即,畸形UTF-16的字符串(正因为如此,ECMAScript的字符串在技术上定义为阵列u16,其通常代表UTF-16的字符串).有一个名为WTF-8的编码用于存储UTF-8中不成对的代理,但我不想使用这样的东西.
我希望拥有通常拥有/借用的类型(如String/ str和CString/ CStr)以及所有或最常用的方法.我不想滚动自己的字符串类型(如果我可以避免).
此外,我的字符串将始终是不可变的,位于Rc包含指向所有字符串的弱指针的数据结构后面(并实现字符串实习).这可能是相关的:也许最好是Rc<Utf16Str>作为字符串类型,其中Utf16Str是未定义的字符串类型(可以定义为just struct Utf16Str([u16])).这样可以避免在访问字符串时遵循两个指针,但我不知道如何Rc使用unsized类型实例化.
鉴于上述要求,仅使用防锈编码非常不方便,因为它将所有非UTF-8编码视为矢量u8.
另外,我不确定使用std库是否可以帮助我.我调查了Utf16Units它,它只是一个迭代器,而不是一个正确的字符串类型.(另外,我知道OsString没有帮助 - 我不在Windows上,甚至没有实现Index<usize>)
由于这里有多个问题,我将尝试分别回答:
我认为您想要的类型是[u16]和Vec<u16>。
默认的字符串类型str和String是环绕[u8]和的包装Vec<u8>(从技术上讲,str它不是原始的,但足够接近)。具有单独类型的目的是要保持不变,即底层字节在UTF-8中格式正确。
类似地,您可能拥有Utf16Str和Utf16String包装类型,[u16]并且Vec<u16>保留了格式良好的UTF-16不变式,即没有不成对的代理。
但是,正如您在问题中指出的那样,JavaScript字符串可以包含未配对的代理。这是因为JavaScript字符串严格来说不是UTF-16,它们实际上是任意序列,u16没有附加的不变性。
无需维护不变性,我认为包装器类型并没有那么有用。
锈编码支持基于字节的UTF-16-LE和UTF-16-BE。您可能需要基于的UTF-16 u16。
std::str::Utf16Units确实不是字符串类型。它是由str::utf16_units()将Rust字符串转换为UTF-16(不是LE或BE)的方法返回的迭代器。您可以.collect()在该迭代器上使用以获取一个Vec<u16>示例。
唯一安全的获取方法是在编译时Rc<[u16]>强制确定Rc<[u16; N]>其大小,这显然是不切实际的。我不建议这种不安全的方法:分配内存,向其中写入一个希望与的内存表示形式匹配的标头RcBox,然后进行转换。
如果要使用原始内存分配,最好使用自己的类型,以便可以使用其私有字段。Tendril会这样做:https://github.com/servo/tendril/blob/master/src/buf32.rs
或者,如果您愿意承担额外的间接费用,那将Rc<Vec<u16>>是安全且容易得多的。