xref: /aosp_15_r20/external/pigweed/pw_status/public/pw_status/try.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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