133d722a9Sopenharmony_ci#[cxx::bridge(namespace = "org::blobstore")]
233d722a9Sopenharmony_cimod ffi {
333d722a9Sopenharmony_ci    // Shared structs with fields visible to both languages.
433d722a9Sopenharmony_ci    struct BlobMetadata {
533d722a9Sopenharmony_ci        size: usize,
633d722a9Sopenharmony_ci        tags: Vec<String>,
733d722a9Sopenharmony_ci    }
833d722a9Sopenharmony_ci
933d722a9Sopenharmony_ci    // Rust types and signatures exposed to C++.
1033d722a9Sopenharmony_ci    extern "Rust" {
1133d722a9Sopenharmony_ci        type MultiBuf;
1233d722a9Sopenharmony_ci
1333d722a9Sopenharmony_ci        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
1433d722a9Sopenharmony_ci    }
1533d722a9Sopenharmony_ci
1633d722a9Sopenharmony_ci    // C++ types and signatures exposed to Rust.
1733d722a9Sopenharmony_ci    unsafe extern "C++" {
1833d722a9Sopenharmony_ci        include!("demo/include/blobstore.h");
1933d722a9Sopenharmony_ci
2033d722a9Sopenharmony_ci        type BlobstoreClient;
2133d722a9Sopenharmony_ci
2233d722a9Sopenharmony_ci        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
2333d722a9Sopenharmony_ci        fn put(&self, parts: &mut MultiBuf) -> u64;
2433d722a9Sopenharmony_ci        fn tag(&self, blobid: u64, tag: &str);
2533d722a9Sopenharmony_ci        fn metadata(&self, blobid: u64) -> BlobMetadata;
2633d722a9Sopenharmony_ci    }
2733d722a9Sopenharmony_ci}
2833d722a9Sopenharmony_ci
2933d722a9Sopenharmony_ci// An iterator over contiguous chunks of a discontiguous file object.
3033d722a9Sopenharmony_ci//
3133d722a9Sopenharmony_ci// Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
3233d722a9Sopenharmony_ci// over some more complex Rust data structure like a rope, or maybe loading
3333d722a9Sopenharmony_ci// chunks lazily from somewhere.
3433d722a9Sopenharmony_cipub struct MultiBuf {
3533d722a9Sopenharmony_ci    chunks: Vec<Vec<u8>>,
3633d722a9Sopenharmony_ci    pos: usize,
3733d722a9Sopenharmony_ci}
3833d722a9Sopenharmony_cipub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
3933d722a9Sopenharmony_ci    let next = buf.chunks.get(buf.pos);
4033d722a9Sopenharmony_ci    buf.pos += 1;
4133d722a9Sopenharmony_ci    next.map_or(&[], Vec::as_slice)
4233d722a9Sopenharmony_ci}
4333d722a9Sopenharmony_ci
4433d722a9Sopenharmony_cifn main() {
4533d722a9Sopenharmony_ci    let client = ffi::new_blobstore_client();
4633d722a9Sopenharmony_ci
4733d722a9Sopenharmony_ci    // Upload a blob.
4833d722a9Sopenharmony_ci    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
4933d722a9Sopenharmony_ci    let mut buf = MultiBuf { chunks, pos: 0 };
5033d722a9Sopenharmony_ci    let blobid = client.put(&mut buf);
5133d722a9Sopenharmony_ci    println!("blobid = {}", blobid);
5233d722a9Sopenharmony_ci
5333d722a9Sopenharmony_ci    // Add a tag.
5433d722a9Sopenharmony_ci    client.tag(blobid, "rust");
5533d722a9Sopenharmony_ci
5633d722a9Sopenharmony_ci    // Read back the tags.
5733d722a9Sopenharmony_ci    let metadata = client.metadata(blobid);
5833d722a9Sopenharmony_ci    println!("tags = {:?}", metadata.tags);
5933d722a9Sopenharmony_ci}
60