#![cfg_attr(feature = "http", feature(impl_trait_in_assoc_type))]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(rust_2018_idioms)]
#![deny(unreachable_pub)]
#![warn(clippy::all, clippy::pedantic, clippy::cargo)]
#![allow(
clippy::module_name_repetitions,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::multiple_crate_versions,
clippy::cast_possible_truncation
)]
pub mod encoding;
pub mod error;
pub mod fenced;
pub mod join;
pub mod key;
pub mod local;
pub mod mem;
#[cfg(feature = "mirror")]
pub mod mirror;
pub mod net;
pub mod sse;
pub mod transport;
#[cfg(feature = "gcs")]
pub mod gcs;
#[cfg(feature = "http")]
pub mod http;
#[cfg(feature = "http")]
pub mod token;
#[cfg(feature = "testing")]
pub mod testing;
use std::future::Future;
use std::ops::Range;
pub use bytes::Bytes;
pub use encoding::{ContentEncoding, MAX_INFLATED_BYTES};
pub use error::{Error, Result};
pub use key::Key;
pub use local::LocalDir;
pub use mem::{Fault, Mem};
#[cfg(feature = "gcs")]
pub use gcs::{Gcs, GcsConfig};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Object {
pub bytes: Bytes,
pub generation: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Meta {
pub key: String,
pub size: u64,
pub generation: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Stat {
pub meta: Meta,
pub content_encoding: Option<ContentEncoding>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Cond {
#[default]
None,
CreateOnly,
IfGeneration(u64),
}
pub trait ObjectStore {
type Get<'a>: Future<Output = Result<Option<Object>>> + 'a
where
Self: 'a;
type GetRange<'a>: Future<Output = Result<Bytes>> + 'a
where
Self: 'a;
type Head<'a>: Future<Output = Result<Option<Meta>>> + 'a
where
Self: 'a;
type Put<'a>: Future<Output = Result<u64>> + 'a
where
Self: 'a;
type List<'a>: Future<Output = Result<Vec<Meta>>> + 'a
where
Self: 'a;
type Delete<'a>: Future<Output = Result<()>> + 'a
where
Self: 'a;
fn get<'a>(&'a self, key: &'a str) -> Self::Get<'a>;
fn get_range<'a>(&'a self, key: &'a str, range: Range<u64>) -> Self::GetRange<'a>;
fn head<'a>(&'a self, key: &'a str) -> Self::Head<'a>;
fn put<'a>(&'a self, key: &'a str, body: Bytes, cond: Cond) -> Self::Put<'a>;
fn list<'a>(&'a self, prefix: &'a str) -> Self::List<'a>;
fn delete<'a>(&'a self, key: &'a str) -> Self::Delete<'a>;
fn put_encoded<'a>(
&'a self,
key: &'a str,
body: Bytes,
cond: Cond,
encoding: ContentEncoding,
) -> impl Future<Output = Result<u64>> + 'a {
let _ = (key, body, cond);
std::future::ready(Err(Error::UnsupportedEncoding { encoding: encoding.as_str().into() }))
}
fn stat<'a>(&'a self, key: &'a str) -> impl Future<Output = Result<Option<Stat>>> + 'a {
let head = self.head(key);
async move { Ok(head.await?.map(|meta| Stat { meta, content_encoding: None })) }
}
fn list_stat<'a>(&'a self, prefix: &'a str) -> impl Future<Output = Result<Vec<Stat>>> + 'a {
let list = self.list(prefix);
async move {
Ok(list.await?.into_iter().map(|meta| Stat { meta, content_encoding: None }).collect())
}
}
}
pub(crate) fn clip(range: &Range<u64>, len: u64) -> Range<usize> {
let start = range.start.min(len);
let end = range.end.clamp(start, len);
start as usize..end as usize
}