dpp/identity/identity_public_key/contract_bounds/
mod.rs1use crate::identifier::Identifier;
2use crate::identity::identity_public_key::contract_bounds::ContractBounds::{
3 SingleContract, SingleContractDocumentType,
4};
5#[cfg(feature = "json-conversion")]
6use crate::serialization::JsonConvertible;
7#[cfg(feature = "value-conversion")]
8use crate::serialization::ValueConvertible;
9use crate::ProtocolError;
10use bincode::{Decode, Encode};
11use serde::{Deserialize, Serialize};
12
13pub type ContractBoundsType = u8;
14
15#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
22#[repr(u8)]
23#[derive(
24 Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd, Hash,
25)]
26#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
27#[serde(tag = "type", rename_all = "camelCase")]
28pub enum ContractBounds {
29 #[serde(rename = "singleContract")]
31 SingleContract { id: Identifier } = 0,
32 #[serde(rename = "documentType", rename_all = "camelCase")]
34 SingleContractDocumentType {
35 id: Identifier,
36 document_type_name: String,
37 } = 1,
38 }
42
43impl ContractBounds {
44 pub fn new_from_type(
46 contract_bounds_type: u8,
47 identifier: Vec<u8>,
48 document_type: String,
49 ) -> Result<Self, ProtocolError> {
50 Ok(match contract_bounds_type {
51 0 => SingleContract {
52 id: Identifier::from_bytes(identifier.as_slice())?,
53 },
54 1 => SingleContractDocumentType {
55 id: Identifier::from_bytes(identifier.as_slice())?,
56 document_type_name: document_type,
57 },
58 _ => {
59 return Err(ProtocolError::InvalidKeyContractBoundsError(format!(
60 "unrecognized contract bounds type: {}",
61 contract_bounds_type
62 )))
63 }
64 })
65 }
66
67 pub fn contract_bounds_type(&self) -> ContractBoundsType {
69 match self {
70 SingleContract { .. } => 0,
71 SingleContractDocumentType { .. } => 1,
72 }
74 }
75
76 pub fn contract_bounds_type_from_str(str: &str) -> Result<ContractBoundsType, ProtocolError> {
77 match str {
78 "singleContract" => Ok(0),
79 "documentType" => Ok(1),
80 _ => Err(ProtocolError::DecodingError(String::from(
81 "Expected type to be one of none, singleContract or singleContractDocumentType",
82 ))),
83 }
84 }
85 pub fn contract_bounds_type_string(&self) -> &str {
87 match self {
88 SingleContract { .. } => "singleContract",
89 SingleContractDocumentType { .. } => "documentType",
90 }
92 }
93
94 pub fn identifier(&self) -> &Identifier {
96 match self {
97 SingleContract { id } => id,
98 SingleContractDocumentType { id, .. } => id,
99 }
101 }
102
103 pub fn document_type(&self) -> Option<&String> {
105 match self {
106 SingleContract { .. } => None,
107 SingleContractDocumentType {
108 document_type_name: document_type,
109 ..
110 } => Some(document_type),
111 }
113 }
114 }
165
166#[cfg(all(test, feature = "json-conversion"))]
167mod tests {
168 use super::*;
169 use crate::serialization::JsonConvertible;
170
171 #[test]
172 fn contract_bounds_single_contract_json_round_trip() {
173 let id = Identifier::from([0xABu8; 32]);
174 let bounds = ContractBounds::SingleContract { id };
175
176 let json = bounds.to_json().expect("to_json should succeed");
177 assert!(
178 json["id"].is_string(),
179 "Identifier should be a base58 string, got: {:?}",
180 json["id"]
181 );
182
183 let expected_base58 = id.to_string(platform_value::string_encoding::Encoding::Base58);
184 assert_eq!(json["id"].as_str().unwrap(), expected_base58);
185
186 let restored = ContractBounds::from_json(json).expect("from_json should succeed");
187 assert_eq!(bounds, restored);
188 }
189
190 #[test]
191 fn contract_bounds_document_type_json_round_trip() {
192 let id = Identifier::from([0xCDu8; 32]);
193 let bounds = ContractBounds::SingleContractDocumentType {
194 id,
195 document_type_name: "myDocument".to_string(),
196 };
197
198 let json = bounds.to_json().expect("to_json should succeed");
199 assert!(json["id"].is_string());
200 assert_eq!(json["documentTypeName"].as_str().unwrap(), "myDocument");
201
202 let restored = ContractBounds::from_json(json).expect("from_json should succeed");
203 assert_eq!(bounds, restored);
204 }
205
206 #[test]
207 fn contract_bounds_value_round_trip() {
208 let id = Identifier::from([0x55u8; 32]);
209 let bounds = ContractBounds::SingleContractDocumentType {
210 id,
211 document_type_name: "note".to_string(),
212 };
213
214 let obj = bounds.to_object().expect("to_object should succeed");
215 let restored = ContractBounds::from_object(obj).expect("from_object should succeed");
216 assert_eq!(bounds, restored);
217 }
218}