remotefs_gcs/lib.rs
1//! # `remotefs-gcs`
2//!
3//! An asynchronous [`remotefs::AsyncRemoteFs`] client backed by Google Cloud
4//! Storage. Every path is absolute and rooted at the bucket (`/` is the
5//! bucket root); trailing-slash marker objects and implicit object prefixes
6//! are presented as directories.
7//!
8//! ## Installation
9//!
10//! ```toml
11//! [dependencies]
12//! remotefs = "1"
13//! remotefs-gcs = "1"
14//! futures = "0.3"
15//! tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
16//! ```
17//!
18//! | Feature | Default | Purpose |
19//! | ----------------- | :-----: | ----------------------------------------------------------- |
20//! | `find` | yes | Enables `remotefs::find_async` |
21//! | `no-log` | no | Disables logging from this crate |
22//! | `tokio` | no | Enables `BlockingGoogleCloudStorageFs` for blocking callers |
23//! | `with-containers` | no | Enables the local testbench integration suite |
24//! | `with-gcs-ci` | no | Enables the optional live smoke test |
25//!
26//! ## Application Default Credentials
27//!
28//! [`GoogleCloudStorageFs::new`] uses Application Default Credentials (ADC):
29//!
30//! ```rust,no_run
31//! use std::path::Path;
32//!
33//! use remotefs::AsyncRemoteFs;
34//! use remotefs::fs::{ReadOptions, WriteOptions};
35//! use remotefs_gcs::GoogleCloudStorageFs;
36//!
37//! # async fn run() -> remotefs::RemoteResult<()> {
38//! let mut client = GoogleCloudStorageFs::new("my-bucket");
39//! client.connect().await?;
40//! let mut source = futures::io::Cursor::new(b"hello".to_vec());
41//! client
42//! .write_file(
43//! Path::new("/docs/hello.txt"),
44//! &WriteOptions::default().size_hint(5),
45//! &mut source,
46//! )
47//! .await?;
48//! let mut destination = futures::io::Cursor::new(Vec::new());
49//! client
50//! .read_file(
51//! Path::new("/docs/hello.txt"),
52//! &ReadOptions::default().offset(1).length(3),
53//! &mut destination,
54//! )
55//! .await?;
56//! assert_eq!(destination.into_inner(), b"ell");
57//! client.disconnect().await?;
58//! # Ok(())
59//! # }
60//! ```
61//!
62//! ## Explicit credentials
63//!
64//! Use [`GoogleCloudStorageCredentials::custom`] to pass any credentials
65//! provider supported by `google-cloud-auth`:
66//!
67//! ```rust,no_run
68//! use remotefs::AsyncRemoteFs;
69//! use remotefs_gcs::credentials::Builder;
70//! use remotefs_gcs::{GoogleCloudStorageCredentials, GoogleCloudStorageFs};
71//!
72//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
73//! let credentials = Builder::default().build()?;
74//! let mut client = GoogleCloudStorageFs::with_credentials(
75//! "my-bucket",
76//! GoogleCloudStorageCredentials::custom(credentials),
77//! );
78//! client.connect().await?;
79//! client.disconnect().await?;
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! [`GoogleCloudStorageCredentials::anonymous`] is useful for public buckets
85//! and local emulators. Pair it with [`GoogleCloudStorageFs::endpoint`] when
86//! the service is not running at Google's default endpoint, and
87//! [`GoogleCloudStorageFs::control_endpoint`] for emulators with separate
88//! object-data and metadata endpoints.
89//!
90//! ## Blocking usage
91//!
92//! Enable the `tokio` feature and call [`GoogleCloudStorageFs::into_blocking`]
93//! to get a [`BlockingGoogleCloudStorageFs`], which implements
94//! [`remotefs::RemoteFs`] and can be stored as `Box<dyn RemoteFs>`. It must
95//! not be called from inside an async context. The supplied handle must belong
96//! to a multi-thread Tokio runtime.
97//!
98//! ```rust,no_run
99//! use remotefs::RemoteFs;
100//! use remotefs_gcs::GoogleCloudStorageFs;
101//!
102//! # #[cfg(feature = "tokio")]
103//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
104//! let runtime = tokio::runtime::Runtime::new()?;
105//! let mut client: Box<dyn RemoteFs> = Box::new(
106//! GoogleCloudStorageFs::new("my-bucket").into_blocking(runtime.handle().clone()),
107//! );
108//! client.connect()?;
109//! client.disconnect()?;
110//! # Ok(())
111//! # }
112//! # #[cfg(not(feature = "tokio"))]
113//! # fn main() {}
114//! ```
115//!
116//! ## Filesystem semantics
117//!
118//! The root directory `/` always exists and is never an object. `list_dir`
119//! consumes every page and merges objects with prefixes. `remove_dir_all`
120//! removes every object below its path with one flat listing.
121//!
122//! `open` returns an owned read stream over a ranged `ReadObject` request;
123//! offsets and lengths are honored natively (`Capabilities::RANGE_READ`).
124//! `create` returns an owned write stream that feeds a resumable upload; the
125//! object is committed only when `finish` succeeds, and a dropped stream
126//! creates nothing. `copy` uses rewrite requests until completion; `rename`
127//! copies and then deletes the source and is not atomic. `append`,
128//! `set_metadata`, `symlink`, and `exec` return
129//! [`remotefs::RemoteErrorType::UnsupportedFeature`].
130//!
131//! [`GoogleCloudStorageFs::new`]: client::GoogleCloudStorageFs::new
132//! [`GoogleCloudStorageFs::endpoint`]: client::GoogleCloudStorageFs::endpoint
133//! [`GoogleCloudStorageFs::control_endpoint`]:
134//! client::GoogleCloudStorageFs::control_endpoint
135//! [`GoogleCloudStorageFs::into_blocking`]:
136//! client::GoogleCloudStorageFs::into_blocking
137//! [`BlockingGoogleCloudStorageFs`]: client::BlockingGoogleCloudStorageFs
138//! [`GoogleCloudStorageCredentials::anonymous`]:
139//! credentials::GoogleCloudStorageCredentials::anonymous
140//! [`GoogleCloudStorageCredentials::custom`]:
141//! credentials::GoogleCloudStorageCredentials::custom
142
143#![doc(html_playground_url = "https://play.rust-lang.org")]
144#![doc(
145 html_favicon_url = "https://raw.githubusercontent.com/remotefs-rs/remotefs-rs/main/assets/logo-128.png"
146)]
147#![doc(
148 html_logo_url = "https://raw.githubusercontent.com/remotefs-rs/remotefs-rs/main/assets/logo.png"
149)]
150
151#[macro_use]
152extern crate log;
153
154pub mod backoff_policy;
155mod client;
156pub mod credentials;
157mod error;
158mod key;
159mod object;
160pub mod retry_policy;
161pub mod retry_throttler;
162mod stream;
163#[cfg(feature = "tokio")]
164#[doc(inline)]
165pub use client::BlockingGoogleCloudStorageFs;
166#[doc(inline)]
167pub use client::GoogleCloudStorageFs;
168#[doc(inline)]
169pub use credentials::GoogleCloudStorageCredentials;