chromium/mojo/public/cpp/bindings/lib/message_fragment.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_FRAGMENT_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_FRAGMENT_H_

#include <stddef.h>

#include <limits>
#include <type_traits>

#include "base/bits.h"
#include "base/check_op.h"
#include "base/component_export.h"
#include "base/logging.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/message.h"

namespace mojo {
namespace internal {

// Sentinel value used to denote an invalid index and thus a null fragment. Note
// that we choose a sentinel value over something more explicit like
// std::optional because this is used heavily in generated code, so code size
// is particularly relevant.
constexpr size_t kInvalidFragmentIndex =;

// MessageFragment provides a common interface for serialization code to
// allocate, initialize, and expose convenient access to aligned blocks of data
// within a Message object. Each MessageFragment corresponds to a logical data
// element (e.g. struct, field, array, array element, etc) within a Message.
//
// A MessageFragment is configured at construction time with a partially
// serialized Message. The fragment is initially null and does not reference
// valid memory.
//
// In order to use `data()` or `operator->` the fragment must first claim a
// chunk of memory within the message. This is done by calling either
// `Allocate()` -- which appends `sizeof(T)` bytes to the end of the Message
// payload and assumes control of those bytes -- or `Claim()` which takes an
// existing pointer within the message payload and assumes control of the first
// `sizeof(T)` bytes at that message offset. In either case, a new `T` is
// constructed over the claimed bytes and can subsequently be read or modified
// using this fragment.
//
// Note that array types use a specialization of this class defined below,
// and must instead call `AllocateArrayData()` to allocate and claim space
// within the Message.
template <typename T>
class MessageFragment {};

// Traits to help infer an array sizing function from the element type. Needed
// because of bool arrays -- everything else is trivially the product of element
// size and element count.
template <typename ElementType>
struct MessageFragmentArrayTraits {};

MessageFragmentArrayTraits<std::optional<ElementType>>;

// Bool arrays are packed bit for bit, so e.g. an 8-element bool array requires
// only a single byte of storage apart from the header.
template <>
struct MessageFragmentArrayTraits<bool> {};

// Optional bool arrays are two consecutive bitfields.
template <>
struct MessageFragmentArrayTraits<std::optional<bool>> {};

template <typename T>
class Array_Data;

// Specialization of MessageFragment<T> specific to Array_Data types.
MessageFragment<Array_Data<T>>;

}  // namespace internal
}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_FRAGMENT_H_