#string #string-literal #reference-counting #arc #rc-str

no-std arcstr

更好的引用计数字符串类型,支持字符串字面量(无分配成本)和引用计数的子字符串

13 个版本 (8 个稳定版)

1.2.0 2024 年 5 月 7 日
1.1.5 2022 年 11 月 12 日
1.1.4 2022 年 6 月 4 日
1.1.3 2022 年 1 月 2 日
0.2.3 2020 年 9 月 6 日

#7 in 内存管理

Download history 77973/week @ 2024-05-03 70644/week @ 2024-05-10 77141/week @ 2024-05-17 73796/week @ 2024-05-24 80307/week @ 2024-05-31 69825/week @ 2024-06-07 69102/week @ 2024-06-14 80522/week @ 2024-06-21 85815/week @ 2024-06-28 72791/week @ 2024-07-05 79234/week @ 2024-07-12 68330/week @ 2024-07-19 65075/week @ 2024-07-26 58051/week @ 2024-08-02 52428/week @ 2024-08-09 44576/week @ 2024-08-16

每月 234,803 次下载
用于 73 个 Crates(直接使用 41 个)

Apache-2.0 OR MIT OR Zlib

105KB
1.5K SLoC

arcstr: 更好的引用计数字符串。

Build Status codecov Docs Latest Version Minimum Rust Version

此 crate 定义了 ArcStr,一个引用计数字符串类型。它本质上试图成为一个更好的 Arc<str>Arc<String>,至少对于大多数用例。

ArcStr 故意放弃了 Arc 中一些很少使用的功能,例如 WeakArc::make_mut 等。作为交换,它获得了许多非常有用的功能,特别是对字符串。特别是对便宜/无成本的 ArcStr 持有静态数据(例如,字符串字面量)的强大支持。

(除此之外,它还是单指针,这可以提高性能和 FFI)

此外,如果启用了 substr 功能(默认情况下是启用的),我们提供了一个 Substr 类型,它本质上是一个 (ArcStr, Range<usize>),具有更好的易用性和更多功能,它表示一个“父” ArcStr 的共享切片(请注意,实际上使用 u32 作为索引类型,但此 API 中未暴露,可以通过 cargo 功能透明地更改)。

功能概述

快速浏览ArcStr的独特特性(注意,在ArcStr的[文档](https://docs.rs/arcstr/%2a/arcstr/struct.ArcStr.html#benefits-of-arcstr-over-arcstr)中有一个关于ArcStr相对于其他替代方案的[优势列表](https://docs.rs/arcstr/%2a/arcstr/struct.ArcStr.html#benefits-of-arcstr-over-arcstr),其中涵盖了一些你可能希望使用它的原因)。注意,它提供了您可能从不可变字符串类型期望的几乎所有字符串-like功能——这些只是独特的卖点。

use arcstr::ArcStr;
// Works in const:
const AMAZING: ArcStr = arcstr::literal!("amazing constant");
assert_eq!(AMAZING, "amazing constant");

// `arcstr::literal!` input can come from `include_str!` too:
const MY_BEST_FILES: ArcStr = arcstr::literal!(include_str!("my-best-files.txt"));

或者,您可以在普通表达式中定义字面量。注意,这些字面量本质上属于"零成本"。具体来说,以下我们不仅没有为实例化wow或任何克隆分配堆内存,而且在克隆、丢弃(或在任何其他操作它们的过程中)时也不需要进行任何原子读取或写入。

let wow: ArcStr = arcstr::literal!("Wow!");
assert_eq!("Wow!", wow);
// This line is probably not something you want to do regularly,
// but as mentioned, causes no extra allocations, nor performs any
// atomic loads, stores, rmws, etc.
let wowzers = wow.clone().clone().clone().clone();

// At some point in the future, we can get a `&'static str` out of one
// of the literal `ArcStr`s too.
let static_str: Option<&'static str> = ArcStr::as_static(&wowzers);
assert_eq!(static_str, Some("Wow!"));

// Note that this returns `None` for dynamically allocated `ArcStr`:
let dynamic_arc = ArcStr::from(format!("cool {}", 123));
assert_eq!(ArcStr::as_static(&dynamic_arc), None);

待办事项:在此处包含Substr的使用,因为它也有一些令人信服的应用场景!

用法

它是一个普通的Rust包,将其添加到您的Cargo.toml的依赖项部分。在您不太可能在这里的情况下,不知道如何操作

[dependencies]
# ...
arcstr = { version = "...", features = ["..."] }

以下是一些可用的Cargo功能。目前默认启用的是substr

  • std(默认关闭):启用后,将使用std::process的终止,而不是使用“双重panic技巧”触发终止。

    基本上,我们需要终止的一种情况是在发生灾难性错误时,您泄露了相同的(动态)ArcStr(在32位系统上为2^31,在64位系统上为2^63)。如果发生这种情况,我们将遵循libstd的先例并直接终止,因为我们已经陷入困境。如果启用了std,我们将使用真实的std::process::abort。如果未启用std,我们将通过在另一个panic正在展开时触发panic来触发abort,这要么被定义为导致终止,要么在实践中导致终止。

    实际上,您永远也不会遇到这种边缘情况,而且它仍在no_std中正常工作,因此no_std是默认设置。如果您必须将其启用,因为您遇到了这种情况并且发现我们的处理不好,请让我知道。

    具体来说,这里的区别是,如果没有这个,这个情况将变成对core::intrinsics::abort的调用,而不是对std::process::abort的调用。这是一个极不可能遇到的边缘情况,但如果您遇到了,使用std::process::abort将导致SIGABRT,而使用core::intrinsics::abort将导致SIGILL,前者具有明显更好的用户体验。话虽如此,您成功泄露2^312^63个相同的ArcStr副本的可能性极低,因此我们认为默认情况下依赖std并不是很有必要。

  • serde(默认关闭):启用ArcStr的serde序列化。请注意,这不会执行任何复杂的去重或其他操作。

  • substr (默认开启):实现 Substr 类型和相关函数。

  • substr-usize-indices(默认关闭,隐含 substr):底层使用 usize 作为边界,而不是 u32

    如果没有这个,如果你使用 Substr 并且索引会溢出 u32,我们会毫不犹豫地 panic。

unsafe 的使用和测试策略

虽然这个crate包含相当数量的 unsafe 代码,但我们有以下几点理由来证明这一点:

  1. 我们拥有非常高的测试覆盖率(基本上唯一未覆盖的函数是内存不足处理程序(它只是调用 alloc::handle_alloc_error)和一个极端的整数溢出,我们只是直接终止程序)。
  2. 所有测试在各种 sanitizers 下都通过:asanmsantsanmiri
  3. 我们有一些 loom 模型,尽管我希望有更多。
  4. 我们的测试在各种不同的目标上通过(多亏了 cross 的许多可能——甚至简单易行)
    • Linux x86、x86_64、armv7(arm32)、aarch64(arm64)、riscv64、mips32 和 mips64(mips32 和 mips64 目标允许我们检查大端 32 位和 64 位。尽管我们目前没有特定于字节序的代码)。
    • Windows 32 位和 64 位,在 GNU 和 MSVC 工具链上。
    • MacOS 在 x86_64 上。

此外,我们在 Rust stable、beta、nightly 和我们的 MSRV(见上方的徽章以了解 MSRV)上进行了测试。

支持的平台

请注意,上述内容 不是 支持的平台列表。一般来说,我预计 arcstr 将支持所有平台上的 Rust,除了那些具有 target_pointer_width="16" 的平台,如果关闭 substr 功能,它们应该可以工作。话虽如此,如果您希望我将平台添加到 CI 覆盖范围以确保它不会崩溃,请随时告诉我(尽管,如果它比添加另一个 cross 目标更困难,我可能需要您证明它不太可能被现有的平台测试覆盖)。

* 这就是为什么有 riscv64 的原因。

依赖项

~170KB