wasmtime/runtime/vm/gc/
i31.rs1use super::VMGcRef;
4use core::fmt;
5
6#[derive(Clone, Copy, PartialEq, Eq, Hash)]
8pub struct I31(pub(super) u32);
9
10impl Default for I31 {
11 #[inline]
12 fn default() -> Self {
13 Self::wrapping_u32(0)
14 }
15}
16
17impl fmt::Debug for I31 {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 f.debug_struct("I31")
20 .field("as_u32", &self.get_u32())
21 .field("as_i32", &self.get_i32())
22 .finish()
23 }
24}
25
26impl I31 {
27 const DISCRIMINANT: u32 = VMGcRef::I31_REF_DISCRIMINANT;
28
29 #[inline]
33 pub fn new_u32(value: u32) -> Option<Self> {
34 if ((value << 1) >> 1) == value {
35 let i31 = Self::wrapping_u32(value);
36 debug_assert_eq!(i31.get_u32(), value);
37 Some(i31)
38 } else {
39 None
40 }
41 }
42
43 #[inline]
47 pub fn new_i32(value: i32) -> Option<Self> {
48 if ((value << 1) >> 1) == value {
49 let i31 = Self::wrapping_i32(value);
50 debug_assert_eq!(i31.get_i32(), value);
51 Some(i31)
52 } else {
53 None
54 }
55 }
56
57 #[inline]
62 pub fn wrapping_u32(value: u32) -> Self {
63 Self((value << 1) | Self::DISCRIMINANT)
64 }
65
66 #[inline]
71 pub fn wrapping_i32(value: i32) -> Self {
72 Self::wrapping_u32(value.cast_unsigned())
73 }
74
75 #[inline]
77 pub fn get_u32(&self) -> u32 {
78 self.0 >> 1
79 }
80
81 #[inline]
83 pub fn get_i32(&self) -> i32 {
84 (self.0 as i32) >> 1
85 }
86}