@@ -7,7 +7,7 @@ use cipherstash_client::{
77 } ,
88} ;
99use itertools:: Itertools ;
10- use std:: { collections:: HashMap , marker:: PhantomData } ;
10+ use std:: { borrow :: Cow , collections:: HashMap , marker:: PhantomData } ;
1111
1212use crate :: {
1313 traits:: { Decryptable , Searchable } ,
@@ -131,11 +131,56 @@ where
131131 S : Searchable ,
132132{
133133 pub fn build ( self ) -> Result < PreparedQuery , QueryError > {
134- let items_len = self . parts . len ( ) ;
134+ PreparedQueryBuilder :: new :: < S > ( ) . build ( self . parts )
135+ }
136+ }
137+
138+ impl < S > QueryBuilder < S , & EncryptedTable < Dynamo > >
139+ where
140+ S : Searchable + Identifiable ,
141+ {
142+ pub async fn load < T : Decryptable > ( self ) -> Result < Vec < T > , QueryError > {
143+ let table = self . backend ;
144+ let query = self . build ( ) ?;
145+
146+ let items = query. send ( table) . await ?;
147+ let results = table. decrypt_all ( items) . await ?;
148+
149+ Ok ( results)
150+ }
151+ }
152+
153+ impl < S > QueryBuilder < S , & EncryptedTable < Dynamo > >
154+ where
155+ S : Searchable + Decryptable + Identifiable ,
156+ {
157+ pub async fn send ( self ) -> Result < Vec < S > , QueryError > {
158+ self . load :: < S > ( ) . await
159+ }
160+ }
161+
162+ pub struct PreparedQueryBuilder {
163+ pub type_name : Cow < ' static , str > ,
164+ pub index_by_name : fn ( & str , IndexType ) -> Option < Box < dyn ComposableIndex > > ,
165+ }
166+
167+ impl PreparedQueryBuilder {
168+ pub fn new < S : Searchable > ( ) -> Self {
169+ Self {
170+ type_name : S :: type_name ( ) ,
171+ index_by_name : S :: index_by_name,
172+ }
173+ }
174+
175+ pub fn build (
176+ & self ,
177+ parts : Vec < ( String , SingleIndex , Plaintext ) > ,
178+ ) -> Result < PreparedQuery , QueryError > {
179+ let items_len = parts. len ( ) ;
135180
136181 // this is the simplest way to brute force the index names but relies on some gross
137182 // stringly typing which doesn't feel good
138- for perm in self . parts . iter ( ) . permutations ( items_len) {
183+ for perm in parts. iter ( ) . permutations ( items_len) {
139184 let ( indexes, plaintexts) : ( Vec < ( & String , & SingleIndex ) > , Vec < & Plaintext > ) =
140185 perm. into_iter ( ) . map ( |x| ( ( & x. 0 , & x. 1 ) , & x. 2 ) ) . unzip ( ) ;
141186
@@ -170,7 +215,7 @@ where
170215 }
171216 } ;
172217
173- if let Some ( composed_index) = S :: index_by_name ( index_name. as_str ( ) , index_type) {
218+ if let Some ( composed_index) = ( self . index_by_name ) ( index_name. as_str ( ) , index_type) {
174219 let mut plaintext = ComposablePlaintext :: new ( plaintexts[ 0 ] . clone ( ) ) ;
175220
176221 for p in plaintexts[ 1 ..] . iter ( ) {
@@ -181,41 +226,17 @@ where
181226
182227 return Ok ( PreparedQuery {
183228 index_name,
184- type_name : S :: type_name ( ) . to_string ( ) ,
229+ type_name : self . type_name . to_string ( ) ,
185230 plaintext,
186231 composed_index,
187232 } ) ;
188233 }
189234 }
190235
191- let fields = self . parts . iter ( ) . map ( |x| & x. 0 ) . join ( "," ) ;
236+ let fields = parts. iter ( ) . map ( |x| & x. 0 ) . join ( "," ) ;
192237
193238 Err ( QueryError :: InvalidQuery ( format ! (
194239 "Could not build query for fields: {fields}"
195240 ) ) )
196241 }
197242}
198-
199- impl < S > QueryBuilder < S , & EncryptedTable < Dynamo > >
200- where
201- S : Searchable + Identifiable ,
202- {
203- pub async fn load < T : Decryptable > ( self ) -> Result < Vec < T > , QueryError > {
204- let table = self . backend ;
205- let query = self . build ( ) ?;
206-
207- let items = query. send ( table) . await ?;
208- let results = table. decrypt_all ( items) . await ?;
209-
210- Ok ( results)
211- }
212- }
213-
214- impl < S > QueryBuilder < S , & EncryptedTable < Dynamo > >
215- where
216- S : Searchable + Decryptable + Identifiable ,
217- {
218- pub async fn send ( self ) -> Result < Vec < S > , QueryError > {
219- self . load :: < S > ( ) . await
220- }
221- }
0 commit comments