49 Result<std::unique_ptr<InputFile>>
NewInputFile(std::string file_location)
override {
50 auto file = FindFile(file_location);
52 return NotFound(
"File does not exist: {}", file_location);
54 return std::make_unique<InMemoryInputFile>(std::move(file_location), std::move(file),
58 Result<std::unique_ptr<InputFile>>
NewInputFile(std::string file_location,
59 size_t length)
override {
60 if (length >
static_cast<size_t>(std::numeric_limits<int64_t>::max())) {
61 return InvalidArgument(
"File length {} exceeds int64_t max", length);
63 auto file = FindFile(file_location);
65 return NotFound(
"File does not exist: {}", file_location);
67 return std::make_unique<InMemoryInputFile>(std::move(file_location), std::move(file),
68 static_cast<int64_t
>(length));
71 Result<std::unique_ptr<OutputFile>>
NewOutputFile(std::string file_location)
override {
72 return std::make_unique<InMemoryOutputFile>(files_, std::move(file_location));
75 void AddFile(std::string file_location, std::span<const std::byte> data) {
76 files_->insert_or_assign(
77 std::move(file_location),
78 std::make_shared<std::vector<std::byte>>(data.begin(), data.end()));
81 void AddFile(std::string file_location, std::string_view data) {
82 AddFile(std::move(file_location),
83 std::as_bytes(std::span<const char>(data.data(), data.size())));
86 std::vector<std::byte>& FileData(
const std::string& file_location) {
87 return *GetOrCreateFile(file_location);
90 const std::vector<std::byte>& FileData(
const std::string& file_location)
const {
91 return *files_->at(file_location);
94 MOCK_METHOD((Result<std::string>),
ReadFile,
95 (
const std::string&, std::optional<size_t>), (
override));
97 MOCK_METHOD(Status,
WriteFile, (
const std::string&, std::string_view), (
override));
99 MOCK_METHOD(Status,
DeleteFile, (
const std::string&), (
override));
103 std::unordered_map<std::string, std::shared_ptr<std::vector<std::byte>>>;
105 class InMemoryInputStream :
public SeekableInputStream {
107 explicit InMemoryInputStream(std::shared_ptr<std::vector<std::byte>> data)
108 : data_(
std::move(data)) {}
110 Result<int64_t> Position()
const override {
return position_; }
112 Status Seek(int64_t position)
override {
113 ICEBERG_PRECHECK(!closed_,
"Input stream is closed");
114 ICEBERG_PRECHECK(position >= 0,
"Position must not be negative: {}", position);
115 position_ = position;
119 Result<int64_t> Read(std::span<std::byte> out)
override {
120 ICEBERG_PRECHECK(!closed_,
"Input stream is closed");
121 auto file_size =
static_cast<int64_t
>(data_->size());
122 ICEBERG_PRECHECK(position_ <= file_size,
"Position {} exceeds file size {}",
123 position_, file_size);
125 std::min(
static_cast<int64_t
>(out.size()), file_size - position_);
126 if (bytes_to_read > 0) {
127 std::memcpy(out.data(), data_->data() +
static_cast<size_t>(position_),
128 static_cast<size_t>(bytes_to_read));
129 position_ += bytes_to_read;
131 return bytes_to_read;
134 Status ReadFully(int64_t position, std::span<std::byte> out)
override {
135 ICEBERG_PRECHECK(!closed_,
"Input stream is closed");
136 ICEBERG_PRECHECK(position >= 0,
"Position must not be negative: {}", position);
137 auto file_size =
static_cast<int64_t
>(data_->size());
138 ICEBERG_PRECHECK(
static_cast<int64_t
>(out.size()) <= file_size - position,
139 "Read out of bounds: offset {} + length {} exceeds file size {}",
140 position, out.size(), file_size);
142 std::memcpy(out.data(), data_->data() +
static_cast<size_t>(position),
148 Status Close()
override {
154 std::shared_ptr<std::vector<std::byte>> data_;
155 int64_t position_ = 0;
156 bool closed_ =
false;
159 class InMemoryOutputStream :
public PositionOutputStream {
161 explicit InMemoryOutputStream(std::shared_ptr<std::vector<std::byte>> data)
162 : data_(
std::move(data)) {}
164 Result<int64_t> Position()
const override {
165 return static_cast<int64_t
>(data_->size());
168 Status Write(std::span<const std::byte> data)
override {
169 ICEBERG_PRECHECK(!closed_,
"Output stream is closed");
170 data_->insert(data_->end(), data.begin(), data.end());
174 Status Flush()
override {
175 ICEBERG_PRECHECK(!closed_,
"Output stream is closed");
179 Status Close()
override {
185 std::shared_ptr<std::vector<std::byte>> data_;
186 bool closed_ =
false;
189 class InMemoryInputFile :
public InputFile {
191 InMemoryInputFile(std::string location, std::shared_ptr<std::vector<std::byte>> data,
192 std::optional<int64_t> length)
193 : location_(
std::move(location)), data_(
std::move(data)), length_(length) {}
195 std::string_view location()
const override {
return location_; }
197 Result<int64_t> Size()
const override {
198 return length_.value_or(
static_cast<int64_t
>(data_->size()));
201 Result<std::unique_ptr<SeekableInputStream>> Open()
override {
202 return std::make_unique<InMemoryInputStream>(data_);
206 std::string location_;
207 std::shared_ptr<std::vector<std::byte>> data_;
208 std::optional<int64_t> length_;
211 class InMemoryOutputFile :
public OutputFile {
213 InMemoryOutputFile(std::shared_ptr<FileMap> files, std::string location)
214 : files_(
std::move(files)), location_(
std::move(location)) {}
216 std::string_view location()
const override {
return location_; }
218 Result<std::unique_ptr<PositionOutputStream>> Create()
override {
219 if (files_->contains(location_)) {
220 return AlreadyExists(
"File already exists: {}", location_);
222 auto file = std::make_shared<std::vector<std::byte>>();
223 files_->emplace(location_, file);
224 return std::make_unique<InMemoryOutputStream>(std::move(file));
227 Result<std::unique_ptr<PositionOutputStream>> CreateOrOverwrite()
override {
228 auto file = std::make_shared<std::vector<std::byte>>();
229 files_->insert_or_assign(location_, file);
230 return std::make_unique<InMemoryOutputStream>(std::move(file));
234 std::shared_ptr<FileMap> files_;
235 std::string location_;
238 std::shared_ptr<std::vector<std::byte>> FindFile(
239 const std::string& file_location)
const {
240 auto file = files_->find(file_location);
241 if (file == files_->end()) {
247 std::shared_ptr<std::vector<std::byte>> GetOrCreateFile(
248 const std::string& file_location) {
249 auto& file = (*files_)[file_location];
251 file = std::make_shared<std::vector<std::byte>>();
256 std::shared_ptr<FileMap> files_ = std::make_shared<FileMap>();