remi/lib.rs
1// ๐ปโโ๏ธ๐งถ remi-rs: Asynchronous Rust crate to handle communication between applications and object storage providers
2// Copyright (c) 2022-2025 Noelware, LLC. <team@noelware.org>
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in all
12// copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20// SOFTWARE.
21
22//! **remi-rs** is a Rust edition of Noelware's Java library [remi](https://github.com/Noelware/remi) that was
23//! discontinuted on **December 15th, 2023** and is the primary library that Noelware uses and maintained.
24//!
25//! **remi-rs** is a easy way to communicate with object storage providers like Azure Blob Storage and Amazon S3.
26//! It is an abstraction on common methods (like fetching, creating, listing, etc.) called a "storage service"
27//! where it implements a set of methods that is commonly used in applications.
28//!
29//! **Warning** โ All code in the repository is VERY EXPERIMENTAL and things can break at anytime &
30//! be removed without any notice.
31//!
32//! ## Projects using `remi-rs`
33//! - [๐ฆ **charted-server**](https://github.com/charted-dev/charted)
34//! - [๐ชถ **Hazel**](https://github.com/Noelware/hazel)
35//! - [๐พ **ume**](https://github.com/auguwu/ume)
36//!
37//! ## Official Crates
38//! - [**remi-gridfs**](https://crates.io/crates/remi-gridfs)
39//! - [**remi-azure**](https://crates.io/crates/remi-azure)
40//! - [**remi-s3**](https://crates.io/crates/remi-s3)
41//! - [**remi-fs**](https://crates.io/crates/remi-fs)
42
43#![doc(html_logo_url = "https://cdn.floofy.dev/images/trans.png")]
44#![doc(html_favicon_url = "https://cdn.floofy.dev/images/trans.png")]
45#![cfg_attr(any(noeldoc, docsrs), feature(doc_cfg))]
46
47use std::{borrow::Cow, path::Path};
48
49// re-export (just in case!~)
50#[doc(hidden)]
51pub use async_trait::async_trait;
52
53#[doc(hidden)]
54pub use bytes::Bytes;
55
56mod blob;
57mod options;
58
59pub use blob::*;
60pub use options::*;
61
62/// A storage service is a base primitive of `remi-rs`: it is the way to interact
63/// with the storage providers in ways that you would commonly use files: open, deleting,
64/// listing, etc.
65#[async_trait]
66pub trait StorageService: Send + Sync {
67 /// Represents a generic error to use for errors that could be emitted
68 /// when calling any function.
69 type Error;
70
71 /// Returns the name of the storage service.
72 ///
73 /// * since 0.1.0
74 fn name(&self) -> Cow<'static, str>
75 where
76 Self: Sized;
77
78 /// Optionally initialize this [`StorageService`] if it requires initialization,
79 /// like creating a directory if it doesn't exist.
80 ///
81 /// * since 0.1.0
82 async fn init(&self) -> Result<(), Self::Error>
83 where
84 Self: Sized,
85 {
86 Ok(())
87 }
88
89 /// Opens a file in the specified `path` and returns the contents as [`Bytes`] if it existed, otherwise
90 /// `None` will be returned to indicate that file doesn't exist.
91 ///
92 /// * since 0.1.0
93 async fn open<P: AsRef<Path> + Send>(&self, path: P) -> Result<Option<Bytes>, Self::Error>
94 where
95 Self: Sized;
96
97 /// Open a file in the given `path` and returns a [`Blob`] structure if the path existed, otherwise
98 /// `None` will be returned to indiciate that a file doesn't exist.
99 ///
100 /// * since 0.1.0
101 async fn blob<P: AsRef<Path> + Send>(&self, path: P) -> Result<Option<Blob>, Self::Error>
102 where
103 Self: Sized;
104
105 /// Iterate over a list of files from a storage service and returns a [`Vec`] of [`Blob`]s.
106 ///
107 /// * since 0.1.0
108 async fn blobs<P: AsRef<Path> + Send>(
109 &self,
110 path: Option<P>,
111 options: Option<ListBlobsRequest>,
112 ) -> Result<Vec<Blob>, Self::Error>
113 where
114 Self: Sized;
115
116 /// Deletes a file in a specified `path`. At the moment, `()` is returned but `bool` might be
117 /// returned to indicate if it actually deleted itself or not.
118 ///
119 /// * since 0.1.0
120 async fn delete<P: AsRef<Path> + Send>(&self, path: P) -> Result<(), Self::Error>
121 where
122 Self: Sized;
123
124 /// Checks the existence of the file by the specified path.
125 ///
126 /// * since: 0.1.0
127 async fn exists<P: AsRef<Path> + Send>(&self, path: P) -> Result<bool, Self::Error>
128 where
129 Self: Sized;
130
131 /// Does a file upload where it writes the byte array as one call and does not do chunking.
132 ///
133 /// * since: 0.1.0
134 async fn upload<P: AsRef<Path> + Send>(&self, path: P, options: UploadRequest) -> Result<(), Self::Error>
135 where
136 Self: Sized;
137
138 #[cfg(feature = "unstable")]
139 #[cfg_attr(any(noeldoc, docsrs), doc(cfg(feature = "unstable")))]
140 /// Performs any healthchecks to determine the storage service's health.
141 async fn healthcheck(&self) -> Result<(), Self::Error> {
142 Ok(())
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use crate::StorageService;
149
150 const _DYN_STORAGE_SERVICE: Option<&dyn StorageService<Error = ()>> = None;
151}