• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <memory>
20 #include <optional>
21 #include <string>
22 #include <unordered_set>
23 #include <vector>
24 
25 #include <cvd_server.pb.h>
26 
27 #include "common/libs/utils/result.h"
28 #include "host/commands/cvd/selector/arguments_lexer.h"
29 
30 namespace cuttlefish {
31 namespace selector {
32 
33 /**
34  * The very first parser for cmdline that separates:
35  *
36  *  1. program name/path
37  *  2. cvd specific options such as --clean, selector options, etc
38  *  3. subcmd
39  *  4. subcmd arguments
40  *
41  * Note that the user's command line arguments are in this order:
42  *  $ program_path/name <optional cvd-specific flags> \
43  *                      subcmd <optional subcmd arguments>
44  *
45  * For the parser's sake, there are a few more rules.
46  *
47  * 1. All the optional cvd-specific flags should be pre-registered. Usually,
48  * the subcmd arguments do not have to be registered. However, cvd-specific
49  * flags must be.
50  *
51  *  E.g. "--clean" is the only registered cvd-specific flag, which happened
52  *      to be bool.
53  *       These are okay:
54  *         cvd --clean start --never-exist-flag
55  *         cvd --noclean stop
56  *         cvd start
57  *
58  *       However, this is not okay:
59  *        cvd --daemon start
60  *
61  *  2. --
62  *  E.g. cvd --clean start --have --some --args -- a b c d e
63  *  -- is basically for subcommands. cvd itself does not use it.
64  *  If -- is within cvd arguments, it is ill-formatted. If it is within
65  *  subcommands arguments, we simply forward it to the subtool as is.
66  *
67  */
68 class ArgumentsSeparator {
69   using CvdProtobufArg = google::protobuf::RepeatedPtrField<std::string>;
70 
71  public:
72   struct FlagsRegistration {
73     std::unordered_set<std::string> known_boolean_flags;
74     std::unordered_set<std::string> known_value_flags;
75     std::unordered_set<std::string> valid_subcommands;
76   };
77   static Result<std::unique_ptr<ArgumentsSeparator>> Parse(
78       const FlagsRegistration& flag_registration,
79       const std::vector<std::string>& input_args);
80   static Result<std::unique_ptr<ArgumentsSeparator>> Parse(
81       const FlagsRegistration& flag_registration,
82       const CvdProtobufArg& input_args);
83   static Result<std::unique_ptr<ArgumentsSeparator>> Parse(
84       const FlagsRegistration& flag_registration, const std::string& input_args,
85       const std::string delim = " ");
86 
ProgPath()87   const std::string& ProgPath() const { return prog_path_; }
CvdArgs()88   const std::vector<std::string>& CvdArgs() const { return cvd_args_; }
SubCmd()89   std::optional<std::string> SubCmd() const { return sub_cmd_; }
SubCmdArgs()90   const std::vector<std::string>& SubCmdArgs() const { return sub_cmd_args_; }
91 
92  private:
93   ArgumentsSeparator(std::unique_ptr<ArgumentsLexer>&& lexer,
94                      const std::vector<std::string>& input_args,
95                      const FlagsRegistration& flag_registration);
96 
97   bool IsFlag(const ArgType arg_type) const;
98   struct Output {
99     std::string prog_path;
100     std::vector<std::string> cvd_args;
101     std::optional<std::string> sub_cmd;
102     std::vector<std::string> sub_cmd_args;
103   };
104   Result<void> Parse();
105   Result<Output> ParseInternal();
106 
107   // internals
108   std::unique_ptr<ArgumentsLexer> lexer_;
109 
110   // inputs
111   std::vector<std::string> input_args_;
112   std::unordered_set<std::string> known_boolean_flags_;
113   std::unordered_set<std::string> known_value_flags_;
114   std::unordered_set<std::string> valid_subcmds_;
115 
116   // outputs
117   std::string prog_path_;
118   std::vector<std::string> cvd_args_;
119   std::optional<std::string> sub_cmd_;
120   std::vector<std::string> sub_cmd_args_;
121 };
122 
123 }  // namespace selector
124 }  // namespace cuttlefish
125