1use serde::{Deserialize, Serialize};
4
5pub const DEFAULT_CONTENT_TYPE: &str = "application/octet-stream";
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ObjectMeta {
11 pub key: String,
12 pub size: usize,
13 pub content_type: String,
14 pub etag: String,
16 #[serde(default)]
17 pub metadata: serde_json::Value,
18}
19
20#[derive(Debug, thiserror::Error)]
22pub enum ObjectError {
23 #[error("bucket '{0}' not found")]
24 BucketNotFound(String),
25 #[error("bucket '{0}' already exists")]
26 BucketExists(String),
27 #[error("object '{0}' not found")]
28 ObjectNotFound(String),
29 #[error("invalid bucket name '{0}'")]
30 InvalidBucketName(String),
31}
32
33pub fn etag_of(data: &[u8]) -> String {
35 let mut h: u64 = 0xcbf2_9ce4_8422_2325;
36 for &b in data {
37 h ^= b as u64;
38 h = h.wrapping_mul(0x0000_0100_0000_01b3);
39 }
40 format!("{h:016x}")
41}
42
43pub fn valid_bucket_name(name: &str) -> bool {
45 !name.is_empty()
46 && name.len() <= 63
47 && name
48 .bytes()
49 .all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'.' || b == b'-')
50}