mongodb_gridfs/
lib.rs

1//! This crate provides an implementation of Mongo GridFS on the top of mongodb's crate.
2//! This implementation only use the _async/await_ version of mongodb.
3//!
4//! From <https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.rst>
5//! > GridFS is a convention drivers use to store and retrieve BSON binary data (type “\x05”) that exceeds MongoDB’s BSON-document size limit of 16 MiB. When this data, called a user file, is written to the system, GridFS divides the file into chunks that are stored as distinct documents in a chunks collection. To retrieve a stored file, GridFS locates and returns all of its component chunks. Internally, GridFS creates a files collection document for each stored file. Files collection documents hold information about stored files, and they are stored in a files collection.
6//! # Examples
7//! Uploading a document:
8//!  ```rust
9//!  # use mongodb::Client;
10//!  # use mongodb::{error::Error, Database};
11//!  use mongodb_gridfs::{options::GridFSBucketOptions, GridFSBucket};
12//!  # use uuid::Uuid;
13//!  
14//!  # fn db_name_new() -> String {
15//!  #     "test_".to_owned()
16//!  #         + Uuid::new_v4()
17//!  #             .hyphenated()
18//!  #             .encode_lower(&mut Uuid::encode_buffer())
19//!  # }
20//!  #
21//!  # #[tokio::main]
22//!  # async fn main() -> Result<(), Error> {
23//!  #    let client = Client::with_uri_str(&std::env::var("MONGO_URI").unwrap_or("mongodb://localhost:27017/".to_string())).await?;
24//!  #    let dbname = db_name_new();
25//!  #    let db: Database = client.database(&dbname);
26//!  let mut bucket = GridFSBucket::new(db.clone(), Some(GridFSBucketOptions::default()));
27//!  let id = bucket
28//!      .upload_from_stream("test.txt", "stream your data here".as_bytes(), None)
29//!      .await?;
30//!  #     println!("{}", id);
31//!  #     db.drop(None).await
32//!  # }
33//!  ```
34//!  Downloading a document:
35//!  ```rust
36//! # #[cfg(feature = "async-std-runtime")]
37//! # use futures::stream::StreamExt;
38//! # #[cfg(any(feature = "default", feature = "tokio-runtime"))]
39//! use tokio_stream::StreamExt;
40//! # use mongodb::Client;
41//! # use mongodb::Database;
42//! use mongodb_gridfs::{options::GridFSBucketOptions, GridFSBucket, GridFSError};
43//! # use uuid::Uuid;
44//!
45//! # fn db_name_new() -> String {
46//! #     "test_".to_owned()
47//! #         + Uuid::new_v4()
48//! #             .hyphenated()
49//! #             .encode_lower(&mut Uuid::encode_buffer())
50//! # }
51//! #
52//! # #[tokio::main]
53//! # async fn main() -> Result<(), GridFSError> {
54//! #     let client = Client::with_uri_str(
55//! #         &std::env::var("MONGO_URI").unwrap_or("mongodb://localhost:27017/".to_string()),
56//! #     )
57//! #     .await?;
58//! #     let dbname = db_name_new();
59//! #     let db: Database = client.database(&dbname);
60//! let bucket = GridFSBucket::new(db.clone(), Some(GridFSBucketOptions::default()));
61//! #     let id = bucket
62//! #         .clone()
63//! #         .upload_from_stream("test.txt", "test data".as_bytes(), None)
64//! #         .await?;
65//! #     println!("{}", id);
66//! #
67//! let mut cursor = bucket.open_download_stream(id).await?;
68//! let buffer = cursor.next().await.unwrap();
69//! #     println!("{:?}", buffer);
70//! #
71//! #     db.drop(None).await?;
72//! #     Ok(())
73//! # }
74//!  ```
75//! # Features
76//! The following features are propagated to mongodb:
77//! - default
78//! - async-std-runtime
79//! - tokio-runtime
80//! # Code Status
81//! | Feature                                     | Status  | Notes                                           |
82//! | ------------------------------------------- | ------- | ----------------------------------------------- |
83//! | GridFSUploadOptions                         | DONE    | `contentType` and `aliases` are not implemented |
84//! | GridFSBucketOption                          | DONE    | concerns not used when ensuring indexes         |
85//! | GridFSFindOptions                           | DONE    |                                                 |
86//! | GridFSDownloadByNameOptions                 | TODO    |                                                 |
87//! | GridFSBucket                                | DONE    |                                                 |
88//! | GridFSBucket . open_upload_stream           | DONE    |                                                 |
89//! | GridFSBucket . open_upload_stream_with_id   |         |                                                 |
90//! | GridFSBucket . upload_from_stream           | NO      | No Implementation planned                         |
91//! | GridFSBucket . upload_from_stream_with_id   | NO      | No Implementation planned                         |
92//! | GridFSBucket . open_download_stream         | DONE    |                                                 |
93//! | GridFSBucket . download_to_stream           | NO      | No Implementation planned                         |
94//! | GridFSBucket . delete                       | DONE    |                                                 |
95//! | GridFSBucket . find                         | DONE    |                                                 |
96//! | GridFSBucket . rename                       | DONE    |                                                 |
97//! | GridFSBucket . drop                         | DONE    |                                                 |
98//! | GridFSBucket . open_download_stream_by_name |         |                                                 |
99//! | GridFSBucket . download_to_stream_by_name   |         |                                                 |
100//! | indexes                                     | DONE   |                                                 |
101
102pub mod bucket;
103pub mod options;
104use std::{
105    error::Error,
106    fmt::{Display, Formatter, Result},
107};
108
109pub use bucket::GridFSBucket;
110
111#[derive(Debug)]
112pub enum GridFSError {
113    MongoError(mongodb::error::Error),
114    FileNotFound(),
115}
116
117impl From<mongodb::error::Error> for GridFSError {
118    fn from(err: mongodb::error::Error) -> GridFSError {
119        GridFSError::MongoError(err)
120    }
121}
122
123impl Error for GridFSError {
124    fn source(&self) -> Option<&(dyn Error + 'static)> {
125        match self {
126            GridFSError::MongoError(e) => Some(e),
127            GridFSError::FileNotFound() => None,
128        }
129    }
130
131    // fn backtrace(&self) -> Option<&std::backtrace::Backtrace> {
132    //     None
133    // }
134
135    fn description(&self) -> &str {
136        "description() is deprecated; use Display"
137    }
138
139    fn cause(&self) -> Option<&dyn Error> {
140        self.source()
141    }
142}
143
144impl Display for GridFSError {
145    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
146        match self {
147            GridFSError::MongoError(me) => write!(f, "{}", me),
148            GridFSError::FileNotFound() => write!(f, "File not found"),
149        }
150    }
151}