blob: b28471f01b32b90025959025e489acbc917ed169 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_WEB_BUNDLE_CHUNKED_BUFFER_H_
#define SERVICES_NETWORK_WEB_BUNDLE_CHUNKED_BUFFER_H_
#include <vector>
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/system/data_pipe_producer.h"
namespace network {
// WebBundleChunkedBuffer keeps the appended bytes as a RefCountedBytes, so we
// don't need to copy the bytes while creating a DataSource to read the data
// using a DataPipeProducer.
class COMPONENT_EXPORT(NETWORK_SERVICE) WebBundleChunkedBuffer {
public:
WebBundleChunkedBuffer();
~WebBundleChunkedBuffer();
// Disallow copy and assign.
WebBundleChunkedBuffer(const WebBundleChunkedBuffer&) = delete;
WebBundleChunkedBuffer& operator=(const WebBundleChunkedBuffer&) = delete;
// Append the bytes as a Chunk.
void Append(const uint8_t* data, size_t num_bytes);
// Returns the available length of bytes after |offset|. If it is larger than
// |max_length| returns |max_length|,
uint64_t GetAvailableLength(uint64_t offset, uint64_t max_length) const;
// Returns whether it contains all of [|offset|, |offset| + |length|) range.
// When |length| is 0, always returns true.
bool ContainsAll(uint64_t offset, uint64_t length) const;
// Read the data to |out|. Returns the total length of the read bytes.
uint64_t ReadData(uint64_t offset, uint64_t max_length, uint8_t* out) const;
// Creates a DataSource to read the data using a DataPipeProducer. If there
// is no data to read, returns nullptr.
std::unique_ptr<mojo::DataPipeProducer::DataSource> CreateDataSource(
uint64_t offset,
uint64_t max_length) const;
// Returns the buffer size.
uint64_t size() const;
private:
friend class WebBundleChunkedBufferTest;
FRIEND_TEST_ALL_PREFIXES(WebBundleChunkedBufferTest, EmptyBuffer);
FRIEND_TEST_ALL_PREFIXES(WebBundleChunkedBufferTest, PartialBuffer);
FRIEND_TEST_ALL_PREFIXES(WebBundleChunkedBufferTest, FindChunk);
class COMPONENT_EXPORT(NETWORK_SERVICE) Chunk {
public:
Chunk(uint64_t start_pos, scoped_refptr<const base::RefCountedBytes> bytes);
~Chunk();
// Allow copy and assign.
Chunk(const Chunk&);
Chunk(Chunk&&);
Chunk& operator=(const Chunk&) = default;
Chunk& operator=(Chunk&&) = default;
uint64_t start_pos() const;
uint64_t end_pos() const;
uint64_t size() const;
const uint8_t* data() const;
private:
uint64_t start_pos_;
scoped_refptr<const base::RefCountedBytes> bytes_;
};
using ChunkVector = std::vector<Chunk>;
explicit WebBundleChunkedBuffer(ChunkVector chunks);
bool empty() const;
uint64_t start_pos() const;
uint64_t end_pos() const;
// Returns the iterator of |chunks_|, which Chunk contains the byte at |pos|.
// If |chunks_| doesn't contains the byte at |pos|, returns |chunks_.end()|.
ChunkVector::const_iterator FindChunk(uint64_t pos) const;
// Creates a new WebBundleChunkedBuffer which keeps a part of |chunks_|
// containing the bytes of [|offset|, |offset| + |length|) range.
std::unique_ptr<const WebBundleChunkedBuffer> CreatePartialBuffer(
uint64_t offset,
uint64_t length) const;
ChunkVector chunks_;
};
} // namespace network
#endif // SERVICES_NETWORK_WEB_BUNDLE_CHUNKED_BUFFER_H_