tagged_pointer_as_enum/
lib.rs

1#![doc = include_str!("../README.md")]
2
3#[cfg(not(target_pointer_width = "64"))]
4compile_error!("Pointer size must be 64 bits");
5
6mod tagged_pointer;
7pub use tagged_pointer::TaggedPointer;
8
9mod tagged_pointer_value;
10pub use tagged_pointer_value::TaggedPointerValue;
11
12#[macro_use]
13mod macros;
14
15impl TaggedPointerValue for bool {}
16
17impl TaggedPointerValue for u8 {}
18impl TaggedPointerValue for u16 {}
19impl TaggedPointerValue for u32 {}
20impl TaggedPointerValue for i8 {}
21impl TaggedPointerValue for i16 {}
22impl TaggedPointerValue for i32 {}
23
24impl<T> TaggedPointerValue for Box<T> {}
25impl<T> TaggedPointerValue for Option<Box<T>> {}
26
27#[cfg(test)]
28mod test {
29    use super::*;
30
31    const TEST_BITS: u8 = 5;
32    const BOOL_TAG: usize = 1;
33    const U8_TAG: usize = 2;
34    const BOX_STRING_TAG: usize = 3;
35    const OPTION_BOX_STRING_TAG: usize = 4;
36
37    #[test]
38    fn test_bool() {
39        let ptr_true = TaggedPointer::<TEST_BITS>::new::<bool, BOOL_TAG>(true);
40        assert_eq!(ptr_true.tag(), BOOL_TAG);
41        assert!(ptr_true.is::<BOOL_TAG>());
42        assert!(!ptr_true.is::<U8_TAG>());
43        assert_eq!(ptr_true.unwrap::<bool>(), true);
44
45        let ptr_false = TaggedPointer::<TEST_BITS>::new::<bool, BOOL_TAG>(false);
46        assert_eq!(ptr_false.tag(), BOOL_TAG);
47        assert!(ptr_false.is::<BOOL_TAG>());
48        assert!(!ptr_false.is::<U8_TAG>());
49        assert_eq!(ptr_false.unwrap::<bool>(), false);
50    }
51
52    #[test]
53    fn test_u8() {
54        let ptr42 = TaggedPointer::<TEST_BITS>::new::<u8, U8_TAG>(42);
55        assert_eq!(ptr42.tag(), U8_TAG);
56        assert!(ptr42.is::<U8_TAG>());
57        assert!(!ptr42.is::<BOOL_TAG>());
58        assert_eq!(ptr42.unwrap::<u8>(), 42);
59    }
60
61    #[test]
62    fn test_box() {
63        let ptr = Box::new(String::from("foo"));
64        let ptr_s = TaggedPointer::<TEST_BITS>::new::<Box<String>, BOX_STRING_TAG>(ptr);
65        assert_eq!(ptr_s.tag(), BOX_STRING_TAG);
66        assert!(ptr_s.is::<BOX_STRING_TAG>());
67        assert!(!ptr_s.is::<BOOL_TAG>());
68        assert_eq!(
69            ptr_s.borrow_value::<Box<String>, String>(),
70            &String::from("foo")
71        );
72        assert_eq!(ptr_s.unwrap::<Box<String>>(), Box::new(String::from("foo")));
73    }
74
75    #[test]
76    fn test_option_box() {
77        let some_ptr = Some(Box::new(String::from("foo")));
78        let ptr_s =
79            TaggedPointer::<TEST_BITS>::new::<Option<Box<String>>, OPTION_BOX_STRING_TAG>(some_ptr);
80        assert_eq!(ptr_s.tag(), OPTION_BOX_STRING_TAG);
81        assert!(ptr_s.is::<OPTION_BOX_STRING_TAG>());
82        assert!(!ptr_s.is::<BOOL_TAG>());
83        assert_eq!(
84            ptr_s.unwrap::<Option<Box<String>>>(),
85            Some(Box::new(String::from("foo")))
86        );
87    }
88
89    #[test]
90    fn test_drop() {
91        let mut ptr = TaggedPointer::<TEST_BITS>::new::<bool, BOOL_TAG>(true);
92        ptr.drop_as::<bool>();
93
94        let mut ptr = TaggedPointer::<TEST_BITS>::new::<u8, U8_TAG>(42);
95        ptr.drop_as::<u8>();
96
97        let mut ptr = TaggedPointer::<TEST_BITS>::new::<Box<String>, BOX_STRING_TAG>(Box::new(
98            String::from("foo"),
99        ));
100        ptr.drop_as::<Box<String>>();
101    }
102}