9 个版本

0.3.0 2019 年 1 月 21 日
0.2.5 2019 年 1 月 13 日
0.1.1 2018 年 12 月 18 日

1359数据结构

Download history 6516/week @ 2024-03-13 6906/week @ 2024-03-20 6911/week @ 2024-03-27 5546/week @ 2024-04-03 8560/week @ 2024-04-10 9713/week @ 2024-04-17 5384/week @ 2024-04-24 6392/week @ 2024-05-01 4380/week @ 2024-05-08 5058/week @ 2024-05-15 8667/week @ 2024-05-22 8358/week @ 2024-05-29 7513/week @ 2024-06-05 8208/week @ 2024-06-12 8453/week @ 2024-06-19 7756/week @ 2024-06-26

33,194 每月下载量
用于 26 个 crate (15 个直接使用)

MIT/Apache

125KB
2K SLoC

ArrayString

基于固定容量栈的泛型字符串

由于 Rust 尚未实现常数泛型,因此使用 typenum 允许泛型数组 (U1 到 U255)

不能超过初始容量(编译时定义),总是占用 capacity + 1 字节内存

不分配堆内存,且在发布版中永远不会崩溃(编译时除去了所有 panic 分支 - 除了 Index/IndexMut 特性,因为它们应该会)

为什么

数据通常是有限的,你不想有一个 30 个字符的电话号码,也不想要一个 100 个字符的用户名。你甚至可能不支持它在你的数据库中。

为什么要有无限容量字符串的堆分配成本,而你又有限制的边界?

基于栈的字符串通常比基于堆的字符串创建、克隆和附加更快(自定义分配器和线程局部变量可能有助于基于堆的字符串)。

但随着数组大小的增加,这一点变得不那么真实,CacheString 占据了一个完整的缓存行,我们接受的最大值是 255 字节 - MaxString(更大的值将仅进行包裹)而且它可能已经比同等大小的基于堆的字符串慢(例如在 std::string::String 中)

其他地方还有基于栈的字符串,它们通常可以有“无限”的容量(堆分配),但基于栈的大小是由库实现者定义的,我们通过实现基于泛型数组的字符串采取了不同的方法。

基于数组的字符串总是占用完整的内存空间,因此它们可能比动态字符串占用更多的内存(在栈上)。

特性

默认值: std

  • std 默认启用,启用 impl Error 特性用于错误处理(删除它以与 #[no_std] 兼容)

  • serde-traits 允许 serde 特性集成(Serialize/Deserialize

    类似于 String,但如果超出容量则会截断

  • diesel-traits 允许 diesel 特性集成(Insertable/Queryable

    类似于 String,但如果超出容量则会截断

  • logs 启用内部日志记录

    你可能只需要在调试此库时使用它

示例

use arraystring::{Error, ArrayString, typenum::U5, typenum::U20};

type Username = ArrayString<U20>;
type Role = ArrayString<U5>;

#[derive(Debug)]
pub struct User {
    pub username: Username,
    pub role: Role,
}

fn main() -> Result<(), Error> {
    let user = User {
        username: Username::try_from_str("user")?,
        role: Role::try_from_str("admin")?
    };
    println!("{:?}", user);

    Ok(())
}

比较

这些基准测试在我流视频和像往常一样使用我的电脑(具有 未公开的规格的同时进行,所以不要过于认真对待实际时间,只需关注比较即可

small-string  (23 bytes)      clone                  4.837 ns
small-string  (23 bytes)      try_from_str          14.777 ns
small-string  (23 bytes)      from_str_truncate     11.360 ns
small-string  (23 bytes)      from_str_unchecked    11.291 ns
small-string  (23 bytes)      try_push_str           1.162 ns
small-string  (23 bytes)      push_str               3.490 ns
small-string  (23 bytes)      push_str_unchecked     1.098 ns
-------------------------------------------------------------
cache-string  (63 bytes)      clone                 10.170 ns
cache-string  (63 bytes)      try_from_str          25.579 ns
cache-string  (63 bytes)      from_str_truncate     16.977 ns
cache-string  (63 bytes)      from_str_unchecked    17.201 ns
cache-string  (63 bytes)      try_push_str           1.160 ns
cache-string  (63 bytes)      push_str               3.486 ns
cache-string  (63 bytes)      push_str_unchecked     1.115 ns
-------------------------------------------------------------
max-string   (255 bytes)      clone                147.410 ns
max-string   (255 bytes)      try_from_str         157.340 ns
max-string   (255 bytes)      from_str_truncate    158.000 ns
max-string   (255 bytes)      from_str_unchecked   158.420 ns
max-string   (255 bytes)      try_push_str           1.167 ns
max-string   (255 bytes)      push_str               4.337 ns
max-string   (255 bytes)      push_str_unchecked     1.103 ns
-------------------------------------------------------------
string (19 bytes)             clone                 33.295 ns
string (19 bytes)             from                  32.512 ns
string (19 bytes)             push str              28.128 ns
-------------------------------------------------------------
inlinable-string (30 bytes)   clone                 16.751 ns
inlinable-string (30 bytes)   from_str              29.310 ns
inlinable-string (30 bytes)   push_str               2.865 ns
-------------------------------------------------------------
smallstring crate (20 bytes)  clone                 60.988 ns
smallstring crate (20 bytes)  from_str              50.233 ns

许可证

MITApache-2.0

依赖项

~0.1–0.8MB
~18K SLoC