| // Copyright 2018 The Fuchsia 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 LIB_FIDL_CPP_MESSAGE_PART_H_ |
| #define LIB_FIDL_CPP_MESSAGE_PART_H_ |
| |
| #include <lib/fidl/internal.h> |
| #include <stdint.h> |
| #include <string.h> |
| #include <zircon/types.h> |
| |
| namespace fidl { |
| |
| // Part of a FIDL message. |
| // |
| // A FIDL message has two parts: the bytes and the handles. This class is used |
| // to represent both kinds of parts. |
| // |
| // Each part of the message has a data buffer, which contains the actual data |
| // for that part of the message, a capacity for that buffer, and the actual |
| // amount of data stored in the buffer, which might be less that the capacity if |
| // the buffer is not completely full. |
| template <typename T> |
| class MessagePart { |
| public: |
| using value_type = T; |
| using const_iterator = const T*; |
| |
| // A message part with no storage. |
| MessagePart() : data_(nullptr), capacity_(0u), actual_(0u) {} |
| |
| // A message part that uses the given storage. |
| // |
| // The constructed |MessagePart| object does not take ownership of the given |
| // storage. |
| MessagePart(T* data, uint32_t capacity, uint32_t actual = 0u) |
| : data_(data), capacity_(capacity), actual_(actual) {} |
| |
| // The copy constructor is deleted because a MessagePart may own handles (see |
| // HandlePart/HandleDispositionPart/HandleInfoPart below), which may not be copied. |
| MessagePart(const MessagePart& other) = delete; |
| MessagePart& operator=(const MessagePart& other) = delete; |
| |
| MessagePart(MessagePart&& other) |
| : data_(other.data_), capacity_(other.capacity_), actual_(other.actual_) { |
| other.data_ = nullptr; |
| other.capacity_ = 0u; |
| other.actual_ = 0u; |
| } |
| |
| // A copy constructor for |other|, which trims the first |pos| number of |T|s from it when |
| // copying. This should not be invoked on any |Handle*Part| specialization of the |MessagePart| |
| // class, as handle containing classes may not be copied (handles must be unique). |
| MessagePart(const MessagePart& other, uint32_t pos) |
| : data_(other.data_ + (pos * sizeof(T))), |
| capacity_(other.capacity_ > pos * sizeof(T) ? other.capacity_ - (pos * sizeof(T)) : 0), |
| actual_(other.actual_ > pos * sizeof(T) ? other.actual_ - (pos * sizeof(T)) : 0) { |
| static_assert( |
| !(std::is_same<zx_handle_t, T>::value || std::is_same<zx_handle_disposition_t, T>::value || |
| std::is_same<zx_handle_info_t, T>::value), |
| "Handle holding containers may not be copied"); |
| } |
| |
| MessagePart& operator=(MessagePart&& other) { |
| if (this == &other) |
| return *this; |
| data_ = other.data_; |
| capacity_ = other.capacity_; |
| actual_ = other.actual_; |
| other.data_ = nullptr; |
| other.capacity_ = 0u; |
| other.actual_ = 0u; |
| return *this; |
| } |
| |
| // Constructs a full |MessagePart| wrapping an array. |
| // The array is assumed to be initialized with data, such that |actual()| |
| // will match exactly the length of the array. |
| template <size_t N> |
| static MessagePart WrapFull(T (&array)[N]) { |
| return MessagePart(array, N, N); |
| } |
| |
| // Constructs an empty |MessagePart| wrapping an array. |
| // The array is assumed to be uninitialized, hence |actual()| is set to 0. |
| template <size_t N> |
| static MessagePart WrapEmpty(T (&array)[N]) { |
| return MessagePart(array, N, 0); |
| } |
| |
| // The data stored in this part of the message. |
| T* data() const { return data_; } |
| |
| // The total amount of storage available for this part of the message. |
| // |
| // This part of the message might not actually use all of this storage. To |
| // determine how much storage is actually being used, see |actual()|. |
| uint32_t capacity() const { return capacity_; } |
| |
| // The amount of storage that is actually being used for this part of the |
| // message. |
| // |
| // There might be more storage available than is actually being used. To |
| // determine how much storage is available, see |capacity()|. |
| uint32_t actual() const { return actual_; } |
| void set_actual(uint32_t actual) { actual_ = actual; } |
| |
| T* begin() { return data_; } |
| const T* begin() const { return data_; } |
| const T* cbegin() const { return data_; } |
| |
| T* end() { return data_ + actual_; } |
| const T* end() const { return data_ + actual_; } |
| const T* cend() const { return data_ + actual_; } |
| |
| size_t size() const { return actual_; } |
| |
| private: |
| T* data_; |
| uint32_t capacity_; |
| uint32_t actual_; |
| }; |
| |
| using BytePart = MessagePart<uint8_t>; |
| using HandlePart = MessagePart<zx_handle_t>; |
| using HandleDispositionPart = MessagePart<zx_handle_disposition_t>; |
| using HandleInfoPart = MessagePart<zx_handle_info_t>; |
| |
| } // namespace fidl |
| |
| #endif // LIB_FIDL_CPP_MESSAGE_PART_H_ |