| {{/* |
| // Copyright 2019 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 "Union:ForwardDeclaration:WireTypesHeader" }} |
| {{ EnsureNamespace . }} |
| class {{ .Name }}; |
| {{- end }} |
| |
| {{- define "Union:WireTypesHeader" }} |
| {{ EnsureNamespace . }} |
| {{ if .IsResourceType }} |
| {{- IfdefFuchsia -}} |
| {{- end }} |
| {{ .Docs }} |
| class {{ .Name }} { |
| public: |
| {{- range .AnonymousChildren }} |
| using {{ .ScopedName }} = {{ .FlattenedName }}; |
| {{- end }} |
| |
| {{ .Name }}() : ordinal_({{ .WireInvalidOrdinal }}), envelope_{} {} |
| |
| {{ if .IsResourceType }} |
| ~{{ .Name }}(); |
| {{ .Name }}({{ .Name }}&& other) { |
| _Move(std::move(other)); |
| } |
| {{ .Name }}& operator=({{ .Name }}&& other) { |
| if (this != &other) { |
| _Move(std::move(other)); |
| } |
| return *this; |
| } |
| {{- else -}} |
| {{ .Name }}(const {{ .Name }}&) = default; |
| {{ .Name }}& operator=(const {{ .Name }}&) = default; |
| {{ .Name }}({{ .Name }}&&) = default; |
| {{ .Name }}& operator=({{ .Name }}&&) = default; |
| {{- end }} |
| |
| enum class {{ .TagEnum.Self }} : fidl_xunion_tag_t { |
| {{- range .Members }} |
| {{ .TagName.Self }} = {{ .Ordinal }}, // {{ .Ordinal | printf "%#x" }} |
| {{- end }} |
| {{- if .IsFlexible }} |
| {{ .TagUnknown.Self }} = ::std::numeric_limits<::fidl_union_tag_t>::max(), |
| {{- end }} |
| }; |
| |
| {{- if .IsFlexible }} |
| constexpr bool IsUnknown() const { |
| return Which() == {{ .TagUnknown }}; |
| } |
| {{- end }} |
| |
| bool has_invalid_tag() const { return ordinal_ == {{ .WireInvalidOrdinal }}; } |
| |
| {{- range $index, $member := .Members }} |
| |
| bool is_{{ .Name }}() const { return ordinal_ == {{ .WireOrdinalName }}; } |
| |
| {{- if .Type.InlineInEnvelope }} |
| {{ .Docs }} |
| static {{ $.Name }} With{{ .UpperCamelCaseName }}({{ .Type }} val) { |
| {{ $.Name }} result; |
| result.ordinal_ = {{ .WireOrdinalName }}; |
| result.envelope_.As<{{ .Type }}>().set_data(std::move(val)); |
| return result; |
| } |
| {{- else }} |
| {{ .Docs }} |
| static {{ $.Name }} With{{ .UpperCamelCaseName }}(::fidl::ObjectView<{{ .Type }}> val) { |
| {{ $.Name }} result; |
| result.ordinal_ = {{ .WireOrdinalName }}; |
| result.envelope_.As<{{ .Type }}>().set_data(std::move(val)); |
| return result; |
| } |
| |
| {{ .Docs }} |
| template <typename... Args> |
| static {{ $.Name }} With{{ .UpperCamelCaseName }}(::fidl::AnyArena& allocator, Args&&... args) { |
| return With{{ .UpperCamelCaseName }}(::fidl::ObjectView<{{ .Type }}>(allocator, |
| std::forward<Args>(args)...)); |
| } |
| {{- end }} |
| |
| {{ "" }} |
| {{- .Docs }} |
| {{ .Type }}& {{ .Name }}() { |
| ZX_ASSERT(ordinal_ == {{ .WireOrdinalName }}); |
| return envelope_.As<{{ .Type }}>().get_data(); |
| } |
| {{- .Docs }} |
| const {{ .Type }}& {{ .Name }}() const { |
| ZX_ASSERT(ordinal_ == {{ .WireOrdinalName }}); |
| return envelope_.As<{{ .Type }}>().get_data(); |
| } |
| {{- end }} |
| |
| {{- if .IsFlexible }} |
| {{ .TagEnum }} Which() const; |
| {{- else }} |
| {{ .TagEnum }} Which() const { |
| ZX_ASSERT(!has_invalid_tag()); |
| return static_cast<{{ .TagEnum }}>(ordinal_); |
| } |
| {{- end }} |
| |
| {{- if .IsResourceType }} |
| void _CloseHandles(); |
| {{- end }} |
| |
| private: |
| enum class {{ .WireOrdinalEnum.Self }} : fidl_xunion_tag_t { |
| {{ .WireInvalidOrdinal.Self }} = 0, |
| {{- range .Members }} |
| {{ .WireOrdinalName.Self }} = {{ .Ordinal }}, // {{ .Ordinal | printf "%#x" }} |
| {{- end }} |
| }; |
| |
| {{- if .IsResourceType }} |
| void _Move({{ .Name }}&& other); |
| {{- end }} |
| |
| static void SizeAndOffsetAssertionHelper(); |
| |
| {{- /* All fields are private to maintain standard layout */}} |
| {{ .WireOrdinalEnum }} ordinal_; |
| FIDL_ALIGNDECL |
| ::fidl::UntypedEnvelope envelope_; |
| }; |
| |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |
| |
| {{- define "Union:WireTypesSource" }} |
| {{- if .IsResourceType }} |
| {{- IfdefFuchsia -}} |
| {{- end }} |
| {{- if .IsFlexible }} |
| auto {{ . }}::Which() const -> {{ .TagEnum }} { |
| ZX_ASSERT(!has_invalid_tag()); |
| {{- if .Members }} |
| switch (ordinal_) { |
| {{- range .Members }} |
| case {{ .WireOrdinalName }}: |
| {{- end }} |
| return static_cast<{{ .TagEnum }}>(ordinal_); |
| default: |
| return {{ .TagUnknown }}; |
| } |
| {{- else }} |
| return {{ .TagUnknown }}; |
| {{- end }} |
| } |
| {{- end }} |
| |
| void {{ . }}::SizeAndOffsetAssertionHelper() { |
| static_assert(sizeof({{ .Name }}) == sizeof(fidl_union_t)); |
| static_assert(offsetof({{ .Name }}, ordinal_) == offsetof(fidl_union_t, tag)); |
| static_assert(offsetof({{ .Name }}, envelope_) == offsetof(fidl_union_t, envelope)); |
| } |
| |
| {{- if .IsResourceType }} |
| {{ . }}::~{{ .Name }}() { |
| switch (ordinal_) { |
| {{- range .Members }} |
| case {{ .WireOrdinalName }}: |
| envelope_.As<{{ .Type }}>().clear_data(); |
| break; |
| {{- end }} |
| default: |
| break; |
| } |
| } |
| |
| void {{ . }}::_Move({{ .Name }}&& other) { |
| ordinal_ = other.ordinal_; |
| switch (ordinal_) { |
| {{- range .Members }} |
| case {{ .WireOrdinalName }}: |
| envelope_.As<{{ .Type }}>() = std::move(other.envelope_.As<{{ .Type }}>()); |
| break; |
| {{- end }} |
| default: |
| break; |
| } |
| } |
| |
| void {{ . }}::_CloseHandles() { |
| switch (ordinal_) { |
| {{- range .Members }} |
| {{- if .Type.IsResource }} |
| case {{ .WireOrdinalName }}: { |
| {{- CloseHandles . true }} |
| break; |
| } |
| {{- end }} |
| {{- end }} |
| default: |
| break; |
| } |
| } |
| {{- end }} |
| |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |
| |
| {{- define "Union: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 IsUnion<{{ . }}> : public std::true_type {}; |
| static_assert(std::is_standard_layout_v<{{ . }}>); |
| |
| template <typename Constraint, bool IsRecursive> |
| struct ::fidl::internal::WireCodingTraits<{{ . }}, Constraint, 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) { |
| fidl_union_t* u = reinterpret_cast<fidl_union_t*>(value); |
| |
| if (unlikely(u->tag == 0)) { |
| if constexpr (Constraint::is_optional) { |
| *position.As<fidl_union_t>() = {}; |
| return; |
| } |
| encoder->SetError(kCodingErrorInvalidUnionTag); |
| return; |
| } |
| |
| RecursionDepth<IsRecursive> inner_depth = recursion_depth.Add(encoder, 1); |
| if (!inner_depth.IsValid()) { |
| return; |
| } |
| |
| *position.As<fidl_xunion_tag_t>() = u->tag; |
| |
| {{/* Two switches here, so they are translated to lookup tables. */}} |
| size_t encode_inline_size; |
| switch (u->tag) { |
| {{- range .Members }} |
| case {{ .Ordinal }}: // {{ .TagName }} |
| encode_inline_size = ::fidl::internal::WireCodingTraits<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>::inline_size; |
| break; |
| {{- end }} |
| default: |
| encode_inline_size = 0; |
| break; |
| } |
| ::fidl::internal::EncodeFn<IsRecursive> encode_fn; |
| switch (u->tag) { |
| {{- range .Members }} |
| case {{ .Ordinal }}: // {{ .TagName }} |
| encode_fn = ::fidl::internal::MakeEncodeFn<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>(); |
| break; |
| {{- end }} |
| default: |
| encode_fn = nullptr; |
| break; |
| } |
| WireEncodeEnvelope(encode_inline_size, encode_fn, encoder, &u->envelope, position + sizeof(fidl_xunion_tag_t), inner_depth); |
| } |
| |
| static void Decode(internal::WireDecoder* decoder, ::fidl::internal::WirePosition position, RecursionDepth<IsRecursive> recursion_depth) { |
| {{ .TagEnum }} tag = *position.As<{{ .TagEnum }}>(); |
| if (unlikely(static_cast<uint64_t>(tag) == 0)) { |
| if constexpr (!Constraint::is_optional) { |
| decoder->SetError(kCodingErrorInvalidUnionTag); |
| return; |
| } |
| static_assert(sizeof(fidl_envelope_t) == sizeof(uint64_t)); |
| if (*(position + sizeof(fidl_xunion_tag_t)).As<uint64_t>() != 0) { |
| decoder->SetError(kCodingErrorZeroTagButNonZeroEnvelope); |
| } |
| return; |
| } |
| |
| RecursionDepth<IsRecursive> inner_depth = recursion_depth.Add(decoder, 1); |
| if (!inner_depth.IsValid()) { |
| return; |
| } |
| |
| {{/* Two switches here, so they are translated to lookup tables. */}} |
| size_t decode_inline_size; |
| switch (tag) { |
| {{- range .Members }} |
| case {{ .TagName }}: |
| decode_inline_size = ::fidl::internal::WireCodingTraits<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>::inline_size; |
| break; |
| {{- end }} |
| default: |
| decode_inline_size = 0; |
| break; |
| } |
| DecodeFn<IsRecursive> decode_fn; |
| switch(tag) { |
| {{- range .Members }} |
| case {{ .TagName }}: |
| decode_fn = ::fidl::internal::MakeDecodeFn<{{ .Type }}, {{ .WireConstraint }}, IsRecursive>(); |
| break; |
| {{- end }} |
| default: |
| decode_fn = nullptr; |
| break; |
| } |
| {{- if .IsFlexible }} |
| ::fidl::internal::WireDecodeFlexibleEnvelope(decode_inline_size, decode_fn, decoder, position + sizeof(fidl_xunion_tag_t), inner_depth); |
| {{- else }} |
| ::fidl::internal::WireDecodeStrictEnvelope(decode_inline_size, decode_fn, decoder, position + sizeof(fidl_xunion_tag_t), inner_depth); |
| {{- end }} |
| } |
| }; |
| |
| // Top-level union. |
| template <bool IsRecursive> |
| struct ::fidl::internal::WireCodingTraits<{{ . }}, ::fidl::internal::WireCodingConstraintEmpty, IsRecursive> |
| : public ::fidl::internal::WireCodingTraits<{{ . }}, ::fidl::internal::WireCodingConstraintUnion<false>, IsRecursive> {}; |
| |
| {{- if .IsResourceType }} |
| {{- EndifFuchsia -}} |
| {{- end }} |
| {{- end }} |