12个版本
0.2.7 | 2023年4月28日 |
---|---|
0.2.6 | 2022年12月20日 |
0.2.3 | 2022年9月4日 |
0.2.2 | 2022年4月28日 |
0.1.3 | 2021年3月19日 |
#330 在 数据结构
每月22次下载
在 2 个crate中使用(通过 btree-vec)
36KB
401 行
tagged-pointer
本crate提供了一个标记指针的实现:以空间高效的方式包含整数标记的指针。
除非使用后备实现(见下面的 假设 部分),TaggedPtr
和 Option<TaggedPtr>
都将具有指针的大小。
本crate只依赖于 core
,因此可以在 no_std
环境中使用。
示例
use core::mem::size_of;
use core::ptr::NonNull;
use tagged_pointer::TaggedPtr;
#[repr(align(4))]
struct Item(u32, u32);
// `TaggedPtr` and `Option<TaggedPtr>` are both the size of a pointer:
assert_eq!(size_of::<TaggedPtr<Item, 2>>(), size_of::<*mut ()>());
assert_eq!(size_of::<Option<TaggedPtr<Item, 2>>>(), size_of::<*mut ()>());
let item1 = Item(1, 2);
let item2 = Item(3, 4);
// We can store two bits of the tag, since `Item` has an alignment of 4.
let tp1 = TaggedPtr::<_, 2>::new(NonNull::from(&item1), 1);
let tp2 = TaggedPtr::<_, 2>::new(NonNull::from(&item2), 3);
let (ptr1, tag1) = tp1.get();
let (ptr2, tag2) = tp2.get();
assert_eq!((ptr1, tag1), (NonNull::from(&item1), 1));
assert_eq!((ptr2, tag2), (NonNull::from(&item2), 3));
假设
此crate依赖于 pointer::align_offset
在某些情况下不会失败。具体来说,当在指向 u8
的指针上以非const上下文调用 align_offset
时,如果所需的对齐小于或等于由提供的指针指向的分配的对齐,则必须成功。在实践中,即使在具有 -Zmiri-symbolic-alignment-check
标志的 Miri 中,这也是正确的,但 align_offset
的规范实际上允许实现不遵循此行为。如果您因此遇到问题,请在 Git仓库 中提交问题。作为一个替代方案,您可以启用 fallback
功能,这会以使 TaggedPtr
大小加倍为代价来避免依赖于 align_offset
。
请注意,此crate始终是安全的:不遵循所需行为的 align_offset
实现可能会引起panic,但不会导致未定义行为。
遗憾的是,目前在Rust中实现空间高效的标记指针没有一种不做出一些假设的方法。然而,这种方法与通常的方法(将指针转换为 usize
并重用低位)相比有一些优点:通常的方法对平台特定的指针表示做出了假设(目前适用于所有由rustc支持的平台,但如果有新架构的支持可能会被否定,并且确实存在不允许重用对齐指针低位位的真实架构),而此crate的假设是平台无关的(除了Rust已施加的要求,如8位字节)并且被所有已知的Rust实现所满足,包括带有 -Zmiri-symbolic-alignment-check
的Miri。
依赖关系
~0–8MB
~57K SLoC