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 latest_not_contested(
66 contract_id: [u8; 32],
67 document_type_name: String,
68 document_type_keeps_history: bool,
69 document_id: [u8; 32],
70 ) -> Self {
71 SingleDocumentDriveQuery {
72 contract_id,
73 document_type_name,
74 document_type_keeps_history,
75 document_id,
76 block_time_ms: None,
77 contested_status: SingleDocumentDriveQueryContestedStatus::NotContested,
78 }
79 }
80
81 pub fn construct_path_query(
83 &self,
84 platform_version: &PlatformVersion,
85 ) -> Result<PathQuery, Error> {
86 match self.contested_status {
87 SingleDocumentDriveQueryContestedStatus::NotContested => {
88 Ok(self.construct_non_contested_path_query(true))
89 }
90 SingleDocumentDriveQueryContestedStatus::MaybeContested => {
91 let non_contested = self.construct_non_contested_path_query(true);
92 let contested = self.construct_contested_path_query(true);
93 PathQuery::merge(
94 vec![&non_contested, &contested],
95 &platform_version.drive.grove_version,
96 )
97 .map_err(Error::from)
98 }
99 SingleDocumentDriveQueryContestedStatus::Contested => {
100 Ok(self.construct_contested_path_query(true))
101 }
102 }
103 }
104
105 fn construct_non_contested_path_query(&self, with_limit_1: bool) -> PathQuery {
107 let mut path =
109 contract_document_type_path_vec(&self.contract_id, self.document_type_name.as_str());
110
111 path.push(vec![0]);
112
113 let mut query = Query::new();
114 query.insert_key(self.document_id.to_vec());
115
116 if self.document_type_keeps_history {
117 if let Some(block_time) = self.block_time_ms {
119 let encoded_block_time = encode_u64(block_time);
120 let mut sub_query = Query::new_with_direction(false);
121 sub_query.insert_range_to_inclusive(..=encoded_block_time);
122 query.set_subquery(sub_query);
123 } else {
124 query.set_subquery_key(vec![0]);
125 }
126 }
127
128 let limit = if with_limit_1 { Some(1) } else { None };
129
130 PathQuery::new(path, SizedQuery::new(query, limit, None))
131 }
132
133 fn construct_contested_path_query(&self, with_limit_1: bool) -> PathQuery {
135 let path = votes::paths::vote_contested_resource_contract_documents_storage_path_vec(
137 &self.contract_id,
138 self.document_type_name.as_str(),
139 );
140
141 let mut query = Query::new();
142 query.insert_key(self.document_id.to_vec());
143
144 let limit = if with_limit_1 { Some(1) } else { None };
145
146 PathQuery::new(path, SizedQuery::new(query, limit, None))
147 }
148}
149
150impl TryFromPlatformVersioned<SingleDocumentDriveQuery> for PathQuery {
151 type Error = Error;
152 fn try_from_platform_versioned(
153 value: SingleDocumentDriveQuery,
154 platform_version: &PlatformVersion,
155 ) -> Result<Self, Self::Error> {
156 value.construct_path_query(platform_version)
157 }
158}