2 个版本

0.1.1 2023 年 9 月 6 日
0.1.0 2020 年 4 月 27 日

#1116算法

MIT/Apache

17KB
191

通过存储其指数表示非负2的幂。

Pow2 类型的范围限制为 1 .. 2^255(包含)。它是一个简单的包装器,围绕 u8 存储指数。

Pow2 通常用于对齐整数值,例如 I/O 缓冲区大小、页面大小等。

不支持负2的幂,因为它们在管理内存、快速乘法等应用中很少或没有应用。

Pow2 可以表示特定整数类型的范围之外的价值。例如,Pow2::from_exponent(40) 不能转换为 u32。转换实现将这种方式与算术溢出类似处理;操作被定义,但可能在运行时失败。

可以定义一个 Pow2 变体系列,每个原始整数类型一个。然而,这种设计的用户体验可能不尽如人意;留待未来研究。

Pow2 定义的运算符是以2的幂的值定义的,而不是指数。例如,Pow2 * Pow2 的结果是指数相加,而不是指数相乘。

示例

const PAGE_SIZE: Pow2 = Pow2::from_exponent(12);
assert_eq!(u32::from(PAGE_SIZE), 0x1000);
let x: u32 = 0x1eee;
assert_eq!(PAGE_SIZE.align_down(x), 0x1000);
assert_eq!(PAGE_SIZE.align_up(x), Some(0x2000));
assert_eq!(PAGE_SIZE.align_up_unchecked(x), 0x2000);

可以使用 pow2_const! 宏来编写常量2的幂,使用值而不是指数。由于当前 const fns 的限制,pow2_const! 宏不检查输入是否是有效的2的幂。如果不是2的幂,则其行为是未定义的。

use pow2::{Pow2, pow2_const};
const PAGE_SIZE: Pow2 = pow2_const!(0x1000);
assert_eq!(PAGE_SIZE.exponent(), 12);

有符号示例

Pow2 与有符号类型一样可以与无符号类型一起使用。

use pow2::Pow2;
const ALIGN4: Pow2 = Pow2::from_exponent(2);
assert_eq!(ALIGN4.align_up(4i32), Some(4i32));
assert_eq!(ALIGN4.align_up(3i32), Some(4i32));
assert_eq!(ALIGN4.align_up(2i32), Some(4i32));
assert_eq!(ALIGN4.align_up(1i32), Some(4i32));
assert_eq!(ALIGN4.align_up(-0i32), Some(0i32));
assert_eq!(ALIGN4.align_up(-1i32), Some(0i32));
assert_eq!(ALIGN4.align_up(-2i32), Some(0i32));
assert_eq!(ALIGN4.align_up(-3i32), Some(0i32));
assert_eq!(ALIGN4.align_up(-4i32), Some(-4i32));
assert_eq!(ALIGN4.align_up(-5i32), Some(-4i32));
assert_eq!(ALIGN4.align_up(-6i32), Some(-4i32));
assert_eq!(ALIGN4.align_up(-7i32), Some(-4i32));
assert_eq!(ALIGN4.align_up(-8i32), Some(-8i32));

不安全代码示例

这个库不包含不安全的代码,但它可以被不安全代码用来操作指针。这是因为Rust允许安全代码操作不安全指针的值,但不能解引用它们。

use pow2::{Pow2, pow2_const};

const U32_ALIGN: Pow2 = Pow2::align_of::<u32>();

let array: [u32; 4] = [ 111, 222, 333, 444 ];
let item_0_address: *const u8 = &array[0] as *const u32 as *const u8;
let item_1_address: *const u8 = &array[1] as *const u32 as *const u8;

assert_eq!(
  U32_ALIGN.align_up((item_0_address as usize + 1) as *const u8).unwrap(),
  item_1_address
);

依赖项

~1–1.6MB
~28K SLoC