drive/query/
single_document_drive_query.rs1use crate::drive::document::paths::contract_document_type_path_vec;
2use crate::util::common::encode::encode_u64;
3
4use crate::drive::votes;
5use crate::error::query::QuerySyntaxError;
6use crate::error::Error;
7use crate::query::Query;
8use grovedb::{PathQuery, SizedQuery};
9use platform_version::version::PlatformVersion;
10use platform_version::TryFromPlatformVersioned;
11
12#[derive(Debug, PartialEq, Clone)]
16#[repr(u8)]
17pub enum SingleDocumentDriveQueryContestedStatus {
18 NotContested = 0,
20 MaybeContested = 1,
23 Contested = 2,
25}
26
27impl TryFrom<i32> for SingleDocumentDriveQueryContestedStatus {
28 type Error = Error;
29
30 fn try_from(value: i32) -> Result<Self, Self::Error> {
31 match value {
32 0 => Ok(SingleDocumentDriveQueryContestedStatus::NotContested),
33 1 => Ok(SingleDocumentDriveQueryContestedStatus::MaybeContested),
34 2 => Ok(SingleDocumentDriveQueryContestedStatus::Contested),
35 n => Err(Error::Query(QuerySyntaxError::Unsupported(format!(
36 "unsupported contested status {}, only 0, 1 and 2 are supported",
37 n
38 )))),
39 }
40 }
41}
42
43#[derive(Debug, PartialEq, Clone)]
45pub struct SingleDocumentDriveQuery {
46 pub contract_id: [u8; 32],
48 pub document_type_name: String,
50 pub document_type_keeps_history: bool,
52 pub document_id: [u8; 32],
54 pub block_time_ms: Option<u64>,
56 pub contested_status: SingleDocumentDriveQueryContestedStatus,
58}
59
60impl SingleDocumentDriveQuery {
61 pub fn construct_path_query(
63 &self,
64 platform_version: &PlatformVersion,
65 ) -> Result<PathQuery, Error> {
66 match self.contested_status {
67 SingleDocumentDriveQueryContestedStatus::NotContested => {
68 Ok(self.construct_non_contested_path_query(true))
69 }
70 SingleDocumentDriveQueryContestedStatus::MaybeContested => {
71 let non_contested = self.construct_non_contested_path_query(true);
72 let contested = self.construct_contested_path_query(true);
73 PathQuery::merge(
74 vec![&non_contested, &contested],
75 &platform_version.drive.grove_version,
76 )
77 .map_err(Error::from)
78 }
79 SingleDocumentDriveQueryContestedStatus::Contested => {
80 Ok(self.construct_contested_path_query(true))
81 }
82 }
83 }
84
85 fn construct_non_contested_path_query(&self, with_limit_1: bool) -> PathQuery {
87 let mut path =
89 contract_document_type_path_vec(&self.contract_id, self.document_type_name.as_str());
90
91 path.push(vec![0]);
92
93 let mut query = Query::new();
94 query.insert_key(self.document_id.to_vec());
95
96 if self.document_type_keeps_history {
97 if let Some(block_time) = self.block_time_ms {
99 let encoded_block_time = encode_u64(block_time);
100 let mut sub_query = Query::new_with_direction(false);
101 sub_query.insert_range_to_inclusive(..=encoded_block_time);
102 query.set_subquery(sub_query);
103 } else {
104 query.set_subquery_key(vec![0]);
105 }
106 }
107
108 let limit = if with_limit_1 { Some(1) } else { None };
109
110 PathQuery::new(path, SizedQuery::new(query, limit, None))
111 }
112
113 fn construct_contested_path_query(&self, with_limit_1: bool) -> PathQuery {
115 let path = votes::paths::vote_contested_resource_contract_documents_storage_path_vec(
117 &self.contract_id,
118 self.document_type_name.as_str(),
119 );
120
121 let mut query = Query::new();
122 query.insert_key(self.document_id.to_vec());
123
124 let limit = if with_limit_1 { Some(1) } else { None };
125
126 PathQuery::new(path, SizedQuery::new(query, limit, None))
127 }
128}
129
130impl TryFromPlatformVersioned<SingleDocumentDriveQuery> for PathQuery {
131 type Error = Error;
132 fn try_from_platform_versioned(
133 value: SingleDocumentDriveQuery,
134 platform_version: &PlatformVersion,
135 ) -> Result<Self, Self::Error> {
136 value.construct_path_query(platform_version)
137 }
138}