• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 ANDROID_APEXD_STATUS_OR_H_
18 #define ANDROID_APEXD_STATUS_OR_H_
19 
20 #include <string>
21 #include <variant>
22 
23 #include <android-base/logging.h>
24 #include <android-base/macros.h>
25 
26 #include "status.h"
27 
28 namespace android {
29 namespace apex {
30 
31 template <typename T>
32 class StatusOr {
33  private:
34   enum class StatusOrTag { kDummy };
35 
36   static constexpr std::in_place_index_t<0> kIndex0{};
37   static constexpr std::in_place_index_t<1> kIndex1{};
38 
39  public:
40   template <class... Args>
StatusOr(Args &&...args)41   explicit StatusOr(Args&&... args)
42       : data_(kIndex1, std::forward<Args>(args)...) {}
43 
Ok()44   bool Ok() const WARN_UNUSED { return data_.index() != 0; }
45 
46   T& operator*() {
47     CHECK(Ok());
48     return *std::get_if<1u>(&data_);
49   }
50 
51   T* operator->() {
52     CHECK(Ok());
53     return std::get_if<1u>(&data_);
54   }
55 
56   const T* operator->() const {
57     CHECK(Ok());
58     return std::get_if<1u>(&data_);
59   }
60 
ErrorStatus()61   const Status& ErrorStatus() const {
62     CHECK(!Ok());
63     const Status& status = *std::get_if<0u>(&data_);
64     CHECK(!status.Ok());
65     return status;
66   }
67 
ErrorMessage()68   const std::string& ErrorMessage() const {
69     return ErrorStatus().ErrorMessage();
70   }
71 
MakeError(const std::string & msg)72   static StatusOr MakeError(const std::string& msg) {
73     return StatusOr(msg, StatusOrTag::kDummy);
74   }
MakeError(const Status & status)75   static StatusOr MakeError(const Status& status) {
76     return StatusOr(status.ErrorMessage(), StatusOrTag::kDummy);
77   }
78   // Added to be compatible with Status, i.e., T::Fail() works for both.
Fail(const std::string & msg)79   static StatusOr Fail(const std::string& msg) {
80     return StatusOr(msg, StatusOrTag::kDummy);
81   }
82 
83  private:
StatusOr(const std::string & msg,StatusOrTag dummy ATTRIBUTE_UNUSED)84   StatusOr(const std::string& msg, StatusOrTag dummy ATTRIBUTE_UNUSED)
85       : data_(kIndex0, msg) {}
86 
87   std::variant<Status, T> data_;
88 };
89 
90 }  // namespace apex
91 }  // namespace android
92 
93 #endif  // ANDROID_APEXD_STATUS_OR_H_
94