• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

input-output-hk / catalyst-libs / 17376694348

01 Sep 2025 11:48AM UTC coverage: 67.994% (+0.1%) from 67.899%
17376694348

Pull #507

github

web-flow
Merge c49eaa49b into c20638587
Pull Request #507: fix(rust/rbac-registration): Validate witness for stake address and payment address URIs in certificate

59 of 81 new or added lines in 4 files covered. (72.84%)

3 existing lines in 2 files now uncovered.

13197 of 19409 relevant lines covered (67.99%)

3038.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.05
/rust/catalyst-types/src/catalyst_id/role_index.rs
1
//! COSE Signature Protected Header `kid` URI Catalyst User Role.
2

3
use std::{
4
    fmt::{Display, Formatter},
5
    num::ParseIntError,
6
    str::FromStr,
7
};
8

9
use displaydoc::Display;
10
use strum::EnumIs;
11
use thiserror::Error;
12

13
/// Role Index parsing error
14
#[derive(Display, Error, Debug)]
15
#[allow(clippy::module_name_repetitions)]
16
pub enum RoleIdError {
17
    /// Invalid parse
18
    Parse(#[from] ParseIntError),
19
}
20

21
/// Project Catalyst User Role Index.
22
///
23
/// The canonical list of role indexes is statically defined. Users are allowed to parse
24
/// custom roles, which will be interpreted as [`Self::Unknown`], and they can verify this
25
/// using the [`RoleId::is_unknown`] helper function.
26
///
27
/// <https://github.com/input-output-hk/catalyst-CIPs/blob/x509-catalyst-role-definitions/CIP-XXXX/README.md>
28
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIs)]
29
#[repr(u8)]
30
#[non_exhaustive]
31
pub enum RoleId {
32
    /// Primary required role use for voting and commenting.
33
    Role0 = 0,
34

35
    /// Delegated representative (dRep) that vote on behalf of delegators.
36
    DelegatedRepresentative = 1,
37

38
    /// Proposer that enabling creation, collaboration, and submission of proposals.
39
    Proposer = 3,
40

41
    /// A custom role.
42
    Unknown(u8),
43
}
44

45
impl RoleId {
46
    /// Is the `RoleId` the default value [`Self::Role0`]
47
    #[must_use]
48
    pub fn is_default(self) -> bool {
9✔
49
        self == Self::Role0
9✔
50
    }
9✔
51

52
    /// Returns the `u8` representation of the role.
53
    #[must_use]
54
    pub const fn as_u8(self) -> u8 {
4✔
55
        match self {
4✔
56
            RoleId::Role0 => 0,
1✔
57
            RoleId::DelegatedRepresentative => 1,
×
UNCOV
58
            RoleId::Proposer => 3,
×
59
            RoleId::Unknown(b) => b,
3✔
60
        }
61
    }
4✔
62
}
63

64
impl Default for RoleId {
65
    fn default() -> Self {
18✔
66
        Self::Role0
18✔
67
    }
18✔
68
}
69

70
impl From<u8> for RoleId {
71
    fn from(value: u8) -> Self {
5✔
72
        match value {
5✔
73
            0 => Self::Role0,
1✔
74
            1 => Self::DelegatedRepresentative,
×
UNCOV
75
            3 => Self::Proposer,
×
76
            b => Self::Unknown(b),
4✔
77
        }
78
    }
5✔
79
}
80

81
impl From<RoleId> for u8 {
82
    fn from(role: RoleId) -> u8 {
×
83
        role.as_u8()
×
84
    }
×
85
}
86

87
impl FromStr for RoleId {
88
    type Err = RoleIdError;
89

90
    fn from_str(s: &str) -> Result<Self, Self::Err> {
261✔
91
        let value: u8 = s.parse()?;
261✔
92

93
        Ok(Self::from(value))
5✔
94
    }
261✔
95
}
96

97
impl Display for RoleId {
98
    fn fmt(
4✔
99
        &self,
4✔
100
        f: &mut Formatter<'_>,
4✔
101
    ) -> Result<(), std::fmt::Error> {
4✔
102
        write!(f, "{}", self.as_u8())
4✔
103
    }
4✔
104
}
105

106
impl<'a, C> minicbor::Decode<'a, C> for RoleId {
107
    fn decode(
256✔
108
        d: &mut minicbor::Decoder<'a>,
256✔
109
        ctx: &mut C,
256✔
110
    ) -> Result<Self, minicbor::decode::Error> {
256✔
111
        <u8 as minicbor::Decode<'a, C>>::decode(d, ctx).map(Self::from)
256✔
112
    }
256✔
113
}
114

115
#[cfg(test)]
116
mod tests {
117
    use minicbor::{Decoder, Encoder};
118

119
    use super::*;
120

121
    #[proptest::property_test]
122
    fn role_encode(i: u16) {
123
        let mut buffer = vec![0u8; 16];
124

125
        let mut encoder = Encoder::new(buffer.as_mut_slice());
126

127
        encoder.int(i.into()).unwrap();
128

129
        let mut decoder = Decoder::new(buffer.as_slice());
130
        let i_str = i.to_string();
131

132
        if i > u16::from(u8::MAX) {
133
            assert!(RoleId::from_str(&i_str).is_err());
134
            assert!(decoder.decode::<RoleId>().is_err());
135
        } else {
136
            let i = u8::try_from(i).unwrap();
137

138
            let r = RoleId::from(i);
139
            let r_str = RoleId::from_str(&i_str).unwrap();
140
            let r_display = r.to_string();
141
            let r_dec: RoleId = decoder.decode().unwrap();
142

143
            assert_eq!(r, r_str);
144
            assert_eq!(r, r_dec);
145
            assert_eq!(i_str, r_display);
146
        }
147
    }
148
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc