#联合 #结构体 # #C 风格 #生成 #现在

不安全_联合

一个用于生成类似 C 风格联合的结构体的宏

3 个版本

使用旧的 Rust 2015

0.0.2 2016 年 3 月 8 日
0.0.1 2016 年 3 月 8 日
0.0.0 2015 年 10 月 18 日

#4#c-style

CC0 许可证

12KB
237

unsafe_unions

更新

(0.0.2):现在库可以在稳定版和 no_std 上运行。

缺点是,现在执行不同操作的方式有点奇怪:不再是不同命名的函数,而是现在有不同“模式”,每种模式对应一个操作。

.get_foo() => .by_ref().foo()
.get_foo_mut() => .by_mut().foo()
.read_foo() => .read().foo()
.write_foo(x) => .write().foo(x)

API

unsafe_unions!{
    [pub] union $union: $repr {
        $variant: $variant_ty,
        ...
    }
    ...
}

$repr 应当是一个大于或等于最大字段大小的 POD 类型。这需要指定,因为我们目前还没有在编译时确定最大变体类型的方法。

生成方法:

/** $union/$union<()> (default mode) **/

/// Creates a new $union with uninitialized memory.
pub fn new() -> Self;

/// Creates a new $union with zeroed memory.
pub fn zeroed() -> Self;

/// Creates a new $union with uninitialized memory and writes `v` to it.
pub unsafe fn $variant(v: $variant_ty) -> Self;

pub fn repr(&self) -> &$repr;
pub fn repr_mut(&mut self) -> &mut $repr;

/// Enters by-ref mode.
pub fn by_ref(&self) -> &$union<ByRef>;

/// Enters by-mut mode.
pub fn by_mut(&mut self) -> &mut $union<ByMut>;

/// Enters read mode.
pub fn read(&self) -> &$union<Read>;

/// Enters write mode.
pub fn write(&mut self) -> &mut $union<Read>;


/** $union<ByRef> (by-ref mode) **/

/// Casts `&self` to `&$variant_ty`.
pub unsafe fn $variant(&self) -> &$variant_ty;


/** $union<ByMut> (by-mut mode) **/

/// Casts `&mut self` to `&mut $variant_ty`.
pub unsafe fn $variant(&mut self) -> &mut $variant_ty;


/** $union<Read> (read mode) **/

/// `ptr::read`-operation
pub unsafe fn $variant(&self) -> $variant_ty;


/** $union<Write> (write mode) **/

/// `ptr::write`-operation
pub unsafe fn $variant(&mut self, v: $variant_ty);

所有 $union-类型也实现了 CloneCopy

示例

#[macro_use]
extern crate unsafe_unions;

unsafe_unions!{
    union UntaggedValue: [u64; 3] {
        nil: (),
        boolean: bool,
        integer: i64,
        floating: f64,
        string: String,
    }
}

fn main(){
    unsafe {
        let mut val: UntaggedValue = UntaggedValue::integer(200);
        assert_eq!(*val.by_ref().integer(), 200);

        *val.by_mut().boolean() = false;
        assert_eq!(*val.by_ref().boolean(), false);
    
        val.write().string("foobar".to_owned());
        assert_eq!(&**val.by_ref().string(), "foobar");

        drop(val.read().string());
    }
}

待办事项

  • 编写文档
  • 编写测试

无运行时依赖