1 // Copyright (c) 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef QUICHE_COMMON_QUICHE_STATUS_UTILS_H_
6 #define QUICHE_COMMON_QUICHE_STATUS_UTILS_H_
7
8 #include <utility>
9
10 #include "absl/base/optimization.h"
11 #include "absl/status/status.h"
12 #include "absl/strings/str_cat.h"
13
14 namespace quiche {
15
16 // A simplified version of the standard google3 "return if error" macro. Unlike
17 // the standard version, this does not come with a StatusBuilder support; the
18 // AppendToStatus() function below is meant to partially fill that gap.
19 #define QUICHE_RETURN_IF_ERROR(expr) \
20 do { \
21 absl::Status quiche_status_macro_value = (expr); \
22 if (ABSL_PREDICT_FALSE(!quiche_status_macro_value.ok())) { \
23 return quiche_status_macro_value; \
24 } \
25 } while (0)
26
27 // Copies absl::Status payloads from `original` to `target`; required to copy a
28 // status correctly.
CopyStatusPayloads(const absl::Status & original,absl::Status & target)29 inline void CopyStatusPayloads(const absl::Status& original,
30 absl::Status& target) {
31 original.ForEachPayload([&](absl::string_view key, const absl::Cord& value) {
32 target.SetPayload(key, value);
33 });
34 }
35
36 // Appends additional into to a status message if the status message is
37 // an error.
38 template <typename... T>
AppendToStatus(absl::Status input,T &&...args)39 absl::Status AppendToStatus(absl::Status input, T&&... args) {
40 if (ABSL_PREDICT_TRUE(input.ok())) {
41 return input;
42 }
43 absl::Status result = absl::Status(
44 input.code(), absl::StrCat(input.message(), std::forward<T>(args)...));
45 CopyStatusPayloads(input, result);
46 return result;
47 }
48
49 } // namespace quiche
50
51 #endif // QUICHE_COMMON_QUICHE_STATUS_UTILS_H_
52