| #include "demo/include/blobstore.h" | 
 | #include "demo/src/main.rs.h" | 
 | #include <algorithm> | 
 | #include <functional> | 
 | #include <set> | 
 | #include <string> | 
 | #include <unordered_map> | 
 |  | 
 | namespace org { | 
 | namespace blobstore { | 
 |  | 
 | // Toy implementation of an in-memory blobstore. | 
 | // | 
 | // In reality the implementation of BlobstoreClient could be a large complex C++ | 
 | // library. | 
 | class BlobstoreClient::impl { | 
 |   friend BlobstoreClient; | 
 |   using Blob = struct { | 
 |     std::string data; | 
 |     std::set<std::string> tags; | 
 |   }; | 
 |   std::unordered_map<uint64_t, Blob> blobs; | 
 | }; | 
 |  | 
 | BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} | 
 |  | 
 | // Upload a new blob and return a blobid that serves as a handle to the blob. | 
 | uint64_t BlobstoreClient::put(MultiBuf &buf) const { | 
 |   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); | 
 |   impl->blobs[blobid] = {std::move(contents), {}}; | 
 |   return blobid; | 
 | } | 
 |  | 
 | // Add tag to an existing blob. | 
 | void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { | 
 |   impl->blobs[blobid].tags.emplace(tag); | 
 | } | 
 |  | 
 | // Retrieve metadata about a blob. | 
 | BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { | 
 |   BlobMetadata metadata{}; | 
 |   auto blob = impl->blobs.find(blobid); | 
 |   if (blob != impl->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 |