1use std::collections::HashMap;
2use std::fmt::Formatter;
3use std::io;
4use std::ops::Bound;
5use std::path::Path;
6use std::sync::Arc;
7use std::{fmt, fs};
8
9use anyhow::Result;
10
11use async_trait::async_trait;
12
13use bytes::Bytes;
14
15use futures::Stream;
16
17use serde::{Deserialize, Serialize};
18use time::OffsetDateTime;
19
20fn file_to_base64<P: AsRef<Path>>(path: P) -> Result<String> {
21 Ok(base64::encode(fs::read(path.as_ref())?))
22}
23
24#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
25#[serde(deny_unknown_fields)]
26pub struct CertificateInfo {
27 pub certificate_b64: String,
28 pub private_key_b64: String,
29}
30
31impl CertificateInfo {
32 pub fn from_path<P: AsRef<Path>, Q: AsRef<Path>>(
33 certificate_path: P,
34 private_key_path: Q,
35 ) -> Result<CertificateInfo> {
36 Ok(Self {
37 certificate_b64: file_to_base64(certificate_path)?,
38 private_key_b64: file_to_base64(private_key_path)?,
39 })
40 }
41}
42
43#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
45#[serde(deny_unknown_fields)]
46pub struct BlobMetaRequest {
47 pub fields: HashMap<String, FieldValue>,
49
50 pub tags: Vec<String>,
52}
53
54impl BlobMetaRequest {
55 pub fn new() -> Self {
56 Self::default()
57 }
58
59 #[must_use]
60 pub fn with_field<S: Into<String>, T: Into<FieldValue>>(mut self, key: S, value: T) -> Self {
61 self.fields.insert(key.into(), value.into());
62 self
63 }
64
65 #[must_use]
66 pub fn with_tag<S: Into<String>>(mut self, s: S) -> Self {
67 self.tags.push(s.into());
68 self
69 }
70
71 pub fn into_meta(
72 self,
73 created_at: OffsetDateTime,
74 modified_at: OffsetDateTime,
75 size: u64,
76 ) -> BlobMeta {
77 BlobMeta {
78 fields: self.fields,
79 tags: self.tags,
80 size,
81 created_at,
82 modified_at,
83 }
84 }
85}
86
87#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
88#[serde(untagged)]
89pub enum FieldValue {
90 Str(String),
91 Numeric(i64),
92}
93
94#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
95pub enum TaggedFieldValue {
96 Str(String),
97 Numeric(i64),
98}
99
100impl From<FieldValue> for TaggedFieldValue {
101 fn from(v: FieldValue) -> Self {
102 match v {
103 FieldValue::Str(s) => TaggedFieldValue::Str(s),
104 FieldValue::Numeric(i) => TaggedFieldValue::Numeric(i),
105 }
106 }
107}
108
109impl From<TaggedFieldValue> for FieldValue {
110 fn from(v: TaggedFieldValue) -> Self {
111 match v {
112 TaggedFieldValue::Str(s) => FieldValue::Str(s),
113 TaggedFieldValue::Numeric(i) => FieldValue::Numeric(i),
114 }
115 }
116}
117
118impl From<String> for FieldValue {
119 fn from(v: String) -> Self {
120 Self::Str(v)
121 }
122}
123
124impl From<&str> for FieldValue {
125 fn from(v: &str) -> Self {
126 Self::Str(String::from(v))
127 }
128}
129
130impl From<&String> for FieldValue {
131 fn from(v: &String) -> Self {
132 Self::Str(String::from(v))
133 }
134}
135
136impl From<i64> for FieldValue {
137 fn from(v: i64) -> Self {
138 Self::Numeric(v)
139 }
140}
141
142impl fmt::Display for FieldValue {
143 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
144 match self {
145 Self::Str(s) => write!(f, "\"{}\"", s),
146 Self::Numeric(i) => write!(f, "{}", i),
147 }
148 }
149}
150
151#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
153#[serde(deny_unknown_fields)]
154pub struct BlobMeta {
155 pub fields: HashMap<String, FieldValue>,
157
158 pub tags: Vec<String>,
160
161 pub size: u64,
163
164 #[serde(with = "time::serde::rfc3339")]
166 pub created_at: OffsetDateTime,
167
168 #[serde(with = "time::serde::rfc3339")]
170 pub modified_at: OffsetDateTime,
171}
172
173impl From<BlobMeta> for BlobMetaRequest {
174 fn from(m: BlobMeta) -> Self {
175 Self {
176 fields: m.fields,
177 tags: m.tags,
178 }
179 }
180}
181
182impl Default for BlobMeta {
183 fn default() -> Self {
184 Self {
185 fields: Default::default(),
186 tags: Default::default(),
187 size: 0,
188 created_at: OffsetDateTime::now_utc(),
189 modified_at: OffsetDateTime::now_utc(),
190 }
191 }
192}
193
194impl BlobMeta {
195 pub fn new() -> Self {
196 Self::default()
197 }
198
199 #[must_use]
200 pub fn with_field<S: Into<String>, T: Into<FieldValue>>(mut self, key: S, value: T) -> Self {
201 self.fields.insert(key.into(), value.into());
202 self
203 }
204
205 #[must_use]
206 pub fn with_tag<S: Into<String>>(mut self, s: S) -> Self {
207 self.tags.push(s.into());
208 self
209 }
210
211 #[must_use]
212 pub fn with_size(mut self, size: u64) -> Self {
213 self.size = size;
214 self
215 }
216}
217
218#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
223#[serde(deny_unknown_fields)]
224pub struct TaggedBlobMeta {
225 pub fields: HashMap<String, TaggedFieldValue>,
227
228 pub tags: Vec<String>,
230
231 pub size: u64,
233
234 #[serde(with = "crate::timestamp_nanos")]
236 pub created_at: OffsetDateTime,
237
238 #[serde(with = "crate::timestamp_nanos")]
240 pub modified_at: OffsetDateTime,
241}
242
243impl From<BlobMeta> for TaggedBlobMeta {
244 fn from(m: BlobMeta) -> Self {
245 Self {
246 fields: m
247 .fields
248 .into_iter()
249 .map(|(k, v)| (k, v.into()))
250 .collect::<HashMap<_, _>>(),
251 tags: m.tags,
252 size: m.size,
253 created_at: m.created_at,
254 modified_at: m.modified_at,
255 }
256 }
257}
258
259impl From<TaggedBlobMeta> for BlobMeta {
260 fn from(m: TaggedBlobMeta) -> Self {
261 Self {
262 fields: m
263 .fields
264 .into_iter()
265 .map(|(k, v)| (k, v.into()))
266 .collect::<HashMap<_, _>>(),
267 tags: m.tags,
268 size: m.size,
269 created_at: m.created_at,
270 modified_at: m.modified_at,
271 }
272 }
273}
274
275#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
276#[serde(deny_unknown_fields)]
277pub struct BlobInfoRequest {
278 pub meta_request: BlobMetaRequest,
279 pub owner: String,
280 pub size: u64,
281}
282
283impl BlobInfoRequest {
284 pub fn into_blob_info(
285 self,
286 created_at: OffsetDateTime,
287 modified_at: OffsetDateTime,
288 ) -> BlobInfo {
289 BlobInfo {
290 meta: self
291 .meta_request
292 .into_meta(created_at, modified_at, self.size),
293 owner: self.owner,
294 }
295 }
296}
297
298#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
299#[serde(deny_unknown_fields)]
300pub struct BlobInfo {
301 pub meta: BlobMeta,
302 pub owner: String,
303}
304
305#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
306#[serde(deny_unknown_fields)]
307pub struct TaggedBlobInfo {
308 pub meta: TaggedBlobMeta,
309 pub owner: String,
310}
311
312impl From<BlobInfo> for TaggedBlobInfo {
313 fn from(v: BlobInfo) -> Self {
314 Self {
315 meta: v.meta.into(),
316 owner: v.owner,
317 }
318 }
319}
320
321impl From<TaggedBlobInfo> for BlobInfo {
322 fn from(v: TaggedBlobInfo) -> Self {
323 Self {
324 meta: v.meta.into(),
325 owner: v.owner,
326 }
327 }
328}
329
330pub struct Blob {
331 pub stream: Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send>,
332 pub current_chunk_size: u64,
333 pub total_blob_size: u64,
334 pub info: BlobInfo,
335}
336
337#[async_trait]
338pub trait StorageNode {
339 async fn put(
340 &self,
341 id: String,
342 info: BlobInfoRequest,
343 stream: Option<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync + Unpin>>,
344 ) -> Result<()>;
345
346 async fn write(
347 &self,
348 id: String,
349 range: (Bound<u64>, Bound<u64>),
350 bytes: Bytes,
351 username: &str,
352 ) -> Result<()>;
353
354 async fn get(&self, blob_id: String, range: Option<(Bound<u64>, Bound<u64>)>) -> Result<Blob>;
355
356 async fn update_meta(&self, blob_id: String, info: BlobInfoRequest) -> Result<()>;
357
358 async fn delete(&self, blob_id: String, username: &str) -> Result<()>;
359
360 async fn get_certificates(&self) -> Option<CertificateInfo>;
361
362 async fn fsync(&self, blob_id: String, username: &str) -> Result<()>;
363
364 async fn flush(&self) -> Result<()>;
365}
366
367pub type DynStorageNode = Arc<dyn StorageNode + Send + Sync>;