• 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 #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