-
Notifications
You must be signed in to change notification settings - Fork 4
/
lib.rs
70 lines (60 loc) · 2.02 KB
/
lib.rs
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
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::pin::Pin;
use ffi::*;
#[cxx::bridge(namespace = "org::blobstore")]
mod ffi {
// Shared structs with fields visible to both languages.
struct BlobMetadata {
size: usize,
tags: Vec<String>,
}
// Rust types and signatures exposed to C++.
extern "Rust" {
type BlobstoreClient;
fn new_blobstore_client() -> Box<BlobstoreClient>;
fn put(&mut self, parts: Pin<&mut MultiBuf>) -> u64;
fn tag(&mut self, blobid: u64, tag: String);
fn metadata(&self, blobid: u64) -> BlobMetadata;
}
// C++ types and signatures exposed to Rust.
unsafe extern "C++" {
include!("multibuf.h");
type MultiBuf;
fn has_more_chunks(&self) -> bool;
fn next_chunk(self: Pin<&mut MultiBuf>) -> Pin<&mut CxxVector<u8>>;
}
}
fn new_blobstore_client() -> Box<BlobstoreClient> {
Box::new(BlobstoreClient { blobs: HashMap::new() })
}
struct Blob {
data: Vec<u8>,
tags: HashSet<String>,
}
struct BlobstoreClient {
blobs: HashMap<u64, Blob>,
}
impl BlobstoreClient {
fn put(&mut self, mut parts: Pin<&mut MultiBuf>) -> u64 {
let mut contents = Vec::<u8>::new();
while parts.has_more_chunks() {
let chunk = parts.as_mut().next_chunk();
contents.extend_from_slice(chunk.as_ref().as_slice());
}
let mut hasher = DefaultHasher::new();
contents.hash(&mut hasher);
let hash = hasher.finish();
self.blobs.insert(hash, Blob { data: contents, tags: HashSet::new() });
hash
}
fn tag(&mut self, blobid: u64, tag: String) {
self.blobs.get_mut(&blobid).unwrap().tags.insert(tag);
}
// Retrieve metadata about a blob.
fn metadata(&self, blobid: u64) -> BlobMetadata {
let blob = self.blobs.get(&blobid).unwrap();
BlobMetadata { size: blob.data.len(), tags: blob.tags.clone().into_iter().collect() }
}
}