1pub type Word = u64;
8
9#[inline]
11pub const fn encode_i32(value: i32) -> Word {
12 value as u32 as Word
13}
14
15#[inline]
17pub const fn decode_i32(word: Word) -> i32 {
18 word as u32 as i32
19}
20
21#[inline]
23pub const fn encode_u32(value: u32) -> Word {
24 value as Word
25}
26
27#[inline]
29pub const fn decode_u32(word: Word) -> u32 {
30 word as u32
31}
32
33#[inline]
35pub const fn encode_i64(value: i64) -> Word {
36 value as Word
37}
38
39#[inline]
41pub const fn decode_i64(word: Word) -> i64 {
42 word as i64
43}
44
45#[inline]
47pub const fn encode_u64(value: u64) -> Word {
48 value
49}
50
51#[inline]
53pub const fn decode_u64(word: Word) -> u64 {
54 word
55}
56
57#[inline]
59pub const fn encode_f32(value: f32) -> Word {
60 value.to_bits() as Word
61}
62
63#[inline]
65pub const fn decode_f32(word: Word) -> f32 {
66 f32::from_bits(word as u32)
67}
68
69#[inline]
71pub const fn encode_f64(value: f64) -> Word {
72 value.to_bits()
73}
74
75#[inline]
77pub const fn decode_f64(word: Word) -> f64 {
78 f64::from_bits(word)
79}
80
81#[inline]
83pub const fn encode_bool(value: bool) -> Word {
84 value as Word
85}
86
87#[inline]
89pub const fn decode_bool(word: Word) -> bool {
90 word != 0
91}
92
93#[inline]
95pub const fn encode_function_ref(id: u32) -> Word {
96 encode_u32(id)
97}
98
99#[inline]
101pub const fn decode_function_ref(word: Word) -> u32 {
102 decode_u32(word)
103}
104
105#[inline]
107pub const fn encode_heap_ref(id: u32) -> Word {
108 encode_u32(id)
109}
110
111#[inline]
113pub const fn decode_heap_ref(word: Word) -> u32 {
114 decode_u32(word)
115}
116
117#[inline]
119pub const fn encode_string_id(id: u32) -> Word {
120 encode_u32(id)
121}
122
123#[inline]
125pub const fn decode_string_id(word: Word) -> u32 {
126 decode_u32(word)
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn narrow_integers_are_canonicalized_to_low_32_bits() {
135 assert_eq!(encode_i32(-1), u64::from(u32::MAX));
136 assert_eq!(decode_i32(u64::MAX), -1);
137 assert_eq!(encode_u32(u32::MAX), u64::from(u32::MAX));
138 assert_eq!(decode_u32(u64::MAX), u32::MAX);
139 }
140
141 #[test]
142 fn wide_integers_preserve_bits() {
143 let signed = i64::MIN + 123;
144 assert_eq!(decode_i64(encode_i64(signed)), signed);
145
146 let unsigned = u64::MAX - 123;
147 assert_eq!(decode_u64(encode_u64(unsigned)), unsigned);
148 }
149
150 #[test]
151 fn floats_preserve_bits_including_nan_payloads() {
152 let f32_bits = 0x7fc1_2345;
153 assert_eq!(encode_f32(f32::from_bits(f32_bits)), u64::from(f32_bits));
154 assert_eq!(decode_f32(u64::MAX).to_bits(), u32::MAX);
155
156 let f64_bits = 0x7ff8_1234_5678_9abc;
157 assert_eq!(encode_f64(f64::from_bits(f64_bits)), f64_bits);
158 assert_eq!(decode_f64(f64_bits).to_bits(), f64_bits);
159 }
160
161 #[test]
162 fn booleans_use_canonical_encoding() {
163 assert_eq!(encode_bool(false), 0);
164 assert_eq!(encode_bool(true), 1);
165 assert!(!decode_bool(0));
166 assert!(decode_bool(1));
167 assert!(decode_bool(Word::MAX));
168 }
169
170 #[test]
171 fn references_and_string_ids_are_numeric_words() {
172 assert_eq!(decode_function_ref(encode_function_ref(7)), 7);
173 assert_eq!(decode_heap_ref(encode_heap_ref(11)), 11);
174 assert_eq!(decode_string_id(encode_string_id(13)), 13);
175 assert_eq!(encode_heap_ref(u32::MAX), u64::from(u32::MAX));
176 }
177}