1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::fmt::{self, Debug, Formatter};
use std::io;
use bytes::Bytes;
use futures::{stream, Stream};
use std::pin::Pin;
type ByteStream = Pin<Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static>>;
pub struct Blob {
key: String,
size: usize,
content_stream: ByteStream,
}
impl Blob {
pub fn new<K: ToString, S: Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static>(
key: K,
size: usize,
stream: S,
) -> Self {
Self {
key: key.to_string(),
size,
content_stream: Box::pin(stream),
}
}
pub fn from_bytes<K: ToString>(key: K, content: Vec<u8>) -> Self {
Self::new(
key,
content.len(),
stream::once(async move { Ok(Bytes::from(content)) }),
)
}
pub fn empty<K: ToString>(key: K, size: usize) -> Self {
Self::new(key, size, stream::empty())
}
pub fn key(&self) -> &str {
&self.key
}
pub fn size(&self) -> usize {
self.size
}
pub fn into_byte_stream(self) -> impl Stream<Item = Result<Bytes, io::Error>> {
self.content_stream
}
}
impl Debug for Blob {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Blob")
.field("key", &self.key)
.field("size", &self.size)
.finish()
}
}
#[cfg(test)]
mod test {
use rand::Rng;
use crate::blob::Blob;
#[test]
fn it_builds_a_new_blob() {
let bytes = rand::thread_rng().gen::<[u8; 32]>().to_vec();
let blob = Blob::from_bytes(String::from("key"), bytes.clone());
assert_eq!(blob.key(), "key");
assert_eq!(blob.size(), bytes.len());
}
}