From 05df0a37b18228109cfa592b4fa2d78331383e6e Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 14 May 2021 23:29:16 +0200 Subject: [PATCH] Add (pretty basic) config dumping and documentation help. --- lib/flags.cc | 40 ++++++++++++++++++++++++++++++++++++++++ lib/proto.cc | 21 +++++++++++++++++++++ lib/proto.h | 3 +++ src/fe-read.cc | 5 ----- tests/proto.cc | 19 +++++++++++++++++++ tests/testproto.proto | 4 +++- 6 files changed, 86 insertions(+), 6 deletions(-) diff --git a/lib/flags.cc b/lib/flags.cc index 1e5bae3d..0831e1e1 100644 --- a/lib/flags.cc +++ b/lib/flags.cc @@ -3,6 +3,7 @@ #include "proto.h" #include "utils.h" #include "fmt/format.h" +#include #include static FlagGroup* currentFlagGroup; @@ -10,6 +11,8 @@ static std::vector all_flags; static std::map flags_by_name; static void doHelp(); +static void doShowConfig(); +static void doDoc(); static FlagGroup helpGroup; static ActionFlag helpFlag = ActionFlag( @@ -17,6 +20,16 @@ static ActionFlag helpFlag = ActionFlag( "Shows the help.", doHelp); +static ActionFlag showConfigFlag = ActionFlag( + { "--show-config", "-c" }, + "Shows the currently set configuration and halts.", + doShowConfig); + +static ActionFlag docFlag = ActionFlag( + { "--doc" }, + "Shows the available configuration options.", + doDoc); + FlagGroup::FlagGroup(const std::initializer_list groups): _groups(groups.begin(), groups.end()) { @@ -239,3 +252,30 @@ static void doHelp() } exit(0); } + +static void doShowConfig() +{ + std::string s; + google::protobuf::TextFormat::PrintToString(config, &s); + std::cout << s << '\n'; + + exit(0); +} + +static void doDoc() +{ + const auto fields = findAllProtoFields(&config); + for (const auto field : fields) + { + const std::string& path = field.first; + const google::protobuf::FieldDescriptor* f = field.second; + + if (f->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) + continue; + + std::string helpText = f->options().GetExtension(help); + std::cout << fmt::format("{}: {}\n", path, helpText); + } + + exit(0); +} diff --git a/lib/proto.cc b/lib/proto.cc index 6004e8e0..4f1c227b 100644 --- a/lib/proto.cc +++ b/lib/proto.cc @@ -132,3 +132,24 @@ std::set iterate(const RangeProto& range) return set; } +std::map findAllProtoFields(google::protobuf::Message* message) +{ + std::map fields; + const auto* descriptor = message->GetDescriptor(); + + std::function recurse = + [&](auto* d, const auto& s) { + for (int i=0; ifield_count(); i++) + { + const google::protobuf::FieldDescriptor* f = d->field(i); + std::string n = s + f->name(); + if (f->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) + recurse(f->message_type(), n + "."); + fields[n] = f; + } + }; + + recurse(descriptor, ""); + return fields; +} + diff --git a/lib/proto.h b/lib/proto.h index dde58cc2..77f91de9 100644 --- a/lib/proto.h +++ b/lib/proto.h @@ -12,6 +12,9 @@ extern void setProtoByString(google::protobuf::Message* message, const std::stri extern std::set iterate(const RangeProto& range); +extern std::map + findAllProtoFields(google::protobuf::Message* message); + extern ConfigProto config; #endif diff --git a/src/fe-read.cc b/src/fe-read.cc index 457ecf33..8bf304c5 100644 --- a/src/fe-read.cc +++ b/src/fe-read.cc @@ -28,11 +28,6 @@ int mainRead(int argc, const char* argv[]) if (!config.has_input() || !config.has_output()) Error() << "incomplete config (did you remember to specify the format?)"; - std::string s; - google::protobuf::TextFormat::PrintToString(config, &s); - std::cout << s << '\n'; - exit(0); - std::unique_ptr fluxSource(FluxSource::create(config.input().disk())); std::unique_ptr decoder(AbstractDecoder::create(config.decoder())); std::unique_ptr writer(ImageWriter::create(config.output().file())); diff --git a/tests/proto.cc b/tests/proto.cc index 2fc204cb..12184b57 100644 --- a/tests/proto.cc +++ b/tests/proto.cc @@ -98,12 +98,31 @@ static void test_range(void) } } +static void test_fields(void) +{ + TestProto proto; + auto fields = findAllProtoFields(&proto); + AssertThat(fields, HasLength(13)); +} + +static void test_options(void) +{ + TestProto proto; + const auto* descriptor = proto.descriptor(); + const auto* field = descriptor->FindFieldByName("i64"); + const auto& options = field->options(); + const std::string s = options.GetExtension(help); + AssertThat(s, Equals("i64")); +} + int main(int argc, const char* argv[]) { test_setting(); test_config(); test_load(); test_range(); + test_fields(); + test_options(); return 0; } diff --git a/tests/testproto.proto b/tests/testproto.proto index aef9ec46..5ce39e83 100644 --- a/tests/testproto.proto +++ b/tests/testproto.proto @@ -1,11 +1,13 @@ syntax = "proto2"; +import "lib/common.proto"; + message TestProto { message SubMessageProto { optional string s = 1; } - optional int64 i64 = 1; + optional int64 i64 = 1 [(help)="i64"]; optional int32 i32 = 2; optional uint64 u64 = 3; optional uint32 u32 = 4;