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 #ifndef INCLUDE_PERFETTO_EXT_BASE_STATUS_OR_H_ 18 #define INCLUDE_PERFETTO_EXT_BASE_STATUS_OR_H_ 19 20 #include <optional> 21 22 #include "perfetto/base/status.h" 23 24 namespace perfetto { 25 namespace base { 26 27 // Union of a object of type |T| with a |base::Status|. Useful for cases where 28 // a |T| indicates a successful result of an operation and |base::Status| 29 // represents an error. 30 // 31 // This class is modelled closely on absl::Status and should essentially 1:1 32 // match it's API. 33 template <typename T> 34 class StatusOr { 35 public: 36 // Matches naming of declarations in similar types e.g. std::optional, 37 // std::variant. 38 using value_type = T; 39 40 // Intentionally implicit to allow idomatic usage (e.g. returning value/status 41 // from base::StatusOr returning function). StatusOr(base::Status status)42 StatusOr(base::Status status) : StatusOr(std::move(status), std::nullopt) { 43 if (status.ok()) { 44 // Matches what Abseil's approach towards OkStatus being passed to 45 // absl::StatusOr<T>. 46 PERFETTO_FATAL("base::OkStatus passed to StatusOr: this is not allowd"); 47 } 48 } StatusOr(T value)49 StatusOr(T value) : StatusOr(base::OkStatus(), std::move(value)) {} 50 ok()51 bool ok() const { return status_.ok(); } status()52 const base::Status& status() const { return status_; } 53 value()54 T& value() { 55 PERFETTO_DCHECK(status_.ok()); 56 return *value_; 57 } value()58 const T& value() const { return *value_; } 59 60 T& operator*() { return value(); } 61 const T& operator*() const { return value(); } 62 63 T* operator->() { return &value(); } 64 const T* operator->() const { return &value(); } 65 66 private: StatusOr(base::Status status,std::optional<T> value)67 StatusOr(base::Status status, std::optional<T> value) 68 : status_(std::move(status)), value_(std::move(value)) { 69 PERFETTO_DCHECK(!status_.ok() || value_.has_value()); 70 } 71 72 base::Status status_; 73 std::optional<T> value_; 74 }; 75 76 // Deduction guide to make returning StatusOr less verbose. 77 template <typename T> 78 StatusOr(T) -> StatusOr<T>; 79 80 } // namespace base 81 } // namespace perfetto 82 83 #endif // INCLUDE_PERFETTO_EXT_BASE_STATUS_OR_H_ 84