| // Copyright 2022 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 SRC_LIB_FIDL_CPP_INCLUDE_LIB_FIDL_CPP_NATURAL_ENCODER_H_ |
| #define SRC_LIB_FIDL_CPP_INCLUDE_LIB_FIDL_CPP_NATURAL_ENCODER_H_ |
| |
| #include <lib/fidl/coding.h> |
| #include <lib/fidl/cpp/wire_format_metadata.h> |
| #include <lib/fidl/internal.h> |
| #include <lib/fidl/llcpp/internal/transport.h> |
| #include <lib/fidl/llcpp/message.h> |
| #include <lib/stdcompat/span.h> |
| #include <zircon/fidl.h> |
| |
| #include <vector> |
| |
| namespace fidl::internal { |
| |
| // Used in the default constructor of MallocedUniquePtr below to do nothing in the case that |
| // no handle metadata is allocated. |
| void ptr_noop(void*); |
| |
| class NaturalEncoder { |
| using MallocedUniquePtr = std::unique_ptr<void, void (*)(void*)>; |
| |
| public: |
| explicit NaturalEncoder(const CodingConfig* coding_config); |
| NaturalEncoder(const CodingConfig* coding_config, internal::WireFormatVersion wire_format); |
| |
| NaturalEncoder(NaturalEncoder&&) noexcept = default; |
| NaturalEncoder& operator=(NaturalEncoder&&) noexcept = default; |
| ~NaturalEncoder() = default; |
| |
| size_t Alloc(size_t size); |
| |
| template <typename T> |
| T* GetPtr(size_t offset) { |
| return reinterpret_cast<T*>(bytes_.data() + offset); |
| } |
| |
| template <typename T> |
| const T* GetPtr(size_t offset) const { |
| return reinterpret_cast<const T*>(bytes_.data() + offset); |
| } |
| |
| void EncodeHandle(fidl_handle_t handle, HandleAttributes attr, size_t offset, bool is_optional); |
| |
| size_t CurrentLength() const { return bytes_.size(); } |
| |
| size_t CurrentHandleCount() const { return handles_.size(); } |
| |
| std::vector<uint8_t> TakeBytes() { return std::move(bytes_); } |
| |
| internal::WireFormatVersion wire_format() const { return wire_format_; } |
| |
| WireFormatMetadata wire_format_metadata() const { |
| return internal::WireFormatMetadataForVersion(wire_format_); |
| } |
| |
| void SetError(const char* error) { |
| if (status_ != ZX_OK) |
| return; |
| status_ = ZX_ERR_INVALID_ARGS; |
| error_ = error; |
| } |
| |
| protected: |
| const CodingConfig* coding_config_; |
| std::vector<uint8_t> bytes_; |
| std::vector<fidl_handle_t> handles_; |
| |
| // When handle ownership is transferred to an |OutgoingMessage|, our class |
| // must no longer close those handles, but still need to keep their backing |
| // storage alive. This is done by moving the vector buffer to a second vector |
| // which does not close handles. |
| std::vector<fidl_handle_t> handles_staging_area_; |
| MallocedUniquePtr handle_metadata_ = MallocedUniquePtr(nullptr, ptr_noop); |
| internal::WireFormatVersion wire_format_ = internal::WireFormatVersion::kV2; |
| zx_status_t status_ = ZX_OK; |
| const char* error_ = nullptr; |
| }; |
| |
| // The NaturalBodyEncoder produces an |OutgoingMessage|, representing an encoded |
| // domain object (typically used as a transactional message body). |
| class NaturalBodyEncoder final : public NaturalEncoder { |
| public: |
| NaturalBodyEncoder(const TransportVTable* vtable, internal::WireFormatVersion wire_format) |
| : NaturalEncoder(vtable->encoding_configuration, wire_format), vtable_(vtable) {} |
| |
| NaturalBodyEncoder(NaturalBodyEncoder&& other) = default; |
| NaturalBodyEncoder& operator=(NaturalBodyEncoder&& other) noexcept = default; |
| |
| ~NaturalBodyEncoder(); |
| |
| enum class MessageType { kTransactional, kStandalone }; |
| |
| // Return a view representing the encoded body. |
| // Caller takes ownership of the handles. |
| // Do not encode another value until the previous message is sent. |
| fidl::OutgoingMessage GetOutgoingMessage(MessageType type) &&; |
| |
| // Free memory and close owned handles. |
| void Reset(); |
| |
| private: |
| friend class NaturalMessageEncoder; |
| |
| struct BodyView { |
| cpp20::span<uint8_t> bytes; |
| fidl_handle_t* handles; |
| fidl_handle_metadata_t* handle_metadata; |
| uint32_t num_handles; |
| const TransportVTable* vtable; |
| }; |
| |
| const TransportVTable* vtable_; |
| }; |
| |
| } // namespace fidl::internal |
| |
| #endif // SRC_LIB_FIDL_CPP_INCLUDE_LIB_FIDL_CPP_NATURAL_ENCODER_H_ |