blob: 1935267bebd5a00cd88d3c2390a049c3471d8a2c [file] [log] [blame]
// 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.
#include "fidl/coded_types_generator.h"
#include <zircon/assert.h>
#include "fidl/coded_ast.h"
#include "fidl/flat/values.h"
#include "fidl/names.h"
#include "fidl/types.h"
namespace fidl {
coded::MemcpyCompatibility ComputeMemcpyCompatibility(const flat::Type* type) {
auto typeshape = type->typeshape(fidl::WireFormat::kV1NoEe);
if (typeshape.max_out_of_line == 0 && typeshape.max_handles == 0 &&
!typeshape.has_flexible_envelope && !typeshape.has_padding) {
return coded::MemcpyCompatibility::kCanMemcpy;
}
return coded::MemcpyCompatibility::kCannotMemcpy;
}
CodedTypesGenerator::FlattenedStructMember::FlattenedStructMember(const flat::StructMember& member)
: FlattenedStructMember(member.type_ctor->type, member.name, member.typeshape(WireFormat::kV2),
member.fieldshape(WireFormat::kV2)) {
ZX_ASSERT(padding == member.fieldshape(WireFormat::kV2).padding);
}
CodedTypesGenerator::FlattenedStructMember::FlattenedStructMember(const flat::Type* type,
SourceSpan name,
fidl::TypeShape typeshape_v2,
fidl::FieldShape fieldshape_v2)
: type(type),
name(name),
inline_size_v2(typeshape_v2.inline_size),
offset_v2(fieldshape_v2.offset),
padding(fieldshape_v2.padding) {
ZX_ASSERT(padding == fieldshape_v2.padding);
}
CodedTypesGenerator::FlattenedStructMember::FlattenedStructMember(const flat::Type* type,
SourceSpan name,
uint32_t inline_size_v2,
uint32_t offset_v2,
uint32_t padding)
: type(type),
name(name),
inline_size_v2(inline_size_v2),
offset_v2(offset_v2),
padding(padding) {}
std::vector<CodedTypesGenerator::FlattenedStructMember> CodedTypesGenerator::FlattenedStructMembers(
const flat::Struct& input) {
auto get_struct_decl = [](const flat::StructMember& member) -> const flat::Struct* {
if (member.type_ctor->type->nullability == types::Nullability::kNullable) {
return nullptr;
}
const flat::Type* type = member.type_ctor->type;
if (type->kind != flat::Type::Kind::kIdentifier) {
return nullptr;
}
auto identifier_type = static_cast<const flat::IdentifierType*>(type);
if (identifier_type->type_decl->kind != flat::Decl::Kind::kStruct) {
return nullptr;
}
return static_cast<const flat::Struct*>(identifier_type->type_decl);
};
std::vector<FlattenedStructMember> result;
for (const auto& member : input.members) {
auto flattened_member = FlattenedStructMember(member);
auto struct_decl = get_struct_decl(member);
if (!struct_decl) {
result.push_back(flattened_member);
continue;
}
if (struct_decl->members.empty()) {
result.push_back(flattened_member);
continue;
}
auto flattened_members = FlattenedStructMembers(*struct_decl);
for (size_t i = 0; i < flattened_members.size(); i++) {
auto inner_member = flattened_members[i];
if (i == flattened_members.size() - 1) {
inner_member.padding += flattened_member.padding;
}
inner_member.offset_v2 += flattened_member.offset_v2;
result.push_back(inner_member);
}
}
return result;
}
std::vector<const coded::Type*> CodedTypesGenerator::AllCodedTypes() const {
std::vector<const coded::Type*> coded_types;
coded_types.reserve(coded_types_.size() + named_coded_types_.size());
for (const auto& coded_type : coded_types_) {
ZX_ASSERT(coded_type.get());
if (!coded_type->is_coding_needed)
continue;
coded_types.push_back(coded_type.get());
}
for (const auto& [_, coded_type] : named_coded_types_) {
ZX_ASSERT(coded_type.get());
coded_types.push_back(coded_type.get());
}
return coded_types;
}
const coded::Type* CodedTypesGenerator::CompileType(const flat::Type* type,
coded::CodingContext context) {
switch (type->kind) {
case flat::Type::Kind::kArray: {
auto array_type = static_cast<const flat::ArrayType*>(type);
auto coded_element_type =
CompileType(array_type->element_type, coded::CodingContext::kOutsideEnvelope);
auto iter = array_type_map_.find(array_type);
if (iter != array_type_map_.end())
return iter->second;
uint32_t array_size_v2 = array_type->typeshape(WireFormat::kV2).inline_size;
uint32_t element_size_v2 = array_type->element_type->typeshape(WireFormat::kV2).inline_size;
auto name = NameCodedArray(coded_element_type->coded_name, array_size_v2);
auto coded_array_type = std::make_unique<coded::ArrayType>(
std::move(name), coded_element_type, array_size_v2, element_size_v2, context);
array_type_map_[array_type] = coded_array_type.get();
coded_types_.push_back(std::move(coded_array_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kVector: {
auto vector_type = static_cast<const flat::VectorType*>(type);
auto iter = vector_type_map_.find(vector_type);
if (iter != vector_type_map_.end())
return iter->second;
auto coded_element_type =
CompileType(vector_type->element_type, coded::CodingContext::kOutsideEnvelope);
uint32_t max_count = vector_type->element_count->value;
uint32_t element_size_v2 = coded_element_type->size_v2;
std::string_view element_name = coded_element_type->coded_name;
auto name = NameCodedVector(element_name, max_count, vector_type->nullability);
auto coded_vector_type = std::make_unique<coded::VectorType>(
std::move(name), coded_element_type, max_count, element_size_v2, vector_type->nullability,
ComputeMemcpyCompatibility(vector_type->element_type));
vector_type_map_[vector_type] = coded_vector_type.get();
coded_types_.push_back(std::move(coded_vector_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kString: {
auto string_type = static_cast<const flat::StringType*>(type);
auto iter = string_type_map_.find(string_type);
if (iter != string_type_map_.end())
return iter->second;
uint32_t max_size = string_type->max_size->value;
auto name = NameCodedString(max_size, string_type->nullability);
auto coded_string_type =
std::make_unique<coded::StringType>(std::move(name), max_size, string_type->nullability);
string_type_map_[string_type] = coded_string_type.get();
coded_types_.push_back(std::move(coded_string_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kHandle: {
auto handle_type = static_cast<const flat::HandleType*>(type);
auto iter = handle_type_map_.find(handle_type);
if (iter != handle_type_map_.end())
return iter->second;
types::RightsWrappedType rights =
*static_cast<const flat::HandleRights*>(handle_type->rights);
auto name = NameCodedHandle(handle_type->subtype, rights, handle_type->nullability);
auto coded_handle_type = std::make_unique<coded::HandleType>(
std::move(name), handle_type->subtype, rights, handle_type->nullability);
handle_type_map_[handle_type] = coded_handle_type.get();
coded_types_.push_back(std::move(coded_handle_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kTransportSide: {
auto channel_end = static_cast<const flat::TransportSideType*>(type);
auto iter = channel_end_map_.find(channel_end);
if (iter != channel_end_map_.end())
return iter->second;
// TODO(fxbug.dev/70186): This is where the separate handling of the old
// vs new syntax channel ends, ends (i.e. in the coded types backend they
// are represented using the same types). As we clean up the old
// representation in fidlc, we'll want to switch the coded AST to better
// match the new representation (client/server end rather than protocol/request).
if (channel_end->end == flat::TransportSide::kClient) {
// In the old syntax this would be represented as an identifier type of a
// protocol decl, so the code in this if statement is copied from the
// kIdentifier > kProtocol code path below in order to maintain the same
// behavior.
auto name = NameCodedProtocolHandle(NameCodedName(channel_end->protocol_decl->name),
channel_end->nullability);
auto coded_protocol_type =
std::make_unique<coded::ProtocolHandleType>(std::move(name), channel_end->nullability);
channel_end_map_[channel_end] = coded_protocol_type.get();
coded_types_.push_back(std::move(coded_protocol_type));
return coded_types_.back().get();
}
// In the old syntax this would be represented as a RequestType,
// so the code in this if statement is copied from the
// kRequestHandle code path below in order to maintain the same
// behavior.
auto name = NameCodedRequestHandle(NameCodedName(channel_end->protocol_decl->name),
channel_end->nullability);
auto coded_request_type =
std::make_unique<coded::RequestHandleType>(std::move(name), channel_end->nullability);
channel_end_map_[channel_end] = coded_request_type.get();
coded_types_.push_back(std::move(coded_request_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kPrimitive: {
auto primitive_type = static_cast<const flat::PrimitiveType*>(type);
auto iter = primitive_type_map_.find(primitive_type);
if (iter != primitive_type_map_.end())
return iter->second;
auto name = NameFlatName(primitive_type->name);
auto coded_primitive_type = std::make_unique<coded::PrimitiveType>(
std::move(name), primitive_type->subtype,
primitive_type->typeshape(WireFormat::kV1NoEe).inline_size, context);
primitive_type_map_[primitive_type] = coded_primitive_type.get();
coded_types_.push_back(std::move(coded_primitive_type));
return coded_types_.back().get();
}
case flat::Type::Kind::kIdentifier: {
auto identifier_type = static_cast<const flat::IdentifierType*>(type);
auto iter = named_coded_types_.find(identifier_type->name);
ZX_ASSERT_MSG(iter != named_coded_types_.end(), "identifier type not found");
// We may need to set the emit-pointer bit on structs, unions, and xunions now.
auto coded_type = iter->second.get();
switch (coded_type->kind) {
case coded::Type::Kind::kStruct: {
// Structs were compiled as part of decl compilation,
// but we may now need to generate the StructPointer.
if (identifier_type->nullability != types::Nullability::kNullable)
return coded_type;
auto iter = struct_type_map_.find(identifier_type);
if (iter != struct_type_map_.end()) {
return iter->second;
}
auto coded_struct_type = static_cast<coded::StructType*>(coded_type);
auto struct_pointer_type = std::make_unique<coded::StructPointerType>(
NamePointer(coded_struct_type->coded_name), coded_struct_type);
coded_struct_type->maybe_reference_type = struct_pointer_type.get();
struct_type_map_[identifier_type] = struct_pointer_type.get();
coded_types_.push_back(std::move(struct_pointer_type));
return coded_types_.back().get();
}
case coded::Type::Kind::kTable: {
// Tables cannot be nullable.
ZX_ASSERT(identifier_type->nullability != types::Nullability::kNullable);
return coded_type;
}
case coded::Type::Kind::kXUnion: {
if (identifier_type->nullability != types::Nullability::kNullable) {
return coded_type;
}
auto coded_xunion_type = static_cast<coded::XUnionType*>(coded_type);
return coded_xunion_type->maybe_reference_type;
}
case coded::Type::Kind::kProtocol: {
auto iter = protocol_type_map_.find(identifier_type);
if (iter != protocol_type_map_.end())
return iter->second;
auto name = NameCodedProtocolHandle(NameCodedName(identifier_type->name),
identifier_type->nullability);
auto coded_protocol_type = std::make_unique<coded::ProtocolHandleType>(
std::move(name), identifier_type->nullability);
protocol_type_map_[identifier_type] = coded_protocol_type.get();
coded_types_.push_back(std::move(coded_protocol_type));
return coded_types_.back().get();
}
case coded::Type::Kind::kEnum:
case coded::Type::Kind::kBits:
return coded_type;
case coded::Type::Kind::kPrimitive:
case coded::Type::Kind::kProtocolHandle:
case coded::Type::Kind::kStructPointer:
case coded::Type::Kind::kRequestHandle:
case coded::Type::Kind::kHandle:
case coded::Type::Kind::kArray:
case coded::Type::Kind::kVector:
case coded::Type::Kind::kString:
ZX_PANIC("anonymous type in named type map");
}
}
case flat::Type::Kind::kBox:
// this defers to the code path for a nullable struct identifier type.
return CompileType(static_cast<const flat::BoxType*>(type)->boxed_type, context);
case flat::Type::Kind::kUntypedNumeric:
ZX_PANIC("should not have untyped numeric here");
}
}
void CodedTypesGenerator::CompileFields(const flat::Decl* decl) {
switch (decl->kind) {
case flat::Decl::Kind::kProtocol: {
auto protocol_decl = static_cast<const flat::Protocol*>(decl);
coded::ProtocolType* coded_protocol =
static_cast<coded::ProtocolType*>(named_coded_types_[decl->name].get());
size_t i = 0;
for (const auto& method_with_info : protocol_decl->all_methods) {
ZX_ASSERT(method_with_info.method != nullptr);
const auto& method = *method_with_info.method;
auto CompileMessage = [&](const std::unique_ptr<flat::TypeConstructor>& payload) -> void {
if (payload && payload->layout.IsSynthetic()) {
auto id = static_cast<const flat::IdentifierType*>(payload->type);
std::unique_ptr<coded::Type>& coded_message =
coded_protocol->messages_during_compile[i++];
bool is_noop = true;
switch (id->type_decl->kind) {
case flat::Decl::Kind::kStruct: {
auto coded_struct = static_cast<coded::StructType*>(coded_message.get());
auto struct_decl = static_cast<const flat::Struct*>(id->type_decl);
ZX_ASSERT_MSG(!struct_decl->members.empty(),
"cannot process empty message payloads");
CompileStructFields(struct_decl, coded_struct);
break;
}
case flat::Decl::Kind::kTable: {
auto coded_table = static_cast<coded::TableType*>(coded_message.get());
auto table_decl = static_cast<const flat::Table*>(id->type_decl);
CompileTableFields(table_decl, coded_table);
is_noop = false;
break;
}
case flat::Decl::Kind::kUnion: {
auto coded_union = static_cast<coded::XUnionType*>(coded_message.get());
auto union_decl = static_cast<const flat::Union*>(id->type_decl);
CompileUnionFields(union_decl, coded_union);
is_noop = false;
break;
}
default: {
ZX_PANIC("only structs, tables, and unions may be used as message payloads");
}
}
coded_message->is_noop = is_noop;
// We move the coded_message to coded_types_ so that we'll generate tables for the
// message in the proper order.
coded_types_.push_back(std::move(coded_message));
// We also keep back pointers to reference to these messages via the
// coded_protocol.
coded_protocol->messages_after_compile.push_back(
static_cast<const coded::Type*>(coded_types_.back().get()));
}
};
if (method.has_request) {
CompileMessage(method.maybe_request);
}
if (method.has_response) {
CompileMessage(method.maybe_response);
}
}
break;
}
case flat::Decl::Kind::kStruct: {
auto struct_decl = static_cast<const flat::Struct*>(decl);
coded::StructType* coded_struct =
static_cast<coded::StructType*>(named_coded_types_[decl->name].get());
CompileStructFields(struct_decl, coded_struct);
break;
}
case flat::Decl::Kind::kTable: {
auto table_decl = static_cast<const flat::Table*>(decl);
coded::TableType* coded_table =
static_cast<coded::TableType*>(named_coded_types_[decl->name].get());
CompileTableFields(table_decl, coded_table);
break;
}
case flat::Decl::Kind::kUnion: {
auto union_decl = static_cast<const flat::Union*>(decl);
auto type = named_coded_types_[decl->name].get();
coded::XUnionType* coded_xunion = static_cast<coded::XUnionType*>(type);
coded::XUnionType* nullable_coded_xunion = coded_xunion->maybe_reference_type;
ZX_ASSERT_MSG(nullable_coded_xunion != nullptr,
"named coded xunion must have a reference type");
ZX_ASSERT_MSG(coded_xunion->fields.empty(),
"the coded xunion fields are being compiled twice");
CompileUnionFields(union_decl, coded_xunion);
CompileUnionFields(union_decl, nullable_coded_xunion);
break;
}
default: {
break;
}
}
}
void CodedTypesGenerator::CompileStructFields(const flat::Struct* struct_decl,
coded::StructType* coded_struct) {
std::vector<coded::StructElement>& struct_elements = coded_struct->elements;
uint32_t field_num = 0;
bool is_noop = true;
for (const auto& member : FlattenedStructMembers(*struct_decl)) {
std::string member_name = coded_struct->coded_name + "_" + std::string(member.name.data());
auto coded_member_type = CompileType(member.type, coded::CodingContext::kOutsideEnvelope);
if (!coded_member_type->is_noop) {
struct_elements.push_back(
coded::StructField(member.type->Resourceness(), member.offset_v2, coded_member_type));
is_noop = false;
}
if (member.padding != 0) {
struct_elements.push_back(coded::StructPadding::FromLength(
member.inline_size_v2 + member.offset_v2, member.padding));
is_noop = false;
}
field_num++;
}
if (field_num == 0) {
coded_struct->is_empty = true;
}
coded_struct->is_noop = is_noop;
}
void CodedTypesGenerator::CompileTableFields(const flat::Table* table_decl,
coded::TableType* coded_table) {
std::vector<coded::TableField>& table_fields = coded_table->fields;
std::map<uint32_t, const flat::Table::Member*> members;
for (const auto& member : table_decl->members) {
auto [_, inserted] = members.emplace(member.ordinal->value, &member);
ZX_ASSERT_MSG(inserted, "duplicate table ordinal");
}
for (const auto& member_pair : members) {
const auto& member = *member_pair.second;
if (!member.maybe_used)
continue;
std::string member_name =
coded_table->coded_name + "_" + std::string(member.maybe_used->name.data());
auto coded_member_type =
CompileType(member.maybe_used->type_ctor->type, coded::CodingContext::kInsideEnvelope);
table_fields.emplace_back(coded_member_type, member.ordinal->value);
}
}
void CodedTypesGenerator::CompileUnionFields(const flat::Union* union_decl,
coded::XUnionType* coded_union) {
std::set<uint32_t> members;
for (const auto& member_ref : union_decl->MembersSortedByXUnionOrdinal()) {
const auto& member = member_ref.get();
auto [_, inserted] = members.emplace(member.ordinal->value);
ZX_ASSERT_MSG(inserted, "duplicate union ordinal");
if (member.maybe_used) {
const auto* coded_member_type =
CompileType(member.maybe_used->type_ctor->type, coded::CodingContext::kInsideEnvelope);
coded_union->fields.emplace_back(coded_member_type);
} else {
coded_union->fields.emplace_back(nullptr);
}
}
}
void CodedTypesGenerator::CompileDecl(const flat::Decl* decl) {
switch (decl->kind) {
case flat::Decl::Kind::kBuiltin: {
ZX_PANIC("unexpected builtin");
}
case flat::Decl::Kind::kBits: {
auto bits_decl = static_cast<const flat::Bits*>(decl);
std::string bits_name = NameCodedName(bits_decl->name);
auto primitive_type = static_cast<const flat::PrimitiveType*>(bits_decl->subtype_ctor->type);
named_coded_types_.emplace(
bits_decl->name,
std::make_unique<coded::BitsType>(
std::move(bits_name), primitive_type->subtype,
primitive_type->typeshape(WireFormat::kV1NoEe).inline_size, bits_decl->mask,
NameFlatName(bits_decl->name), bits_decl->strictness));
break;
}
case flat::Decl::Kind::kEnum: {
auto enum_decl = static_cast<const flat::Enum*>(decl);
std::string enum_name = NameCodedName(enum_decl->name);
std::vector<uint64_t> members;
for (const auto& member : enum_decl->members) {
std::unique_ptr<flat::ConstantValue> value;
uint64_t uint64 = 0;
bool ok = member.value->Value().Convert(flat::ConstantValue::Kind::kUint64, &value);
if (ok) {
uint64 = static_cast<flat::NumericConstantValue<uint64_t>*>(value.get())->value;
} else {
ok = member.value->Value().Convert(flat::ConstantValue::Kind::kInt64, &value);
if (ok) {
// Note: casting int64_t to uint64_t is well-defined.
uint64 = static_cast<uint64_t>(
static_cast<flat::NumericConstantValue<int64_t>*>(value.get())->value);
} else {
ZX_PANIC("failed to convert enum member to uint64 or int64");
}
}
members.push_back(uint64);
}
named_coded_types_.emplace(
enum_decl->name,
std::make_unique<coded::EnumType>(
std::move(enum_name), enum_decl->type->subtype,
enum_decl->type->typeshape(WireFormat::kV1NoEe).inline_size, std::move(members),
NameFlatName(enum_decl->name), enum_decl->strictness));
break;
}
case flat::Decl::Kind::kProtocol: {
auto protocol_decl = static_cast<const flat::Protocol*>(decl);
std::string protocol_name = NameCodedName(protocol_decl->name);
std::string protocol_qname = NameFlatName(protocol_decl->name);
std::vector<std::unique_ptr<coded::Type>> protocol_messages;
for (const auto& method_with_info : protocol_decl->all_methods) {
ZX_ASSERT(method_with_info.method != nullptr);
const auto& method = *method_with_info.method;
std::string method_name = NameMethod(protocol_name, method);
std::string method_qname = NameMethod(protocol_qname, method);
auto CreateMessage = [&](const std::unique_ptr<flat::TypeConstructor>& payload,
types::MessageKind kind) -> void {
if (payload && payload->layout.IsSynthetic()) {
std::string message_name = NameMessage(method_name, kind);
std::string message_qname = NameMessage(method_qname, kind);
auto id = static_cast<const flat::IdentifierType*>(payload->type);
switch (id->type_decl->kind) {
case flat::Decl::Kind::kStruct: {
auto struct_decl = static_cast<const flat::Struct*>(id->type_decl);
ZX_ASSERT_MSG(!struct_decl->members.empty(),
"cannot process empty message payloads");
protocol_messages.push_back(
CompileStructDecl(struct_decl, message_name, message_qname));
break;
}
case flat::Decl::Kind::kTable: {
auto table_decl = static_cast<const flat::Table*>(id->type_decl);
protocol_messages.push_back(std::make_unique<coded::TableType>(
std::move(message_name), std::vector<coded::TableField>(),
std::move(message_qname), table_decl->resourceness));
break;
}
case flat::Decl::Kind::kUnion: {
auto union_decl = static_cast<const flat::Union*>(id->type_decl);
protocol_messages.push_back(CompileUnionDecl(
union_decl, message_name, message_qname, types::Nullability::kNonnullable));
break;
}
default: {
ZX_PANIC("only structs, tables, and unions may be used as message payloads");
}
}
}
};
if (method.has_request) {
CreateMessage(method.maybe_request, types::MessageKind::kRequest);
}
if (method.has_response) {
auto kind =
method.has_request ? types::MessageKind::kResponse : types::MessageKind::kEvent;
CreateMessage(method.maybe_response, kind);
}
}
named_coded_types_.emplace(
decl->name, std::make_unique<coded::ProtocolType>(std::move(protocol_messages)));
break;
}
case flat::Decl::Kind::kTable: {
auto table_decl = static_cast<const flat::Table*>(decl);
std::string table_name = NameCodedName(table_decl->name);
named_coded_types_.emplace(decl->name,
std::make_unique<coded::TableType>(
std::move(table_name), std::vector<coded::TableField>(),
NameFlatName(table_decl->name), table_decl->resourceness));
break;
}
case flat::Decl::Kind::kStruct: {
auto struct_decl = static_cast<const flat::Struct*>(decl);
std::string name = NameCodedName(struct_decl->name);
std::string qname = NameFlatName(struct_decl->name);
named_coded_types_.emplace(decl->name, CompileStructDecl(struct_decl, name, qname));
break;
}
case flat::Decl::Kind::kUnion: {
auto union_decl = static_cast<const flat::Union*>(decl);
std::string qname = NameFlatName(union_decl->name);
// Always create the reference type
std::unique_ptr<coded::XUnionType> nullable_xunion_type =
CompileUnionDecl(union_decl, NameCodedNullableName(union_decl->name), qname,
types::Nullability::kNullable);
coded::XUnionType* nullable_xunion_ptr = nullable_xunion_type.get();
coded_types_.push_back(std::move(nullable_xunion_type));
named_coded_types_.emplace(
decl->name, CompileUnionDecl(union_decl, NameCodedName(union_decl->name), qname,
types::Nullability::kNonnullable, nullable_xunion_ptr));
break;
}
case flat::Decl::Kind::kNewType:
// TODO(fxbug.dev/7807): Implement.
ZX_PANIC("coding tables for new-type not implemented yet");
case flat::Decl::Kind::kConst:
case flat::Decl::Kind::kResource:
case flat::Decl::Kind::kService:
case flat::Decl::Kind::kTypeAlias:
// Nothing to do.
break;
}
}
std::unique_ptr<coded::StructType> CodedTypesGenerator::CompileStructDecl(
const flat::Struct* struct_decl, std::string name, std::string qname) {
auto typeshape_v2 = TypeShape::ForEmptyPayload();
typeshape_v2 = struct_decl->typeshape(WireFormat::kV2);
return std::make_unique<coded::StructType>(std::move(name), std::vector<coded::StructElement>(),
typeshape_v2.inline_size, typeshape_v2.has_envelope,
std::move(qname));
}
std::unique_ptr<coded::XUnionType> CodedTypesGenerator::CompileUnionDecl(
const flat::Union* union_decl, std::string name, std::string qname,
types::Nullability nullability, coded::XUnionType* reference_type) {
auto xunion_type = std::make_unique<coded::XUnionType>(
std::move(name), std::vector<coded::XUnionField>(), std::move(qname), nullability,
union_decl->strictness, union_decl->resourceness.value());
if (reference_type != nullptr) {
xunion_type->maybe_reference_type = reference_type;
}
return xunion_type;
}
void CodedTypesGenerator::CompileCodedTypes() {
for (const auto& decl : compilation_->all_libraries_declaration_order) {
CompileDecl(decl);
}
for (const auto& decl : compilation_->declaration_order) {
CompileFields(decl);
}
}
} // namespace fidl