rusty-packets: move C++ and pybind11 to their own file
Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost SimpleHalTest
Change-Id: I787160993d299b0102daa0a92add4b61f036be43
diff --git a/system/gd/packet/parser/Android.bp b/system/gd/packet/parser/Android.bp
index a77fa2c..3bc09d6 100644
--- a/system/gd/packet/parser/Android.bp
+++ b/system/gd/packet/parser/Android.bp
@@ -33,6 +33,7 @@
"main.cc",
"language_y.yy",
"language_l.ll",
+ "gen_cpp.cc",
],
static_libs: [
"libc++fs",
diff --git a/system/gd/packet/parser/gen_cpp.cc b/system/gd/packet/parser/gen_cpp.cc
new file mode 100644
index 0000000..a534e35
--- /dev/null
+++ b/system/gd/packet/parser/gen_cpp.cc
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <cerrno>
+#include <cstdio>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <queue>
+#include <regex>
+#include <sstream>
+#include <vector>
+
+#include "declarations.h"
+#include "struct_parser_generator.h"
+
+void parse_namespace(
+ const std::string& root_namespace,
+ const std::filesystem::path& input_file_relative_path,
+ std::vector<std::string>* token) {
+ std::filesystem::path gen_namespace = root_namespace / input_file_relative_path;
+ std::string gen_namespace_str = gen_namespace;
+ std::regex path_tokenizer("/");
+ auto it = std::sregex_token_iterator(gen_namespace_str.cbegin(), gen_namespace_str.cend(), path_tokenizer, -1);
+ std::sregex_token_iterator it_end = {};
+ for (; it != it_end; ++it) {
+ token->push_back(it->str());
+ }
+}
+
+void generate_namespace_open(const std::vector<std::string>& token, std::ostream& output) {
+ for (const auto& ns : token) {
+ output << "namespace " << ns << " {" << std::endl;
+ }
+}
+
+void generate_namespace_close(const std::vector<std::string>& token, std::ostream& output) {
+ for (auto it = token.rbegin(); it != token.rend(); ++it) {
+ output << "} //namespace " << *it << std::endl;
+ }
+}
+
+bool generate_cpp_headers_one_file(
+ const Declarations& decls,
+ const std::filesystem::path& input_file,
+ const std::filesystem::path& include_dir,
+ const std::filesystem::path& out_dir,
+ const std::string& root_namespace) {
+ auto gen_relative_path = input_file.lexically_relative(include_dir).parent_path();
+
+ auto input_filename = input_file.filename().string().substr(0, input_file.filename().string().find(".pdl"));
+ auto gen_path = out_dir / gen_relative_path;
+
+ std::filesystem::create_directories(gen_path);
+
+ auto gen_file = gen_path / (input_filename + ".h");
+
+ std::cout << "generating " << gen_file << std::endl;
+
+ std::ofstream out_file;
+ out_file.open(gen_file);
+ if (!out_file.is_open()) {
+ std::cerr << "can't open " << gen_file << std::endl;
+ return false;
+ }
+
+ out_file << "\n\n";
+ out_file << "#pragma once\n";
+ out_file << "\n\n";
+ out_file << "#include <cstdint>\n";
+ out_file << "#include <sstream>\n";
+ out_file << "#include <string>\n";
+ out_file << "#include <type_traits>\n";
+ out_file << "#include <functional>\n";
+ out_file << "\n\n";
+ out_file << "#include \"os/log.h\"\n";
+ out_file << "#include \"packet/base_packet_builder.h\"\n";
+ out_file << "#include \"packet/bit_inserter.h\"\n";
+ out_file << "#include \"packet/custom_field_fixed_size_interface.h\"\n";
+ out_file << "#include \"packet/iterator.h\"\n";
+ out_file << "#include \"packet/packet_builder.h\"\n";
+ out_file << "#include \"packet/packet_struct.h\"\n";
+ out_file << "#include \"packet/packet_view.h\"\n";
+ out_file << "\n#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)\n";
+ out_file << "#include \"packet/raw_builder.h\"\n";
+ out_file << "\n#endif\n";
+ out_file << "#include \"packet/parser/checksum_type_checker.h\"\n";
+ out_file << "#include \"packet/parser/custom_type_checker.h\"\n";
+ out_file << "\n\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
+ c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
+ ((CustomFieldDef*)c.second)->GenInclude(out_file);
+ }
+ }
+ out_file << "\n\n";
+
+ std::vector<std::string> namespace_list;
+ parse_namespace(root_namespace, gen_relative_path, &namespace_list);
+ generate_namespace_open(namespace_list, out_file);
+ out_file << "\n\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
+ c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
+ ((CustomFieldDef*)c.second)->GenUsing(out_file);
+ }
+ }
+ out_file << "\n\n";
+
+ out_file << "using ::bluetooth::packet::BasePacketBuilder;";
+ out_file << "using ::bluetooth::packet::BitInserter;";
+ out_file << "using ::bluetooth::packet::CustomFieldFixedSizeInterface;";
+ out_file << "using ::bluetooth::packet::CustomTypeChecker;";
+ out_file << "using ::bluetooth::packet::Iterator;";
+ out_file << "using ::bluetooth::packet::kLittleEndian;";
+ out_file << "using ::bluetooth::packet::PacketBuilder;";
+ out_file << "using ::bluetooth::packet::PacketStruct;";
+ out_file << "using ::bluetooth::packet::PacketView;";
+ out_file << "\n#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)\n";
+ out_file << "using ::bluetooth::packet::RawBuilder;";
+ out_file << "\n#endif\n";
+ out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
+ out_file << "\n\n";
+
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
+ EnumGen gen(*enum_def);
+ gen.GenDefinition(out_file);
+ out_file << "\n\n";
+ }
+ }
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
+ EnumGen gen(*enum_def);
+ gen.GenLogging(out_file);
+ out_file << "\n\n";
+ }
+ }
+ for (const auto& ch : decls.type_defs_queue_) {
+ if (ch.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
+ const auto* checksum_def = dynamic_cast<const ChecksumDef*>(ch.second);
+ checksum_def->GenChecksumCheck(out_file);
+ }
+ }
+ out_file << "\n/* Done ChecksumChecks */\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM) {
+ if (c.second->size_ == -1 /* Variable Size */) {
+ const auto* custom_field_def = dynamic_cast<const CustomFieldDef*>(c.second);
+ custom_field_def->GenCustomFieldCheck(out_file, decls.is_little_endian);
+ } else { // fixed size
+ const auto* custom_field_def = dynamic_cast<const CustomFieldDef*>(c.second);
+ custom_field_def->GenFixedSizeCustomFieldCheck(out_file);
+ }
+ }
+ }
+ out_file << "\n";
+
+ for (auto& s : decls.type_defs_queue_) {
+ if (s.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
+ const auto* struct_def = dynamic_cast<const StructDef*>(s.second);
+ struct_def->GenDefinition(out_file);
+ out_file << "\n";
+ }
+ }
+
+ {
+ StructParserGenerator spg(decls);
+ spg.Generate(out_file);
+ out_file << "\n\n";
+ }
+
+ for (const auto& packet_def : decls.packet_defs_queue_) {
+ packet_def.second.GenParserDefinition(out_file);
+ out_file << "\n\n";
+ }
+
+ for (const auto& packet_def : decls.packet_defs_queue_) {
+ packet_def.second.GenBuilderDefinition(out_file);
+ out_file << "\n\n";
+ }
+
+ generate_namespace_close(namespace_list, out_file);
+
+ out_file.close();
+
+ return true;
+}
+
+// Get the out_file shard at a symbol_count
+std::ofstream& get_out_file(size_t symbol_count, size_t symbol_total, std::vector<std::ofstream>* out_files) {
+ auto symbols_per_shard = symbol_total / out_files->size();
+ auto file_index = std::min(symbol_count / symbols_per_shard, out_files->size() - 1);
+ return out_files->at(file_index);
+}
+
+bool generate_pybind11_sources_one_file(
+ const Declarations& decls,
+ const std::filesystem::path& input_file,
+ const std::filesystem::path& include_dir,
+ const std::filesystem::path& out_dir,
+ const std::string& root_namespace,
+ size_t num_shards) {
+ auto gen_relative_path = input_file.lexically_relative(include_dir).parent_path();
+
+ auto input_filename = input_file.filename().string().substr(0, input_file.filename().string().find(".pdl"));
+ auto gen_path = out_dir / gen_relative_path;
+
+ std::filesystem::create_directories(gen_path);
+
+ auto gen_relative_header = gen_relative_path / (input_filename + ".h");
+
+ std::vector<std::string> namespace_list;
+ parse_namespace(root_namespace, gen_relative_path, &namespace_list);
+
+ std::vector<std::ofstream> out_file_shards(num_shards);
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ auto filename = gen_path / (input_filename + "_python3_shard_" + std::to_string(i) + ".cc");
+ std::cout << "generating " << filename << std::endl;
+ auto& out_file = out_file_shards[i];
+ out_file.open(filename);
+ if (!out_file.is_open()) {
+ std::cerr << "can't open " << filename << std::endl;
+ return false;
+ }
+ out_file << "#include <pybind11/pybind11.h>\n";
+ out_file << "#include <pybind11/stl.h>\n";
+ out_file << "\n\n";
+ out_file << "#include " << gen_relative_header << "\n";
+ out_file << "\n\n";
+ out_file << "#include \"packet/raw_builder.h\"\n";
+ out_file << "\n\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM) {
+ const auto* custom_def = dynamic_cast<const CustomFieldDef*>(c.second);
+ custom_def->GenPyBind11Include(out_file);
+ }
+ }
+
+ out_file << "\n\n";
+
+ generate_namespace_open(namespace_list, out_file);
+ out_file << "\n\n";
+
+ for (const auto& c : decls.type_defs_queue_) {
+ if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
+ c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
+ const auto* custom_def = dynamic_cast<const CustomFieldDef*>(c.second);
+ custom_def->GenUsing(out_file);
+ }
+ }
+ out_file << "\n\n";
+
+ out_file << "using ::bluetooth::packet::BasePacketBuilder;";
+ out_file << "using ::bluetooth::packet::BitInserter;";
+ out_file << "using ::bluetooth::packet::CustomTypeChecker;";
+ out_file << "using ::bluetooth::packet::Iterator;";
+ out_file << "using ::bluetooth::packet::kLittleEndian;";
+ out_file << "using ::bluetooth::packet::PacketBuilder;";
+ out_file << "using ::bluetooth::packet::BaseStruct;";
+ out_file << "using ::bluetooth::packet::PacketStruct;";
+ out_file << "using ::bluetooth::packet::PacketView;";
+ out_file << "using ::bluetooth::packet::RawBuilder;";
+ out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
+ out_file << "\n\n";
+
+ out_file << "namespace py = pybind11;\n\n";
+
+ out_file << "void define_" << input_filename << "_submodule_shard_" << std::to_string(i) << "(py::module& m) {\n\n";
+ }
+ size_t symbol_total = 0;
+ // Only count types that will be generated
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ symbol_total++;
+ } else if (e.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
+ symbol_total++;
+ }
+ }
+ // View and builder are counted separately
+ symbol_total += decls.packet_defs_queue_.size() * 2;
+ size_t symbol_count = 0;
+
+ for (const auto& e : decls.type_defs_queue_) {
+ if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
+ const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
+ EnumGen gen(*enum_def);
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
+ gen.GenDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ symbol_count++;
+ }
+ }
+
+ for (const auto& s : decls.type_defs_queue_) {
+ if (s.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
+ const auto* struct_def = dynamic_cast<const StructDef*>(s.second);
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
+ struct_def->GenDefinitionPybind11(out_file);
+ out_file << "\n";
+ symbol_count++;
+ }
+ }
+
+ for (const auto& packet_def : decls.packet_defs_queue_) {
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
+ packet_def.second.GenParserDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ symbol_count++;
+ }
+
+ for (const auto& p : decls.packet_defs_queue_) {
+ auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
+ p.second.GenBuilderDefinitionPybind11(out_file);
+ out_file << "\n\n";
+ symbol_count++;
+ }
+
+ for (auto& out_file : out_file_shards) {
+ out_file << "}\n\n";
+ generate_namespace_close(namespace_list, out_file);
+ }
+
+ auto gen_file_main = gen_path / (input_filename + "_python3.cc");
+ std::ofstream out_file_main;
+ out_file_main.open(gen_file_main);
+ if (!out_file_main.is_open()) {
+ std::cerr << "can't open " << gen_file_main << std::endl;
+ return false;
+ }
+ out_file_main << "#include <pybind11/pybind11.h>\n";
+ generate_namespace_open(namespace_list, out_file_main);
+
+ out_file_main << "namespace py = pybind11;\n\n";
+
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ out_file_main << "void define_" << input_filename << "_submodule_shard_" << std::to_string(i)
+ << "(py::module& m);\n";
+ }
+
+ out_file_main << "void define_" << input_filename << "_submodule(py::module& m) {\n\n";
+ for (size_t i = 0; i < out_file_shards.size(); i++) {
+ out_file_main << "define_" << input_filename << "_submodule_shard_" << std::to_string(i) << "(m);\n";
+ }
+ out_file_main << "}\n\n";
+
+ generate_namespace_close(namespace_list, out_file_main);
+
+ return true;
+}
diff --git a/system/gd/packet/parser/main.cc b/system/gd/packet/parser/main.cc
index 3f9e409..69a8b29 100644
--- a/system/gd/packet/parser/main.cc
+++ b/system/gd/packet/parser/main.cc
@@ -35,31 +35,20 @@
void yyset_debug(int, void*);
void yyset_in(FILE*, void*);
-namespace {
+bool generate_cpp_headers_one_file(
+ const Declarations& decls,
+ const std::filesystem::path& input_file,
+ const std::filesystem::path& include_dir,
+ const std::filesystem::path& out_dir,
+ const std::string& root_namespace);
-void parse_namespace(const std::string& root_namespace, const std::filesystem::path& input_file_relative_path,
- std::vector<std::string>* token) {
- std::filesystem::path gen_namespace = root_namespace / input_file_relative_path;
- std::string gen_namespace_str = gen_namespace;
- std::regex path_tokenizer("/");
- auto it = std::sregex_token_iterator(gen_namespace_str.cbegin(), gen_namespace_str.cend(), path_tokenizer, -1);
- std::sregex_token_iterator it_end = {};
- for (; it != it_end; ++it) {
- token->push_back(it->str());
- }
-}
-
-void generate_namespace_open(const std::vector<std::string>& token, std::ostream& output) {
- for (const auto& ns : token) {
- output << "namespace " << ns << " {" << std::endl;
- }
-}
-
-void generate_namespace_close(const std::vector<std::string>& token, std::ostream& output) {
- for (auto it = token.rbegin(); it != token.rend(); ++it) {
- output << "} //namespace " << *it << std::endl;
- }
-}
+bool generate_pybind11_sources_one_file(
+ const Declarations& decls,
+ const std::filesystem::path& input_file,
+ const std::filesystem::path& include_dir,
+ const std::filesystem::path& out_dir,
+ const std::string& root_namespace,
+ size_t num_shards);
bool parse_declarations_one_file(const std::filesystem::path& input_file, Declarations* declarations) {
void* scanner;
@@ -98,316 +87,6 @@
return true;
}
-bool generate_cpp_headers_one_file(const Declarations& decls, const std::filesystem::path& input_file,
- const std::filesystem::path& include_dir, const std::filesystem::path& out_dir,
- const std::string& root_namespace) {
- auto gen_relative_path = input_file.lexically_relative(include_dir).parent_path();
-
- auto input_filename = input_file.filename().string().substr(0, input_file.filename().string().find(".pdl"));
- auto gen_path = out_dir / gen_relative_path;
-
- std::filesystem::create_directories(gen_path);
-
- auto gen_file = gen_path / (input_filename + ".h");
-
- std::cout << "generating " << gen_file << std::endl;
-
- std::ofstream out_file;
- out_file.open(gen_file);
- if (!out_file.is_open()) {
- std::cerr << "can't open " << gen_file << std::endl;
- return false;
- }
-
- out_file << "\n\n";
- out_file << "#pragma once\n";
- out_file << "\n\n";
- out_file << "#include <cstdint>\n";
- out_file << "#include <sstream>\n";
- out_file << "#include <string>\n";
- out_file << "#include <type_traits>\n";
- out_file << "#include <functional>\n";
- out_file << "\n\n";
- out_file << "#include \"os/log.h\"\n";
- out_file << "#include \"packet/base_packet_builder.h\"\n";
- out_file << "#include \"packet/bit_inserter.h\"\n";
- out_file << "#include \"packet/custom_field_fixed_size_interface.h\"\n";
- out_file << "#include \"packet/iterator.h\"\n";
- out_file << "#include \"packet/packet_builder.h\"\n";
- out_file << "#include \"packet/packet_struct.h\"\n";
- out_file << "#include \"packet/packet_view.h\"\n";
- out_file << "\n#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)\n";
- out_file << "#include \"packet/raw_builder.h\"\n";
- out_file << "\n#endif\n";
- out_file << "#include \"packet/parser/checksum_type_checker.h\"\n";
- out_file << "#include \"packet/parser/custom_type_checker.h\"\n";
- out_file << "\n\n";
-
- for (const auto& c : decls.type_defs_queue_) {
- if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
- c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
- ((CustomFieldDef*)c.second)->GenInclude(out_file);
- }
- }
- out_file << "\n\n";
-
- std::vector<std::string> namespace_list;
- parse_namespace(root_namespace, gen_relative_path, &namespace_list);
- generate_namespace_open(namespace_list, out_file);
- out_file << "\n\n";
-
- for (const auto& c : decls.type_defs_queue_) {
- if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
- c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
- ((CustomFieldDef*)c.second)->GenUsing(out_file);
- }
- }
- out_file << "\n\n";
-
- out_file << "using ::bluetooth::packet::BasePacketBuilder;";
- out_file << "using ::bluetooth::packet::BitInserter;";
- out_file << "using ::bluetooth::packet::CustomFieldFixedSizeInterface;";
- out_file << "using ::bluetooth::packet::CustomTypeChecker;";
- out_file << "using ::bluetooth::packet::Iterator;";
- out_file << "using ::bluetooth::packet::kLittleEndian;";
- out_file << "using ::bluetooth::packet::PacketBuilder;";
- out_file << "using ::bluetooth::packet::PacketStruct;";
- out_file << "using ::bluetooth::packet::PacketView;";
- out_file << "\n#if defined(PACKET_FUZZ_TESTING) || defined(PACKET_TESTING) || defined(FUZZ_TARGET)\n";
- out_file << "using ::bluetooth::packet::RawBuilder;";
- out_file << "\n#endif\n";
- out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
- out_file << "\n\n";
-
- for (const auto& e : decls.type_defs_queue_) {
- if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
- const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
- EnumGen gen(*enum_def);
- gen.GenDefinition(out_file);
- out_file << "\n\n";
- }
- }
- for (const auto& e : decls.type_defs_queue_) {
- if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
- const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
- EnumGen gen(*enum_def);
- gen.GenLogging(out_file);
- out_file << "\n\n";
- }
- }
- for (const auto& ch : decls.type_defs_queue_) {
- if (ch.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
- const auto* checksum_def = dynamic_cast<const ChecksumDef*>(ch.second);
- checksum_def->GenChecksumCheck(out_file);
- }
- }
- out_file << "\n/* Done ChecksumChecks */\n";
-
- for (const auto& c : decls.type_defs_queue_) {
- if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM) {
- if (c.second->size_ == -1 /* Variable Size */) {
- const auto* custom_field_def = dynamic_cast<const CustomFieldDef*>(c.second);
- custom_field_def->GenCustomFieldCheck(out_file, decls.is_little_endian);
- } else { // fixed size
- const auto* custom_field_def = dynamic_cast<const CustomFieldDef*>(c.second);
- custom_field_def->GenFixedSizeCustomFieldCheck(out_file);
- }
- }
- }
- out_file << "\n";
-
- for (auto& s : decls.type_defs_queue_) {
- if (s.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
- const auto* struct_def = dynamic_cast<const StructDef*>(s.second);
- struct_def->GenDefinition(out_file);
- out_file << "\n";
- }
- }
-
- {
- StructParserGenerator spg(decls);
- spg.Generate(out_file);
- out_file << "\n\n";
- }
-
- for (const auto& packet_def : decls.packet_defs_queue_) {
- packet_def.second.GenParserDefinition(out_file);
- out_file << "\n\n";
- }
-
- for (const auto& packet_def : decls.packet_defs_queue_) {
- packet_def.second.GenBuilderDefinition(out_file);
- out_file << "\n\n";
- }
-
- generate_namespace_close(namespace_list, out_file);
-
- out_file.close();
-
- return true;
-}
-
-// Get the out_file shard at a symbol_count
-std::ofstream& get_out_file(size_t symbol_count, size_t symbol_total, std::vector<std::ofstream>* out_files) {
- auto symbols_per_shard = symbol_total / out_files->size();
- auto file_index = std::min(symbol_count / symbols_per_shard, out_files->size() - 1);
- return out_files->at(file_index);
-}
-
-bool generate_pybind11_sources_one_file(const Declarations& decls, const std::filesystem::path& input_file,
- const std::filesystem::path& include_dir, const std::filesystem::path& out_dir,
- const std::string& root_namespace, size_t num_shards) {
- auto gen_relative_path = input_file.lexically_relative(include_dir).parent_path();
-
- auto input_filename = input_file.filename().string().substr(0, input_file.filename().string().find(".pdl"));
- auto gen_path = out_dir / gen_relative_path;
-
- std::filesystem::create_directories(gen_path);
-
- auto gen_relative_header = gen_relative_path / (input_filename + ".h");
-
- std::vector<std::string> namespace_list;
- parse_namespace(root_namespace, gen_relative_path, &namespace_list);
-
- std::vector<std::ofstream> out_file_shards(num_shards);
- for (size_t i = 0; i < out_file_shards.size(); i++) {
- auto filename = gen_path / (input_filename + "_python3_shard_" + std::to_string(i) + ".cc");
- std::cout << "generating " << filename << std::endl;
- auto& out_file = out_file_shards[i];
- out_file.open(filename);
- if (!out_file.is_open()) {
- std::cerr << "can't open " << filename << std::endl;
- return false;
- }
- out_file << "#include <pybind11/pybind11.h>\n";
- out_file << "#include <pybind11/stl.h>\n";
- out_file << "\n\n";
- out_file << "#include " << gen_relative_header << "\n";
- out_file << "\n\n";
- out_file << "#include \"packet/raw_builder.h\"\n";
- out_file << "\n\n";
-
- for (const auto& c : decls.type_defs_queue_) {
- if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM) {
- const auto* custom_def = dynamic_cast<const CustomFieldDef*>(c.second);
- custom_def->GenPyBind11Include(out_file);
- }
- }
-
- out_file << "\n\n";
-
- generate_namespace_open(namespace_list, out_file);
- out_file << "\n\n";
-
- for (const auto& c : decls.type_defs_queue_) {
- if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM ||
- c.second->GetDefinitionType() == TypeDef::Type::CHECKSUM) {
- const auto* custom_def = dynamic_cast<const CustomFieldDef*>(c.second);
- custom_def->GenUsing(out_file);
- }
- }
- out_file << "\n\n";
-
- out_file << "using ::bluetooth::packet::BasePacketBuilder;";
- out_file << "using ::bluetooth::packet::BitInserter;";
- out_file << "using ::bluetooth::packet::CustomTypeChecker;";
- out_file << "using ::bluetooth::packet::Iterator;";
- out_file << "using ::bluetooth::packet::kLittleEndian;";
- out_file << "using ::bluetooth::packet::PacketBuilder;";
- out_file << "using ::bluetooth::packet::BaseStruct;";
- out_file << "using ::bluetooth::packet::PacketStruct;";
- out_file << "using ::bluetooth::packet::PacketView;";
- out_file << "using ::bluetooth::packet::RawBuilder;";
- out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
- out_file << "\n\n";
-
- out_file << "namespace py = pybind11;\n\n";
-
- out_file << "void define_" << input_filename << "_submodule_shard_" << std::to_string(i) << "(py::module& m) {\n\n";
- }
- size_t symbol_total = 0;
- // Only count types that will be generated
- for (const auto& e : decls.type_defs_queue_) {
- if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
- symbol_total++;
- } else if (e.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
- symbol_total++;
- }
- }
- // View and builder are counted separately
- symbol_total += decls.packet_defs_queue_.size() * 2;
- size_t symbol_count = 0;
-
- for (const auto& e : decls.type_defs_queue_) {
- if (e.second->GetDefinitionType() == TypeDef::Type::ENUM) {
- const auto* enum_def = dynamic_cast<const EnumDef*>(e.second);
- EnumGen gen(*enum_def);
- auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
- gen.GenDefinitionPybind11(out_file);
- out_file << "\n\n";
- symbol_count++;
- }
- }
-
- for (const auto& s : decls.type_defs_queue_) {
- if (s.second->GetDefinitionType() == TypeDef::Type::STRUCT) {
- const auto* struct_def = dynamic_cast<const StructDef*>(s.second);
- auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
- struct_def->GenDefinitionPybind11(out_file);
- out_file << "\n";
- symbol_count++;
- }
- }
-
- for (const auto& packet_def : decls.packet_defs_queue_) {
- auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
- packet_def.second.GenParserDefinitionPybind11(out_file);
- out_file << "\n\n";
- symbol_count++;
- }
-
- for (const auto& p : decls.packet_defs_queue_) {
- auto& out_file = get_out_file(symbol_count, symbol_total, &out_file_shards);
- p.second.GenBuilderDefinitionPybind11(out_file);
- out_file << "\n\n";
- symbol_count++;
- }
-
- for (auto& out_file : out_file_shards) {
- out_file << "}\n\n";
- generate_namespace_close(namespace_list, out_file);
- }
-
- auto gen_file_main = gen_path / (input_filename + "_python3.cc");
- std::ofstream out_file_main;
- out_file_main.open(gen_file_main);
- if (!out_file_main.is_open()) {
- std::cerr << "can't open " << gen_file_main << std::endl;
- return false;
- }
- out_file_main << "#include <pybind11/pybind11.h>\n";
- generate_namespace_open(namespace_list, out_file_main);
-
- out_file_main << "namespace py = pybind11;\n\n";
-
- for (size_t i = 0; i < out_file_shards.size(); i++) {
- out_file_main << "void define_" << input_filename << "_submodule_shard_" << std::to_string(i)
- << "(py::module& m);\n";
- }
-
- out_file_main << "void define_" << input_filename << "_submodule(py::module& m) {\n\n";
- for (size_t i = 0; i < out_file_shards.size(); i++) {
- out_file_main << "define_" << input_filename << "_submodule_shard_" << std::to_string(i) << "(m);\n";
- }
- out_file_main << "}\n\n";
-
- generate_namespace_close(namespace_list, out_file_main);
-
- return true;
-}
-
-} // namespace
-
// TODO(b/141583809): stop leaks
extern "C" const char* __asan_default_options() {
return "detect_leaks=0";