1/*
2 * Copyright (C) 2015 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#ifndef ART_CMDLINE_CMDLINE_PARSE_RESULT_H_
18#define ART_CMDLINE_CMDLINE_PARSE_RESULT_H_
19
20#include "cmdline_result.h"
21#include "detail/cmdline_parser_detail.h"
22
23namespace art {
24// Result of a type-parsing attempt. If successful holds the strongly-typed value,
25// otherwise it holds either a usage or a failure string message that should be displayed back
26// to the user.
27//
28// CmdlineType::Parse/CmdlineType::ParseAndAppend must return this type.
29template <typename T>
30struct CmdlineParseResult : CmdlineResult {
31  using CmdlineResult::CmdlineResult;
32
33  // Create an error result with the usage error code and the specified message.
34  static CmdlineParseResult Usage(const std::string& message) {
35    return CmdlineParseResult(kUsage, message);
36  }
37
38  // Create an error result with the failure error code and no message.
39  static CmdlineParseResult<T> Failure()  {
40    return CmdlineParseResult(kFailure);
41  }
42
43  // Create an error result with the failure error code and no message.
44  static CmdlineParseResult<T> Failure(const std::string& message) {
45    return CmdlineParseResult(kFailure, message);
46  }
47
48  // Create a successful result which holds the specified value.
49  static CmdlineParseResult<T> Success(const T& value) {
50    return CmdlineParseResult(value);
51  }
52
53  // Create a successful result, taking over the value.
54  static CmdlineParseResult<T> Success(T&& value) {
55    return CmdlineParseResult(std::forward<T>(value));
56  }
57
58  // Create succesful result, without any values. Used when a value was successfully appended
59  // into an existing object.
60  static CmdlineParseResult<T> SuccessNoValue() {
61    return CmdlineParseResult(T {});
62  }
63
64  // Create an error result with the OutOfRange error and the specified message.
65  static CmdlineParseResult<T> OutOfRange(const std::string& message) {
66    return CmdlineParseResult(kOutOfRange, message);
67  }
68
69  // Create an error result with the OutOfRange code and a custom message
70  // which is printed from the actual/min/max values.
71  // Values are converted to string using the ostream<< operator.
72  static CmdlineParseResult<T> OutOfRange(const T& value,
73                                          const T& min,
74                                          const T& max) {
75    return CmdlineParseResult(kOutOfRange,
76                              "actual: " + art::detail::ToStringAny(value) +
77                              ", min: " + art::detail::ToStringAny(min) +
78                              ", max: " + art::detail::ToStringAny(max));
79  }
80
81  // Get a read-only reference to the underlying value.
82  // The result must have been successful and must have a value.
83  const T& GetValue() const {
84    assert(IsSuccess());
85    assert(has_value_);
86    return value_;
87  }
88
89  // Get a mutable reference to the underlying value.
90  // The result must have been successful and must have a value.
91  T& GetValue() {
92    assert(IsSuccess());
93    assert(has_value_);
94    return value_;
95  }
96
97  // Take over the value.
98  // The result must have been successful and must have a value.
99  T&& ReleaseValue() {
100    assert(IsSuccess());
101    assert(has_value_);
102    return std::move(value_);
103  }
104
105  // Whether or not the result has a value (e.g. created with Result::Success).
106  // Error results never have values, success results commonly, but not always, have values.
107  bool HasValue() const {
108    return has_value_;
109  }
110
111  // Cast an error-result from type T2 to T1.
112  // Safe since error-results don't store a typed value.
113  template <typename T2>
114  static CmdlineParseResult<T> CastError(const CmdlineParseResult<T2>& other) {
115    assert(other.IsError());
116    return CmdlineParseResult<T>(other.GetStatus());
117  }
118
119  // Make sure copying is allowed
120  CmdlineParseResult(const CmdlineParseResult&) = default;
121  // Make sure moving is cheap
122  CmdlineParseResult(CmdlineParseResult&&) = default;
123
124 private:
125  explicit CmdlineParseResult(const T& value)
126    : CmdlineResult(kSuccess), value_(value), has_value_(true) {}
127  explicit CmdlineParseResult(T&& value)
128    : CmdlineResult(kSuccess), value_(std::forward<T>(value)), has_value_(true) {}
129  explicit CmdlineParseResult()
130    : CmdlineResult(kSuccess), value_(), has_value_(false) {}
131
132  T value_;
133  bool has_value_ = false;
134};
135
136}  // namespace art
137
138#endif  // ART_CMDLINE_CMDLINE_PARSE_RESULT_H_
139