indy_data_types/identifiers/
schema.rs1use crate::did::DidValue;
2use crate::qualifiable::{self, qualifiable_type};
3use crate::{Qualifiable, Validatable, ValidationError};
4
5use super::DELIMITER;
6
7qualifiable_type!(SchemaId, "A V1 schema identifier");
8
9impl SchemaId {
10 pub const PREFIX: &'static str = "schema";
11 pub const MARKER: &'static str = "2";
12
13 pub fn new(did: &DidValue, name: &str, version: &str) -> SchemaId {
14 let id = format!(
15 "{}{}{}{}{}{}{}",
16 did.0,
17 DELIMITER,
18 Self::MARKER,
19 DELIMITER,
20 name,
21 DELIMITER,
22 version
23 );
24 Self::from(qualifiable::combine(
25 Self::PREFIX,
26 did.get_method(),
27 id.as_str(),
28 ))
29 }
30
31 pub fn parts(&self) -> Option<(Option<&str>, DidValue, String, String)> {
32 let parts = self.0.split_terminator(DELIMITER).collect::<Vec<&str>>();
33
34 if parts.len() == 1 {
35 return None;
37 }
38
39 if parts.len() == 4 {
40 let did = parts[0].to_string();
42 let name = parts[2].to_string();
43 let version = parts[3].to_string();
44 return Some((None, DidValue(did), name, version));
45 }
46
47 if parts.len() == 8 {
48 let method = parts[1];
50 let did = parts[2..5].join(DELIMITER);
51 let name = parts[6].to_string();
52 let version = parts[7].to_string();
53 return Some((Some(method), DidValue(did), name, version));
54 }
55
56 None
57 }
58}
59
60impl Qualifiable for SchemaId {
61 fn prefix() -> &'static str {
62 Self::PREFIX
63 }
64
65 fn combine(method: Option<&str>, entity: &str) -> Self {
66 let sid = Self(entity.to_owned());
67 match sid.parts() {
68 Some((_, did, name, version)) => {
69 Self::new(&did.default_method(method), &name, &version)
70 }
71 None => sid,
72 }
73 }
74
75 fn to_unqualified(&self) -> Self {
76 match self.parts() {
77 Some((method, did, name, version)) => {
78 let did = if let Some(method) = method {
79 did.remove_method(method)
80 } else {
81 did
82 };
83 Self::new(&did, &name, &version)
84 }
85 None => self.clone(),
86 }
87 }
88}
89
90impl Validatable for SchemaId {
91 fn validate(&self) -> Result<(), ValidationError> {
92 if self.0.parse::<i32>().is_ok() {
93 return Ok(());
94 }
95
96 self.parts().ok_or(format!(
97 "SchemaId validation failed: {:?}, doesn't match pattern",
98 self.0
99 ))?;
100
101 Ok(())
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 fn _did() -> DidValue {
110 DidValue("NcYxiDXkpYi6ov5FcYDi1e".to_string())
111 }
112
113 fn _did_qualified() -> DidValue {
114 DidValue("did:sov:NcYxiDXkpYi6ov5FcYDi1e".to_string())
115 }
116
117 fn _schema_id_seq_no() -> SchemaId {
118 SchemaId("1".to_string())
119 }
120
121 fn _schema_id_unqualified() -> SchemaId {
122 SchemaId("NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0".to_string())
123 }
124
125 fn _schema_id_qualified() -> SchemaId {
126 SchemaId("schema:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0".to_string())
127 }
128
129 fn _schema_id_invalid() -> SchemaId {
130 SchemaId("NcYxiDXkpYi6ov5FcYDi1e:2".to_string())
131 }
132
133 mod to_unqualified {
134 use super::*;
135
136 #[test]
137 fn test_schema_id_unqualify_for_id_as_seq_no() {
138 assert_eq!(_schema_id_seq_no(), _schema_id_seq_no().to_unqualified());
139 }
140
141 #[test]
142 fn test_schema_id_parts_for_id_as_unqualified() {
143 assert_eq!(
144 _schema_id_unqualified(),
145 _schema_id_unqualified().to_unqualified()
146 );
147 }
148
149 #[test]
150 fn test_schema_id_parts_for_id_as_qualified() {
151 assert_eq!(
152 _schema_id_unqualified(),
153 _schema_id_qualified().to_unqualified()
154 );
155 }
156
157 #[test]
158 fn test_schema_id_parts_for_invalid_unqualified() {
159 assert_eq!(_schema_id_invalid(), _schema_id_invalid().to_unqualified());
160 }
161 }
162
163 mod parts {
164 use super::*;
165
166 #[test]
167 fn test_schema_id_parts_for_id_as_seq_no() {
168 assert!(_schema_id_seq_no().parts().is_none());
169 }
170
171 #[test]
172 fn test_schema_id_parts_for_id_as_unqualified() {
173 let (_, did, _, _) = _schema_id_unqualified().parts().unwrap();
174 assert_eq!(_did(), did);
175 }
176
177 #[test]
178 fn test_schema_id_parts_for_id_as_qualified() {
179 let (_, did, _, _) = _schema_id_qualified().parts().unwrap();
180 assert_eq!(_did_qualified(), did);
181 }
182
183 #[test]
184 fn test_schema_id_parts_for_invalid_unqualified() {
185 assert!(_schema_id_invalid().parts().is_none());
186 }
187 }
188
189 mod validate {
190 use super::*;
191
192 #[test]
193 fn test_validate_schema_id_as_seq_no() {
194 _schema_id_seq_no().validate().unwrap();
195 }
196
197 #[test]
198 fn test_validate_schema_id_as_unqualified() {
199 _schema_id_unqualified().validate().unwrap();
200 }
201
202 #[test]
203 fn test_validate_schema_id_as_fully_qualified() {
204 _schema_id_qualified().validate().unwrap();
205 }
206
207 #[test]
208 fn test_validate_schema_id_for_invalid_unqualified() {
209 _schema_id_invalid().validate().unwrap_err();
210 }
211
212 #[test]
213 fn test_validate_schema_id_for_invalid_fully_qualified() {
214 let id = SchemaId("schema:sov:NcYxiDXkpYi6ov5FcYDi1e:2:1.0".to_string());
215 id.validate().unwrap_err();
216 }
217 }
218
219 mod to_qualified {
220 use super::*;
221
222 #[test]
223 fn test_schema_to_qualified() {
224 assert_eq!(
225 _schema_id_unqualified().to_qualified("sov").unwrap(),
226 _schema_id_qualified()
227 )
228 }
229 }
230}