1
- #![ allow( dead_code, unused_variables) ]
2
1
// TODO(RUST-1395) Remove these allows.
2
+ #![ allow( dead_code, unused_variables) ]
3
3
4
+ mod download;
4
5
pub mod options;
5
6
6
7
use core:: task:: { Context , Poll } ;
7
- use std:: pin:: Pin ;
8
+ use std:: {
9
+ pin:: Pin ,
10
+ sync:: { atomic:: AtomicBool , Arc } ,
11
+ } ;
12
+
13
+ use serde:: { Deserialize , Serialize } ;
14
+ use tokio:: io:: ReadBuf ;
8
15
9
16
use crate :: {
17
+ bson:: { doc, oid:: ObjectId , Binary , Bson , DateTime , Document } ,
10
18
concern:: { ReadConcern , WriteConcern } ,
11
19
cursor:: Cursor ,
12
20
error:: Result ,
13
- selection_criteria:: SelectionCriteria ,
21
+ options:: SelectionCriteria ,
22
+ Collection ,
14
23
Database ,
15
24
} ;
16
- use bson :: { oid :: ObjectId , Bson , DateTime , Document } ;
25
+
17
26
use options:: * ;
18
- use serde:: { Deserialize , Serialize } ;
19
- use tokio:: io:: ReadBuf ;
20
27
21
28
pub const DEFAULT_BUCKET_NAME : & str = "fs" ;
22
29
pub const DEFAULT_CHUNK_SIZE_BYTES : u32 = 255 * 1024 ;
23
30
24
31
// Contained in a "chunks" collection for each user file
32
+ #[ derive( Debug , Deserialize , Serialize ) ]
25
33
struct Chunk {
34
+ #[ serde( rename = "_id" ) ]
26
35
id : ObjectId ,
27
36
files_id : Bson ,
28
37
n : u32 ,
29
38
// default size is 255 KiB
30
- data : Vec < u8 > ,
39
+ data : Binary ,
31
40
}
32
41
33
42
/// A collection in which information about stored files is stored. There will be one files
34
43
/// collection document per stored file.
35
- #[ derive( Serialize , Deserialize ) ]
44
+ #[ derive( Debug , Deserialize , Serialize ) ]
45
+ #[ serde( rename_all = "camelCase" ) ]
36
46
pub struct FilesCollectionDocument {
37
- id : Bson ,
38
- length : i64 ,
39
- chunk_size : u32 ,
40
- upload_date : DateTime ,
41
- filename : String ,
42
- metadata : Document ,
47
+ #[ serde( rename = "_id" ) ]
48
+ pub id : Bson ,
49
+ pub length : u64 ,
50
+ pub chunk_size : u32 ,
51
+ pub upload_date : DateTime ,
52
+ pub filename : Option < String > ,
53
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
54
+ pub metadata : Option < Document > ,
55
+ }
56
+
57
+ #[ derive( Debug ) ]
58
+ struct GridFsBucketInner {
59
+ options : GridFsBucketOptions ,
60
+ files : Collection < FilesCollectionDocument > ,
61
+ chunks : Collection < Chunk > ,
62
+ created_indexes : AtomicBool ,
43
63
}
44
64
45
65
/// Struct for storing GridFS managed files within a [`Database`].
66
+ #[ derive( Debug , Clone ) ]
46
67
pub struct GridFsBucket {
47
- // Contains a "chunks" collection
48
- pub ( crate ) db : Database ,
49
- pub ( crate ) options : GridFsBucketOptions ,
68
+ inner : Arc < GridFsBucketInner > ,
50
69
}
51
70
52
71
// TODO: RUST-1395 Add documentation and example code for this struct.
@@ -134,30 +153,67 @@ impl tokio::io::AsyncRead for GridFsDownloadStream {
134
153
}
135
154
}
136
155
137
- impl futures_util:: io:: AsyncRead for GridFsDownloadStream {
138
- fn poll_read (
139
- self : Pin < & mut Self > ,
140
- cx : & mut Context < ' _ > ,
141
- buf : & mut [ u8 ] ,
142
- ) -> Poll < core:: result:: Result < usize , futures_util:: io:: Error > > {
143
- todo ! ( )
156
+ impl GridFsBucket {
157
+ pub ( crate ) fn new ( db : Database , mut options : GridFsBucketOptions ) -> GridFsBucket {
158
+ if options. read_concern . is_none ( ) {
159
+ options. read_concern = db. read_concern ( ) . cloned ( ) ;
160
+ }
161
+ if options. write_concern . is_none ( ) {
162
+ options. write_concern = db. write_concern ( ) . cloned ( ) ;
163
+ }
164
+ if options. selection_criteria . is_none ( ) {
165
+ options. selection_criteria = db. selection_criteria ( ) . cloned ( ) ;
166
+ }
167
+
168
+ let bucket_name = options
169
+ . bucket_name
170
+ . as_deref ( )
171
+ . unwrap_or ( DEFAULT_BUCKET_NAME ) ;
172
+
173
+ let files = db. collection :: < FilesCollectionDocument > ( & format ! ( "{}.files" , bucket_name) ) ;
174
+ let chunks = db. collection :: < Chunk > ( & format ! ( "{}.chunks" , bucket_name) ) ;
175
+
176
+ GridFsBucket {
177
+ inner : Arc :: new ( GridFsBucketInner {
178
+ options,
179
+ files,
180
+ chunks,
181
+ created_indexes : AtomicBool :: new ( false ) ,
182
+ } ) ,
183
+ }
144
184
}
145
- }
146
185
147
- impl GridFsBucket {
148
186
/// Gets the read concern of the [`GridFsBucket`].
149
187
pub fn read_concern ( & self ) -> Option < & ReadConcern > {
150
- self . options . read_concern . as_ref ( )
188
+ self . inner . options . read_concern . as_ref ( )
151
189
}
152
190
153
191
/// Gets the write concern of the [`GridFsBucket`].
154
192
pub fn write_concern ( & self ) -> Option < & WriteConcern > {
155
- self . options . write_concern . as_ref ( )
193
+ self . inner . options . write_concern . as_ref ( )
156
194
}
157
195
158
196
/// Gets the selection criteria of the [`GridFsBucket`].
159
197
pub fn selection_criteria ( & self ) -> Option < & SelectionCriteria > {
160
- self . options . selection_criteria . as_ref ( )
198
+ self . inner . options . selection_criteria . as_ref ( )
199
+ }
200
+
201
+ /// Gets the chunk size in bytes for the [`GridFsBucket`].
202
+ fn chunk_size_bytes ( & self ) -> u32 {
203
+ self . inner
204
+ . options
205
+ . chunk_size_bytes
206
+ . unwrap_or ( DEFAULT_CHUNK_SIZE_BYTES )
207
+ }
208
+
209
+ /// Gets a handle to the files collection for the [`GridFsBucket`].
210
+ fn files ( & self ) -> & Collection < FilesCollectionDocument > {
211
+ & self . inner . files
212
+ }
213
+
214
+ /// Gets a handle to the chunks collection for the [`GridFsBucket`].
215
+ fn chunks ( & self ) -> & Collection < Chunk > {
216
+ & self . inner . chunks
161
217
}
162
218
163
219
/// Opens a [`GridFsUploadStream`] that the application can write the contents of the file to.
@@ -173,19 +229,6 @@ impl GridFsBucket {
173
229
todo ! ( )
174
230
}
175
231
176
- /// Opens a [`GridFsUploadStream`] that the application can write the contents of the file to.
177
- /// The driver generates a unique [`Bson::ObjectId`] for the file id.
178
- ///
179
- /// Returns a [`GridFsUploadStream`] to which the application will write the contents.
180
- pub async fn open_upload_stream (
181
- & self ,
182
- filename : String ,
183
- options : impl Into < Option < GridFsUploadOptions > > ,
184
- ) -> Result < GridFsUploadStream > {
185
- self . open_upload_stream_with_id ( Bson :: ObjectId ( ObjectId :: new ( ) ) , filename, options)
186
- . await
187
- }
188
-
189
232
/// Uploads a user file to a GridFS bucket. The application supplies a custom file id. Uses the
190
233
/// `tokio` crate's `AsyncRead` trait for the `source`.
191
234
pub async fn upload_from_tokio_reader_with_id (
@@ -244,6 +287,19 @@ impl GridFsBucket {
244
287
. await
245
288
}
246
289
290
+ /// Opens a [`GridFsUploadStream`] that the application can write the contents of the file to.
291
+ /// The driver generates a unique [`Bson::ObjectId`] for the file id.
292
+ ///
293
+ /// Returns a [`GridFsUploadStream`] to which the application will write the contents.
294
+ pub async fn open_upload_stream (
295
+ & self ,
296
+ filename : String ,
297
+ options : impl Into < Option < GridFsUploadOptions > > ,
298
+ ) -> Result < GridFsUploadStream > {
299
+ self . open_upload_stream_with_id ( Bson :: ObjectId ( ObjectId :: new ( ) ) , filename, options)
300
+ . await
301
+ }
302
+
247
303
/// Opens and returns a [`GridFsDownloadStream`] from which the application can read
248
304
/// the contents of the stored file specified by `id`.
249
305
pub async fn open_download_stream ( & self , id : Bson ) -> Result < GridFsDownloadStream > {
@@ -261,52 +317,6 @@ impl GridFsBucket {
261
317
todo ! ( )
262
318
}
263
319
264
- /// Downloads the contents of the stored file specified by `id` and writes
265
- /// the contents to the `destination`. Uses the `tokio` crate's `AsyncWrite`
266
- /// trait for the `destination`.
267
- pub async fn download_to_tokio_writer (
268
- & self ,
269
- id : Bson ,
270
- destination : impl tokio:: io:: AsyncWrite ,
271
- ) {
272
- todo ! ( )
273
- }
274
-
275
- /// Downloads the contents of the stored file specified by `id` and writes
276
- /// the contents to the `destination`. Uses the `futures-0.3` crate's `AsyncWrite`
277
- /// trait for the `destination`.
278
- pub async fn download_to_futures_0_3_writer (
279
- & self ,
280
- id : Bson ,
281
- destination : impl futures_util:: AsyncWrite ,
282
- ) {
283
- todo ! ( )
284
- }
285
-
286
- /// Downloads the contents of the stored file specified by `filename` and by
287
- /// the revision in `options` and writes the contents to the `destination`. Uses the
288
- /// `tokio` crate's `AsyncWrite` trait for the `destination`.
289
- pub async fn download_to_tokio_writer_by_name (
290
- & self ,
291
- filename : String ,
292
- destination : impl tokio:: io:: AsyncWrite ,
293
- options : impl Into < Option < GridFsDownloadByNameOptions > > ,
294
- ) {
295
- todo ! ( )
296
- }
297
-
298
- /// Downloads the contents of the stored file specified by `filename` and by
299
- /// the revision in `options` and writes the contents to the `destination`. Uses the
300
- /// `futures-0.3` crate's `AsyncWrite` trait for the `destination`.
301
- pub async fn download_to_futures_0_3_writer_by_name (
302
- & self ,
303
- filename : String ,
304
- destination : impl futures_util:: AsyncWrite ,
305
- options : impl Into < Option < GridFsDownloadByNameOptions > > ,
306
- ) {
307
- todo ! ( )
308
- }
309
-
310
320
/// Given an `id`, deletes the stored file's files collection document and
311
321
/// associated chunks from a [`GridFsBucket`].
312
322
pub async fn delete ( & self , id : Bson ) {
0 commit comments