indy_data_types/identifiers/
rev_reg.rs1use once_cell::sync::Lazy;
2
3use regex::Regex;
4
5use super::cred_def::CredentialDefinitionId;
6use super::DELIMITER;
7use crate::did::DidValue;
8use crate::qualifiable::{self, qualifiable_type, Qualifiable};
9use crate::{Validatable, ValidationError};
10
11static QUALIFIED_REV_REG_ID: Lazy<Regex> = Lazy::new(|| {
12 Regex::new("(^revreg:(?P<method>[a-z0-9]+):)?(?P<did>.+):4:(?P<cred_def_id>.+):(?P<rev_reg_type>.+):(?P<tag>.+)$").unwrap()
13});
14
15qualifiable_type!(RevocationRegistryId, "A revocation registry identifier");
16
17impl RevocationRegistryId {
18 pub const PREFIX: &'static str = "revreg";
19 pub const MARKER: &'static str = "4";
20
21 pub fn new(
22 did: &DidValue,
23 cred_def_id: &CredentialDefinitionId,
24 rev_reg_type: &str,
25 tag: &str,
26 ) -> RevocationRegistryId {
27 let id = format!(
28 "{}{}{}{}{}{}{}{}{}",
29 did.0,
30 DELIMITER,
31 Self::MARKER,
32 DELIMITER,
33 cred_def_id.0,
34 DELIMITER,
35 rev_reg_type,
36 DELIMITER,
37 tag
38 );
39 Self::from(qualifiable::combine(
40 Self::PREFIX,
41 did.get_method(),
42 id.as_str(),
43 ))
44 }
45
46 pub fn parts(&self) -> Option<(DidValue, CredentialDefinitionId, String, String)> {
47 QUALIFIED_REV_REG_ID.captures(&self.0).map(|caps| {
48 (
49 DidValue(caps["did"].to_string()),
50 CredentialDefinitionId(caps["cred_def_id"].to_string()),
51 caps["rev_reg_type"].to_string(),
52 caps["tag"].to_string(),
53 )
54 })
55 }
56}
57
58impl Qualifiable for RevocationRegistryId {
59 fn prefix() -> &'static str {
60 Self::PREFIX
61 }
62
63 fn combine(method: Option<&str>, entity: &str) -> Self {
64 let sid = Self(entity.to_owned());
65 match sid.parts() {
66 Some((did, cred_def_id, rev_reg_type, tag)) => Self::new(
67 &did.default_method(method),
68 &cred_def_id.default_method(method),
69 &rev_reg_type,
70 &tag,
71 ),
72 None => sid,
73 }
74 }
75
76 fn to_unqualified(&self) -> Self {
77 match self.parts() {
78 Some((did, cred_def_id, rev_reg_type, tag)) => Self::new(
79 &did.to_unqualified(),
80 &cred_def_id.to_unqualified(),
81 &rev_reg_type,
82 &tag,
83 ),
84 None => self.clone(),
85 }
86 }
87}
88
89impl Validatable for RevocationRegistryId {
90 fn validate(&self) -> Result<(), ValidationError> {
91 self.parts().ok_or(format!(
92 "Revocation Registry Id validation failed: {:?}, doesn't match pattern",
93 self.0
94 ))?;
95 Ok(())
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 fn _did() -> DidValue {
104 DidValue("NcYxiDXkpYi6ov5FcYDi1e".to_string())
105 }
106
107 fn _rev_reg_type() -> String {
108 "CL_ACCUM".to_string()
109 }
110
111 fn _tag() -> String {
112 "TAG_1".to_string()
113 }
114
115 fn _did_qualified() -> DidValue {
116 DidValue("did:sov:NcYxiDXkpYi6ov5FcYDi1e".to_string())
117 }
118
119 fn _cred_def_id_unqualified() -> CredentialDefinitionId {
120 CredentialDefinitionId(
121 "NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag".to_string(),
122 )
123 }
124
125 fn _cred_def_id_qualified() -> CredentialDefinitionId {
126 CredentialDefinitionId("creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:schema:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag".to_string())
127 }
128
129 fn _rev_reg_id_unqualified() -> RevocationRegistryId {
130 RevocationRegistryId("NcYxiDXkpYi6ov5FcYDi1e:4:NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag:CL_ACCUM:TAG_1".to_string())
131 }
132
133 fn _rev_reg_id_qualified() -> RevocationRegistryId {
134 RevocationRegistryId("revreg:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:4:creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:schema:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag:CL_ACCUM:TAG_1".to_string())
135 }
136
137 mod to_unqualified {
138 use super::*;
139
140 #[test]
141 fn test_rev_reg_id_parts_for_id_as_unqualified() {
142 assert_eq!(
143 _rev_reg_id_unqualified(),
144 _rev_reg_id_unqualified().to_unqualified()
145 );
146 }
147
148 #[test]
149 fn test_rev_reg_id_parts_for_id_as_qualified() {
150 assert_eq!(
151 _rev_reg_id_unqualified(),
152 _rev_reg_id_qualified().to_unqualified()
153 );
154 }
155 }
156
157 mod parts {
158 use super::*;
159
160 #[test]
161 fn test_rev_reg_id_parts_for_id_as_unqualified() {
162 let (did, cred_def_id, rev_reg_type, tag) = _rev_reg_id_unqualified().parts().unwrap();
163 assert_eq!(_did(), did);
164 assert_eq!(_cred_def_id_unqualified(), cred_def_id);
165 assert_eq!(_rev_reg_type(), rev_reg_type);
166 assert_eq!(_tag(), tag);
167 }
168
169 #[test]
170 fn test_rev_reg_id_parts_for_id_as_qualified() {
171 let (did, cred_def_id, rev_reg_type, tag) = _rev_reg_id_qualified().parts().unwrap();
172 assert_eq!(_did_qualified(), did);
173 assert_eq!(_cred_def_id_qualified(), cred_def_id);
174 assert_eq!(_rev_reg_type(), rev_reg_type);
175 assert_eq!(_tag(), tag);
176 }
177 }
178
179 mod validate {
180 use super::*;
181
182 #[test]
183 fn test_validate_rev_reg_id_as_unqualified() {
184 _rev_reg_id_unqualified().validate().unwrap();
185 }
186
187 #[test]
188 fn test_validate_rev_reg_id_as_fully_qualified() {
189 _rev_reg_id_qualified().validate().unwrap();
190 }
191 }
192
193 mod to_qualified {
194 use super::*;
195
196 #[test]
197 fn test_red_def_to_qualified() {
198 assert_eq!(
199 _rev_reg_id_unqualified().to_qualified("sov").unwrap(),
200 _rev_reg_id_qualified()
201 )
202 }
203 }
204}