1#![warn(unused_extern_crates)]
2#![recursion_limit = "128"]
3#[macro_use]
4extern crate log;
5#[macro_use]
6extern crate serde_derive;
7#[macro_use]
8extern crate failure;
9#[macro_use]
10extern crate azure_sdk_core;
11
12pub mod attachment;
13mod authorization_token;
14pub mod clients;
15pub mod collection;
16mod consistency_level;
17mod database;
18mod document;
19mod document_attributes;
20mod errors;
21pub(crate) mod from_headers;
22mod headers;
23mod indexing_directive;
24pub mod offer;
25mod partition_key_range;
26mod partition_keys;
27mod permission;
28mod permission_resource;
29mod permission_token;
30pub mod prelude;
31mod query;
32mod requests;
33mod resource;
34mod resource_quota;
35pub mod responses;
36pub mod stored_procedure;
37mod to_json_vector;
38mod traits;
39pub mod trigger;
40mod user;
41mod user_defined_function;
42
43pub use self::attachment::Attachment;
44pub use self::authorization_token::*;
45use self::collection::IndexingPolicy;
46pub use self::consistency_level::ConsistencyLevel;
47pub use self::database::{Database, DatabaseName};
48pub use self::document::{Document, DocumentName};
49pub use self::document_attributes::DocumentAttributes;
50pub use self::indexing_directive::IndexingDirective;
51pub use self::offer::Offer;
52pub use self::partition_key_range::PartitionKeyRange;
53pub use self::permission::{Permission, PermissionMode, PermissionName};
54pub use self::permission_resource::PermissionResource;
55pub use self::permission_token::PermissionToken;
56pub use self::query::{Param, ParamDef, Query};
57pub use self::requests::*;
58pub use self::resource::Resource;
59pub use self::resource_quota::ResourceQuota;
60pub use self::traits::*;
61pub use self::trigger::{Trigger, TriggerName};
62use crate::clients::*;
63use crate::collection::Collection;
64use crate::collection::CollectionName;
65use crate::headers::*;
66pub use crate::partition_keys::PartitionKeys;
67use crate::stored_procedure::Parameters;
68pub use crate::user::{User, UserName};
69pub use crate::user_defined_function::UserDefinedFunctionName;
70use http::request::Builder;
71
72#[allow(dead_code)]
73#[derive(Debug, Clone, Copy)]
74pub enum ResourceType {
75 Databases,
76 Collections,
77 Documents,
78 StoredProcedures,
79 Users,
80 Permissions,
81 Attachments,
82 PartitionKeyRanges,
83 UserDefinedFunctions,
84 Triggers,
85}
86
87pub trait CosmosClientRequired<'a> {
88 fn cosmos_client(&'a self) -> &'a dyn CosmosClient;
89}
90
91pub trait DatabaseRequired<'a> {
92 fn database(&self) -> &'a str;
93}
94
95pub trait QueryCrossPartitionSupport {
96 type O;
97 fn with_query_cross_partition(self, query_cross_partition: bool) -> Self::O;
98}
99
100pub trait QueryCrossPartitionOption {
101 fn query_cross_partition(&self) -> bool;
102
103 #[must_use]
104 fn add_header(&self, builder: Builder) -> Builder {
105 builder.header(
106 HEADER_DOCUMENTDB_QUERY_ENABLECROSSPARTITION,
107 self.query_cross_partition().to_string(),
108 )
109 }
110}
111
112pub trait ParallelizeCrossPartitionQuerySupport {
113 type O;
114 fn with_parallelize_cross_partition_query(
115 self,
116 parallelize_cross_partition_query: bool,
117 ) -> Self::O;
118}
119
120pub trait ParametersOption<'a> {
121 fn parameters(&self) -> Option<&'a Parameters>;
122
123 fn generate_body(&self) -> String {
124 if let Some(parameters) = self.parameters() {
125 parameters.to_json()
126 } else {
127 String::from("[]")
128 }
129 }
130}
131
132pub trait ParametersSupport<'a> {
133 type O;
134 fn with_parameters(self, parameters: &'a Parameters) -> Self::O;
135}
136
137pub trait ParallelizeCrossPartitionQueryOption {
138 fn parallelize_cross_partition_query(&self) -> bool;
139
140 #[must_use]
141 fn add_header(&self, builder: Builder) -> Builder {
142 builder.header(
143 HEADER_DOCUMENTDB_QUERY_PARALLELIZECROSSPARTITIONQUERY,
144 self.parallelize_cross_partition_query().to_string(),
145 )
146 }
147}
148
149pub trait IsUpsertSupport {
150 type O;
151 fn with_is_upsert(self, is_upsert: bool) -> Self::O;
152}
153
154pub trait IsUpsertOption {
155 fn is_upsert(&self) -> bool;
156
157 #[must_use]
158 fn add_header(&self, builder: Builder) -> Builder {
159 builder.header(HEADER_DOCUMENTDB_IS_UPSERT, self.is_upsert().to_string())
160 }
161}
162
163pub trait AIMSupport {
164 type O;
165 fn with_a_im(self, a_im: bool) -> Self::O;
166}
167
168pub trait AIMOption {
169 fn a_im(&self) -> bool;
170
171 #[must_use]
172 fn add_header(&self, builder: Builder) -> Builder {
173 if self.a_im() {
174 builder.header(HEADER_A_IM, "Incremental feed")
175 } else {
176 builder
177 }
178 }
179}
180
181pub trait AllowTentativeWritesSupport {
182 type O;
183 fn with_allow_tentative_writes(self, allow_tentative_writes: bool) -> Self::O;
184}
185
186pub trait AllowTentativeWritesOption {
187 fn allow_tentative_writes(&self) -> bool;
188
189 #[must_use]
190 fn add_header(&self, builder: Builder) -> Builder {
191 builder.header(
192 HEADER_ALLOW_MULTIPLE_WRITES,
193 self.allow_tentative_writes().to_string(),
194 )
195 }
196}
197
198pub trait ConsistencyLevelSupport<'a> {
199 type O;
200 fn with_consistency_level(self, consistency_level: ConsistencyLevel<'a>) -> Self::O;
201}
202
203pub trait ConsistencyLevelOption<'a> {
204 fn consistency_level(&self) -> Option<ConsistencyLevel<'a>>;
205
206 #[must_use]
207 fn add_header(&self, builder: Builder) -> Builder {
208 if let Some(consistency_level) = self.consistency_level() {
209 let builder = builder.header(
210 HEADER_CONSISTENCY_LEVEL,
211 consistency_level.to_consistency_level_header(),
212 );
213
214 if let ConsistencyLevel::Session(session_token) = consistency_level {
217 builder.header(HEADER_SESSION_TOKEN, session_token.as_ref())
218 } else {
219 builder
220 }
221 } else {
222 builder
223 }
224 }
225}
226
227pub trait PartitionRangeIdSupport<'a> {
228 type O;
229 fn with_partition_range_id(self, partition_range_id: &'a str) -> Self::O;
230}
231
232pub trait PartitionRangeIdOption<'a> {
233 fn partition_range_id(&self) -> Option<&'a str>;
234
235 #[must_use]
236 fn add_header(&self, builder: Builder) -> Builder {
237 if let Some(partition_range_id) = self.partition_range_id() {
238 builder.header(HEADER_DOCUMENTDB_PARTITIONRANGEID, partition_range_id)
239 } else {
240 builder
241 }
242 }
243}
244
245pub trait ContinuationSupport<'a> {
246 type O;
247 fn with_continuation(self, continuation: &'a str) -> Self::O;
248}
249
250pub trait ContinuationOption<'a> {
251 fn continuation(&self) -> Option<&'a str>;
252
253 #[must_use]
254 fn add_header(&self, builder: Builder) -> Builder {
255 if let Some(continuation) = self.continuation() {
256 builder.header(HEADER_CONTINUATION, continuation)
257 } else {
258 builder
259 }
260 }
261}
262
263pub trait IndexingDirectiveSupport {
264 type O;
265 fn with_indexing_directive(self, indexing_directive: IndexingDirective) -> Self::O;
266}
267
268pub trait IndexingDirectiveOption {
269 fn indexing_directive(&self) -> IndexingDirective;
270
271 #[must_use]
272 fn add_header(&self, builder: Builder) -> Builder {
273 match self.indexing_directive() {
274 IndexingDirective::Default => builder, IndexingDirective::Exclude => builder.header(HEADER_INDEXING_DIRECTIVE, "Exclude"),
276 IndexingDirective::Include => builder.header(HEADER_INDEXING_DIRECTIVE, "Include"),
277 }
278 }
279}
280
281pub trait MaxItemCountSupport {
282 type O;
283 fn with_max_item_count(self, max_item_count: i32) -> Self::O;
284}
285
286pub trait MaxItemCountOption {
287 fn max_item_count(&self) -> i32;
288
289 #[must_use]
290 fn add_header(&self, builder: Builder) -> Builder {
291 if self.max_item_count() <= 0 {
292 builder.header(HEADER_MAX_ITEM_COUNT, -1)
293 } else {
294 builder.header(HEADER_MAX_ITEM_COUNT, self.max_item_count())
295 }
296 }
297}
298
299pub trait PartitionKeySupport<'a> {
300 type O;
301 fn with_partition_key(self, partition_key: &'a self::collection::PartitionKey) -> Self::O;
302}
303
304pub trait PartitionKeyOption<'a> {
305 fn partition_key(&self) -> Option<&'a self::collection::PartitionKey>;
306}
307
308pub trait PartitionKeyRequired<'a> {
309 fn partition_key(&self) -> &'a self::collection::PartitionKey;
310}
311
312pub trait PartitionKeysSupport<'a> {
313 type O;
314 fn with_partition_keys(self, partition_keys: &'a PartitionKeys) -> Self::O;
315}
316
317pub trait TriggerOperationRequired {
318 fn trigger_operation(&self) -> self::trigger::TriggerOperation;
319}
320
321pub trait TriggerOperationSupport {
322 type O;
323 fn with_trigger_operation(self, a: self::trigger::TriggerOperation) -> Self::O;
324}
325
326pub trait TriggerTypeRequired {
327 fn trigger_type(&self) -> self::trigger::TriggerType;
328}
329
330pub trait TriggerTypeSupport {
331 type O;
332 fn with_trigger_type(self, a: self::trigger::TriggerType) -> Self::O;
333}
334
335pub(crate) fn add_partition_keys_header(
336 partition_keys: &PartitionKeys,
337 builder: Builder,
338) -> Builder {
339 let serialized = partition_keys.to_json();
340 builder.header(HEADER_DOCUMENTDB_PARTITIONKEY, serialized)
341}
342
343pub trait PartitionKeysRequired<'a> {
344 fn partition_keys(&self) -> &'a PartitionKeys;
345
346 #[must_use]
347 fn add_header(&self, builder: Builder) -> Builder {
348 add_partition_keys_header(self.partition_keys(), builder)
349 }
350}
351
352pub trait PartitionKeysOption<'a> {
353 fn partition_keys(&self) -> Option<&'a PartitionKeys>;
354
355 #[must_use]
356 fn add_header(&self, builder: Builder) -> Builder {
357 if let Some(partition_keys) = self.partition_keys() {
358 let serialized = partition_keys.to_json();
359 builder.header(HEADER_DOCUMENTDB_PARTITIONKEY, serialized)
360 } else {
361 builder
362 }
363 }
364}
365
366pub trait MediaRequired<'a> {
367 fn media(&self) -> &'a str;
368}
369
370pub trait MediaSupport<'a> {
371 type O;
372 fn with_media(self, media: &'a str) -> Self::O;
373}
374
375pub trait StoredProcedureBodyRequired<'a> {
376 fn body(&self) -> &'a str;
377}
378
379pub trait StoredProcedureBodySupport<'a> {
380 type O;
381 fn with_body(self, body: &'a str) -> Self::O;
382}
383
384pub trait UserDefinedFunctionBodyRequired<'a> {
385 fn body(&self) -> &'a str;
386}
387
388pub trait UserDefinedFunctionBodySupport<'a> {
389 type O;
390 fn with_body(self, body: &'a str) -> Self::O;
391}
392
393pub trait TriggerBodyRequired<'a> {
394 fn body(&self) -> &'a str;
395}
396
397pub trait TriggerBodySupport<'a> {
398 type O;
399 fn with_body(self, body: &'a str) -> Self::O;
400}
401
402pub trait ExpirySecondsOption {
403 fn expiry_seconds(&self) -> u64;
404
405 #[must_use]
406 fn add_header(&self, builder: Builder) -> Builder {
407 builder.header(HEADER_DOCUMENTDB_EXPIRY_SECONDS, self.expiry_seconds())
408 }
409}
410
411pub trait ExpirySecondsSupport {
412 type O;
413 fn with_expiry_seconds(self, expiry_seconds: u64) -> Self::O;
414}
415
416pub trait DatabaseClientRequired<'a, C>
417where
418 C: CosmosClient,
419{
420 fn database_client(&self) -> &'a dyn DatabaseClient<C>;
421}
422
423pub trait DatabaseSupport<'a> {
424 type O;
425 fn with_database(self, database: &'a str) -> Self::O;
426}
427
428pub trait CollectionClientRequired<'a, C, D>
429where
430 C: CosmosClient,
431 D: DatabaseClient<C>,
432{
433 fn collection_client(&self) -> &'a dyn CollectionClient<C, D>;
434}
435
436pub trait AttachmentClientRequired<'a, C, D, COLL, DOC>
441where
442 C: CosmosClient,
443 D: DatabaseClient<C>,
444 COLL: CollectionClient<C, D>,
445{
446 fn attachment_client(&self) -> &'a dyn AttachmentClient<C, D, COLL, DOC>;
447}
448
449pub trait StoredProcedureClientRequired<'a, C, D, COLL>
450where
451 C: CosmosClient,
452 D: DatabaseClient<C>,
453 COLL: CollectionClient<C, D>,
454{
455 fn stored_procedure_client(&self) -> &'a dyn StoredProcedureClient<C, D, COLL>;
456}
457
458pub trait UserDefinedFunctionClientRequired<'a, C, D, COLL>
459where
460 C: CosmosClient,
461 D: DatabaseClient<C>,
462 COLL: CollectionClient<C, D>,
463{
464 fn user_defined_function_client(&self) -> &'a dyn UserDefinedFunctionClient<C, D, COLL>;
465}
466
467pub trait TriggerClientRequired<'a, C, D, COLL>
468where
469 C: CosmosClient,
470 D: DatabaseClient<C>,
471 COLL: CollectionClient<C, D>,
472{
473 fn trigger_client(&'a self) -> &'a dyn TriggerClient<C, D, COLL>;
474}
475
476pub trait UserClientRequired<'a, C, D>
477where
478 C: CosmosClient,
479 D: DatabaseClient<C>,
480{
481 fn user_client(&'a self) -> &'a dyn UserClient<C, D>;
482}
483
484pub trait StoredProcedureNameRequired<'a> {
485 fn stored_procedure_name(&self) -> &'a str;
486}
487
488pub trait StoredProcedureNameSupport<'a> {
489 type O;
490 fn with_stored_procedure_name(self, stored_procedure_name: &'a str) -> Self::O;
491}
492
493pub trait DocumentClientRequired<'a, C, D, COLL>
494where
495 C: CosmosClient,
496 D: DatabaseClient<C>,
497 COLL: CollectionClient<C, D>,
498{
499 fn document_client(&'a self) -> &'a dyn DocumentClient<C, D, COLL>;
500}
501
502pub trait PermissionClientRequired<'a, C, D, USER>
503where
504 C: CosmosClient,
505 D: DatabaseClient<C>,
506 USER: UserClient<C, D>,
507{
508 fn permission_client(&self) -> &'a dyn PermissionClient<C, D, USER>;
509}
510
511pub trait OfferRequired {
512 fn offer(&self) -> Offer;
513
514 #[must_use]
515 fn add_header(&self, builder: Builder) -> Builder {
516 match self.offer() {
517 Offer::Throughput(throughput) => builder.header(HEADER_OFFER_THROUGHPUT, throughput),
518 Offer::S1 => builder.header(HEADER_OFFER_TYPE, "S1"),
519 Offer::S2 => builder.header(HEADER_OFFER_TYPE, "S2"),
520 Offer::S3 => builder.header(HEADER_OFFER_TYPE, "S3"),
521 }
522 }
523}
524
525pub trait OfferSupport {
526 type O;
527 fn with_offer(self, offer: Offer) -> Self::O;
528}
529
530pub trait CollectionNameRequired<'a> {
531 fn collection_name(&self) -> &'a dyn CollectionName;
532}
533
534pub trait CollectionNameSupport<'a> {
535 type O;
536 fn with_collection_name(self, collection_name: &'a dyn CollectionName) -> Self::O;
537}
538
539pub trait CollectionRequired<'a> {
540 fn collection(&self) -> &'a Collection;
541}
542
543pub trait CollectionSupport<'a> {
544 type O;
545 fn with_collection(self, collection: &'a Collection) -> Self::O;
546}
547
548pub trait IndexingPolicyRequired<'a> {
549 fn indexing_policy(&self) -> &'a IndexingPolicy;
550}
551
552pub trait IndexingPolicySupport<'a> {
553 type O;
554 fn with_indexing_policy(self, offer: &'a IndexingPolicy) -> Self::O;
555}
556
557pub trait DocumentIdRequired<'a> {
563 fn document_id(&self) -> &'a str;
564}
565
566pub trait DocumentIdSupport<'a> {
567 type O;
568 fn with_document_id(self, document_id: &'a str) -> Self::O;
569}
570
571pub trait QueryRequired<'a> {
572 fn query(&self) -> &'a Query<'a>;
573}
574
575pub trait QuerySupport<'a> {
576 type O;
577 fn with_query(self, query: &'a Query<'a>) -> Self::O;
578}
579
580pub trait DatabaseNameRequired<'a> {
581 fn database_name(&'a self) -> &'a dyn DatabaseName;
582}
583
584pub trait DatabaseNameSupport<'a> {
585 type O;
586 fn with_database_name(self, database_name: &'a dyn DatabaseName) -> Self::O;
587}
588
589pub trait UserNameRequired<'a> {
590 fn user_name(&self) -> &'a dyn UserName;
591}
592
593pub trait UserNameSupport<'a> {
594 type O;
595 fn with_user_name(self, user_name: &'a dyn UserName) -> Self::O;
596}