blob: 7a16be729b4948b3004dc171414dcb6d8de9e243 [file] [log] [blame] [edit]
{{/*
// Copyright 2021 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:NaturalTypesHeader" }}
{{ EnsureNamespace . }}
class {{ .Name }};
{{- end }}
{{- define "Union:NaturalTypesHeader" }}
{{ EnsureNamespace . }}
{{ if .IsResourceType }}
{{- IfdefFuchsia -}}
{{- end }}
extern "C" const fidl_type_t {{ .CodingTableType.Name }};
{{ .Docs }}
class {{ .Name }} {
private:
using Storage_ =
std::variant<
std::monostate
{{- range .Members }}
, {{ .Type }}
{{- end -}}
>;
public:
// TODO: share union tag types between wire & natural.
enum class {{ .TagEnum.Self }} : fidl_union_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 }}
// Create an unknown value of this union.
{{ .Name }}() : storage_(std::make_shared<Storage_>()) {}
{{- end }}
{{ .Name }}({{ .Name }}&& other) noexcept
: {{ .Name }}(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{}) {
*storage_ = std::move(*other.storage_);
}
{{ .Name }}& operator=({{ .Name }}&& other) noexcept {
if (this != &other) {
*storage_ = std::move(*other.storage_);
}
return *this;
}
{{- if not .IsResourceType }}
{{ .Name }}(const {{ .Name }}& other) noexcept : {{ .Name }}(other.CloneStorage_()){}
{{ .Name }}& operator=(const {{ .Name }}& other) noexcept {
if (this != &other) {
storage_ = other.CloneStorage_();
}
return *this;
}
bool operator==(const {{ .Name }}& other) const noexcept {
return *storage_ == *other.storage_;
}
bool operator!=(const {{ .Name }}& other) const noexcept {
return *storage_ != *other.storage_;
}
{{- end }}
constexpr {{ .TagEnum }} Which() const {
return {{ .Name }}::IndexToTag(storage_->index()).value();
}
{{- range .Members }}
static {{ $.Name }} With{{ .UpperCamelCaseName }}({{ .Type }} val) {
return {{ $.Name }}(std::make_shared<Storage_>(
std::in_place_index_t<{{ .NaturalIndex }}>{},
std::move(val)));
}
const ::fidl::internal::UnionMemberView<{{ .NaturalIndex }}, Storage_> {{ .Name }}() const {
return ::fidl::internal::UnionMemberView<{{ .NaturalIndex }}, Storage_>(storage_);
}
::fidl::internal::UnionMemberView<{{ .NaturalIndex }}, Storage_> {{ .Name }}() {
return ::fidl::internal::UnionMemberView<{{ .NaturalIndex }}, Storage_>(storage_);
}
{{- end }}
{{ .Name }}(::fidl::internal::DefaultConstructPossiblyInvalidObjectTag) : storage_(std::make_shared<Storage_>()) {}
private:
std::shared_ptr<Storage_> storage_;
{{- if not .IsResourceType }}
std::shared_ptr<Storage_> CloneStorage_() const;
{{- end }}
friend struct ::fidl::internal::NaturalUnionCodingTraits<{{ . }}>;
static constexpr auto kMembers = std::make_tuple(
::fidl::internal::NaturalUnionMember<::fidl::internal::NaturalCodingConstraintEmpty>()
{{- range $i, $m := .Members }}
, ::fidl::internal::NaturalUnionMember<{{ $m.NaturalConstraint }}>()
{{- end -}}
);
explicit {{ .Name }}(std::shared_ptr<Storage_> storage) : storage_(std::move(storage)) {}
static constexpr size_t TagToIndex(::fidl::internal::NaturalDecoder* decoder, {{ .TagEnum }} tag) {
switch (tag) {
{{- range .Members }}
case {{ .TagName }}: return {{ .NaturalIndex }};
{{- end }}
{{- if .IsFlexible }}
case {{ .TagUnknown }}: return 0;
{{- end }}
default: {
decoder->SetError(::fidl::internal::kCodingErrorUnknownUnionTag);
return 0;
}
}
}
static constexpr std::optional<{{ .TagEnum }}> IndexToTag(size_t index) {
switch (index) {
{{- range .Members }}
case {{ .NaturalIndex }}: return {{ .TagName }};
{{- end }}
{{- if .IsFlexible }}
default: return {{ .TagUnknown }};
{{- else }}
default: return std::nullopt;
{{- end }}
}
}
};
{{ if .IsResourceType }}
{{- EndifFuchsia -}}
{{- end }}
{{- end }}
{{- define "Union:Traits:NaturalTypesHeader" }}
{{ if .IsResourceType }}
{{- IfdefFuchsia -}}
{{- end }}
extern "C" const fidl_type_t {{ .CodingTableType.Self }};
{{ if .IsResourceType }}
template <>
struct IsResource<{{ . }}> : public std::true_type {};
{{- end }}
template <>
struct IsFidlType<{{ . }}> : public std::true_type {};
template <>
struct IsUnion<{{ . }}> : public std::true_type {};
template <>
struct internal::NaturalCodingTraits<{{ . }}, ::fidl::internal::NaturalCodingConstraintEmpty> final
: public ::fidl::internal::NaturalUnionCodingTraits<{{ . }}> {};
{{ if .IsResourceType }}
{{- EndifFuchsia -}}
{{- end }}
{{- end }}
{{- define "Union:NaturalTypesSource" }}
{{ if .IsResourceType }}
{{- IfdefFuchsia -}}
{{- end }}
{{- EnsureNamespace "" }}
{{ if not .IsResourceType }}
std::shared_ptr<{{ . }}::Storage_> {{ .NoLeading }}::CloneStorage_() const {
const Storage_& storage = *storage_;
switch (storage_->index()) {
{{- range $i, $m := .Members }}
case {{ Add $i 1 }}:
return std::make_shared<Storage_>(
std::in_place_index<{{ Add $i 1 }}>,
::fidl::internal::NaturalClone(std::get<{{ Add $i 1 }}>(storage)));
{{- end }}
default:
return std::make_shared<Storage_>();
}
}
{{- end }}
{{ if .IsResourceType }}
{{- EndifFuchsia -}}
{{ end }}
{{- end }}
{{- define "Union:Traits:TypeConversionsHeader" }}
{{ if .IsResourceType }}
{{- IfdefFuchsia -}}
{{- end }}
{{ $wireType := .Wire }}
{{ $naturalType := .Unified }}
template <>
struct WireNaturalConversionTraits<{{ $wireType }}, {{ $naturalType }}> {
static {{ $naturalType }} ToNatural({{ $wireType }} src);
static {{ $wireType }} ToWire(fidl::AnyArena& arena, {{ $naturalType }} src);
};
template <>
struct WireNaturalConversionTraits<{{ $wireType }}, std::unique_ptr<{{ $naturalType }}>> {
static std::unique_ptr<{{ $naturalType }}> ToNatural({{ $wireType }} src);
static {{ $wireType }} ToWire(fidl::AnyArena& arena, std::unique_ptr<{{ $naturalType }}> src);
};
template <>
struct NaturalTypeForWireType<{{ $wireType }}> {
using type = std::unique_ptr<{{ $naturalType }}>;
};
template <>
struct WireTypeForNaturalType<{{ $naturalType }}> {
using type = {{ $wireType }};
};
template <>
struct WireTypeForNaturalType<std::unique_ptr<{{ $naturalType }}>> {
using type = {{ $wireType }};
};
{{ if .IsResourceType }}
{{- EndifFuchsia -}}
{{ end }}
{{- end }}
{{- define "Union:Traits:TypeConversionsSource" }}
{{ if .IsResourceType }}
{{- IfdefFuchsia -}}
{{- end }}
{{ $wireType := .Wire }}
{{ $naturalType := .Unified }}
{{ $naturalType }} WireNaturalConversionTraits<{{ $wireType }}, {{ $naturalType }}>::ToNatural({{ $wireType }} src) {
switch (src.Which()) {
{{- range .Members }}
case {{ .TagName.Wire }}:
return {{ $naturalType }}::With{{ .UpperCamelCaseName }}(
WireNaturalConversionTraits<{{ .Type.Wire }}, {{ .Type.Unified }}>::ToNatural(std::move(src.{{ .Name }}())));
{{- end }}
{{- if .IsFlexible }}
default:
return {{ $naturalType }}();
{{- else }}
default:
ZX_PANIC("unknown union tag in strict union");
{{- end }}
}
}
{{ $wireType }} WireNaturalConversionTraits<{{ $wireType }}, {{ $naturalType }}>::ToWire(fidl::AnyArena& arena, {{ $naturalType }} src) {
switch (src.Which()) {
{{- range .Members }}
case {{ .TagName.Unified }}:
return {{ $wireType }}::With{{ .UpperCamelCaseName }}(
{{- if not .Type.InlineInEnvelope }}arena, {{- end }}
WireNaturalConversionTraits<{{ .Type.Wire }}, {{ .Type.Unified }}>::ToWire(arena, std::move(src.{{ .Name }}().value())));
{{- end }}
{{- if .IsFlexible }}
default:
return {{ $wireType }}();
{{- end }}
}
}
std::unique_ptr<{{ $naturalType }}> WireNaturalConversionTraits<{{ .Wire }}, std::unique_ptr<{{ $naturalType }}>>::ToNatural({{ .Wire }} src) {
if (src.has_invalid_tag()) {
return nullptr;
}
return std::make_unique<{{ $naturalType }}>(WireNaturalConversionTraits<{{ .Wire }}, {{ $naturalType }}>::ToNatural(std::move(src)));
}
{{ $wireType }} WireNaturalConversionTraits<{{ $wireType }}, std::unique_ptr<{{ $naturalType }}>>::ToWire(fidl::AnyArena& arena, std::unique_ptr<{{ $naturalType }}> src) {
if (!src) {
return {{ $wireType }}();
}
return WireNaturalConversionTraits<{{ $wireType }}, {{ $naturalType }}>::ToWire(arena, std::move(*src));
}
{{ if .IsResourceType }}
{{- EndifFuchsia -}}
{{ end }}
{{- end }}