blob: 88802522312776fcc3d4015a02a6c66e447240b8 [file] [log] [blame]
// Copyright 2023 The Pigweed 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
//
// https://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.
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "pw_preprocessor/util.h"
#include "pw_varint/varint.h"
/// @file pw_containers/inline_var_len_entry_queue.h
///
/// A `InlineVarLenEntryQueue` is a queue of inline variable-length binary
/// entries. It is implemented as a ring (circular) buffer and supports
/// operations to append entries and overwrite if necessary. Entries may be zero
/// bytes up to the maximum size supported by the queue.
///
/// The `InlineVarLenEntryQueue` has a few interesting properties.
///
/// - Data and metadata are stored inline in a contiguous block of
/// `uint32_t`-aligned memory.
/// - The data structure is trivially copyable.
/// - All state changes are accomplished with a single update to a `uint32_t`.
/// The memory is always in a valid state and may be parsed offline.
///
/// This data structure is a much simpler version of
/// @cpp_class{pw::ring_buffer::PrefixedEntryRingBuffer}. Prefer this
/// sized-entry ring buffer to `PrefixedEntryRingBuffer` when:
/// - A simple ring buffer of variable-length entries is needed. Advanced
/// features like multiple readers and a user-defined preamble are not
/// required.
/// - A consistent, parsable, in-memory representation is required (e.g. to
/// decode the buffer from a block of memory).
/// - C support is required.
///
/// `InlineVarLenEntryQueue` is implemented in C and provides complete C and C++
/// APIs. The `InlineVarLenEntryQueue` C++ class is structured similarly to
/// `pw::InlineQueue` and `pw::Vector`.
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/// @defgroup inline_var_len_entry_queue_c_api InlineVarLenEntryQueue C API
/// @{
/// Handle that refers to a `InlineVarLenEntryQueue`. In memory, the queue is a
/// `uint32_t` array.
typedef uint32_t* pw_InlineVarLenEntryQueue_Handle;
typedef const uint32_t* pw_InlineVarLenEntryQueue_ConstHandle;
/// Declares and initializes a `InlineVarLenEntryQueue` that can hold up to
/// `max_size_bytes` bytes. `max_size_bytes` is the largest supported size for a
/// single entry; attempting to store larger entries is invalid and will fail an
/// assertion.
///
/// @param variable variable name for the queue
/// @param max_size_bytes the capacity of the queue
#define PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(variable, max_size_bytes) \
uint32_t variable[PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 + \
_PW_VAR_QUEUE_DATA_SIZE_UINT32(max_size_bytes)] = { \
_PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes), /*head=*/0u, /*tail=*/0u}
/// The size of the `InlineVarLenEntryQueue` header, in `uint32_t` elements.
/// This header stores the buffer length and head and tail offsets.
///
/// The underlying `uint32_t` array of a `InlineVarLenEntryQueue` must be larger
/// than this size.
#define PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 (3)
/// Initializes a `InlineVarLenEntryQueue` in place in a `uint32_t` array. The
/// array MUST be larger than
/// @c_macro{PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32} (3) elements.
static inline void pw_InlineVarLenEntryQueue_Init(uint32_t array[],
size_t array_size_uint32);
/// Empties the queue.
static inline void pw_InlineVarLenEntryQueue_Clear(
pw_InlineVarLenEntryQueue_Handle queue);
/// Appends an entry to the end of the queue.
///
/// @pre The entry MUST NOT be larger than `max_size_bytes()`.
void pw_InlineVarLenEntryQueue_Push(pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
uint32_t data_size_bytes);
/// Appends an entry to the end of the queue, removing entries with `Pop`
/// as necessary to make room.
///
/// @pre The entry MUST NOT be larger than `max_size_bytes()`.
void pw_InlineVarLenEntryQueue_PushOverwrite(
pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
uint32_t data_size_bytes);
/// Removes the first entry from queue.
///
/// @pre The queue MUST have at least one entry.
void pw_InlineVarLenEntryQueue_Pop(pw_InlineVarLenEntryQueue_Handle queue);
/// Iterator object for a `InlineVarLenEntryQueue`. Iterators are checked for
/// equality with @cpp_func{pw_InlineVarLenEntryQueue_Iterator_Equal}.
///
/// Iterators are invalidated by any operations that change the container or
/// its underlying data (push/pop/init).
typedef struct {
// Private: do not access these fields directly!
pw_InlineVarLenEntryQueue_ConstHandle _pw_queue;
uint32_t _pw_offset;
} pw_InlineVarLenEntryQueue_Iterator;
/// An entry in the queue. Entries may be stored in up to two segments, so this
/// struct includes pointers to both portions of the entry.
typedef struct {
const uint8_t* data_1;
uint32_t size_1;
const uint8_t* data_2;
uint32_t size_2;
} pw_InlineVarLenEntryQueue_Entry;
/// Returns an iterator to the start of the `InlineVarLenEntryQueue`.
static inline pw_InlineVarLenEntryQueue_Iterator
pw_InlineVarLenEntryQueue_Begin(pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns an iterator that points past the end of the queue.
static inline pw_InlineVarLenEntryQueue_Iterator pw_InlineVarLenEntryQueue_End(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Advances an iterator to point to the next entry in the queue. It is
/// invalid to call `Advance` on an iterator equal to the `End` iterator.
void pw_InlineVarLenEntryQueue_Iterator_Advance(
pw_InlineVarLenEntryQueue_Iterator* iterator);
/// Compares two iterators for equality.
static inline bool pw_InlineVarLenEntryQueue_Iterator_Equal(
const pw_InlineVarLenEntryQueue_Iterator* lhs,
const pw_InlineVarLenEntryQueue_Iterator* rhs);
/// Dereferences an iterator, loading the entry it points to.
pw_InlineVarLenEntryQueue_Entry pw_InlineVarLenEntryQueue_GetEntry(
const pw_InlineVarLenEntryQueue_Iterator* iterator);
/// Copies the contents of the entry to the provided buffer. The entry may be
/// split into two regions; this serializes it into one buffer.
///
/// @param entry The entry whose contents to copy
/// @param dest The buffer into which to copy the serialized entry
/// @param count Copy up to this many bytes; must not be larger than the `dest`
/// buffer, but may be larger than the entry
uint32_t pw_InlineVarLenEntryQueue_Entry_Copy(
const pw_InlineVarLenEntryQueue_Entry* entry, void* dest, uint32_t count);
/// Returns the byte at the specified index in the entry. Asserts if index is
/// out-of-bounds.
static inline uint8_t pw_InlineVarLenEntryQueue_Entry_At(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index);
/// Returns the number of variable-length entries in the queue. This is O(n) in
/// the number of entries in the queue.
uint32_t pw_InlineVarLenEntryQueue_Size(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the combined size in bytes of all entries in the queue, excluding
/// metadata. This is O(n) in the number of entries in the queue.
uint32_t pw_InlineVarLenEntryQueue_SizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the the maximum number of bytes that can be stored in the queue.
/// This is largest possible value of `size_bytes()`, and the size of the
/// largest single entry that can be stored in this queue. Attempting to store a
/// larger entry is invalid and results in a crash.
static inline uint32_t pw_InlineVarLenEntryQueue_MaxSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the size of the raw underlying `InlineVarLenEntryQueue` storage.
/// This size may be used to copy a `InlineVarLenEntryQueue` into another
/// 32-bit aligned memory location.
static inline uint32_t pw_InlineVarLenEntryQueue_RawStorageSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns true if the `InlineVarLenEntryQueue` is empty, false if it has at
/// least one entry.
static inline bool pw_InlineVarLenEntryQueue_Empty(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// @}
// Implementation details.
#define _PW_VAR_QUEUE_DATA_SIZE_UINT32(max_size_bytes) \
((_PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes) + 3 /* round up */) / 4)
#define _PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes) \
(PW_VARINT_ENCODED_SIZE_BYTES(max_size_bytes) + max_size_bytes + \
1 /*end byte*/)
#define _PW_VAR_QUEUE_ARRAY_SIZE_BYTES queue[0]
#define _PW_VAR_QUEUE_HEAD queue[1]
#define _PW_VAR_QUEUE_TAIL queue[2] // points after the last byte
#define _PW_VAR_QUEUE_DATA ((const uint8_t*)&queue[3])
#define _PW_VAR_QUEUE_GET_ARRAY_SIZE_BYTES(array_size_uint32) \
(uint32_t)(array_size_uint32 - \
PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32) * \
sizeof(uint32_t)
static inline void pw_InlineVarLenEntryQueue_Init(uint32_t array[],
size_t array_size_uint32) {
array[0] = _PW_VAR_QUEUE_GET_ARRAY_SIZE_BYTES(array_size_uint32);
array[1] = 0; // head
array[2] = 0; // tail
}
static inline void pw_InlineVarLenEntryQueue_Clear(
pw_InlineVarLenEntryQueue_Handle queue) {
_PW_VAR_QUEUE_HEAD = 0; // head
_PW_VAR_QUEUE_TAIL = 0; // tail
}
static inline pw_InlineVarLenEntryQueue_Iterator
pw_InlineVarLenEntryQueue_Begin(pw_InlineVarLenEntryQueue_ConstHandle queue) {
pw_InlineVarLenEntryQueue_Iterator begin = {queue, _PW_VAR_QUEUE_HEAD};
return begin;
}
static inline pw_InlineVarLenEntryQueue_Iterator pw_InlineVarLenEntryQueue_End(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
pw_InlineVarLenEntryQueue_Iterator end = {queue, _PW_VAR_QUEUE_TAIL};
return end;
}
static inline bool pw_InlineVarLenEntryQueue_Iterator_Equal(
const pw_InlineVarLenEntryQueue_Iterator* lhs,
const pw_InlineVarLenEntryQueue_Iterator* rhs) {
return lhs->_pw_offset == rhs->_pw_offset && lhs->_pw_queue == rhs->_pw_queue;
}
// Private function that returns a pointer to the specified index in the Entry.
static inline const uint8_t* _pw_InlineVarLenEntryQueue_Entry_GetPointer(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index) {
if (index < entry->size_1) {
return &entry->data_1[index];
}
return &entry->data_2[index - entry->size_1];
}
const uint8_t* _pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index);
static inline uint8_t pw_InlineVarLenEntryQueue_Entry_At(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index) {
return *_pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(entry, index);
}
static inline uint32_t pw_InlineVarLenEntryQueue_RawStorageSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 * sizeof(uint32_t) +
_PW_VAR_QUEUE_ARRAY_SIZE_BYTES;
}
static inline uint32_t pw_InlineVarLenEntryQueue_MaxSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return _PW_VAR_QUEUE_ARRAY_SIZE_BYTES - 1 -
(uint32_t)pw_varint_EncodedSizeBytes(_PW_VAR_QUEUE_ARRAY_SIZE_BYTES -
1);
}
static inline bool pw_InlineVarLenEntryQueue_Empty(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return _PW_VAR_QUEUE_HEAD == _PW_VAR_QUEUE_TAIL;
}
// These macros are not part of the public API, so undefine them.
#undef _PW_VAR_QUEUE_ARRAY_SIZE_BYTES
#undef _PW_VAR_QUEUE_HEAD
#undef _PW_VAR_QUEUE_TAIL
#undef _PW_VAR_QUEUE_DATA
#ifdef __cplusplus
} // extern "C"
#include <cstddef>
#include <limits>
#include <type_traits>
#include <utility>
#include "pw_containers/internal/raw_storage.h"
#include "pw_span/span.h"
namespace pw {
// A`BasicInlineVarLenEntryQueue` with a known maximum size of a single entry.
// The member functions are immplemented in the generic-capacity base.
// TODO: b/303056683 - Add helper for calculating kMaxSizeBytes for N entries of
// a particular size.
template <typename T,
size_t kMaxSizeBytes = containers::internal::kGenericSized>
class BasicInlineVarLenEntryQueue
: public BasicInlineVarLenEntryQueue<T,
containers::internal::kGenericSized> {
private:
using Base =
BasicInlineVarLenEntryQueue<T, containers::internal::kGenericSized>;
public:
constexpr BasicInlineVarLenEntryQueue() : Base(kMaxSizeBytes) {}
// `BasicInlineVarLenEntryQueue` is trivially copyable.
BasicInlineVarLenEntryQueue(const BasicInlineVarLenEntryQueue&) = default;
BasicInlineVarLenEntryQueue& operator=(const BasicInlineVarLenEntryQueue&) =
default;
private:
static_assert(kMaxSizeBytes <=
std::numeric_limits<typename Base::size_type>::max());
using Base::Init; // Disallow Init since the size template param is not used.
uint32_t data_[_PW_VAR_QUEUE_DATA_SIZE_UINT32(kMaxSizeBytes)];
};
/// @defgroup inline_var_len_entry_queue_cpp_api
/// @{
/// Variable-length entry queue class template for any byte type (e.g.
/// ``std::byte`` or ``uint8_t``).
///
/// ``BasicInlineVarLenEntryQueue`` instances are declared with their capacity
/// / max single entry size (``BasicInlineVarLenEntryQueue<char, 64>``), but
/// may be referred to without the size
/// (``BasicInlineVarLenEntryQueue<char>&``).
template <typename T>
class BasicInlineVarLenEntryQueue<T, containers::internal::kGenericSized> {
public:
class Entry;
using value_type = Entry;
using size_type = std::uint32_t;
using pointer = const value_type*;
using const_pointer = pointer;
using reference = const value_type&;
using const_reference = reference;
// Refers to an entry in-place in the queue. Entries may not be contiguous.
class iterator;
// Currently, iterators provide read-only access.
// TODO: b/303046109 - Provide a non-const iterator.
using const_iterator = iterator;
/// @copydoc pw_InlineVarLenEntryQueue_Init
template <size_t kArraySize>
static BasicInlineVarLenEntryQueue& Init(uint32_t (&array)[kArraySize]) {
static_assert(
kArraySize > PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32,
"InlineVarLenEntryQueue must be backed by an array with more than "
"PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 (3) elements");
return Init(array, kArraySize);
}
/// @copydoc pw_InlineVarLenEntryQueue_Init
static BasicInlineVarLenEntryQueue& Init(uint32_t array[],
size_t array_size_uint32) {
pw_InlineVarLenEntryQueue_Init(array, array_size_uint32);
return *std::launder(reinterpret_cast<BasicInlineVarLenEntryQueue*>(array));
}
/// Returns the first entry in the queue.
Entry front() const { return *begin(); }
/// @copydoc pw_InlineVarLenEntryQueue_Begin
const_iterator begin() const {
return const_iterator(pw_InlineVarLenEntryQueue_Begin(array_));
}
const_iterator cbegin() const { return begin(); }
/// @copydoc pw_InlineVarLenEntryQueue_End
const_iterator end() const {
return const_iterator(pw_InlineVarLenEntryQueue_End(array_));
}
const_iterator cend() const { return end(); }
/// @copydoc pw_InlineVarLenEntryQueue_Empty
[[nodiscard]] bool empty() const {
return pw_InlineVarLenEntryQueue_Empty(array_);
}
/// @copydoc pw_InlineVarLenEntryQueue_Size
size_type size() const { return pw_InlineVarLenEntryQueue_Size(array_); }
/// @copydoc pw_InlineVarLenEntryQueue_SizeBytes
size_type size_bytes() const {
return pw_InlineVarLenEntryQueue_SizeBytes(array_);
}
/// @copydoc pw_InlineVarLenEntryQueue_MaxSizeBytes
size_type max_size_bytes() const {
return pw_InlineVarLenEntryQueue_MaxSizeBytes(array_);
}
/// Underlying storage of the variable-length entry queue. May be used to
/// memcpy the queue.
span<const T> raw_storage() const {
return span<const T>(reinterpret_cast<const T*>(array_),
pw_InlineVarLenEntryQueue_RawStorageSizeBytes(array_));
}
/// @copydoc pw_InlineVarLenEntryQueue_Clear
void clear() { pw_InlineVarLenEntryQueue_Clear(array_); }
/// @copydoc pw_InlineVarLenEntryQueue_Push
void push(span<const T> value) {
pw_InlineVarLenEntryQueue_Push(
array_, value.data(), static_cast<size_type>(value.size()));
}
/// @copydoc pw_InlineVarLenEntryQueue_PushOverwrite
void push_overwrite(span<const T> value) {
pw_InlineVarLenEntryQueue_PushOverwrite(
array_, value.data(), static_cast<size_type>(value.size()));
}
/// @copydoc pw_InlineVarLenEntryQueue_Pop
void pop() { pw_InlineVarLenEntryQueue_Pop(array_); }
protected:
constexpr BasicInlineVarLenEntryQueue(uint32_t max_size_bytes)
: array_{_PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes), 0, 0} {}
BasicInlineVarLenEntryQueue(const BasicInlineVarLenEntryQueue&) = default;
BasicInlineVarLenEntryQueue& operator=(const BasicInlineVarLenEntryQueue&) =
default;
private:
static_assert(std::is_integral_v<T> || std::is_same_v<T, std::byte>);
static_assert(sizeof(T) == sizeof(std::byte));
uint32_t array_[PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32];
};
/// Refers to an entry in-place in the queue. Entries may be discontiguous.
template <typename T>
class BasicInlineVarLenEntryQueue<T>::Entry {
public:
using value_type = T;
using size_type = std::uint32_t;
using pointer = const T*;
using const_pointer = pointer;
using reference = const T&;
using const_reference = reference;
/// Iterator for the bytes in an Entry. Entries may be discontiguous, so a
/// pointer cannot serve as an iterator.
class iterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = const T*;
using reference = const T&;
using iterator_category = std::forward_iterator_tag;
constexpr iterator() : entry_(nullptr), index_(0) {}
constexpr iterator(const iterator&) = default;
constexpr iterator& operator=(const iterator&) = default;
constexpr iterator& operator++() {
index_ += 1;
return *this;
}
constexpr iterator operator++(int) {
iterator previous_value(*this);
operator++();
return previous_value;
}
reference operator*() const { return *GetIndex(*entry_, index_); }
pointer operator->() const { return GetIndex(*entry_, index_); }
bool operator==(const iterator& rhs) const {
return entry_->data_1 == rhs.entry_->data_1 && index_ == rhs.index_;
}
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
private:
friend class Entry;
constexpr iterator(const pw_InlineVarLenEntryQueue_Entry& entry,
size_t index)
: entry_(&entry), index_(index) {}
const pw_InlineVarLenEntryQueue_Entry* entry_;
size_t index_;
};
// TODO: b/303046109 - Provide mutable access to Entry contents.
using const_iterator = iterator;
constexpr Entry(const Entry&) = default;
constexpr Entry& operator=(const Entry&) = default;
const_reference at(size_t index) const {
return *reinterpret_cast<const T*>(
_pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(&entry_, index));
}
const_reference operator[](size_t index) const {
return *GetIndex(entry_, index);
}
const_reference front() const { return *entry_.data_1; }
const_reference back() const { *GetIndex(entry_, size() - 1); }
/// Entries may be stored in up to two segments, so this returns spans
/// refering to both portions of the entry. If the entry is contiguous, the
/// second span is empty.
std::pair<span<const value_type>, span<const value_type>> contiguous_data()
const {
return std::make_pair(
span(reinterpret_cast<const_pointer>(entry_.data_1), entry_.size_1),
span(reinterpret_cast<const_pointer>(entry_.data_2), entry_.size_2));
}
/// @copydoc pw_InlineVarLenEntryQueue_Entry_Copy
///
/// Copying with `copy()` is likely more efficient than an iterator-based copy
/// with `std::copy()`, since `copy()` uses one or two `memcpy` calls instead
/// of copying byte-by-byte.
size_type copy(T* dest, size_type count) const {
return pw_InlineVarLenEntryQueue_Entry_Copy(&entry_, dest, count);
}
const_iterator begin() const { return const_iterator(entry_, 0); }
const_iterator cbegin() const { return begin(); }
const_iterator end() const { return const_iterator(entry_, size()); }
const_iterator cend() const { return cend(); }
[[nodiscard]] bool empty() const { return size() == 0; }
size_type size() const { return entry_.size_1 + entry_.size_2; }
private:
friend class BasicInlineVarLenEntryQueue;
static const T* GetIndex(const pw_InlineVarLenEntryQueue_Entry& entry,
size_t index) {
return reinterpret_cast<const T*>(
_pw_InlineVarLenEntryQueue_Entry_GetPointer(&entry, index));
}
explicit constexpr Entry(const pw_InlineVarLenEntryQueue_Entry& entry)
: entry_(entry) {}
constexpr Entry() : entry_{} {}
pw_InlineVarLenEntryQueue_Entry entry_;
};
/// Iterator object for a `InlineVarLenEntryQueue`.
///
/// Iterators are invalidated by any operations that change the container or
/// its underlying data (push/pop/init).
template <typename T>
class BasicInlineVarLenEntryQueue<T>::iterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = Entry;
using pointer = const Entry*;
using reference = const Entry&;
using iterator_category = std::forward_iterator_tag;
constexpr iterator() : iterator_{}, entry_{} {}
constexpr iterator(const iterator&) = default;
constexpr iterator& operator=(const iterator&) = default;
iterator& operator++() {
pw_InlineVarLenEntryQueue_Iterator_Advance(&iterator_);
entry_.entry_.data_1 = nullptr; // mark the entry as unloaded
return *this;
}
iterator operator++(int) {
iterator previous_value(*this);
operator++();
return previous_value;
}
reference operator*() const {
LoadEntry();
return entry_;
}
pointer operator->() const {
LoadEntry();
return &entry_;
}
bool operator==(const iterator& rhs) const {
return pw_InlineVarLenEntryQueue_Iterator_Equal(&iterator_, &rhs.iterator_);
}
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
private:
friend class BasicInlineVarLenEntryQueue;
explicit constexpr iterator(const pw_InlineVarLenEntryQueue_Iterator& it)
: iterator_(it) {}
void LoadEntry() const {
if (entry_.entry_.data_1 == nullptr) {
entry_.entry_ = pw_InlineVarLenEntryQueue_GetEntry(&iterator_);
}
}
pw_InlineVarLenEntryQueue_Iterator iterator_;
mutable Entry entry_;
};
/// Variable-length entry queue that uses ``std::byte`` for the byte type.
template <size_t kMaxSizeBytes = containers::internal::kGenericSized>
using InlineVarLenEntryQueue =
BasicInlineVarLenEntryQueue<std::byte, kMaxSizeBytes>;
/// @}
} // namespace pw
#endif // __cplusplus