#string #byte #byte-slice #type #owned #unsafe #annoyed

nightly no-std generic-str

对Rust有两种字符串类型感到烦恼?现在不再有了

4个版本

0.3.1 2022年1月10日
0.3.0 2022年1月10日
0.2.2 2021年11月11日
0.2.1 2021年11月10日

算法类别中排名第2137

MIT许可证

120KB
1.5K SLoC

generic-str

docs

Rust中真正的唯一字符串类型!

本项目旨在验证我几个月前的一个想法。有很多不安全代码,并且需要使用nightly版本。在以下环境中测试:cargo 1.58.0-nightly (2e2a16e98 2021-11-08)

说明

Rust有几种不同的字符串类型,其中两种主要的竞争者是

  • &str,它是一个'字符串引用'。它是不可变的,并且其可变性受到限制。
  • String是一个'所有者字符串'。它是可变的,并且可以简单地进行修改。

事实证明,这两种字符串并没有太大的区别。str只是一个由[u8]字节切片支持的字符串。同样,String也只是一个由某种形式的Vec<u8>支持的字符串。

那么它们为什么会是不同的类型呢?我们理论上不能有像这样的东西吗?

type str = StringBase<[u8]>;
type String = StringBase<Vec<u8>>;

这就是本项目的内容。它与标准库字符串的功能对等性很高。也实现了许多标准特质的实现。

generic-vec

关于是否将Allocator作为自定义Vec存储的最佳抽象进行了一些讨论。[有关讨论](https://internals.rust-lang.org/t/is-custom-allocators-the-right-abstraction/13460)。我对这个概念非常感兴趣,并在本项目使用了RustyYato提供的[实现](https://github.com/RustyYato/generic-vec)。

所以现在我有

use generic_vec::{GenericVec, raw::Heap};
pub type String<A = Global> = OwnedString<u8, Box<[MaybeUninit<u8>], A>>;
pub type OwnedString<S> = StringBase<GenericVec<u8, S>>;

这可能看起来更复杂,但你说得对。在实现上,GenericVec<U, Heap<U, A>>应该与Vec<u8>相同,因此在功能上应该与之前相同。

但是,凭借这个存储后端系统的额外功能,它允许静态分配但可调整大小的†字符串!

pub type ArrayString<const N: usize> = OwnedString<[MaybeUninit<u8>; N]>;

并且我可以重用之前实现String时使用的所有相同代码,因为所有这些都在基础OwnedString类型上实现,用于需要可调整大小的字符串操作。

†:显然,它们不能调整大小超过预定义的N值,并且如果你尝试超过这个值,它将引发恐慌。

依赖关系

~145KB