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 , Bson , DateTime , Document , RawBinaryRef } ,
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
25
- struct Chunk {
32
+ #[ derive( Debug , Deserialize , Serialize ) ]
33
+ struct Chunk < ' a > {
34
+ #[ serde( rename = "_id" ) ]
26
35
id : ObjectId ,
27
36
files_id : Bson ,
28
37
n : u32 ,
29
- // default size is 255 KiB
30
- data : Vec < u8 > ,
38
+ # [ serde ( borrow ) ]
39
+ data : RawBinaryRef < ' a > ,
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" ) ]
46
+ #[ non_exhaustive]
36
47
pub struct FilesCollectionDocument {
37
- id : Bson ,
38
- length : i64 ,
39
- chunk_size : u32 ,
40
- upload_date : DateTime ,
41
- filename : String ,
42
- metadata : Document ,
48
+ #[ serde( rename = "_id" ) ]
49
+ pub id : Bson ,
50
+ pub length : u64 ,
51
+ pub chunk_size : u32 ,
52
+ pub upload_date : DateTime ,
53
+ pub filename : Option < String > ,
54
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
55
+ pub metadata : Option < Document > ,
56
+ }
57
+
58
+ #[ derive( Debug ) ]
59
+ struct GridFsBucketInner {
60
+ options : GridFsBucketOptions ,
61
+ files : Collection < FilesCollectionDocument > ,
62
+ chunks : Collection < Chunk < ' static > > ,
63
+ created_indexes : AtomicBool ,
43
64
}
44
65
45
66
/// Struct for storing GridFS managed files within a [`Database`].
67
+ #[ derive( Debug , Clone ) ]
46
68
pub struct GridFsBucket {
47
- // Contains a "chunks" collection
48
- pub ( crate ) db : Database ,
49
- pub ( crate ) options : GridFsBucketOptions ,
69
+ inner : Arc < GridFsBucketInner > ,
50
70
}
51
71
52
72
// TODO: RUST-1395 Add documentation and example code for this struct.
@@ -134,30 +154,67 @@ impl tokio::io::AsyncRead for GridFsDownloadStream {
134
154
}
135
155
}
136
156
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 ! ( )
157
+ impl GridFsBucket {
158
+ pub ( crate ) fn new ( db : Database , mut options : GridFsBucketOptions ) -> GridFsBucket {
159
+ if options. read_concern . is_none ( ) {
160
+ options. read_concern = db. read_concern ( ) . cloned ( ) ;
161
+ }
162
+ if options. write_concern . is_none ( ) {
163
+ options. write_concern = db. write_concern ( ) . cloned ( ) ;
164
+ }
165
+ if options. selection_criteria . is_none ( ) {
166
+ options. selection_criteria = db. selection_criteria ( ) . cloned ( ) ;
167
+ }
168
+
169
+ let bucket_name = options
170
+ . bucket_name
171
+ . as_deref ( )
172
+ . unwrap_or ( DEFAULT_BUCKET_NAME ) ;
173
+
174
+ let files = db. collection :: < FilesCollectionDocument > ( & format ! ( "{}.files" , bucket_name) ) ;
175
+ let chunks = db. collection :: < Chunk > ( & format ! ( "{}.chunks" , bucket_name) ) ;
176
+
177
+ GridFsBucket {
178
+ inner : Arc :: new ( GridFsBucketInner {
179
+ options,
180
+ files,
181
+ chunks,
182
+ created_indexes : AtomicBool :: new ( false ) ,
183
+ } ) ,
184
+ }
144
185
}
145
- }
146
186
147
- impl GridFsBucket {
148
187
/// Gets the read concern of the [`GridFsBucket`].
149
188
pub fn read_concern ( & self ) -> Option < & ReadConcern > {
150
- self . options . read_concern . as_ref ( )
189
+ self . inner . options . read_concern . as_ref ( )
151
190
}
152
191
153
192
/// Gets the write concern of the [`GridFsBucket`].
154
193
pub fn write_concern ( & self ) -> Option < & WriteConcern > {
155
- self . options . write_concern . as_ref ( )
194
+ self . inner . options . write_concern . as_ref ( )
156
195
}
157
196
158
197
/// Gets the selection criteria of the [`GridFsBucket`].
159
198
pub fn selection_criteria ( & self ) -> Option < & SelectionCriteria > {
160
- self . options . selection_criteria . as_ref ( )
199
+ self . inner . options . selection_criteria . as_ref ( )
200
+ }
201
+
202
+ /// Gets the chunk size in bytes for the [`GridFsBucket`].
203
+ fn chunk_size_bytes ( & self ) -> u32 {
204
+ self . inner
205
+ . options
206
+ . chunk_size_bytes
207
+ . unwrap_or ( DEFAULT_CHUNK_SIZE_BYTES )
208
+ }
209
+
210
+ /// Gets a handle to the files collection for the [`GridFsBucket`].
211
+ fn files ( & self ) -> & Collection < FilesCollectionDocument > {
212
+ & self . inner . files
213
+ }
214
+
215
+ /// Gets a handle to the chunks collection for the [`GridFsBucket`].
216
+ fn chunks ( & self ) -> & Collection < Chunk > {
217
+ & self . inner . chunks
161
218
}
162
219
163
220
/// Opens a [`GridFsUploadStream`] that the application can write the contents of the file to.
@@ -173,19 +230,6 @@ impl GridFsBucket {
173
230
todo ! ( )
174
231
}
175
232
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
233
/// Uploads a user file to a GridFS bucket. The application supplies a custom file id. Uses the
190
234
/// `tokio` crate's `AsyncRead` trait for the `source`.
191
235
pub async fn upload_from_tokio_reader_with_id (
@@ -244,6 +288,19 @@ impl GridFsBucket {
244
288
. await
245
289
}
246
290
291
+ /// Opens a [`GridFsUploadStream`] that the application can write the contents of the file to.
292
+ /// The driver generates a unique [`Bson::ObjectId`] for the file id.
293
+ ///
294
+ /// Returns a [`GridFsUploadStream`] to which the application will write the contents.
295
+ pub async fn open_upload_stream (
296
+ & self ,
297
+ filename : String ,
298
+ options : impl Into < Option < GridFsUploadOptions > > ,
299
+ ) -> Result < GridFsUploadStream > {
300
+ self . open_upload_stream_with_id ( Bson :: ObjectId ( ObjectId :: new ( ) ) , filename, options)
301
+ . await
302
+ }
303
+
247
304
/// Opens and returns a [`GridFsDownloadStream`] from which the application can read
248
305
/// the contents of the stored file specified by `id`.
249
306
pub async fn open_download_stream ( & self , id : Bson ) -> Result < GridFsDownloadStream > {
@@ -261,52 +318,6 @@ impl GridFsBucket {
261
318
todo ! ( )
262
319
}
263
320
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
321
/// Given an `id`, deletes the stored file's files collection document and
311
322
/// associated chunks from a [`GridFsBucket`].
312
323
pub async fn delete ( & self , id : Bson ) {
0 commit comments