// 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_