drive/util/object_size_info/
contract_info.rs1#[cfg(feature = "server")]
2use crate::drive::contract::DataContractFetchInfo;
3#[cfg(feature = "server")]
4use crate::drive::Drive;
5#[cfg(feature = "server")]
6use crate::error::document::DocumentError;
7#[cfg(feature = "server")]
8use crate::error::Error;
9#[cfg(feature = "server")]
10use crate::fees::op::LowLevelDriveOperation;
11#[cfg(feature = "server")]
12use dpp::block::block_info::BlockInfo;
13use dpp::data_contract::accessors::v0::DataContractV0Getters;
14#[cfg(feature = "server")]
15use dpp::data_contract::document_type::DocumentTypeRef;
16use dpp::data_contract::DataContract;
17use dpp::identifier::Identifier;
18#[cfg(feature = "server")]
19use dpp::ProtocolError;
20#[cfg(feature = "server")]
21use grovedb::TransactionArg;
22#[cfg(feature = "server")]
23use platform_version::version::PlatformVersion;
24use std::sync::Arc;
25
26#[allow(clippy::large_enum_variant)]
30#[derive(Clone, Debug)]
31#[cfg(feature = "server")]
32pub enum DataContractInfo<'a> {
33 DataContractId(Identifier),
37
38 #[cfg(feature = "server")]
39 DataContractFetchInfo(Arc<DataContractFetchInfo>),
43
44 BorrowedDataContract(&'a DataContract),
47
48 OwnedDataContract(DataContract),
51}
52
53#[cfg(feature = "server")]
54impl<'a> DataContractInfo<'a> {
55 #[cfg(feature = "server")]
56 pub(crate) fn resolve(
58 self,
59 drive: &Drive,
60 block_info: &BlockInfo,
61 transaction: TransactionArg,
62 drive_operations: &mut Vec<LowLevelDriveOperation>,
63 platform_version: &PlatformVersion,
64 ) -> Result<DataContractResolvedInfo<'a>, Error> {
65 match self {
66 DataContractInfo::DataContractId(contract_id) => {
67 let contract_fetch_info = drive
68 .get_contract_with_fetch_info_and_add_to_operations(
69 contract_id.into_buffer(),
70 Some(&block_info.epoch),
71 true,
72 transaction,
73 drive_operations,
74 platform_version,
75 )?
76 .ok_or(Error::Document(DocumentError::DataContractNotFound))?;
77 Ok(DataContractResolvedInfo::ArcDataContractFetchInfo(
78 contract_fetch_info,
79 ))
80 }
81 DataContractInfo::DataContractFetchInfo(contract_fetch_info) => Ok(
82 DataContractResolvedInfo::ArcDataContractFetchInfo(contract_fetch_info),
83 ),
84 DataContractInfo::BorrowedDataContract(contract) => {
85 Ok(DataContractResolvedInfo::BorrowedDataContract(contract))
86 }
87 DataContractInfo::OwnedDataContract(contract) => {
88 Ok(DataContractResolvedInfo::OwnedDataContract(contract))
89 }
90 }
91 }
92}
93
94#[allow(clippy::large_enum_variant)]
98#[derive(Clone, Debug, PartialEq)]
99pub enum DataContractOwnedResolvedInfo {
100 #[cfg(feature = "server")]
101 DataContractFetchInfo(Arc<DataContractFetchInfo>),
104
105 OwnedDataContract(DataContract),
109}
110
111impl DataContractOwnedResolvedInfo {
112 pub fn id(&self) -> Identifier {
114 match self {
115 #[cfg(feature = "server")]
116 DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => {
117 fetch_info.contract.id()
118 }
119 DataContractOwnedResolvedInfo::OwnedDataContract(data_contract) => data_contract.id(),
120 }
121 }
122}
123impl AsRef<DataContract> for DataContractOwnedResolvedInfo {
124 fn as_ref(&self) -> &DataContract {
126 match self {
127 #[cfg(feature = "server")]
128 DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => {
129 &fetch_info.contract
130 }
131 DataContractOwnedResolvedInfo::OwnedDataContract(owned) => owned,
132 }
133 }
134}
135
136impl DataContractOwnedResolvedInfo {
137 pub fn into_owned(self) -> DataContract {
139 match self {
140 #[cfg(feature = "server")]
141 DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => {
142 fetch_info.contract.clone()
143 }
144 DataContractOwnedResolvedInfo::OwnedDataContract(owned) => owned,
145 }
146 }
147}
148
149#[allow(clippy::large_enum_variant)]
153#[derive(Clone, Debug, PartialEq)]
154pub enum DataContractResolvedInfo<'a> {
155 #[cfg(feature = "server")]
156 ArcDataContractFetchInfo(Arc<DataContractFetchInfo>),
159
160 ArcDataContract(Arc<DataContract>),
162
163 BorrowedDataContract(&'a DataContract),
166
167 OwnedDataContract(DataContract),
171}
172
173impl<'a> From<&'a DataContractOwnedResolvedInfo> for DataContractResolvedInfo<'a> {
174 fn from(value: &'a DataContractOwnedResolvedInfo) -> Self {
175 match value {
176 #[cfg(feature = "server")]
177 DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => {
178 DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info.clone())
179 }
180 DataContractOwnedResolvedInfo::OwnedDataContract(data_contract) => {
181 DataContractResolvedInfo::BorrowedDataContract(data_contract)
182 }
183 }
184 }
185}
186
187impl DataContractResolvedInfo<'_> {
188 pub fn id(&self) -> Identifier {
190 match self {
191 #[cfg(feature = "server")]
192 DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info) => {
193 fetch_info.contract.id()
194 }
195 DataContractResolvedInfo::BorrowedDataContract(data_contract) => data_contract.id(),
196 DataContractResolvedInfo::OwnedDataContract(data_contract) => data_contract.id(),
197 DataContractResolvedInfo::ArcDataContract(data_contract) => data_contract.id(),
198 }
199 }
200}
201impl AsRef<DataContract> for DataContractResolvedInfo<'_> {
202 fn as_ref(&self) -> &DataContract {
204 match self {
205 #[cfg(feature = "server")]
206 DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info) => &fetch_info.contract,
207 DataContractResolvedInfo::BorrowedDataContract(borrowed) => borrowed,
208 DataContractResolvedInfo::OwnedDataContract(owned) => owned,
209 DataContractResolvedInfo::ArcDataContract(data_contract) => data_contract.as_ref(),
210 }
211 }
212}
213
214#[allow(clippy::enum_variant_names)]
216#[derive(Clone, Debug)]
217#[cfg(feature = "server")]
218pub enum DocumentTypeInfo<'a> {
219 DocumentTypeName(String),
221
222 DocumentTypeNameAsStr(&'a str),
224
225 DocumentTypeRef(DocumentTypeRef<'a>),
227}
228
229#[cfg(feature = "server")]
230impl<'a> DocumentTypeInfo<'a> {
231 pub fn resolve(self, contract: &'a DataContract) -> Result<DocumentTypeRef<'a>, ProtocolError> {
233 match self {
234 DocumentTypeInfo::DocumentTypeName(document_type_name) => contract
235 .document_type_for_name(document_type_name.as_str())
236 .map_err(ProtocolError::DataContractError),
237 DocumentTypeInfo::DocumentTypeNameAsStr(document_type_name) => contract
238 .document_type_for_name(document_type_name)
239 .map_err(ProtocolError::DataContractError),
240 DocumentTypeInfo::DocumentTypeRef(document_type_ref) => Ok(document_type_ref),
241 }
242 }
243}
244
245#[cfg(all(feature = "server", test))]
246mod tests {
247 use super::*;
248 use dpp::tests::fixtures::get_data_contract_fixture;
249 use dpp::version::PlatformVersion;
250
251 fn sample_contract() -> DataContract {
252 let platform_version = PlatformVersion::latest();
253 get_data_contract_fixture(None, 0, platform_version.protocol_version).data_contract_owned()
254 }
255
256 #[test]
257 fn owned_resolved_info_id_and_as_ref() {
258 let contract = sample_contract();
259 let expected_id = contract.id();
260 let owned = DataContractOwnedResolvedInfo::OwnedDataContract(contract);
261 assert_eq!(owned.id(), expected_id);
262 let as_ref: &DataContract = owned.as_ref();
263 assert_eq!(as_ref.id(), expected_id);
264 }
265
266 #[test]
267 fn owned_resolved_info_into_owned_returns_inner() {
268 let contract = sample_contract();
269 let expected_id = contract.id();
270 let owned = DataContractOwnedResolvedInfo::OwnedDataContract(contract);
271 let unwrapped = owned.into_owned();
272 assert_eq!(unwrapped.id(), expected_id);
273 }
274
275 #[test]
276 fn resolved_info_borrowed_and_owned() {
277 let contract = sample_contract();
278 let id = contract.id();
279
280 let borrowed: DataContractResolvedInfo =
281 DataContractResolvedInfo::BorrowedDataContract(&contract);
282 assert_eq!(borrowed.id(), id);
283 let as_ref: &DataContract = borrowed.as_ref();
284 assert_eq!(as_ref.id(), id);
285
286 let owned_wrapper = DataContractResolvedInfo::OwnedDataContract(contract);
287 assert_eq!(owned_wrapper.id(), id);
288 let as_ref2: &DataContract = owned_wrapper.as_ref();
289 assert_eq!(as_ref2.id(), id);
290 }
291
292 #[test]
293 fn resolved_info_arc_contract() {
294 use std::sync::Arc;
295 let contract = sample_contract();
296 let id = contract.id();
297 let arc = Arc::new(contract);
298 let info: DataContractResolvedInfo = DataContractResolvedInfo::ArcDataContract(arc);
299 assert_eq!(info.id(), id);
300 let as_ref: &DataContract = info.as_ref();
301 assert_eq!(as_ref.id(), id);
302 }
303
304 #[test]
305 fn from_owned_resolved_info_produces_borrowed_variant() {
306 let contract = sample_contract();
307 let id = contract.id();
308 let owned = DataContractOwnedResolvedInfo::OwnedDataContract(contract);
309 let borrowed: DataContractResolvedInfo = (&owned).into();
310 match borrowed {
311 DataContractResolvedInfo::BorrowedDataContract(b) => {
312 assert_eq!(b.id(), id);
313 }
314 _ => panic!("expected BorrowedDataContract"),
315 }
316 }
317
318 #[test]
319 fn document_type_info_resolve_errors_for_missing_type() {
320 let contract = sample_contract();
321 let info = DocumentTypeInfo::DocumentTypeName("missing".to_string());
322 assert!(info.resolve(&contract).is_err());
323
324 let info = DocumentTypeInfo::DocumentTypeNameAsStr("nope_at_all");
325 assert!(info.resolve(&contract).is_err());
326 }
327}