1 // Copyright 2020 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <utility> 17 18 #include "pw_status/status.h" 19 #include "pw_status/status_with_size.h" 20 21 // Macros for cleanly working with Status or StatusWithSize objects in functions 22 // that return Status. 23 24 /// Returns early if `expr` is a non-OK `Status` or `Result`. 25 #define PW_TRY(expr) _PW_TRY(_PW_TRY_UNIQUE(__LINE__), expr, return) 26 27 #define _PW_TRY(result, expr, return_stmt) \ 28 do { \ 29 if (auto result = (expr); !result.ok()) { \ 30 return_stmt ::pw::internal::ConvertToStatus(result); \ 31 } \ 32 } while (0) 33 34 /// Returns early if `expression` is a non-OK `Result`. 35 /// If `expression` is okay, assigns the inner value to `lhs`. 36 #define PW_TRY_ASSIGN(lhs, expression) \ 37 _PW_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), lhs, expression, return) 38 39 #define _PW_TRY_ASSIGN(result, lhs, expr, return_stmt) \ 40 auto result = (expr); \ 41 if (!result.ok()) { \ 42 return_stmt ::pw::internal::ConvertToStatus(result); \ 43 } \ 44 lhs = ::pw::internal::ConvertToValue(result) 45 46 /// Returns early if `expr` is a non-OK `Status` or `StatusWithSize`. 47 /// 48 /// This is designed for use in functions that return a `StatusWithSize`. 49 #define PW_TRY_WITH_SIZE(expr) _PW_TRY_WITH_SIZE(_PW_TRY_UNIQUE(__LINE__), expr) 50 51 #define _PW_TRY_WITH_SIZE(result, expr) \ 52 do { \ 53 if (auto result = (expr); !result.ok()) { \ 54 return ::pw::internal::ConvertToStatusWithSize(result); \ 55 } \ 56 } while (0) 57 58 #define _PW_TRY_UNIQUE(line) _PW_TRY_UNIQUE_EXPANDED(line) 59 #define _PW_TRY_UNIQUE_EXPANDED(line) _pw_try_unique_name_##line 60 61 /// Like `PW_TRY`, but using `co_return` instead of early `return`. 62 /// 63 /// This is necessary because only `co_return` can be used inside of a 64 /// coroutine, and there is no way to detect whether particular code is running 65 /// within a coroutine or not. 66 #define PW_CO_TRY(expr) _PW_TRY(_PW_TRY_UNIQUE(__LINE__), expr, co_return) 67 68 /// Like `PW_TRY_ASSIGN`, but using `co_return` instead of early `return`. 69 /// 70 /// This is necessary because only `co_return` can be used inside of a 71 /// coroutine, and there is no way to detect whether particular code is running 72 /// within a coroutine or not. 73 #define PW_CO_TRY_ASSIGN(lhs, expression) \ 74 _PW_TRY_ASSIGN(_PW_TRY_UNIQUE(__LINE__), lhs, expression, co_return) 75