Skip to main content

unified_bridge/
rollup_index.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{NetworkId, RollupId};
4
5/// A rollup index.
6///
7/// Rollups are numbered from 0 to `u32::MAX - 1`.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Hash)]
9#[cfg_attr(feature = "testutils", derive(arbitrary::Arbitrary))]
10pub struct RollupIndex(
11    #[cfg_attr(feature = "testutils", arbitrary(with = |u: &mut arbitrary::Unstructured| u.int_in_range(0..=u32::MAX - 1)))]
12     u32,
13);
14
15// No Display implementation on purpose: the integer here is off-by-one compared
16// to NetworkIds. We don't want ourselves to mistakenly write eg. `error
17// handling certificate from network {rollup_index}`, so let's force Debug
18// representation here.
19
20impl<'de> Deserialize<'de> for RollupIndex {
21    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22    where
23        D: serde::Deserializer<'de>,
24    {
25        let id = u32::deserialize(deserializer)?;
26        if id == u32::MAX {
27            return Err(serde::de::Error::custom("Rollup ID cannot be u32::MAX"));
28        }
29        Ok(RollupIndex(id))
30    }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
34#[error("Invalid rollup index")]
35pub struct InvalidRollupIndexError;
36
37impl RollupIndex {
38    pub const BITS: usize = u32::BITS as usize;
39
40    #[inline]
41    pub const fn new(value: u32) -> Result<RollupIndex, InvalidRollupIndexError> {
42        if value == u32::MAX {
43            return Err(InvalidRollupIndexError);
44        }
45        Ok(RollupIndex(value))
46    }
47
48    #[inline]
49    pub const fn to_u32(self) -> u32 {
50        self.0
51    }
52
53    #[inline]
54    pub const fn to_be_bytes(self) -> [u8; 4] {
55        self.0.to_be_bytes()
56    }
57
58    #[inline]
59    pub const fn to_le_bytes(self) -> [u8; 4] {
60        self.0.to_le_bytes()
61    }
62}
63
64impl TryFrom<u32> for RollupIndex {
65    type Error = InvalidRollupIndexError;
66
67    #[inline]
68    fn try_from(value: u32) -> Result<Self, Self::Error> {
69        RollupIndex::new(value)
70    }
71}
72
73impl From<RollupIndex> for u32 {
74    #[inline]
75    fn from(value: RollupIndex) -> Self {
76        value.0
77    }
78}
79
80impl TryFrom<NetworkId> for RollupIndex {
81    type Error = InvalidRollupIndexError;
82
83    #[inline]
84    fn try_from(value: NetworkId) -> Result<Self, Self::Error> {
85        if value.to_u32() == 0 {
86            return Err(InvalidRollupIndexError);
87        }
88        Ok(RollupIndex(value.to_u32() - 1))
89    }
90}
91
92impl From<RollupIndex> for NetworkId {
93    #[inline]
94    fn from(value: RollupIndex) -> Self {
95        NetworkId::new(value.0 + 1)
96    }
97}
98
99impl From<RollupId> for RollupIndex {
100    #[inline]
101    fn from(value: RollupId) -> Self {
102        RollupIndex(value.to_u32() - 1)
103    }
104}