binarystore: Initial implementation

Dummy BinaryStore class implementation where most functions just return.
Implement getBaseBlobId/getBlobIds/canHandleBlobId and add unit tests
using real objects.

Signed-off-by: Kun Yi <kunyi@google.com>
Change-Id: Iaf8c59f3c4b1bab9de186333074a9cd0160a5764
diff --git a/binarystore.hpp b/binarystore.hpp
index 11ca241..a54eaf5 100644
--- a/binarystore.hpp
+++ b/binarystore.hpp
@@ -1,6 +1,9 @@
 #pragma once
 
+#include <unistd.h>
+
 #include <cstdint>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -15,25 +18,139 @@
 
 /**
  * @class BinaryStoreInterface is an abstraction for a storage location.
- *        Each instance would be uniquely identified by a baseId string.
+ *     Each instance would be uniquely identified by a baseId string.
  */
 class BinaryStoreInterface
 {
   public:
     virtual ~BinaryStoreInterface() = default;
 
+    /**
+     * @returns baseId string of the storage.
+     */
     virtual std::string getBaseBlobId() const = 0;
+
+    /**
+     * @returns List of all open blob IDs, plus the base.
+     */
     virtual std::vector<std::string> getBlobIds() const = 0;
-    virtual bool canHandleBlob(const std::string& blobId) const = 0;
+
+    /**
+     * Opens a blob given its name. If there is no one, create one.
+     * @param blobId: The blob id to operate on.
+     * @param flags: Either read flag or r/w flag has to be specified.
+     * @returns True if open/create successfully.
+     */
     virtual bool openOrCreateBlob(const std::string& blobId,
                                   uint16_t flags) = 0;
+
+    /**
+     * Deletes a blob given its name. If there is no one,
+     * @param blobId: The blob id to operate on.
+     * @returns True if deleted.
+     */
     virtual bool deleteBlob(const std::string& blobId) = 0;
+
+    /**
+     * Reads data from the currently opened blob.
+     * @param offset: offset into the blob to read
+     * @param requestedSize: how many bytes to read
+     * @returns Bytes able to read. Returns empty if nothing can be read or
+     *          if there is no open blob.
+     */
     virtual std::vector<uint8_t> read(uint32_t offset,
                                       uint32_t requestedSize) = 0;
+
+    /**
+     * Writes data to the currently openend blob.
+     * @param offset: offset into the blob to write
+     * @param data: bytes to write
+     * @returns True if able to write the entire data successfully
+     */
     virtual bool write(uint32_t offset, const std::vector<uint8_t>& data) = 0;
+
+    /**
+     * TODO
+     */
     virtual bool commit() = 0;
+
+    /**
+     * TODO
+     */
     virtual bool close() = 0;
+
+    /**
+     * TODO
+     */
     virtual bool stat() = 0;
 };
 
+// TODO: move to protobuf definition
+struct BinaryBlobSingle
+{
+    std::string id;
+    std::vector<uint8_t> data;
+};
+
+struct BinaryBlob
+{
+    std::string baseBlobId;
+    std::vector<BinaryBlobSingle> blobs;
+};
+
+/**
+ * @class BinaryStore instantiates a concrete implementation of
+ *     BinaryStoreInterface. The dependency on file is injected through its
+ *     constructor.
+ */
+class BinaryStore : public BinaryStoreInterface
+{
+  public:
+    BinaryStore(const std::string& baseBlobId, int fd, uint32_t offset,
+                uint32_t maxSize) :
+        baseBlobId_(baseBlobId),
+        fd_(fd), offset_(offset), maxSize_(maxSize)
+    {
+    }
+
+    BinaryStore() = delete;
+    ~BinaryStore() = default;
+    BinaryStore(const BinaryStore&) = delete;
+    BinaryStore& operator=(const BinaryStore&) = delete;
+    BinaryStore(BinaryStore&&) = default;
+    BinaryStore& operator=(BinaryStore&&) = default;
+
+    std::string getBaseBlobId() const override;
+    std::vector<std::string> getBlobIds() const override;
+    bool openOrCreateBlob(const std::string& blobId, uint16_t flags) override;
+    bool deleteBlob(const std::string& blobId) override;
+    std::vector<uint8_t> read(uint32_t offset, uint32_t requestedSize) override;
+    bool write(uint32_t offset, const std::vector<uint8_t>& data) override;
+    bool commit() override;
+    bool close() override;
+    bool stat() override;
+
+    /**
+     * Helper factory method to create a BinaryStore instance
+     * @param baseBlobId: base id for the created instance
+     * @param sysfilePath: path to the storage location
+     * @param offset: offset into the file for serializing the final blob
+     * @param maxSize: max size in bytes that this BinaryStore can expand to.
+     *     Writing data more than allowed size will return failure.
+     * @returns unique_ptr to constructed BinaryStore. Caller should take
+     *     ownership of the instance.
+     */
+    static std::unique_ptr<BinaryStoreInterface>
+        createFromConfig(const std::string& baseBlobId,
+                         const std::string& sysfilePath, uint32_t offset,
+                         uint32_t maxSize);
+
+  private:
+    std::string baseBlobId_;
+    int fd_;
+    uint32_t offset_;
+    uint32_t maxSize_;
+    BinaryBlob blob_;
+};
+
 } // namespace binstore