#ifndef MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_H_
#define MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_H_
#include <stdint.h>
#include <optional>
#include <utility>
#include <vector>
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/checked_iterators.h"
#include "base/containers/heap_array.h"
#include "base/containers/span.h"
#include "base/memory/raw_span.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "mojo/public/cpp/system/buffer.h"
namespace mojo_base {
class BigBuffer;
class BigBufferView;
namespace internal {
class COMPONENT_EXPORT(MOJO_BASE) BigBufferSharedMemoryRegion {
public:
BigBufferSharedMemoryRegion();
BigBufferSharedMemoryRegion(mojo::ScopedSharedBufferHandle buffer_handle,
size_t size);
BigBufferSharedMemoryRegion(BigBufferSharedMemoryRegion&& other);
BigBufferSharedMemoryRegion(const BigBufferSharedMemoryRegion&) = delete;
BigBufferSharedMemoryRegion& operator=(const BigBufferSharedMemoryRegion&) =
delete;
~BigBufferSharedMemoryRegion();
BigBufferSharedMemoryRegion& operator=(BigBufferSharedMemoryRegion&& other);
void* memory() const { return buffer_mapping_.get(); }
size_t size() const { return size_; }
mojo::ScopedSharedBufferHandle TakeBufferHandle();
private:
friend class mojo_base::BigBuffer;
friend class mojo_base::BigBufferView;
size_t size_;
mojo::ScopedSharedBufferHandle buffer_handle_;
mojo::ScopedSharedBufferMapping buffer_mapping_;
};
}
class COMPONENT_EXPORT(MOJO_BASE) BigBuffer {
public:
using value_type = uint8_t;
using iterator = base::CheckedContiguousIterator<uint8_t>;
using const_iterator = base::CheckedContiguousIterator<const uint8_t>;
static constexpr size_t kMaxInlineBytes = 64 * 1024;
enum class StorageType {
kBytes,
kSharedMemory,
kInvalidBuffer,
};
BigBuffer();
BigBuffer(base::span<const uint8_t> data);
explicit BigBuffer(internal::BigBufferSharedMemoryRegion shared_memory);
explicit BigBuffer(size_t size);
BigBuffer(BigBuffer&& other);
BigBuffer& operator=(BigBuffer&& other);
~BigBuffer();
BigBuffer Clone() const;
uint8_t* data() { return const_cast<uint8_t*>(std::as_const(*this).data()); }
const uint8_t* data() const;
size_t size() const;
StorageType storage_type() const { return storage_type_; }
base::span<const uint8_t> byte_span() const {
CHECK_EQ(storage_type_, StorageType::kBytes);
return bytes_.as_span();
}
internal::BigBufferSharedMemoryRegion& shared_memory() {
CHECK_EQ(storage_type_, StorageType::kSharedMemory);
return shared_memory_.value();
}
iterator begin() {
uint8_t* const ptr = data();
return UNSAFE_BUFFERS(iterator(ptr, ptr + size()));
}
const_iterator begin() const {
const uint8_t* const ptr = data();
return UNSAFE_BUFFERS(const_iterator(ptr, ptr + size()));
}
const_iterator cbegin() const { return begin(); }
iterator end() {
uint8_t* const ptr = data();
const size_t len = size();
return UNSAFE_BUFFERS(iterator(ptr, ptr + len, ptr + len));
}
const_iterator end() const {
const uint8_t* const ptr = data();
const size_t len = size();
return UNSAFE_BUFFERS(const_iterator(ptr, ptr + len, ptr + len));
}
const_iterator cend() const { return end(); }
void WriteIntoTrace(perfetto::TracedValue context) const;
private:
friend class BigBufferView;
StorageType storage_type_ = StorageType::kBytes;
base::HeapArray<uint8_t> bytes_;
std::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
};
class COMPONENT_EXPORT(MOJO_BASE) BigBufferView {
public:
BigBufferView();
BigBufferView(BigBufferView&& other);
explicit BigBufferView(base::span<const uint8_t> bytes);
BigBufferView(const BigBufferView&) = delete;
BigBufferView& operator=(const BigBufferView&) = delete;
~BigBufferView();
BigBufferView& operator=(BigBufferView&& other);
base::span<const uint8_t> data() const;
void SetBytes(base::span<const uint8_t> bytes);
void SetSharedMemory(internal::BigBufferSharedMemoryRegion shared_memory);
[[nodiscard]] static BigBuffer ToBigBuffer(BigBufferView view);
BigBuffer::StorageType storage_type() const { return storage_type_; }
base::span<const uint8_t> bytes() const {
DCHECK_EQ(storage_type_, BigBuffer::StorageType::kBytes);
return bytes_;
}
internal::BigBufferSharedMemoryRegion& shared_memory() {
DCHECK_EQ(storage_type_, BigBuffer::StorageType::kSharedMemory);
return shared_memory_.value();
}
static BigBufferView CreateInvalidForTest();
private:
BigBuffer::StorageType storage_type_ = BigBuffer::StorageType::kBytes;
base::raw_span<const uint8_t> bytes_;
std::optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
};
}
#endif