| {{/* |
| // 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. |
| */}} |
| |
| {{- define "Table:ForwardDeclaration:WireTypesHeader" }} |
| {{ EnsureNamespace . }} |
| class {{ .Name }}; |
| {{- end }} |
| |
| {{/* TODO(fxbug.dev/36441): Remove __Fuchsia__ ifdefs once we have non-Fuchsia |
| emulated handles for C++. */}} |
| {{- define "Table:WireTypesHeader" }} |
| {{ if .IsResourceType }} |
| {{- IfdefFuchsia -}} |
| {{- end }} |
| |
| {{ EnsureNamespace "" }} |
| template<> |
| class {{ .WireTableBuilder }}; |
| template<> |
| class {{ .WireTableExternalBuilder }}; |
| |
| template <> |
| struct {{ .WireTableFrame }} final { |
| public: |
| {{ .WireTableFrame.Self }}() = default; |
| // In its intended usage, WireTableFrame will be referenced by an ObjectView. |
| // If the ObjectView is assigned before a move or copy, then it will reference |
| // the old invalid object. Because this is unsafe, copies are disallowed and |
| // moves are only allowed by friend classes that operate safely. |
| {{ .WireTableFrame.Self }}(const {{ .WireTableFrame.Self }}&) = delete; |
| {{ .WireTableFrame.Self }}& operator=(const {{ .WireTableFrame.Self }}&) = delete; |
| |
| private: |
| {{ .WireTableFrame.Self }}({{ .WireTableFrame.Self }}&&) noexcept = default; |
| {{ .WireTableFrame.Self }}& operator=({{ .WireTableFrame.Self }}&&) noexcept = default; |
| |
| bool HasUnknownData() const; |
| |
| {{- range $index, $item := .FrameItems }} |
| {{- if $item }} |
| ::fidl::Envelope<{{ $item.Type }}> {{ $item.Name }}_; |
| {{- else }} |
| [[maybe_unused]] ::fidl::UntypedEnvelope reserved_{{ $index }}_; |
| {{- end }} |
| {{- end }} |
| |
| friend class {{ . }}; |
| friend ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableBuilder }}>; |
| friend ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableExternalBuilder }}>; |
| }; |
| |
| {{ EnsureNamespace . }} |
| extern "C" const fidl_type_t {{ .CodingTableType.Name }}; |
| {{ .Docs }} |
| class {{ .Name }} { |
| public: |
| {{- range .AnonymousChildren }} |
| using {{ .ScopedName }} = {{ .FlattenedName }}; |
| {{- end }} |
| {{ .Name }}() = default; |
| {{ .Name }}(const {{ .Name }}& other) noexcept = default; |
| {{ .Name }}& operator=(const {{ .Name }}& other) noexcept = default; |
| {{ .Name }}({{ .Name }}&& other) noexcept = default; |
| {{ .Name }}& operator=({{ .Name }}&& other) noexcept = default; |
| |
| ~{{ .Name }}() = default; |
| |
| // Returns whether no field is set. |
| bool IsEmpty() const { return max_ordinal_ == 0; } |
| |
| // Returns whether the table references unknown fields. |
| bool HasUnknownData() const; |
| |
| {{- if .IsResourceType }} |
| void _CloseHandles(); |
| {{- end }} |
| |
| // Return a builder that by defaults allocates of an arena. |
| static {{ .WireTableBuilder }} Builder(::fidl::AnyArena& arena); |
| |
| // Return a builder that relies on explicitly allocating |fidl::ObjectView|s. |
| static {{ .WireTableExternalBuilder }} ExternalBuilder(::fidl::ObjectView<{{ .WireTableFrame }}> frame); |
| |
| {{- range .Members }} |
| {{ "" }} |
| {{- .Docs }} |
| const {{ .Type }}& {{ .Name }}() const { |
| ZX_ASSERT({{ .MethodHasName }}()); |
| return frame_ptr_->{{ .Name }}_.get_data(); |
| } |
| {{ .Type }}& {{ .Name }}() { |
| ZX_ASSERT({{ .MethodHasName }}()); |
| return frame_ptr_->{{ .Name }}_.get_data(); |
| } |
| bool {{ .MethodHasName }}() const { |
| return max_ordinal_ >= {{ .Ordinal }} && frame_ptr_->{{ .Name }}_.has_data(); |
| } |
| {{- end }} |
| |
| {{- /* Temporarily special case fuchsia.hardware.goldfish because of out of tree users. */}} |
| #if defined(FIDL_WIRE_ALLOW_DEPRECATED_MUTABLE_TABLES) || {{ eq .Namespace.String "::fuchsia_hardware_goldfish::wire" }} |
| public: |
| #else // !defined(FIDL_WIRE_ALLOW_DEPRECATED_MUTABLE_TABLES) |
| private: |
| #endif // FIDL_WIRE_ALLOW_DEPRECATED_MUTABLE_TABLES |
| {{ range .Members }} |
| |
| {{- if .Type.InlineInEnvelope }} |
| {{ $.Name }}& set_{{ .Name }}({{ .Type }} elem) { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.set_data(std::move(elem)); |
| max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>({{ .Ordinal }})); |
| return *this; |
| } |
| {{- else }} |
| {{- /* TODO(fxbug.dev/7999): The elem pointer should be const if it has no handles. */}} |
| {{ $.Name }}& set_{{ .Name }}(::fidl::ObjectView<{{ .Type }}> elem) { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.set_data(elem); |
| max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>({{ .Ordinal }})); |
| return *this; |
| } |
| {{ $.Name }}& set_{{ .Name }}(std::nullptr_t) { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.set_data(nullptr); |
| return *this; |
| } |
| template <typename... Args> |
| {{ $.Name }}& set_{{ .Name }}(::fidl::AnyArena& allocator, Args&&... args) { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.set_data( |
| ::fidl::ObjectView<{{ .Type }}>(allocator, std::forward<Args>(args)...)); |
| max_ordinal_ = std::max(max_ordinal_, static_cast<uint64_t>({{ .Ordinal }})); |
| return *this; |
| } |
| {{- end }} |
| |
| {{ $.Name }}& clear_{{ .Name }}() { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.clear_data(); |
| return *this; |
| } |
| {{- end }} |
| |
| explicit {{ .Name }}(::fidl::AnyArena& allocator) |
| : frame_ptr_(::fidl::ObjectView<{{ .WireTableFrame }}>(allocator)) {} |
| // This constructor allows a user controlled allocation (not using a Arena). |
| // It should only be used when performance is key. |
| // As soon as the frame is given to the table, it must not be used directly or for another table. |
| explicit {{ .Name }}(::fidl::ObjectView<{{ .WireTableFrame }}>&& frame) |
| : frame_ptr_(std::move(frame)) {} |
| |
| void Allocate(::fidl::AnyArena& allocator) { |
| max_ordinal_ = 0; |
| frame_ptr_ = ::fidl::ObjectView<{{ .WireTableFrame }}>(allocator); |
| } |
| void Init(::fidl::ObjectView<{{ .WireTableFrame }}>&& frame_ptr) { |
| max_ordinal_ = 0; |
| frame_ptr_ = std::move(frame_ptr); |
| } |
| |
| private: |
| friend ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableBuilder }}>; |
| friend ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableExternalBuilder }}>; |
| |
| uint64_t max_ordinal_ = 0; |
| ::fidl::ObjectView<{{ .WireTableFrame }}> frame_ptr_; |
| }; |
| |
| {{- EnsureNamespace "" }} |
| template<typename BuilderImpl> |
| class ::fidl::internal::WireTableBaseBuilder<{{ . }}, BuilderImpl> { |
| public: |
| // Build and return the table. The builder should not be used after this. |
| {{ . }} Build() { |
| ZX_DEBUG_ASSERT(table_.frame_ptr_ != nullptr); |
| {{ . }} t = std::move(table_); |
| // Poison this builder to prevent accidental reuse. |
| table_.frame_ptr_ = nullptr; |
| return t; |
| } |
| |
| {{- range .Members }} |
| {{ .Docs }} |
| {{- if .Type.InlineInEnvelope }} |
| BuilderImpl& {{ .Name }}({{ .Type }} elem) { |
| ZX_DEBUG_ASSERT(table_.frame_ptr_ != nullptr); |
| table_.frame_ptr_->{{ .Name }}_.set_data(std::move(elem)); |
| table_.max_ordinal_ = std::max(table_.max_ordinal_, static_cast<uint64_t>({{ .Ordinal }})); |
| return *static_cast<BuilderImpl*>(this); |
| } |
| {{- else }} |
| {{- /* TODO(fxbug.dev/7999): The elem pointer should be const if it has no handles. */}} |
| BuilderImpl& {{ .Name }}(::fidl::ObjectView<{{ .Type }}> elem) { |
| ZX_DEBUG_ASSERT(table_.frame_ptr_ != nullptr); |
| table_.frame_ptr_->{{ .Name }}_.set_data(elem); |
| table_.max_ordinal_ = std::max(table_.max_ordinal_, static_cast<uint64_t>({{ .Ordinal }})); |
| return *static_cast<BuilderImpl*>(this); |
| } |
| {{- end }} |
| {{- end }} |
| protected: |
| WireTableBaseBuilder(::fidl::ObjectView<{{ .WireTableFrame }}>&& frame) |
| : table_(std::move(frame)) {} |
| |
| private: |
| {{ . }} table_; |
| }; |
| |
| template<> |
| class {{ .WireTableBuilder }} final : public ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableBuilder }}> { |
| using Base = ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableBuilder }}>; |
| public: |
| {{- range .Members }} |
| {{- if not .Type.InlineInEnvelope }} |
| using Base::{{ .Name }}; |
| {{ .Docs }} |
| template <typename... Args> |
| {{ $.WireTableBuilder }}& {{ .Name }}(Args&&... args_) { |
| {{ .Name }}(::fidl::ObjectView<{{ .Type }}>(arena_.get(), std::forward<Args>(args_)...)); |
| return *this; |
| } |
| {{- end }} |
| {{- end }} |
| private: |
| friend class {{ . }}; |
| {{ .WireTableBuilder.Self }}(::fidl::AnyArena& arena) |
| : Base(::fidl::ObjectView<{{ .WireTableFrame }}>(arena)), |
| arena_(arena) {} |
| |
| [[maybe_unused]] std::reference_wrapper<::fidl::AnyArena> arena_; |
| |
| }; |
| |
| template<> |
| class {{ .WireTableExternalBuilder }} final : public ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableExternalBuilder }}> { |
| using Base = ::fidl::internal::WireTableBaseBuilder<{{ . }}, {{ .WireTableExternalBuilder }}>; |
| private: |
| friend class {{ . }}; |
| using Base::Base; |
| {{ .WireTableExternalBuilder.Self }}({{ .WireTableFrame }}* frame) |
| : Base(::fidl::ObjectView<{{ .WireTableFrame }}>::FromExternal(frame)) {} |
| }; |
| |
| {{- EnsureNamespace . }} |
| inline {{ .WireTableBuilder }} {{ .Name }}::Builder(::fidl::AnyArena& arena) { |
| return {{ .WireTableBuilder }}(arena); |
| } |
| inline {{ .WireTableExternalBuilder }} {{ .Name }}::ExternalBuilder(::fidl::ObjectView<{{ .WireTableFrame }}> frame) { |
| return {{ .WireTableExternalBuilder }}(std::move(frame)); |
| } |
| |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{ end }} |
| {{- end }} |
| |
| {{- define "Table:WireTypesSource" }} |
| {{ if .IsResourceType }} |
| {{/* TODO(fxbug.dev/36441): Remove __Fuchsia__ ifdefs once we have non-Fuchsia |
| emulated handles for C++. */}} |
| {{- IfdefFuchsia -}} |
| {{- end }} |
| |
| {{ EnsureNamespace "" }} |
| bool {{ .WireTableFrame }}::HasUnknownData() const { |
| {{- range $index, $item := .FrameItems }} |
| {{- if not $item }} |
| if (!reserved_{{ $index }}_.IsZeroEnvelope()) { |
| return true; |
| } |
| {{- end }} |
| {{- end }} |
| return false; |
| } |
| |
| bool {{ . }}::HasUnknownData() const { |
| if (max_ordinal_ > {{ .BiggestOrdinal }}) { |
| return true; |
| } |
| if (frame_ptr_ == nullptr) { |
| return false; |
| } |
| return frame_ptr_->HasUnknownData(); |
| } |
| |
| {{ if .IsResourceType }} |
| void {{ . }}::_CloseHandles() { |
| {{- range .Members }} |
| {{- if .Type.IsResource }} |
| if (has_{{ .Name }}()) { |
| {{- CloseHandles . true false }} |
| } |
| {{- end }} |
| {{- end }} |
| } |
| {{- end }} |
| |
| {{ if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |
| |
| {{/* TODO(fxbug.dev/36441): Remove __Fuchsia__ ifdefs once we have non-Fuchsia |
| emulated handles for C++. */}} |
| {{- define "Table:Traits:WireTypesHeader" }} |
| {{ if .IsResourceType }} |
| {{- IfdefFuchsia -}} |
| template <> |
| struct IsResource<{{ . }}> : public std::true_type {}; |
| {{- end }} |
| |
| template <> |
| struct TypeTraits<{{ . }}> { |
| static constexpr const fidl_type_t* kType = &{{ .CodingTableType }}; |
| static constexpr uint32_t kMaxNumHandles = {{ .TypeShapeV2.MaxHandles }}; |
| static constexpr uint32_t kPrimarySize = {{ .TypeShapeV2.InlineSize }}; |
| static constexpr uint32_t kPrimarySizeV1 = {{ .TypeShapeV1.InlineSize }}; |
| [[maybe_unused]] |
| static constexpr uint32_t kMaxOutOfLine = {{ .TypeShapeV2.MaxOutOfLine }}; |
| static constexpr uint32_t kMaxOutOfLineV1 = {{ .TypeShapeV1.MaxOutOfLine }}; |
| static constexpr bool kHasPointer = {{ .TypeShapeV2.HasPointer }}; |
| }; |
| |
| template <> |
| struct IsFidlType<{{ . }}> : public std::true_type {}; |
| template <> |
| struct IsTable<{{ . }}> : public std::true_type {}; |
| static_assert(std::is_standard_layout_v<{{ . }}>); |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |
| |