drive/util/object_size_info/
contract_info.rs

1#[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/// Represents various forms of accessing or representing a data contract.
27/// This enum is used to handle different scenarios in which data contracts
28/// might be needed, providing a unified interface to access their data.
29#[allow(clippy::large_enum_variant)]
30#[derive(Clone, Debug)]
31#[cfg(feature = "server")]
32pub enum DataContractInfo<'a> {
33    /// A unique identifier for a data contract. This variant is typically used
34    /// when only the identity of the data contract is required without needing
35    /// to access the full contract itself.
36    DataContractId(Identifier),
37
38    #[cfg(feature = "server")]
39    /// Information necessary for fetching a data contract, encapsulated in an
40    /// `Arc` for thread-safe shared ownership. This variant is used when the
41    /// data needs to be fetched or is not immediately available.
42    DataContractFetchInfo(Arc<DataContractFetchInfo>),
43
44    /// A borrowed reference to a data contract. This variant is used for temporary,
45    /// read-only access to a data contract, avoiding ownership transfer.
46    BorrowedDataContract(&'a DataContract),
47
48    /// An owned version of a data contract. This variant is used when full ownership
49    /// and possibly mutability of the data contract is necessary.
50    OwnedDataContract(DataContract),
51}
52
53#[cfg(feature = "server")]
54impl<'a> DataContractInfo<'a> {
55    #[cfg(feature = "server")]
56    /// Resolve the data contract info into an object that contains the data contract
57    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/// Contains resolved data contract information, typically used after initial
95/// fetching or retrieval steps have been completed. This enum simplifies handling
96/// of data contract states post-retrieval.
97#[allow(clippy::large_enum_variant)]
98#[derive(Clone, Debug, PartialEq)]
99pub enum DataContractOwnedResolvedInfo {
100    #[cfg(feature = "server")]
101    /// Information necessary for fetched data contracts, encapsulated in an
102    /// `Arc` to ensure thread-safe shared ownership and access.
103    DataContractFetchInfo(Arc<DataContractFetchInfo>),
104
105    /// An owned instance of a data contract. This variant provides full control
106    /// and mutability over the data contract, suitable for scenarios requiring
107    /// modifications or extended operations on the data contract.
108    OwnedDataContract(DataContract),
109}
110
111impl DataContractOwnedResolvedInfo {
112    /// The id of the contract
113    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    /// The ref of the contract
125    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    /// Get the contract as owned
138    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/// Contains resolved data contract information, typically used after initial
150/// fetching or retrieval steps have been completed. This enum simplifies handling
151/// of data contract states post-retrieval.
152#[allow(clippy::large_enum_variant)]
153#[derive(Clone, Debug, PartialEq)]
154pub enum DataContractResolvedInfo<'a> {
155    #[cfg(feature = "server")]
156    /// Information necessary for fetched data contracts, encapsulated in an
157    /// `Arc` to ensure thread-safe shared ownership and access.
158    ArcDataContractFetchInfo(Arc<DataContractFetchInfo>),
159
160    /// Arc Data contract
161    ArcDataContract(Arc<DataContract>),
162
163    /// A borrowed reference to a resolved data contract. This variant is suitable
164    /// for scenarios where temporary, read-only access to a data contract is required.
165    BorrowedDataContract(&'a DataContract),
166
167    /// An owned instance of a data contract. This variant provides full control
168    /// and mutability over the data contract, suitable for scenarios requiring
169    /// modifications or extended operations on the data contract.
170    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    /// The id of the contract
189    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    /// The ref of the contract
203    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/// Enumerates methods for identifying or referencing document types, accommodating various application needs.
215#[allow(clippy::enum_variant_names)]
216#[derive(Clone, Debug)]
217#[cfg(feature = "server")]
218pub enum DocumentTypeInfo<'a> {
219    /// Contains the document type name as an owned `String`, suitable for dynamic or mutable scenarios.
220    DocumentTypeName(String),
221
222    /// References the document type name via a borrowed `&'a str`, ideal for static or temporary usage.
223    DocumentTypeNameAsStr(&'a str),
224
225    /// References a document type that has already been resolved through `DocumentTypeRef`.
226    DocumentTypeRef(DocumentTypeRef<'a>),
227}
228
229#[cfg(feature = "server")]
230impl<'a> DocumentTypeInfo<'a> {
231    /// Resolve the data contract info into an object that contains the data contract
232    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}