Skip to main content

stack_assembly/
value.rs

1use std::fmt;
2
3/// # A unit of data
4///
5/// StackAssembly is an _untyped_ languages. All of its values, both on the
6/// [`OperandStack`] and in [`Memory`], are 32 bits wide. Depending on the
7/// situation, they may be interpreted as unsigned or signed.
8///
9/// You can create an instance of `Value` through its `From` implementations.
10///
11/// ```
12/// use stack_assembly::Value;
13///
14/// Value::from(3i32);
15/// Value::from(5u32);
16/// ```
17///
18/// [`OperandStack`]: crate::OperandStack
19/// [`Memory`]: crate::Memory
20#[derive(Clone, Copy, Eq, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
21#[repr(transparent)]
22pub struct Value {
23    inner: u32,
24}
25
26impl Value {
27    /// # Convert the value to an `i32`
28    ///
29    /// Since all values are 32 bits wide, this is always possible. Interprets
30    /// the bits of the value as a signed (two's complement) integer.
31    pub fn to_i32(self) -> i32 {
32        i32::from_le_bytes(self.inner.to_le_bytes())
33    }
34
35    /// # Convert the value to a `u32`
36    ///
37    /// Since all values are 32 bits wide, this is always possible. Interprets
38    /// the bits of the value as an unsigned integer.
39    pub fn to_u32(self) -> u32 {
40        self.inner
41    }
42
43    /// # Convert to a `bool`
44    ///
45    /// A zero value is considered `false`, while any other value is considered
46    /// `true`.
47    pub fn to_bool(self) -> bool {
48        self.inner != 0
49    }
50}
51
52impl From<bool> for Value {
53    fn from(value: bool) -> Self {
54        let inner = if value { 1 } else { 0 };
55        Self { inner }
56    }
57}
58
59impl From<i32> for Value {
60    fn from(value: i32) -> Self {
61        let inner = u32::from_le_bytes(value.to_le_bytes());
62        Self { inner }
63    }
64}
65
66impl From<u32> for Value {
67    fn from(inner: u32) -> Self {
68        Self { inner }
69    }
70}
71
72impl fmt::Debug for Value {
73    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74        // Let's bypass this type and format the inner value. This is just a
75        // wrapper anyway, and showing it in debug output is unnecessary noise.
76        self.inner.fmt(f)
77    }
78}