6个版本

0.2.0 2022年4月6日
0.1.4 2022年4月5日

#1630 in Rust模式

MIT 许可证

34KB
494

stuff

crates.io docs.rs Build Status

一个将事物塞入指针的crate。

此crate使用miri(带有-Zmiri-tag-raw-pointers)进行测试。

stuff 帮助您

  • 将任意数据塞入指针
  • 将指针或任意数据塞入固定大小的存储(u64,u128)

可移植和溯源友好的方式。

它是通过提供围绕它的抽象来实现的,完全抽象了溯源和指针,使用户只能在自己的整数(指针地址)上执行位填充。

StuffedPtr 是此crate的主要类型。它是一个大小取决于Backend选择(默认为usize,也支持u64u128)的类型。它可以存储指针或一些其他数据。

您可以选择任意的位填充,取决于StuffingStrategy,这是一个控制其他数据(或指针本身)如何打包到后端的不可安全特性。虽然这个特性仍然是不可安全的,但它比手动完成一切要安全得多。

示例:NaN-Boxing

指针隐藏在浮点数的NaN值中。NaN Boxing通常还涉及隐藏布尔值或null,但我们只关注浮点数和指针(指向一个作为“对象”类型的HashMap的指针)。

有关更多详细信息,请参阅构建解释器

use std::collections::HashMap;

use stuff::{StuffedPtr, StuffingStrategy};

// Create a unit struct for our strategy
struct NanBoxStrategy;

// implementation detail of NaN boxing, a quiet NaN mask
const QNAN: u64 = 0x7ffc000000000000; 
// implementation detail of NaN boxing, the sign bit of an f64
const SIGN_BIT: u64 = 0x8000000000000000; 

unsafe impl StuffingStrategy<u64> for NanBoxStrategy {
    type Other = f64;

    fn is_other(data: u64) -> bool {
        (data & QNAN) != QNAN
    }

    fn stuff_other(inner: Self::Other) -> u64 {
        unsafe { std::mem::transmute(inner) } // both are 64 bit POD's
    }

    unsafe fn extract_other(data: u64) -> Self::Other {
        std::mem::transmute(data) // both are 64 bit POD's
    }

    fn stuff_ptr(addr: usize) -> u64 {
        // add the QNAN and SIGN_BIT
        SIGN_BIT | QNAN | u64::try_from(addr).unwrap()
    }

    fn extract_ptr(inner: u64) -> usize {
        // keep everything except for QNAN and SIGN_BIT
        (inner & !(SIGN_BIT | QNAN)).try_into().unwrap()
    }
}

// a very, very crude representation of an object
type Object = HashMap<String, u32>;

// our value type
type Value = StuffedPtr<Object, NanBoxStrategy, u64>;

fn main() {
    let float: Value = StuffedPtr::new_other(123.5);
    assert_eq!(float.copy_other(), Some(123.5));

    let object: Object = HashMap::from([("a".to_owned(), 457)]);
    let boxed = Box::new(object);
    let ptr: Value = StuffedPtr::new_ptr(Box::into_raw(boxed));

    let object = unsafe { &*ptr.get_ptr().unwrap() };
    assert_eq!(object.get("a"), Some(&457));

    drop(unsafe { Box::from_raw(ptr.get_ptr().unwrap()) });
    // be careful, `ptr` is a dangling pointer now!
}

MSRV策略

stuff当前的MSRV是1.34.2。此版本可能会在非破坏性更改中增加,但除非必要,否则会避免此类更改。可能需要较新Rust版本的功能可能会在未来通过可选功能进行限制。

依赖项

~58KB