| {{/* |
| // 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 }} |
| |
| {{- 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; |
| uint64_t ComputeMaxOrdinal() 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 . }} |
| {{ .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 }} |
| [[ nodiscard ]] {{ .Type }}& {{ .Name }}() const { |
| ZX_ASSERT({{ .MethodHasName }}()); |
| return frame_ptr_->{{ .Name }}_.get_data(); |
| } |
| [[ nodiscard ]] 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(https://fxbug.dev/42160282): 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 }}& {{ .MethodClearName }}() { |
| ZX_DEBUG_ASSERT(frame_ptr_ != nullptr); |
| frame_ptr_->{{ .Name }}_.clear_data(); |
| max_ordinal_ = frame_ptr_->ComputeMaxOrdinal(); |
| 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> { |
| protected: |
| // |Wrapper_Ignore_Me_| wraps a |fidl::ObjectView<T>| and reduces its |
| // priority in overload resolution. When the user writes `{}` as the |
| // setter argument, that would default construct the field instead of |
| // constructing a NULL object view. |
| template <typename U> |
| struct Wrapper_Ignore_Me_ { |
| Wrapper_Ignore_Me_(U v) : value(v) {} |
| U value; |
| }; |
| |
| 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 }} |
| [[ nodiscard ]] bool {{ .MethodHasName }}() const { |
| return table_.{{ .MethodHasName }}(); |
| } |
| |
| // Clears the {{ .Name }} field. |
| // |
| // This method should be used sparingly, such as only during tests, as it has |
| // O(number_of_fields) complexity. |
| void {{ .MethodClearName }}() { |
| table_.{{ .MethodClearName }}(); |
| } |
| |
| // Getter for {{ .Name }}. |
| // |
| {{ .Docs }} |
| [[ nodiscard ]] {{ .Type }}& {{ .Name }}() const { |
| return table_.{{ .Name }}(); |
| } |
| |
| // Setter for {{ .Name }}. |
| // |
| {{ .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(https://fxbug.dev/42160282): The elem pointer should be const if it has no handles. */}} |
| BuilderImpl& {{ .Name }}(Wrapper_Ignore_Me_<::fidl::ObjectView<{{ .Type }}>> elem) { |
| ZX_DEBUG_ASSERT(table_.frame_ptr_ != nullptr); |
| ZX_DEBUG_ASSERT(elem.value.get() != nullptr); |
| table_.frame_ptr_->{{ .Name }}_.set_data(elem.value); |
| 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 First = {{ .Type }}, |
| typename... Args, |
| std::enable_if_t<!std::is_same_v<cpp20::remove_cvref_t<First>, fidl::ObjectView<{{ .Type }}>>, int> = 0 |
| > |
| {{ $.WireTableBuilder }}& {{ .Name }}(First&& first, Args&&... args_) { |
| fidl::ObjectView<{{ .Type }}> view_(arena_.get(), std::forward<First>(first), std::forward<Args>(args_)...); |
| {{ .Name }}(Base::Wrapper_Ignore_Me_<fidl::ObjectView<{{ .Type }}>>(view_)); |
| 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 }} |
| {{- IfdefFuchsia -}} |
| {{- end }} |
| |
| {{ EnsureNamespace "" }} |
| bool {{ .WireTableFrame }}::HasUnknownData() const { |
| {{- range $index, $item := .FrameItems }} |
| {{- if not $item }} |
| if (!reserved_{{ $index }}_.IsZeroEnvelope()) { |
| return true; |
| } |
| {{- end }} |
| {{- end }} |
| return false; |
| } |
| |
| uint64_t {{ .WireTableFrame.NoLeading }}::ComputeMaxOrdinal() const { |
| uint64_t max_ordinal = 0; |
| {{- range $index, $item := .FrameItems }} |
| {{- if not $item }} |
| if (!reserved_{{ $index }}_.IsZeroEnvelope()) { |
| max_ordinal = {{ $index }}; |
| } |
| {{- else }} |
| if (!{{ $item }}_.has_data()) { |
| max_ordinal = {{ $item.Ordinal }}; |
| } |
| {{- end }} |
| {{- end }} |
| return max_ordinal; |
| } |
| |
| 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 }} |
| } |
| {{- end }} |
| {{- end }} |
| } |
| {{- end }} |
| |
| {{ if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |
| |
| {{- define "Table:Traits:WireTypesHeader" }} |
| {{ if .IsResourceType }} |
| {{- IfdefFuchsia -}} |
| template <> |
| struct IsResource<{{ . }}> : public std::true_type {}; |
| {{- end }} |
| |
| template <> |
| struct TypeTraits<{{ . }}> { |
| static constexpr uint32_t kMaxNumHandles = {{ .TypeShapeV2.MaxHandles }}; |
| static constexpr uint32_t kMaxDepth = {{ .TypeShapeV2.Depth }}; |
| static constexpr uint32_t kPrimarySize = {{ .TypeShapeV2.InlineSize }}; |
| [[maybe_unused]] |
| static constexpr uint32_t kMaxOutOfLine = {{ .TypeShapeV2.MaxOutOfLine }}; |
| static constexpr bool kHasFlexibleEnvelope = {{ .TypeShapeV2.HasFlexibleEnvelope }}; |
| static constexpr bool kHasPointer = {{ .TypeShapeV2.HasPointer }}; |
| }; |
| |
| template <> |
| struct IsFidlType<{{ . }}> : public std::true_type {}; |
| template <> |
| struct IsWire<{{ . }}> : public std::true_type {}; |
| template <> |
| struct IsTable<{{ . }}> : public std::true_type {}; |
| static_assert(std::is_standard_layout_v<{{ . }}>); |
| |
| template <bool IsRecursive> |
| struct ::fidl::internal::WireCodingTraits<{{ . }}, ::fidl::internal::WireCodingConstraintEmpty, IsRecursive> |
| : ::fidl::internal::WireTableCodingTraitsBase<IsRecursive> { |
| using Base = ::fidl::internal::WireTableCodingTraitsBase<IsRecursive>; |
| static constexpr size_t inline_size = {{ .TypeShapeV2.InlineSize }}; |
| static constexpr bool is_memcpy_compatible = false; |
| |
| static void Encode(internal::WireEncoder* encoder, {{ . }}* value, ::fidl::internal::WirePosition position, RecursionDepth<IsRecursive> recursion_depth) { |
| RecursionDepth<IsRecursive> inner_depth = recursion_depth.Add(encoder, 2); |
| if (!inner_depth.IsValid()) { |
| return; |
| } |
| |
| ::fidl::internal::WirePosition vector_position; |
| if (Base::PreworkResult::kEarlyExit == |
| Base::PrepareForBodyEncode(encoder, value, position, &vector_position)) { |
| return; |
| } |
| |
| fidl_vector_t* vec = reinterpret_cast<fidl_vector_t*>(value); |
| fidl_envelope_t* envelopes = static_cast<fidl_envelope_t*>(vec->data); |
| for (size_t i = 0; i < vec->count; i++) { |
| {{/* Two switches here, so they are translated to lookup tables. */}} |
| size_t encode_inline_size = 0; |
| switch (i) { |
| {{- range .Members }} |
| case {{ Sub .Ordinal 1 }}: |
| encode_inline_size = ::fidl::internal::WireCodingTraits<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>::inline_size; |
| break; |
| {{- end }} |
| } |
| ::fidl::internal::EncodeFn<IsRecursive> encode_fn = nullptr; |
| switch (i) { |
| {{- range .Members }} |
| case {{ Sub .Ordinal 1 }}: |
| encode_fn = ::fidl::internal::MakeEncodeFn<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>(); |
| break; |
| {{- end }} |
| } |
| WirePosition envelope_position = vector_position + i * sizeof(fidl_envelope_t); |
| WireEncodeEnvelope(encode_inline_size, encode_fn, encoder, &envelopes[i], envelope_position, inner_depth); |
| } |
| } |
| static void Decode(internal::WireDecoder* decoder, ::fidl::internal::WirePosition position, RecursionDepth<IsRecursive> recursion_depth) { |
| RecursionDepth<IsRecursive> inner_depth = recursion_depth.Add(decoder, 2); |
| if (!inner_depth.IsValid()) { |
| return; |
| } |
| |
| ::fidl::internal::WirePosition vector_position; |
| if (Base::PreworkResult::kEarlyExit == Base::DecodePrework(decoder, position, &vector_position)) { |
| return; |
| } |
| |
| fidl_vector_t* vec = position.As<fidl_vector_t>(); |
| for (size_t i = 0; i < vec->count; i++) { |
| {{/* Two switches here, so they are translated to lookup tables. */}} |
| size_t decode_inline_size = 0; |
| switch (i) { |
| {{- range .Members }} |
| case {{ Sub .Ordinal 1 }}: |
| decode_inline_size = ::fidl::internal::WireCodingTraits<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>::inline_size; |
| break; |
| {{- end }} |
| } |
| DecodeFn<IsRecursive> decode_fn = nullptr; |
| switch(i) { |
| {{- range .Members }} |
| case {{ Sub .Ordinal 1 }}: |
| decode_fn = ::fidl::internal::MakeDecodeFn<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>(); |
| break; |
| {{- end }} |
| } |
| ::fidl::internal::WireDecodeOptionalEnvelope(decode_inline_size, decode_fn, decoder, vector_position + i * sizeof(fidl_envelope_t), inner_depth); |
| } |
| } |
| }; |
| |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |