1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//! Pointer type that allows packing additional data along with the
//! underlying memory offset.
//!
//! ## Example usage
//!
//! To demonstrate the usage of this crate, we shall define an `EitherBox`
//! abstraction that does not require additional storage to keep track of
//! its variant, other than one bit that is stored inline with the memory
//! offset of the packed pointer.
//!
//! ```
//! use std::mem::ManuallyDrop;
//!
//! use packed_ptr::alloc::boxed::PackedBox;
//!
//! union EitherUnion<L, R> {
//! left: ManuallyDrop<L>,
//! right: ManuallyDrop<R>,
//! }
//!
//! struct EitherBox<L, R> {
//! inner: PackedBox<1, EitherUnion<L, R>>,
//! }
//!
//! enum Either<L, R> {
//! Left(L),
//! Right(R),
//! }
//!
//! impl<L, R> EitherBox<L, R> {
//! fn left(value: L) -> Self {
//! let inner = PackedBox::new(EitherUnion {
//! left: ManuallyDrop::new(value),
//! })
//! .unwrap();
//! Self { inner }
//! }
//!
//! fn right(value: R) -> Self {
//! let mut inner = PackedBox::new(EitherUnion {
//! right: ManuallyDrop::new(value),
//! })
//! .unwrap();
//! inner.set_bit_high(0);
//! Self { inner }
//! }
//!
//! fn get_ref(&self) -> Either<&L, &R> {
//! match self.inner.get_bit(0) {
//! false => Either::Left(unsafe { &self.inner.as_ref().left }),
//! true => Either::Right(unsafe { &self.inner.as_ref().right }),
//! }
//! }
//! }
//! ```