azure_sdk_cosmos/
lib.rs

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 we have a Session consistency level we make sure to pass
215            // the x-ms-session-token header too.
216            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, // nothing to do
275            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
436//pub trait CollectionRequired<'a> {
437//    fn collection(&self) -> &'a str;
438//}
439
440pub 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
557//pub trait CollectionSupport<'a> {
558//    type O;
559//    fn with_collection(self, collection: &'a str) -> Self::O;
560//}
561
562pub 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}