blob: 6c333090c54c92a1cf8d12fc1e92051459f3c5a8 [file] [log] [blame] [edit]
/*
* Copyright (C) 2022 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 "host/commands/cvd/frontline_parser.h"
#include <sstream>
#include <type_traits>
#include <vector>
#include <android-base/file.h>
#include <android-base/strings.h>
#include "common/libs/utils/flag_parser.h"
#include "host/commands/cvd/selector/selector_constants.h"
namespace cuttlefish {
Result<std::unique_ptr<FrontlineParser>> FrontlineParser::Parse(
ParserParam param) {
CF_EXPECT(!param.all_args.empty());
FrontlineParser* frontline_parser = new FrontlineParser(param);
CF_EXPECT(frontline_parser != nullptr,
"Memory allocation for FrontlineParser failed.");
CF_EXPECT(frontline_parser->Separate());
return std::unique_ptr<FrontlineParser>(frontline_parser);
}
FrontlineParser::FrontlineParser(const ParserParam& param)
: server_supported_subcmds_{param.server_supported_subcmds},
all_args_(param.all_args),
internal_cmds_(param.internal_cmds),
cvd_flags_(param.cvd_flags) {}
Result<void> FrontlineParser::Separate() {
arguments_separator_ = CF_EXPECT(CallSeparator());
return {};
}
Result<cvd_common::Args> FrontlineParser::ValidSubcmdsList() {
cvd_common::Args valid_subcmds(server_supported_subcmds_);
std::copy(internal_cmds_.cbegin(), internal_cmds_.cend(),
std::back_inserter(valid_subcmds));
return valid_subcmds;
}
static Result<std::unordered_set<std::string>> BoolFlagNames(
const std::vector<CvdFlagProxy>& flags) {
std::unordered_set<std::string> output;
for (const auto& flag : flags) {
if (flag.GetType() == CvdFlagProxy::FlagType::kBool) {
output.insert(CF_EXPECT(flag.Name()));
}
}
return output;
}
static Result<std::unordered_set<std::string>> ValueFlagNames(
const std::vector<CvdFlagProxy>& flags) {
std::unordered_set<std::string> output;
for (const auto& flag : flags) {
if (flag.GetType() == CvdFlagProxy::FlagType::kInt32 ||
flag.GetType() == CvdFlagProxy::FlagType::kString) {
output.insert(CF_EXPECT(flag.Name()));
}
}
return output;
}
Result<std::unique_ptr<selector::ArgumentsSeparator>>
FrontlineParser::CallSeparator() {
auto valid_subcmds_vector = CF_EXPECT(ValidSubcmdsList());
std::unordered_set<std::string> valid_subcmds{valid_subcmds_vector.begin(),
valid_subcmds_vector.end()};
auto cvd_flags = cvd_flags_.Flags();
auto known_bool_flags = CF_EXPECT(BoolFlagNames(cvd_flags));
auto known_value_flags = CF_EXPECT(ValueFlagNames(cvd_flags));
ArgumentsSeparator::FlagsRegistration flag_registration{
.known_boolean_flags = known_bool_flags,
.known_value_flags = known_value_flags,
.valid_subcommands = valid_subcmds};
auto arguments_separator =
CF_EXPECT(ArgumentsSeparator::Parse(flag_registration, all_args_));
CF_EXPECT(arguments_separator != nullptr);
return arguments_separator;
}
const std::string& FrontlineParser::ProgPath() const {
return arguments_separator_->ProgPath();
}
std::optional<std::string> FrontlineParser::SubCmd() const {
return arguments_separator_->SubCmd();
}
const cvd_common::Args& FrontlineParser::SubCmdArgs() const {
return arguments_separator_->SubCmdArgs();
}
const cvd_common::Args& FrontlineParser::CvdArgs() const {
return arguments_separator_->CvdArgs();
}
} // namespace cuttlefish