Skip to main content

hopper_core/abi/
boolean.rs

1//! Alignment-1 boolean wire type.
2
3use core::fmt;
4
5/// Boolean wire type stored as a single byte.
6///
7/// `0x00` = `false`, any non-zero = `true`.
8/// Normalizes to `0x01` on write.
9#[derive(Clone, Copy, PartialEq, Eq, Default)]
10#[repr(transparent)]
11pub struct WireBool([u8; 1]);
12
13const _: () = assert!(core::mem::size_of::<WireBool>() == 1);
14const _: () = assert!(core::mem::align_of::<WireBool>() == 1);
15
16impl WireBool {
17    pub const FALSE: Self = Self([0]);
18    pub const TRUE: Self = Self([1]);
19
20    #[inline(always)]
21    pub const fn new(v: bool) -> Self {
22        Self([v as u8])
23    }
24
25    #[inline(always)]
26    pub const fn get(self) -> bool {
27        self.0[0] != 0
28    }
29
30    #[inline(always)]
31    pub fn set(&mut self, v: bool) {
32        self.0[0] = v as u8;
33    }
34}
35
36impl From<bool> for WireBool {
37    #[inline(always)]
38    fn from(v: bool) -> Self {
39        Self::new(v)
40    }
41}
42
43impl From<WireBool> for bool {
44    #[inline(always)]
45    fn from(w: WireBool) -> Self {
46        w.get()
47    }
48}
49
50impl fmt::Debug for WireBool {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "WireBool({})", self.get())
53    }
54}
55
56impl fmt::Display for WireBool {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.get())
59    }
60}
61
62// SAFETY: align_of == 1, all bit patterns valid (any non-zero = true), Copy, no drop.
63unsafe impl crate::abi::WireType for WireBool {
64    const WIRE_SIZE: usize = 1;
65    const CANONICAL_NAME: &'static str = "bool";
66}
67
68// Bytemuck proof (Hopper Safety Audit Must-Fix #5). `#[repr(transparent)]`
69// over `[u8; 1]` with every bit pattern decoding to a valid `WireBool`
70// satisfies the `bytemuck::Pod + Zeroable` obligations.
71#[cfg(feature = "hopper-native-backend")]
72unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Zeroable for WireBool {}
73#[cfg(feature = "hopper-native-backend")]
74unsafe impl ::hopper_runtime::__hopper_native::bytemuck::Pod for WireBool {}
75
76// SAFETY: #[repr(transparent)] over [u8; 1], all bit patterns valid.
77unsafe impl crate::account::Pod for WireBool {}
78// Audit Step 5 seal: Hopper-authored primitive.
79unsafe impl ::hopper_runtime::__sealed::HopperZeroCopySealed for WireBool {}
80
81impl crate::account::FixedLayout for WireBool {
82    const SIZE: usize = 1;
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn bool_roundtrip() {
91        assert!(WireBool::new(true).get());
92        assert!(!WireBool::new(false).get());
93    }
94
95    #[test]
96    fn nonzero_is_true() {
97        let w = WireBool([0xFF]);
98        assert!(w.get());
99    }
100}