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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use generic_array::{
typenum::{UTerm, Unsigned},
ArrayLength, GenericArray,
};
use std::mem;
pub enum TagPosition {
Lo,
Hi,
}
impl TagPosition {
fn to_skip<T: Tag>(&self) -> usize {
match self {
TagPosition::Lo => 0,
TagPosition::Hi => {
let usize_bits = mem::size_of::<usize>() * 8;
usize_bits - <T::Size as Unsigned>::to_usize()
}
}
}
}
pub fn strip<T1: Tag, T2: Tag>(data: usize) -> usize {
let mask1: usize = std::usize::MAX >> <T1::Size as Unsigned>::to_usize();
let mask2: usize = std::usize::MAX << <T2::Size as Unsigned>::to_usize();
data & mask1 & mask2
}
pub fn read_tag<T: Tag>(data: usize, position: TagPosition) -> GenericArray<bool, T::Size> {
let to_skip = position.to_skip::<T>();
let mut array = GenericArray::default();
array
.iter_mut()
.enumerate()
.skip(to_skip)
.for_each(|(index, bit)| *bit = ((data >> index) & 1) == 1);
array
}
pub fn set_tag<T: Tag>(
mut data: usize,
bits: GenericArray<bool, T::Size>,
position: TagPosition,
) -> usize {
let to_skip = position.to_skip::<T>();
bits.iter()
.enumerate()
.skip(to_skip)
.for_each(|(index, bit)| {
let value = if *bit { 1 } else { 0 };
data = (data & !(1 << index)) | (value << index);
});
data
}
pub trait Tag: Copy {
type Size: ArrayLength<bool>;
fn deserialize(bits: GenericArray<bool, Self::Size>) -> Self;
fn serialize(self) -> GenericArray<bool, Self::Size>;
}
#[derive(Debug, Clone, Copy)]
pub struct NullTag;
impl Tag for NullTag {
type Size = UTerm;
fn deserialize(_bits: GenericArray<bool, Self::Size>) -> Self {
Self
}
fn serialize(self) -> GenericArray<bool, Self::Size> {
GenericArray::default()
}
}