1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(u8)]
14pub enum GcColor {
15 White = 0,
17 Gray = 1,
19 Black = 2,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[repr(u8)]
26pub enum Generation {
27 Young = 0,
28 Old = 1,
29}
30
31#[repr(C)]
33#[derive(Debug, Clone, Copy)]
34pub struct GcHeader {
35 flags: u8,
37 pub kind: u8,
39 _reserved: u16,
41 pub size: u32,
43}
44
45impl GcHeader {
46 pub fn new(kind: u8, size: u32) -> Self {
48 Self {
49 flags: 0, kind,
51 _reserved: 0,
52 size,
53 }
54 }
55
56 #[inline(always)]
58 pub fn color(&self) -> GcColor {
59 match self.flags & 0b11 {
60 0 => GcColor::White,
61 1 => GcColor::Gray,
62 2 => GcColor::Black,
63 _ => GcColor::White, }
65 }
66
67 #[inline(always)]
69 pub fn set_color(&mut self, color: GcColor) {
70 self.flags = (self.flags & !0b11) | (color as u8);
71 }
72
73 #[inline(always)]
75 pub fn generation(&self) -> Generation {
76 if (self.flags >> 2) & 1 == 0 {
77 Generation::Young
78 } else {
79 Generation::Old
80 }
81 }
82
83 #[inline(always)]
85 pub fn set_generation(&mut self, generation: Generation) {
86 self.flags = (self.flags & !0b100) | ((generation as u8) << 2);
87 }
88
89 #[inline(always)]
91 pub fn is_forwarded(&self) -> bool {
92 (self.flags >> 3) & 1 != 0
93 }
94
95 #[inline(always)]
97 pub fn set_forwarded(&mut self, forwarded: bool) {
98 if forwarded {
99 self.flags |= 0b1000;
100 } else {
101 self.flags &= !0b1000;
102 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_header_size() {
112 assert_eq!(std::mem::size_of::<GcHeader>(), 8);
113 }
114
115 #[test]
116 fn test_color_roundtrip() {
117 let mut h = GcHeader::new(0, 64);
118 assert_eq!(h.color(), GcColor::White);
119
120 h.set_color(GcColor::Gray);
121 assert_eq!(h.color(), GcColor::Gray);
122
123 h.set_color(GcColor::Black);
124 assert_eq!(h.color(), GcColor::Black);
125
126 h.set_color(GcColor::White);
127 assert_eq!(h.color(), GcColor::White);
128 }
129
130 #[test]
131 fn test_generation_roundtrip() {
132 let mut h = GcHeader::new(0, 64);
133 assert_eq!(h.generation(), Generation::Young);
134
135 h.set_generation(Generation::Old);
136 assert_eq!(h.generation(), Generation::Old);
137
138 h.set_color(GcColor::Gray);
140 assert_eq!(h.generation(), Generation::Old);
141 assert_eq!(h.color(), GcColor::Gray);
142 }
143
144 #[test]
145 fn test_forwarded_flag() {
146 let mut h = GcHeader::new(0, 64);
147 assert!(!h.is_forwarded());
148
149 h.set_forwarded(true);
150 assert!(h.is_forwarded());
151 assert_eq!(h.color(), GcColor::White);
153 assert_eq!(h.generation(), Generation::Young);
154
155 h.set_forwarded(false);
156 assert!(!h.is_forwarded());
157 }
158}