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