tagged-pointer-as-enum

A set of structs, traits and macros to implement tagged pointers.

Basic usage

```rust // import macro use taggedpointerasenum::taggedenum;

// declare it like a normal enum but inside taggedenum! macro taggedenum! { enum E { // specify how many bits you want to be used by tag. // should be at least log2(count(variants) + 1), but you can set more // if you need to keep ABI stable after adding new variants bits = 2;

    A(u8),
    B(Box<String>),
    C(i16),
}

}

// macro generates constructors: let a = E::A(42u8); let b = E::B(Box::new(String::from("foo"))); let c = E::C(300i16);

// and a helper module with tags asserteq!(tags::A, 1); asserteq!(tags::B, 2); assert_eq!(tags::C, 3);

// these tags can be used to check variant of enum asserteq!(a.tag(), tags::A); asserteq!(b.tag(), tags::B); assert_eq!(c.tag(), tags::C);

// only variants that behave like containers can be borrowed asserteq!(b.borrowvalue::, String>(), &String::from("foo")); // borrowing values variants is impossible // because there's no memory location containing value WITHOUT tag

// of course, you can get values back asserteq!(a.unwrap::(), 42); asserteq!(b.unwrap::>(), Box::new(String::from("foo"))); assert_eq!(c.unwrap::(), 300); ```

Custom variant types

By default the following types can be used as variants:

It is possible to use other types by implementing TaggedPointerValue for them:

```rust use taggedpointerasenum::{taggedenum, TaggedPointerValue};

struct Custom { low: u8, high: u8 }

// even if it looks like a marker trait in fact it's not impl TaggedPointerValue for Custom {}

tagged_enum! { enum E { bits = 1;

    Custom(Custom),
}

}

let custom = E::Custom(Custom { low: 1, high: 2 }); let unwrapped = custom.unwrap::(); asserteq!(unwrapped.low, 1); asserteq!(unwrapped.high, 2); ```

Implementing default traits

Out of the box tagged_enum! macro generates a struct that doesn't implement any builtin traits.

It is possible to attach #[derive(...)] metadata similar to how it's usually attached to native Rust enums, however all variant types must also implement these traits.

Only the following traits are supported

Also, Drop is auto-implemented for all tagged enums.

```rust use taggedpointerasenum::{taggedenum, TaggedPointerValue};

[derive(Debug)]

struct NumAbsCompare { n: i32 } impl TaggedPointerValue for NumAbsCompare {}

// implement comparison by absolute value impl PartialEq for NumAbsCompare { fn eq(&self, other: &Self) -> bool { self.n.abs() == other.n.abs() } }

tagged_enum! { #[derive(Debug, PartialEq)] enum E { bits = 2;

    I32(i32),
    NumAbsCompare(NumAbsCompare),
}

}

// variants ARE equal if they have the same tag and value asserteq!( E::NumAbsCompare(NumAbsCompare { n: 100 }), E::NumAbsCompare(NumAbsCompare { n: -100 }), ); // variants ARE NOT equal if tags are different assertne!( E::NumAbsCompare(NumAbsCompare { n: 100 }), E::I32(100), ); // variants ARE NOT equal if values are different assert_ne!( E::NumAbsCompare(NumAbsCompare { n: 100 }), E::NumAbsCompare(NumAbsCompare { n: 101 }), ); ```