blob: c810969c0b3434fee763cf8f6b77a6057568b95e [file] [log] [blame]
// 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.
package templates
const Table = `
{{- define "TableForwardDeclaration" }}
class {{ .Name }};
{{- end }}
{{- define "TableDeclaration" }}
{{range .DocComments}}
//{{ . }}
{{- end}}
class {{ .Name }} {
public:
static const fidl_type_t* FidlType;
{{- range .Members }}
{{range .DocComments}}
//{{ . }}
{{- end}}
const {{ .Type.Decl }}* {{ .Name }}() const {
return {{ .FieldPresenceName }} ? &{{ .FieldDataName }}.value : nullptr;
}
bool {{ .MethodHasName }}() const {
return {{ .FieldPresenceName }};
}
{{range .DocComments}}
//{{ . }}
{{- end}}
{{ .Type.Decl }}* mutable_{{ .Name }}() {
if (!{{ .FieldPresenceName }}) {
{{ .FieldPresenceName }} = true;
Construct(&{{ .FieldDataName }}.value);
}
return &{{ .FieldDataName }}.value;
}
void set_{{ .Name }}({{ .Type.Decl }} value) {
if (!{{ .FieldPresenceName }}) {
{{ .FieldPresenceName }} = true;
Construct(&{{ .FieldDataName }}.value, std::move(value));
} else {
{{ .FieldDataName }}.value = std::move(value);
}
}
void {{ .MethodClearName }}() {
if (!{{ .FieldPresenceName }}) {
return;
}
{{ .FieldPresenceName }} = false;
Destruct(&{{ .FieldDataName }}.value);
}
{{- end }}
{{ .Name }}();
{{ .Name }}({{ .Name }}&& other);
~{{ .Name }}();
{{ .Name }}& operator=({{ .Name }}&& other);
static inline ::std::unique_ptr<{{ .Name }}> New() { return ::std::make_unique<{{ .Name }}>(); }
void Encode(::fidl::Encoder* encoder, size_t offset);
static void Decode(::fidl::Decoder* decoder, {{ .Name }}* value, size_t offset);
zx_status_t Clone({{ .Name }}* result) const;
private:
template <class T, class... Args>
void Construct(T* p, Args&&... args) {
new (p) T(std::forward<Args>(args)...);
}
template <class T>
void Destruct(T* p) {
p->~T();
}
{{- range .Members }}
bool {{ .FieldPresenceName }} : 1;
{{- end }}
{{- range .Members }}
{{/* The raw values of a table field are placed inside a union to ensure
that they're not initialized (since table fields are optional by
default). Placement new must be used to initialize the value. */ -}}
union {{ .ValueUnionName }} {
{{ .ValueUnionName }}() {}
~{{ .ValueUnionName }}() {}
{{ .Type.Decl }} value;
};
{{ .ValueUnionName }} {{ .FieldDataName }};
{{- end }}
};
bool operator==(const {{ .Name }}& lhs, const {{ .Name }}& rhs);
inline bool operator!=(const {{ .Name }}& lhs, const {{ .Name }}& rhs) {
return !(lhs == rhs);
}
using {{ .Name }}Ptr = ::std::unique_ptr<{{ .Name }}>;
{{- end }}
{{- define "TableDefinition" }}
extern "C" const fidl_type_t {{ .TableType }};
const fidl_type_t* {{ .Name }}::FidlType = &{{ .TableType }};
{{ .Name }}::{{ .Name }}() :
{{- range $index, $element := .Members }}
{{if $index}},{{end}}
has_{{ $element.Name }}_(false)
{{- end }} {
}
{{ .Name }}::{{ .Name }}({{ .Name }}&& other) {
{{- range .Members }}
{{ .FieldPresenceName }} = other.{{ .FieldPresenceName }};
if ({{ .FieldPresenceName }}) {
Construct(&{{ .FieldDataName }}.value, std::move(other.{{ .FieldDataName }}.value));
}
{{- end }}
}
{{ .Name }}::~{{ .Name }}() {
{{- range .Members }}
if ({{ .FieldPresenceName }}) {
Destruct(&{{ .FieldDataName }}.value);
}
{{- end }}
}
{{ .Name }}& {{ .Name }}::operator=({{ .Name }}&& other) {
{{- range .Members }}
if (other.{{ .FieldPresenceName }}) {
if ({{ .FieldPresenceName }}) {
{{ .FieldDataName }}.value = std::move(other.{{ .FieldDataName }}.value);
} else {
{{ .FieldPresenceName }} = true;
Construct(&{{ .FieldDataName }}.value, std::move(other.{{ .FieldDataName }}.value));
}
} else if ({{ .FieldPresenceName }}) {
{{ .FieldPresenceName }} = false;
Destruct(&{{ .FieldDataName }}.value);
}
{{- end }}
return *this;
}
void {{ .Name }}::Encode(::fidl::Encoder* encoder, size_t offset) {
size_t max_ordinal = 0;
{{- range .Members }}
if ({{ .FieldPresenceName }}) max_ordinal = {{ .Ordinal }};
{{- end }}
::fidl::EncodeVectorPointer(encoder, max_ordinal, offset);
if (max_ordinal == 0) return;
size_t base = encoder->Alloc(max_ordinal * 2 * sizeof(uint64_t));
{{- range .Members }}
if ({{ .FieldPresenceName }}) {
const size_t length_before = encoder->CurrentLength();
const size_t handles_before = encoder->CurrentHandleCount();
::fidl::Encode(
encoder,
&{{ .FieldDataName }}.value,
encoder->Alloc(::fidl::CodingTraits<{{ .Type.Decl }}>::encoded_size));
size_t envelope_base = base + ({{ .Ordinal }} - 1) * 2 * sizeof(uint64_t);
uint64_t num_bytes_then_num_handles =
(encoder->CurrentLength() - length_before) |
((encoder->CurrentHandleCount() - handles_before) << 32);
::fidl::Encode(encoder, &num_bytes_then_num_handles, envelope_base);
*encoder->GetPtr<uintptr_t>(envelope_base + sizeof(uint64_t)) = FIDL_ALLOC_PRESENT;
}
{{- end }}
}
void {{ .Name }}::Decode(::fidl::Decoder* decoder, {{ .Name }}* value, size_t offset) {
fidl_vector_t* encoded = decoder->GetPtr<fidl_vector_t>(offset);
size_t base;
size_t count;
if (!encoded->data) {
goto clear_all;
}
base = decoder->GetOffset(encoded->data);
count = encoded->count;
{{- range .Members }}
if (count >= {{ .Ordinal }}) {
size_t envelope_base = base + ({{ .Ordinal }} - 1) * 2 * sizeof(uint64_t);
uint64_t presence;
::fidl::Decode(decoder, &presence, envelope_base + sizeof(uint64_t));
if (presence != 0) {
::fidl::Decode(decoder, value->mutable_{{ .Name }}(), decoder->GetOffset(presence));
} else {
value->{{ .MethodClearName }}();
}
} else {
goto done_{{ .Ordinal }};
}
{{- end }}
return;
// Clear unset values.
clear_all:
{{- range .Members }}
done_{{ .Ordinal }}:
value->{{ .MethodClearName }}();
{{- end }}
return;
}
zx_status_t {{ .Name }}::Clone({{ .Name }}* result) const {
{{- range .Members }}
if ({{ .FieldPresenceName }}) {
zx_status_t _status = ::fidl::Clone({{ .FieldDataName }}.value, result->mutable_{{ .Name }}());
if (_status != ZX_OK)
return _status;
} else {
result->{{ .MethodClearName }}();
}
{{- end }}
return ZX_OK;
}
bool operator==(const {{ .Name }}& lhs, const {{ .Name }}& rhs) {
{{- range .Members }}
if (lhs.{{ .MethodHasName }}()) {
if (!rhs.{{ .MethodHasName }}()) {
return false;
}
if (!::fidl::Equals(*lhs.{{ .Name }}(), *rhs.{{ .Name }}())) {
return false;
}
} else if (rhs.{{ .MethodHasName }}()) {
return false;
}
{{- end }}
return true;
}
{{- end }}
{{- define "TableTraits" }}
template <>
struct CodingTraits<{{ .Namespace }}::{{ .Name }}>
: public EncodableCodingTraits<{{ .Namespace }}::{{ .Name }}, {{ .Size }}> {};
inline zx_status_t Clone(const {{ .Namespace }}::{{ .Name }}& value,
{{ .Namespace }}::{{ .Name }}* result) {
return value.Clone(result);
}
{{- end }}
`