1 /*
2  * Copyright (C) 2019 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 <string>
20 #include <variant>
21 
22 #include <android-base/logging.h>
23 
24 namespace android {
25 namespace jsonpb {
26 
27 template <typename T>
28 struct ErrorOr {
29   template <class... Args>
ErrorOrErrorOr30   explicit ErrorOr(Args&&... args) : data_(kIndex1, std::forward<Args>(args)...) {}
31   T& operator*() {
32     CHECK(ok());
33     return *std::get_if<1u>(&data_);
34   }
35   const T& operator*() const {
36     CHECK(ok());
37     return *std::get_if<1u>(&data_);
38   }
39   T* operator->() {
40     CHECK(ok());
41     return std::get_if<1u>(&data_);
42   }
43   const T* operator->() const {
44     CHECK(ok());
45     return std::get_if<1u>(&data_);
46   }
errorErrorOr47   const std::string& error() const {
48     CHECK(!ok());
49     return *std::get_if<0u>(&data_);
50   }
okErrorOr51   bool ok() const { return data_.index() != 0; }
MakeErrorErrorOr52   static ErrorOr<T> MakeError(const std::string& message) {
53     return ErrorOr<T>(message, Tag::kDummy);
54   }
55 
56  private:
57   enum class Tag { kDummy };
58   static constexpr std::in_place_index_t<0> kIndex0{};
59   static constexpr std::in_place_index_t<1> kIndex1{};
ErrorOrErrorOr60   ErrorOr(const std::string& msg, Tag) : data_(kIndex0, msg) {}
61 
62   std::variant<std::string, T> data_;
63 };
64 
65 template <typename T>
MakeError(const std::string & message)66 inline ErrorOr<T> MakeError(const std::string& message) {
67   return ErrorOr<T>::MakeError(message);
68 }
69 
70 }  // namespace jsonpb
71 }  // namespace android
72