You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-16 06:10:26 +02:00
Add CXX tutorial (#1392)
Add a number of slides that cover most of CXX's functionality and demonstrate how it can be used. Fixes #823. --------- Co-authored-by: Martin Geisler <mgeisler@google.com>
This commit is contained in:
55
third_party/cxx/blobstore/src/blobstore.cc
vendored
Normal file
55
third_party/cxx/blobstore/src/blobstore.cc
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
#include "include/blobstore.h"
|
||||
#include "main.rs.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
namespace org {
|
||||
namespace blobstore {
|
||||
|
||||
BlobstoreClient::BlobstoreClient() {}
|
||||
|
||||
// Upload a new blob and return a blobid that serves as a handle to the blob.
|
||||
uint64_t BlobstoreClient::put(MultiBuf &buf) {
|
||||
std::string contents;
|
||||
|
||||
// Traverse the caller's chunk iterator.
|
||||
//
|
||||
// In reality there might be sophisticated batching of chunks and/or parallel
|
||||
// upload implemented by the blobstore's C++ client.
|
||||
while (true) {
|
||||
auto chunk = next_chunk(buf);
|
||||
if (chunk.size() == 0) {
|
||||
break;
|
||||
}
|
||||
contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
|
||||
}
|
||||
|
||||
// Insert into map and provide caller the handle.
|
||||
auto blobid = std::hash<std::string>{}(contents);
|
||||
blobs[blobid] = {std::move(contents), {}};
|
||||
return blobid;
|
||||
}
|
||||
|
||||
// Add tag to an existing blob.
|
||||
void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) {
|
||||
blobs[blobid].tags.emplace(tag);
|
||||
}
|
||||
|
||||
// Retrieve metadata about a blob.
|
||||
BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
|
||||
BlobMetadata metadata{};
|
||||
auto blob = blobs.find(blobid);
|
||||
if (blob != blobs.end()) {
|
||||
metadata.size = blob->second.data.size();
|
||||
std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
|
||||
[&](auto &t) { metadata.tags.emplace_back(t); });
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobstoreClient> new_blobstore_client() {
|
||||
return std::make_unique<BlobstoreClient>();
|
||||
}
|
||||
|
||||
} // namespace blobstore
|
||||
} // namespace org
|
69
third_party/cxx/blobstore/src/main.rs
vendored
Normal file
69
third_party/cxx/blobstore/src/main.rs
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
//! Example project demonstrating usage of CXX.
|
||||
// ANCHOR: bridge
|
||||
#[allow(unsafe_op_in_unsafe_fn)]
|
||||
#[cxx::bridge(namespace = "org::blobstore")]
|
||||
mod ffi {
|
||||
// Shared structs with fields visible to both languages.
|
||||
struct BlobMetadata {
|
||||
size: usize,
|
||||
tags: Vec<String>,
|
||||
}
|
||||
|
||||
// ANCHOR: rust_bridge
|
||||
// Rust types and signatures exposed to C++.
|
||||
extern "Rust" {
|
||||
type MultiBuf;
|
||||
|
||||
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
|
||||
}
|
||||
// ANCHOR_END: rust_bridge
|
||||
|
||||
// ANCHOR: cpp_bridge
|
||||
// C++ types and signatures exposed to Rust.
|
||||
unsafe extern "C++" {
|
||||
include!("include/blobstore.h");
|
||||
|
||||
type BlobstoreClient;
|
||||
|
||||
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
|
||||
fn put(self: Pin<&mut BlobstoreClient>, parts: &mut MultiBuf) -> u64;
|
||||
fn tag(self: Pin<&mut BlobstoreClient>, blobid: u64, tag: &str);
|
||||
fn metadata(&self, blobid: u64) -> BlobMetadata;
|
||||
}
|
||||
// ANCHOR_END: cpp_bridge
|
||||
}
|
||||
// ANCHOR_END: bridge
|
||||
|
||||
/// An iterator over contiguous chunks of a discontiguous file object.
|
||||
///
|
||||
/// Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
|
||||
/// over some more complex Rust data structure like a rope, or maybe loading
|
||||
/// chunks lazily from somewhere.
|
||||
pub struct MultiBuf {
|
||||
chunks: Vec<Vec<u8>>,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
/// Pulls the next chunk from the buffer.
|
||||
pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
|
||||
let next = buf.chunks.get(buf.pos);
|
||||
buf.pos += 1;
|
||||
next.map_or(&[], Vec::as_slice)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut client = ffi::new_blobstore_client();
|
||||
|
||||
// Upload a blob.
|
||||
let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
|
||||
let mut buf = MultiBuf { chunks, pos: 0 };
|
||||
let blobid = client.pin_mut().put(&mut buf);
|
||||
println!("blobid = {}", blobid);
|
||||
|
||||
// Add a tag.
|
||||
client.pin_mut().tag(blobid, "rust");
|
||||
|
||||
// Read back the tags.
|
||||
let metadata = client.metadata(blobid);
|
||||
println!("tags = {:?}", metadata.tags);
|
||||
}
|
Reference in New Issue
Block a user