1 // Copyright 2020 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 CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_STATUS_MACROS_H_ 6 #define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_STATUS_MACROS_H_ 7 8 #include "chrome/browser/policy/messaging_layer/util/status.h" 9 #include "chrome/browser/policy/messaging_layer/util/statusor.h" 10 11 namespace reporting { 12 13 // Run a command that returns a Status. If the called code returns an 14 // error status, return that status up out of this method too. 15 // 16 // Example: 17 // RETURN_IF_ERROR(DoThings(4)); 18 #define RETURN_IF_ERROR(expr) \ 19 do { \ 20 /* Using _status below to avoid capture problems if expr is "status". */ \ 21 const ::reporting::Status _status = (expr); \ 22 if (__builtin_expect(!_status.ok(), 0)) \ 23 return _status; \ 24 } while (0) 25 26 // Internal helper for concatenating macro values. 27 #define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y 28 #define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y) 29 30 #define ASSIGN_OR_RETURN_IMPL(result, lhs, rexpr) \ 31 auto result = rexpr; \ 32 if (__builtin_expect(!result.ok(), 0)) { \ 33 return result.status(); \ 34 } \ 35 lhs = std::move(result).ValueOrDie() 36 37 // Executes an expression that returns a StatusOr, extracting its value 38 // into the variable defined by lhs (or returning on error). 39 // 40 // Example: Assigning to an existing value 41 // ValueType value; 42 // ASSIGN_OR_RETURN(value, MaybeGetValue(arg)); 43 // 44 // Example: Creating and assigning variable in one line. 45 // ASSIGN_OR_RETURN(ValueType value, MaybeGetValue(arg)); 46 // DoSomethingWithValueType(value); 47 // 48 // WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used 49 // in a single statement (e.g. as the body of an if statement without {})! 50 #define ASSIGN_OR_RETURN(lhs, rexpr) \ 51 ASSIGN_OR_RETURN_IMPL( \ 52 STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr) 53 54 #define ASSIGN_OR_ONCE_CALLBACK_AND_RETURN_IMPL(result, lhs, callback, rexpr) \ 55 const auto result = (rexpr); \ 56 if (__builtin_expect(!result.ok(), 0)) { \ 57 std::move(callback).Run(result.status()); \ 58 return; \ 59 } \ 60 lhs = result.ValueOrDie(); 61 62 // Executes an expression that returns a StatusOr, extracting its value into the 63 // variabled defined by lhs (or calls callback with error and returns). 64 // 65 // Example: 66 // base::OnceCallback<void(Status)> callback = 67 // base::BindOnce([](Status status) {...}); 68 // ASSIGN_OR_ONCE_CALLBACK_AND_RETURN(ValueType value, 69 // callback, 70 // MaybeGetValue(arg)); 71 // 72 // WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used 73 // in a single statement (e.g. as the body of an if statement without {})! 74 #define ASSIGN_OR_ONCE_CALLBACK_AND_RETURN(lhs, callback, rexpr) \ 75 ASSIGN_OR_ONCE_CALLBACK_AND_RETURN_IMPL( \ 76 STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, callback, \ 77 rexpr) 78 79 } // namespace reporting 80 81 #endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_STATUS_MACROS_H_ 82