Add (pretty basic) config dumping and documentation help.

This commit is contained in:
David Given
2021-05-14 23:29:16 +02:00
parent 25f2c3a8c1
commit 05df0a37b1
6 changed files with 86 additions and 6 deletions

View File

@@ -3,6 +3,7 @@
#include "proto.h"
#include "utils.h"
#include "fmt/format.h"
#include <google/protobuf/text_format.h>
#include <regex>
static FlagGroup* currentFlagGroup;
@@ -10,6 +11,8 @@ static std::vector<Flag*> all_flags;
static std::map<const std::string, Flag*> 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<FlagGroup*> 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);
}

View File

@@ -132,3 +132,24 @@ std::set<unsigned> iterate(const RangeProto& range)
return set;
}
std::map<std::string, const google::protobuf::FieldDescriptor*> findAllProtoFields(google::protobuf::Message* message)
{
std::map<std::string, const google::protobuf::FieldDescriptor*> fields;
const auto* descriptor = message->GetDescriptor();
std::function<void(const google::protobuf::Descriptor*, const std::string&)> recurse =
[&](auto* d, const auto& s) {
for (int i=0; i<d->field_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;
}

View File

@@ -12,6 +12,9 @@ extern void setProtoByString(google::protobuf::Message* message, const std::stri
extern std::set<unsigned> iterate(const RangeProto& range);
extern std::map<std::string, const google::protobuf::FieldDescriptor*>
findAllProtoFields(google::protobuf::Message* message);
extern ConfigProto config;
#endif

View File

@@ -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(FluxSource::create(config.input().disk()));
std::unique_ptr<AbstractDecoder> decoder(AbstractDecoder::create(config.decoder()));
std::unique_ptr<ImageWriter> writer(ImageWriter::create(config.output().file()));

View File

@@ -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;
}

View File

@@ -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;