chromium/third_party/crashpad/crashpad/client/length_delimited_ring_buffer.h

// Copyright 2023 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CRASHPAD_CLIENT_LENGTH_DELIMITED_RING_BUFFER_H_
#define CRASHPAD_CLIENT_LENGTH_DELIMITED_RING_BUFFER_H_

#include <stdint.h>
#include <string.h>

#include <algorithm>
#include <array>
#include <limits>
#include <optional>
#include <type_traits>
#include <vector>

#include "base/numerics/safe_math.h"

namespace crashpad {

//! \brief Capacity of a `RingBufferData`, in bytes.
RingBufferCapacity;

namespace internal {

//! \brief Default capacity of `RingBufferData`, in bytes.
inline constexpr RingBufferCapacity kDefaultRingBufferDataCapacity =;

//! \brief A tuple holding the current range of bytes which can be read from or
//!     have been written to.
struct Range final {};

// This struct is persisted to disk, so its size must not change.
static_assert;

//! \brief The number of bits encoded in each byte of a Base 128-encoded varint.
inline constexpr int kBase128ByteValueBits =;

//! \!brief Calculates the length in bytes of `value` encoded using
//!    little-endian Base 128 varint encoding.
//! \sa https://developers.google.com/protocol-buffers/docs/encoding#varints
//!
//! `LengthDelimitedRingBufferWriter` uses varint-encoded delimiters to enable
//! zero-copy deserialization of the ringbuffer's contents when storing
//! protobufs inside the ringbuffer, e.g. via
//! `google::protobuf::util::ParseDelimitedFromZeroCopyStream()` or similar.
//!
//! \sa
//! https://github.com/protocolbuffers/protobuf/blob/3202b9da88ceb75b65bbabaf4033c95e872f828d/src/google/protobuf/util/delimited_message_util.h#L85
//! \sa
//! https://github.com/protocolbuffers/protobuf/blob/8bd49dea5e167a389d94b71d24c981d8f9fa0c99/src/google/protobuf/io/zero_copy_stream_impl_lite.h#L68
//! \sa
//! https://github.com/protocolbuffers/protobuf/blob/8bd49dea5e167a389d94b71d24c981d8f9fa0c99/src/google/protobuf/io/coded_stream.h#L171
//!
//! \!param[in] value Value to be encoded in Base 128 varint encoding.
//! \!return The length in bytes of `value` in Base 128 varint encoding.
template <typename IntegerType>
constexpr Range::Length Base128VarintEncodedLength(IntegerType value) {}

// Note that std::array capacity is a size_t, not a RingBufferCapacity.
RingBufferArray;

//! \return The size of the `RingBufferArray` as a `Range::Length`.
template <size_t ArrayCapacity>
constexpr Range::Length RingBufferArraySize(
    const RingBufferArray<ArrayCapacity>& ring_buffer_data) {}

//! \brief Reads data from the ring buffer into a target buffer.
//! \param[in] ring_buffer_data The ring buffer to read.
//! \param[in,out] ring_buffer_read_range The range of the data available
//!     to read. Upon return, set to the remaining range of data available
//!     to read, if any.
//! \param[in] target_buffer Buffer into which data will be written.
//! \param[in] target_buffer_length Number of bytes to write into
//!     `target_buffer`.
//!
//! \return `true` if the read succeeded, `false` otherwise. On success, updates
//!     `ring_buffer_read_range` to reflect the bytes consumed.
//!
//! The bytes can wrap around the end of the ring buffer, in which case the read
//! continues at the beginning of the ring buffer (if the ring buffer is long
//! enough).
template <typename RingBufferArrayType>
bool ReadBytesFromRingBuffer(const RingBufferArrayType& ring_buffer_data,
                             internal::Range& ring_buffer_read_range,
                             uint8_t* target_buffer,
                             Range::Length target_buffer_length) {}

//! \brief Reads a single little-endian Base 128 varint-encoded integer from
//!     the ring buffer.
//! \param[in] ring_buffer_data The ring buffer to read.
//! \param[in,out] ring_buffer_read_range The range of the data available
//!     to read. Upon return, set to the remaining range of data available
//!     to read, if any.
//! \param[out] result Upon success, set to the decoded value read from the
//!     buffer.
//!
//! \return The length in bytes of the varint if the read succeeded,
//!    `std::nullopt` otherwise. On success, updates `ring_buffer_read_range`
//!    to reflect the bytes available to read.
//!
//! The varint can wrap around the end of the ring buffer, in which case the
//! read continues at the beginning of the ring buffer (if the ring buffer is
//! long enough).
template <typename RingBufferArrayType, typename IntegerType>
std::optional<Range::Length> ReadBase128VarintFromRingBuffer(
    const RingBufferArrayType& ring_buffer_data,
    internal::Range& ring_buffer_read_range,
    IntegerType& result) {}

//! \brief Writes data from the source buffer into the ring buffer.
//! \param[in] source_buffer Buffer from which data will be read.
//! \param[in] source_buffer_length The length in bytes of `source_buffer`.
//! \param[in] ring_buffer_data The ring buffer into which data will be read.
//! \param[in,out] ring_buffer_write_range The range of the data available
//!     to write. Upon return, set to the remaining range of data available
//!     to write, if any.
//!
//! \return `true` if write read succeeded, `false` otherwise. On success,
//! updates
//!     `ring_buffer_write_range` to reflect the bytes written.
//!
//! The bytes can wrap around the end of the ring buffer, in which case the
//! write continues at the beginning of the ring buffer (if the ring buffer is
//! long enough).
template <typename RingBufferArrayType>
bool WriteBytesToRingBuffer(const uint8_t* const source_buffer,
                            Range::Length source_buffer_length,
                            RingBufferArrayType& ring_buffer_data,
                            internal::Range& ring_buffer_write_range) {}

//! \brief Writes a single Base 128 varint-encoded little-endian unsigned
//!     integer into the ring buffer.
//! \param[in] value The value to encode and write into the ring buffer.
//! \param[in] ring_buffer_data The ring buffer into which to write.
//! \param[in,out] ring_buffer_write_range The range of the data available
//!     to write. Upon return, set to the remaining range of data available
//!     to write, if any.
//!
//! \return The length in bytes of the varint if the write succeeded,
//!    `std::nullopt` otherwise. On success, updates `write_buffer_read_range`
//!    to reflect the range available to write, if any.
//!
//! The varint can wrap around the end of the ring buffer, in which case the
//! write continues at the beginning of the ring buffer (if the ring buffer is
//! long enough).
template <typename RingBufferArrayType, typename IntegerType>
std::optional<int> WriteBase128VarintToRingBuffer(
    IntegerType value,
    RingBufferArrayType& ring_buffer_data,
    internal::Range& ring_buffer_write_range) {}

}  // namespace internal

//! \brief Storage for a ring buffer which can hold up to
//! `RingBufferCapacity`
//!     bytes of Base 128-varint delimited variable-length items.
//!
//! This struct contains a header immediately followed by the ring buffer
//! data. The current read offset and length are stored in `header.data_range`.
//!
//! The structure of this object is:
//!
//! `|magic|version|data_offset|data_length|ring_buffer_data|`
//!
//! To write data to this object, see `LengthDelimitedRingBufferWriter`.
//! To read data from this object, see `LengthDelimitedRingBufferReader`.
//!
//! The bytes of this structure are suitable for direct serialization from
//! memory to disk, e.g. as a crashpad::Annotation.
template <RingBufferCapacity Capacity>
struct RingBufferData final {};

// Ensure the ring buffer is packed correctly at its default capacity.
static_assert;

// Allow just `RingBufferData foo;` to be declared without template arguments
// using C++17 class template argument deduction.
template <
    RingBufferCapacity Capacity = internal::kDefaultRingBufferDataCapacity>
RingBufferData() -> RingBufferData<Capacity>;

//! \brief Reads variable-length data buffers from a `RingBufferData`,
//!     delimited by Base128 varint-encoded length delimiters.
//!
//! Holds a reference to a `RingBufferData` with the capacity to hold
//! `RingBufferDataType::size()` bytes of variable-length buffers each
//! preceded by its length (encoded as a Base128 length varint).
//!
//! Provides reading capabilities via `Pop()`.
template <typename RingBufferDataType>
class LengthDelimitedRingBufferReader final {};

// Allow just `LengthDelimitedRingBufferReader reader(foo);` to be declared
// without template arguments using C++17 class template argument deduction.
template <typename RingBufferDataType>
LengthDelimitedRingBufferReader(RingBufferDataType&)
    -> LengthDelimitedRingBufferReader<RingBufferDataType>;

//! \brief Writes variable-length data buffers to a `RingBufferData`,
//!     delimited by Base128 varint-encoded length delimiters.
//!
//! Holds a reference to a `RingBufferData` with the capacity to hold
//! `RingBufferDataType::size()` bytes of variable-length buffers each
//! preceded by its length (encoded as a Base128 length varint).
//!
//! Provides writing capabilities via `Push()`.
template <typename RingBufferDataType>
class LengthDelimitedRingBufferWriter final {};

// Allow just `LengthDelimitedRingBufferWriter writer(foo);` to be declared
// without template arguments using C++17 class template argument deduction.
template <typename RingBufferDataType>
LengthDelimitedRingBufferWriter(RingBufferDataType&)
    -> LengthDelimitedRingBufferWriter<RingBufferDataType>;

}  // namespace crashpad

#endif  // CRASHPAD_CLIENT_LENGTH_DELIMITED_RING_BUFFER_H_