1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_result: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker========= 4*61c4878aSAndroid Build Coastguard Workerpw_result 5*61c4878aSAndroid Build Coastguard Worker========= 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_result 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker - **Easy**: Minimal boilerplate via with ``PW_TRY_ASSIGN`` macro and chaining 10*61c4878aSAndroid Build Coastguard Worker - **Reliable**: Propagate errors consistently for less bugs 11*61c4878aSAndroid Build Coastguard Worker - **Battle-tested**: Just like ``absl::StatusOr``, deployed extensively 12*61c4878aSAndroid Build Coastguard Worker 13*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>`` is a union of an error (:cpp:class:`pw::Status`) and a value 14*61c4878aSAndroid Build Coastguard Worker(``T``), in a type-safe and convenient wrapper. This enables operations to 15*61c4878aSAndroid Build Coastguard Workerreturn either a value on success, or an error code on failure, in one type. 16*61c4878aSAndroid Build Coastguard WorkerPropagating errors with this one type is less burdensome than other methods, 17*61c4878aSAndroid Build Coastguard Workerreducing the temptation to write code that crashes or fails silently in error 18*61c4878aSAndroid Build Coastguard Workercases. Take the following lengthy code for example: 19*61c4878aSAndroid Build Coastguard Worker 20*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h" 23*61c4878aSAndroid Build Coastguard Worker #include "pw_result/result.h" 24*61c4878aSAndroid Build Coastguard Worker #include "pw_status/try.h" 25*61c4878aSAndroid Build Coastguard Worker 26*61c4878aSAndroid Build Coastguard Worker pw::Result<int> GetBatteryVoltageMillivolts(); // Can fail 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker pw::Status UpdateChargerDisplay() { 29*61c4878aSAndroid Build Coastguard Worker const pw::Result<int> battery_mv = GetBatteryVoltageMillivolts(); 30*61c4878aSAndroid Build Coastguard Worker if (!battery_mv.ok()) { 31*61c4878aSAndroid Build Coastguard Worker // Voltage read failed; propagate the status to callers. 32*61c4878aSAndroid Build Coastguard Worker return battery_mv.status(); 33*61c4878aSAndroid Build Coastguard Worker } 34*61c4878aSAndroid Build Coastguard Worker PW_LOG_INFO("Battery voltage: %d mV", *battery_mv); 35*61c4878aSAndroid Build Coastguard Worker SetDisplayBatteryVoltage(*battery_mv); 36*61c4878aSAndroid Build Coastguard Worker return pw::OkStatus(); 37*61c4878aSAndroid Build Coastguard Worker } 38*61c4878aSAndroid Build Coastguard Worker 39*61c4878aSAndroid Build Coastguard WorkerThe ``PW_TRY_ASSIGN`` macro enables shortening the above to: 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 42*61c4878aSAndroid Build Coastguard Worker 43*61c4878aSAndroid Build Coastguard Worker pw::Status UpdateChargerDisplay() { 44*61c4878aSAndroid Build Coastguard Worker PW_TRY_ASSIGN(const int battery_mv, GetBatteryVoltageMillivolts()); 45*61c4878aSAndroid Build Coastguard Worker PW_LOG_INFO("Battery voltage: %d mV", battery_mv); 46*61c4878aSAndroid Build Coastguard Worker SetDisplayBatteryVoltage(battery_mv); 47*61c4878aSAndroid Build Coastguard Worker return pw::OkStatus(); 48*61c4878aSAndroid Build Coastguard Worker } 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard WorkerThe ``pw::Result<T>`` class is based on Abseil's ``absl::StatusOr<T>`` class. 51*61c4878aSAndroid Build Coastguard WorkerSee Abseil's `documentation 52*61c4878aSAndroid Build Coastguard Worker<https://abseil.io/docs/cpp/guides/status#returning-a-status-or-a-value>`_ and 53*61c4878aSAndroid Build Coastguard Worker`usage tips <https://abseil.io/tips/181>`_ for extra guidance. 54*61c4878aSAndroid Build Coastguard Worker 55*61c4878aSAndroid Build Coastguard Worker----------- 56*61c4878aSAndroid Build Coastguard WorkerGet started 57*61c4878aSAndroid Build Coastguard Worker----------- 58*61c4878aSAndroid Build Coastguard WorkerTo deploy ``pw_result``, depend on the library: 59*61c4878aSAndroid Build Coastguard Worker 60*61c4878aSAndroid Build Coastguard Worker.. tab-set:: 61*61c4878aSAndroid Build Coastguard Worker 62*61c4878aSAndroid Build Coastguard Worker .. tab-item:: Bazel 63*61c4878aSAndroid Build Coastguard Worker 64*61c4878aSAndroid Build Coastguard Worker Add ``@pigweed//pw_result`` to the ``deps`` list in your Bazel target: 65*61c4878aSAndroid Build Coastguard Worker 66*61c4878aSAndroid Build Coastguard Worker .. code-block:: 67*61c4878aSAndroid Build Coastguard Worker 68*61c4878aSAndroid Build Coastguard Worker cc_library("...") { 69*61c4878aSAndroid Build Coastguard Worker # ... 70*61c4878aSAndroid Build Coastguard Worker deps = [ 71*61c4878aSAndroid Build Coastguard Worker # ... 72*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_result", 73*61c4878aSAndroid Build Coastguard Worker # ... 74*61c4878aSAndroid Build Coastguard Worker ] 75*61c4878aSAndroid Build Coastguard Worker } 76*61c4878aSAndroid Build Coastguard Worker 77*61c4878aSAndroid Build Coastguard Worker This assumes that your Bazel ``WORKSPACE`` has a `repository 78*61c4878aSAndroid Build Coastguard Worker <https://bazel.build/concepts/build-ref#repositories>`_ named ``@pigweed`` 79*61c4878aSAndroid Build Coastguard Worker that points to the upstream Pigweed repository. 80*61c4878aSAndroid Build Coastguard Worker 81*61c4878aSAndroid Build Coastguard Worker .. tab-item:: GN 82*61c4878aSAndroid Build Coastguard Worker 83*61c4878aSAndroid Build Coastguard Worker Add ``$dir_pw_result`` to the ``deps`` list in your ``pw_executable()`` 84*61c4878aSAndroid Build Coastguard Worker build target: 85*61c4878aSAndroid Build Coastguard Worker 86*61c4878aSAndroid Build Coastguard Worker .. code-block:: 87*61c4878aSAndroid Build Coastguard Worker 88*61c4878aSAndroid Build Coastguard Worker pw_executable("...") { 89*61c4878aSAndroid Build Coastguard Worker # ... 90*61c4878aSAndroid Build Coastguard Worker deps = [ 91*61c4878aSAndroid Build Coastguard Worker # ... 92*61c4878aSAndroid Build Coastguard Worker "$dir_pw_result", 93*61c4878aSAndroid Build Coastguard Worker # ... 94*61c4878aSAndroid Build Coastguard Worker ] 95*61c4878aSAndroid Build Coastguard Worker } 96*61c4878aSAndroid Build Coastguard Worker 97*61c4878aSAndroid Build Coastguard Worker .. tab-item:: CMake 98*61c4878aSAndroid Build Coastguard Worker 99*61c4878aSAndroid Build Coastguard Worker Add ``pw_result`` to your ``pw_add_library`` or similar CMake target: 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard Worker .. code-block:: 102*61c4878aSAndroid Build Coastguard Worker 103*61c4878aSAndroid Build Coastguard Worker pw_add_library(my_library STATIC 104*61c4878aSAndroid Build Coastguard Worker HEADERS 105*61c4878aSAndroid Build Coastguard Worker ... 106*61c4878aSAndroid Build Coastguard Worker PRIVATE_DEPS 107*61c4878aSAndroid Build Coastguard Worker # ... 108*61c4878aSAndroid Build Coastguard Worker pw_result 109*61c4878aSAndroid Build Coastguard Worker # ... 110*61c4878aSAndroid Build Coastguard Worker ) 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard Worker .. tab-item:: Zephyr 113*61c4878aSAndroid Build Coastguard Worker 114*61c4878aSAndroid Build Coastguard Worker There are two ways to use ``pw_result`` from a Zephyr project: 115*61c4878aSAndroid Build Coastguard Worker 116*61c4878aSAndroid Build Coastguard Worker * Depend on ``pw_result`` in your CMake target (see CMake tab). This is 117*61c4878aSAndroid Build Coastguard Worker the Pigweed team's suggested approach since it enables precise CMake 118*61c4878aSAndroid Build Coastguard Worker dependency analysis. 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard Worker * Add ``CONFIG_PIGWEED_RESULT=y`` to the Zephyr project's configuration, 121*61c4878aSAndroid Build Coastguard Worker which causes ``pw_result`` to become a global dependency and have the 122*61c4878aSAndroid Build Coastguard Worker includes exposed to all targets. The Pigweed team does not recommend 123*61c4878aSAndroid Build Coastguard Worker this approach, though it is the typical Zephyr solution. 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard Worker------ 126*61c4878aSAndroid Build Coastguard WorkerGuides 127*61c4878aSAndroid Build Coastguard Worker------ 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard WorkerOverview 130*61c4878aSAndroid Build Coastguard Worker======== 131*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>`` objects represent either: 132*61c4878aSAndroid Build Coastguard Worker 133*61c4878aSAndroid Build Coastguard Worker* A value (accessed with ``operator*`` or ``operator->``) and an OK status 134*61c4878aSAndroid Build Coastguard Worker* An error (accessed with ``.status()``) and no value 135*61c4878aSAndroid Build Coastguard Worker 136*61c4878aSAndroid Build Coastguard WorkerIf ``result.ok()`` returns ``true`` the instance contains a valid value (of type 137*61c4878aSAndroid Build Coastguard Worker``T``). Otherwise, it does not contain a valid value, and attempting to access 138*61c4878aSAndroid Build Coastguard Workerthe value is an error. 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard WorkerA ``pw::Result<T>`` instance can never contain both an OK status and a value. In 141*61c4878aSAndroid Build Coastguard Workermost cases, this is the appropriate choice. For cases where both a size and a 142*61c4878aSAndroid Build Coastguard Workerstatus must be returned, see :ref:`module-pw_status-guide-status-with-size`. 143*61c4878aSAndroid Build Coastguard Worker 144*61c4878aSAndroid Build Coastguard Worker.. warning:: 145*61c4878aSAndroid Build Coastguard Worker 146*61c4878aSAndroid Build Coastguard Worker Be careful not to use large value types in ``pw::Result`` objects, since they 147*61c4878aSAndroid Build Coastguard Worker are embedded by value. This can quickly consume stack. 148*61c4878aSAndroid Build Coastguard Worker 149*61c4878aSAndroid Build Coastguard WorkerReturning a result from a function 150*61c4878aSAndroid Build Coastguard Worker================================== 151*61c4878aSAndroid Build Coastguard WorkerTo return a result from a function, return either a value (implicitly indicating 152*61c4878aSAndroid Build Coastguard Workersuccess), or a `non-OK pw::Status <module-pw_status-codes>` object otherwise (to 153*61c4878aSAndroid Build Coastguard Workerindicate failure). 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard Worker pw::Result<float> GetAirPressureSensor() { 158*61c4878aSAndroid Build Coastguard Worker uint32_t sensor_value; 159*61c4878aSAndroid Build Coastguard Worker if (!vendor_raw_sensor_read(&sensor_value)) { 160*61c4878aSAndroid Build Coastguard Worker return pw::Status::Unavailable(); // Converted to error Result 161*61c4878aSAndroid Build Coastguard Worker } 162*61c4878aSAndroid Build Coastguard Worker return sensor_value / 216.5; // Converted to OK Result with float 163*61c4878aSAndroid Build Coastguard Worker } 164*61c4878aSAndroid Build Coastguard Worker 165*61c4878aSAndroid Build Coastguard WorkerAccessing the contained value 166*61c4878aSAndroid Build Coastguard Worker============================= 167*61c4878aSAndroid Build Coastguard WorkerAccessing the value held by a ``pw::Result<T>`` should be performed via 168*61c4878aSAndroid Build Coastguard Worker``operator*`` or ``operator->``, after a call to ``ok()`` has verified that the 169*61c4878aSAndroid Build Coastguard Workervalue is present. 170*61c4878aSAndroid Build Coastguard Worker 171*61c4878aSAndroid Build Coastguard WorkerAccessing the value via ``operator->`` avoids introducing an extra local 172*61c4878aSAndroid Build Coastguard Workervariable to capture the result. 173*61c4878aSAndroid Build Coastguard Worker 174*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard Worker #include "pw_result/result.h" 177*61c4878aSAndroid Build Coastguard Worker 178*61c4878aSAndroid Build Coastguard Worker void Example() { 179*61c4878aSAndroid Build Coastguard Worker if (pw::Result<Foo> foo = TryCreateFoo(); foo.ok()) { 180*61c4878aSAndroid Build Coastguard Worker foo->DoBar(); // Note direct access to value inside the Result 181*61c4878aSAndroid Build Coastguard Worker } 182*61c4878aSAndroid Build Coastguard Worker } 183*61c4878aSAndroid Build Coastguard Worker 184*61c4878aSAndroid Build Coastguard WorkerPropagating errors from results 185*61c4878aSAndroid Build Coastguard Worker=============================== 186*61c4878aSAndroid Build Coastguard Worker``pw::Result`` instances are compatible with the ``PW_TRY`` and 187*61c4878aSAndroid Build Coastguard Worker``PW_TRY_ASSIGN`` macros, which enable concise propagation of errors for 188*61c4878aSAndroid Build Coastguard Workerfalliable operations that return values: 189*61c4878aSAndroid Build Coastguard Worker 190*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 191*61c4878aSAndroid Build Coastguard Worker 192*61c4878aSAndroid Build Coastguard Worker #include "pw_status/try.h" 193*61c4878aSAndroid Build Coastguard Worker #include "pw_result/result.h" 194*61c4878aSAndroid Build Coastguard Worker 195*61c4878aSAndroid Build Coastguard Worker pw::Result<int> GetAnswer(); // Example function. 196*61c4878aSAndroid Build Coastguard Worker 197*61c4878aSAndroid Build Coastguard Worker pw::Status UseAnswerWithTry() { 198*61c4878aSAndroid Build Coastguard Worker const pw::Result<int> answer = GetAnswer(); 199*61c4878aSAndroid Build Coastguard Worker PW_TRY(answer.status()); 200*61c4878aSAndroid Build Coastguard Worker if (answer.value() == 42) { 201*61c4878aSAndroid Build Coastguard Worker WhatWasTheUltimateQuestion(); 202*61c4878aSAndroid Build Coastguard Worker } 203*61c4878aSAndroid Build Coastguard Worker return pw::OkStatus(); 204*61c4878aSAndroid Build Coastguard Worker } 205*61c4878aSAndroid Build Coastguard Worker 206*61c4878aSAndroid Build Coastguard WorkerWith the ``PW_TRY_ASSIGN`` macro, you can combine declaring the result with the 207*61c4878aSAndroid Build Coastguard Workerreturn: 208*61c4878aSAndroid Build Coastguard Worker 209*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 210*61c4878aSAndroid Build Coastguard Worker 211*61c4878aSAndroid Build Coastguard Worker pw::Status UseAnswerWithTryAssign() { 212*61c4878aSAndroid Build Coastguard Worker PW_TRY_ASSIGN(const int answer, GetAnswer()); 213*61c4878aSAndroid Build Coastguard Worker PW_LOG_INFO("Got answer: %d", static_cast<int>(answer)); 214*61c4878aSAndroid Build Coastguard Worker return pw::OkStatus(); 215*61c4878aSAndroid Build Coastguard Worker } 216*61c4878aSAndroid Build Coastguard Worker 217*61c4878aSAndroid Build Coastguard WorkerChaining results 218*61c4878aSAndroid Build Coastguard Worker================ 219*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>`` also supports chained operations, similar to the additions 220*61c4878aSAndroid Build Coastguard Workermade to ``std::optional<T>`` in C++23. These operations allow functions to be 221*61c4878aSAndroid Build Coastguard Workerapplied to a ``pw::Result<T>`` that would perform additional computation. 222*61c4878aSAndroid Build Coastguard Worker 223*61c4878aSAndroid Build Coastguard WorkerThese operations do not incur any additional FLASH or RAM cost compared to a 224*61c4878aSAndroid Build Coastguard Workertraditional if/else ladder, as can be seen in the `Code size analysis`_. 225*61c4878aSAndroid Build Coastguard Worker 226*61c4878aSAndroid Build Coastguard WorkerWithout chaining or ``PW_TRY_ASSIGN``, invoking multiple falliable operations is 227*61c4878aSAndroid Build Coastguard Workerverbose: 228*61c4878aSAndroid Build Coastguard Worker 229*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 230*61c4878aSAndroid Build Coastguard Worker 231*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> GetCuteCat(const Image& img) { 232*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> cropped = CropToCat(img); 233*61c4878aSAndroid Build Coastguard Worker if (!cropped.ok()) { 234*61c4878aSAndroid Build Coastguard Worker return cropped.status(); 235*61c4878aSAndroid Build Coastguard Worker } 236*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> with_tie = AddBowTie(*cropped); 237*61c4878aSAndroid Build Coastguard Worker if (!with_tie.ok()) { 238*61c4878aSAndroid Build Coastguard Worker return with_tie.status(); 239*61c4878aSAndroid Build Coastguard Worker } 240*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> with_sparkles = MakeEyesSparkle(*with_tie); 241*61c4878aSAndroid Build Coastguard Worker if (!with_sparkles.ok()) { 242*61c4878aSAndroid Build Coastguard Worker return with_parkes.status(); 243*61c4878aSAndroid Build Coastguard Worker } 244*61c4878aSAndroid Build Coastguard Worker return AddRainbow(MakeSmaller(*with_sparkles)); 245*61c4878aSAndroid Build Coastguard Worker } 246*61c4878aSAndroid Build Coastguard Worker 247*61c4878aSAndroid Build Coastguard WorkerLeveraging ``PW_TRY_ASSIGN`` reduces the verbosity: 248*61c4878aSAndroid Build Coastguard Worker 249*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 250*61c4878aSAndroid Build Coastguard Worker 251*61c4878aSAndroid Build Coastguard Worker // Without chaining but using PW_TRY_ASSIGN. 252*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> GetCuteCat(const Image& img) { 253*61c4878aSAndroid Build Coastguard Worker PW_TRY_ASSIGN(Image cropped, CropToCat(img)); 254*61c4878aSAndroid Build Coastguard Worker PW_TRY_ASSIGN(Image with_tie, AddBowTie(*cropped)); 255*61c4878aSAndroid Build Coastguard Worker PW_TRY_ASSIGN(Image with_sparkles, MakeEyesSparkle(*with_tie)); 256*61c4878aSAndroid Build Coastguard Worker return AddRainbow(MakeSmaller(*with_sparkles)); 257*61c4878aSAndroid Build Coastguard Worker } 258*61c4878aSAndroid Build Coastguard Worker 259*61c4878aSAndroid Build Coastguard WorkerWith chaining we can reduce the code even further: 260*61c4878aSAndroid Build Coastguard Worker 261*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 262*61c4878aSAndroid Build Coastguard Worker 263*61c4878aSAndroid Build Coastguard Worker pw::Result<Image> GetCuteCat(const Image& img) { 264*61c4878aSAndroid Build Coastguard Worker return CropToCat(img) 265*61c4878aSAndroid Build Coastguard Worker .and_then(AddBoeTie) 266*61c4878aSAndroid Build Coastguard Worker .and_then(MakeEyesSparkle) 267*61c4878aSAndroid Build Coastguard Worker .transform(MakeSmaller) 268*61c4878aSAndroid Build Coastguard Worker .transform(AddRainbow); 269*61c4878aSAndroid Build Coastguard Worker } 270*61c4878aSAndroid Build Coastguard Worker 271*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>::and_then`` 272*61c4878aSAndroid Build Coastguard Worker--------------------------- 273*61c4878aSAndroid Build Coastguard WorkerThe ``pw::Result<T>::and_then`` member function will return the result of the 274*61c4878aSAndroid Build Coastguard Workerinvocation of the provided function on the contained value if it exists. 275*61c4878aSAndroid Build Coastguard WorkerOtherwise, returns the contained status in a ``pw::Result<U>``, which is the 276*61c4878aSAndroid Build Coastguard Workerreturn type of provided function. 277*61c4878aSAndroid Build Coastguard Worker 278*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 279*61c4878aSAndroid Build Coastguard Worker 280*61c4878aSAndroid Build Coastguard Worker // Expositional prototype of and_then: 281*61c4878aSAndroid Build Coastguard Worker template <typename T> 282*61c4878aSAndroid Build Coastguard Worker class Result { 283*61c4878aSAndroid Build Coastguard Worker template <typename U> 284*61c4878aSAndroid Build Coastguard Worker Result<U> and_then(Function<Result<U>(T)> func); 285*61c4878aSAndroid Build Coastguard Worker }; 286*61c4878aSAndroid Build Coastguard Worker 287*61c4878aSAndroid Build Coastguard Worker Result<Foo> CreateFoo(); 288*61c4878aSAndroid Build Coastguard Worker Result<Bar> CreateBarFromFoo(const Foo& foo); 289*61c4878aSAndroid Build Coastguard Worker 290*61c4878aSAndroid Build Coastguard Worker Result<Bar> bar = CreateFoo().and_then(CreateBarFromFoo); 291*61c4878aSAndroid Build Coastguard Worker 292*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>::or_else`` 293*61c4878aSAndroid Build Coastguard Worker-------------------------- 294*61c4878aSAndroid Build Coastguard WorkerThe ``pw::Result<T>::or_else`` member function will return ``*this`` if it 295*61c4878aSAndroid Build Coastguard Workercontains a value. Otherwise, it will return the result of the provided function. 296*61c4878aSAndroid Build Coastguard WorkerThe function must return a type convertible to a ``pw::Result<T>`` or ``void``. 297*61c4878aSAndroid Build Coastguard WorkerThis is particularly useful for handling errors. 298*61c4878aSAndroid Build Coastguard Worker 299*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 300*61c4878aSAndroid Build Coastguard Worker 301*61c4878aSAndroid Build Coastguard Worker // Expositional prototype of or_else: 302*61c4878aSAndroid Build Coastguard Worker template <typename T> 303*61c4878aSAndroid Build Coastguard Worker class Result { 304*61c4878aSAndroid Build Coastguard Worker template <typename U> 305*61c4878aSAndroid Build Coastguard Worker requires std::is_convertible_v<U, Result<T>> 306*61c4878aSAndroid Build Coastguard Worker Result<T> or_else(Function<U(Status)> func); 307*61c4878aSAndroid Build Coastguard Worker 308*61c4878aSAndroid Build Coastguard Worker Result<T> or_else(Function<void(Status)> func); 309*61c4878aSAndroid Build Coastguard Worker }; 310*61c4878aSAndroid Build Coastguard Worker 311*61c4878aSAndroid Build Coastguard Worker // Without or_else: 312*61c4878aSAndroid Build Coastguard Worker Result<Image> GetCuteCat(const Image& image) { 313*61c4878aSAndroid Build Coastguard Worker Result<Image> cropped = CropToCat(image); 314*61c4878aSAndroid Build Coastguard Worker if (!cropped.ok()) { 315*61c4878aSAndroid Build Coastguard Worker PW_LOG_ERROR("Failed to crop cat: %d", cropped.status().code()); 316*61c4878aSAndroid Build Coastguard Worker return cropped.status(); 317*61c4878aSAndroid Build Coastguard Worker } 318*61c4878aSAndroid Build Coastguard Worker return cropped; 319*61c4878aSAndroid Build Coastguard Worker } 320*61c4878aSAndroid Build Coastguard Worker 321*61c4878aSAndroid Build Coastguard Worker // With or_else: 322*61c4878aSAndroid Build Coastguard Worker Result<Image> GetCuteCat(const Image& image) { 323*61c4878aSAndroid Build Coastguard Worker return CropToCat(image).or_else( 324*61c4878aSAndroid Build Coastguard Worker [](Status s) { PW_LOG_ERROR("Failed to crop cat: %d", s.code()); }); 325*61c4878aSAndroid Build Coastguard Worker } 326*61c4878aSAndroid Build Coastguard Worker 327*61c4878aSAndroid Build Coastguard WorkerAnother useful scenario for ``pw::Result<T>::or_else`` is providing a default 328*61c4878aSAndroid Build Coastguard Workervalue that is expensive to compute. Typically, default values are provided by 329*61c4878aSAndroid Build Coastguard Workerusing ``pw::Result<T>::value_or``, but that requires the default value to be 330*61c4878aSAndroid Build Coastguard Workerconstructed regardless of whether you actually need it. 331*61c4878aSAndroid Build Coastguard Worker 332*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 333*61c4878aSAndroid Build Coastguard Worker 334*61c4878aSAndroid Build Coastguard Worker // With value_or: 335*61c4878aSAndroid Build Coastguard Worker Image GetCuteCat(const Image& image) { 336*61c4878aSAndroid Build Coastguard Worker // GenerateCuteCat() must execute regardless of the success of CropToCat 337*61c4878aSAndroid Build Coastguard Worker return CropToCat(image).value_or(GenerateCuteCat()); 338*61c4878aSAndroid Build Coastguard Worker } 339*61c4878aSAndroid Build Coastguard Worker 340*61c4878aSAndroid Build Coastguard Worker // With or_else: 341*61c4878aSAndroid Build Coastguard Worker Image GetCuteCat(const Image& image) { 342*61c4878aSAndroid Build Coastguard Worker // GenerateCuteCat() only executes if CropToCat fails. 343*61c4878aSAndroid Build Coastguard Worker return *CropToCat(image).or_else([](Status) { return GenerateCuteCat(); }); 344*61c4878aSAndroid Build Coastguard Worker } 345*61c4878aSAndroid Build Coastguard Worker 346*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>::transform`` 347*61c4878aSAndroid Build Coastguard Worker---------------------------- 348*61c4878aSAndroid Build Coastguard WorkerThe ``pw::Result<T>::transform`` member method will return a ``pw::Result<U>`` 349*61c4878aSAndroid Build Coastguard Workerwhich contains the result of the invocation of the given function if ``*this`` 350*61c4878aSAndroid Build Coastguard Workercontains a value. Otherwise, it returns a ``pw::Result<U>`` with the same 351*61c4878aSAndroid Build Coastguard Worker``pw::Status`` value as ``*this``. 352*61c4878aSAndroid Build Coastguard Worker 353*61c4878aSAndroid Build Coastguard WorkerThe monadic methods for ``and_then`` and ``transform`` are fairly similar. The 354*61c4878aSAndroid Build Coastguard Workerprimary difference is that ``and_then`` requires the provided function to return 355*61c4878aSAndroid Build Coastguard Workera ``pw::Result``, whereas ``transform`` functions can return any type. Users 356*61c4878aSAndroid Build Coastguard Workershould be aware that if they provide a function that returns a ``pw::Result`` to 357*61c4878aSAndroid Build Coastguard Worker``transform``, this will return a ``pw::Result<pw::Result<U>>``. 358*61c4878aSAndroid Build Coastguard Worker 359*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 360*61c4878aSAndroid Build Coastguard Worker 361*61c4878aSAndroid Build Coastguard Worker // Expositional prototype of transform: 362*61c4878aSAndroid Build Coastguard Worker template <typename T> 363*61c4878aSAndroid Build Coastguard Worker class Result { 364*61c4878aSAndroid Build Coastguard Worker template <typename U> 365*61c4878aSAndroid Build Coastguard Worker Result<U> transform(Function<U(T)> func); 366*61c4878aSAndroid Build Coastguard Worker }; 367*61c4878aSAndroid Build Coastguard Worker 368*61c4878aSAndroid Build Coastguard Worker Result<int> ConvertStringToInteger(std::string_view); 369*61c4878aSAndroid Build Coastguard Worker int MultiplyByTwo(int x); 370*61c4878aSAndroid Build Coastguard Worker 371*61c4878aSAndroid Build Coastguard Worker Result<int> x = ConvertStringToInteger("42") 372*61c4878aSAndroid Build Coastguard Worker .transform(MultiplyByTwo); 373*61c4878aSAndroid Build Coastguard Worker 374*61c4878aSAndroid Build Coastguard WorkerResults with custom error types: ``pw::expected`` 375*61c4878aSAndroid Build Coastguard Worker================================================= 376*61c4878aSAndroid Build Coastguard WorkerMost error codes can fit into one of the status codes supported by 377*61c4878aSAndroid Build Coastguard Worker``pw::Status``. However, custom error codes are occasionally needed for 378*61c4878aSAndroid Build Coastguard Workerinterfacing with other libraries, or other special situations. This module 379*61c4878aSAndroid Build Coastguard Workerincludes the ``pw::expected`` type for these situtaions. 380*61c4878aSAndroid Build Coastguard Worker 381*61c4878aSAndroid Build Coastguard Worker``pw::expected`` is either an alias for ``std::expected`` or a polyfill for that 382*61c4878aSAndroid Build Coastguard Workertype if it is not available. This type has a similar use case to ``pw::Result``, 383*61c4878aSAndroid Build Coastguard Workerin that it either returns a type ``T`` or an error, but the error may be any 384*61c4878aSAndroid Build Coastguard Workertype ``E``, not just ``pw::Status``. The ``PW_TRY`` and ``PW_TRY_ASSIGN`` 385*61c4878aSAndroid Build Coastguard Workermacros do not work with ``pw::expected`` but it should be usable in any place 386*61c4878aSAndroid Build Coastguard Workerthat ``std::expected`` from the ``C++23`` standard could be used. 387*61c4878aSAndroid Build Coastguard Worker 388*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 389*61c4878aSAndroid Build Coastguard Worker 390*61c4878aSAndroid Build Coastguard Worker #include "pw_result/expected.h" 391*61c4878aSAndroid Build Coastguard Worker 392*61c4878aSAndroid Build Coastguard Worker pw::expected<float, const char*> ReadBatteryVoltageOrError(); 393*61c4878aSAndroid Build Coastguard Worker 394*61c4878aSAndroid Build Coastguard Worker void TrySensorRead() { 395*61c4878aSAndroid Build Coastguard Worker pw::expected<float, const char*> voltage = ReadBatteryVoltageOrError(); 396*61c4878aSAndroid Build Coastguard Worker if (!voltage.has_value()) { 397*61c4878aSAndroid Build Coastguard Worker PW_LOG_ERROR("Couldn't read battery: %s", voltage.error()); 398*61c4878aSAndroid Build Coastguard Worker return; 399*61c4878aSAndroid Build Coastguard Worker } 400*61c4878aSAndroid Build Coastguard Worker PW_LOG_ERROR("Battery: %f", voltage.value()); 401*61c4878aSAndroid Build Coastguard Worker } 402*61c4878aSAndroid Build Coastguard Worker 403*61c4878aSAndroid Build Coastguard WorkerFor more information, see the `standard library reference 404*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/utility/expected>`_. 405*61c4878aSAndroid Build Coastguard Worker 406*61c4878aSAndroid Build Coastguard Worker------ 407*61c4878aSAndroid Build Coastguard WorkerDesign 408*61c4878aSAndroid Build Coastguard Worker------ 409*61c4878aSAndroid Build Coastguard Worker.. inclusive-language: disable 410*61c4878aSAndroid Build Coastguard Worker 411*61c4878aSAndroid Build Coastguard Worker``pw::Result<T>``'s implementation is closely based on Abseil's `StatusOr<T> 412*61c4878aSAndroid Build Coastguard Workerclass <https://github.com/abseil/abseil-cpp/blob/master/absl/status/statusor.h>`_. 413*61c4878aSAndroid Build Coastguard WorkerThere are a few differences: 414*61c4878aSAndroid Build Coastguard Worker 415*61c4878aSAndroid Build Coastguard Worker.. inclusive-language: enable 416*61c4878aSAndroid Build Coastguard Worker 417*61c4878aSAndroid Build Coastguard Worker* ``pw::Result<T>`` objects represent their status code with a ``pw::Status`` 418*61c4878aSAndroid Build Coastguard Worker member rather than an ``absl::Status``. The ``pw::Status`` objects are less 419*61c4878aSAndroid Build Coastguard Worker sophisticated but smaller than ``absl::Status`` objects. In particular, 420*61c4878aSAndroid Build Coastguard Worker ``pw::Status`` objects do not support string errors, and are limited to the 421*61c4878aSAndroid Build Coastguard Worker canonical error codes. 422*61c4878aSAndroid Build Coastguard Worker* ``pw::Result<T>`` objects are usable in ``constexpr`` statements if the value 423*61c4878aSAndroid Build Coastguard Worker type ``T`` is trivially destructible. 424*61c4878aSAndroid Build Coastguard Worker 425*61c4878aSAndroid Build Coastguard Worker------- 426*61c4878aSAndroid Build Coastguard WorkerRoadmap 427*61c4878aSAndroid Build Coastguard Worker------- 428*61c4878aSAndroid Build Coastguard WorkerThis module is stable. 429*61c4878aSAndroid Build Coastguard Worker 430*61c4878aSAndroid Build Coastguard Worker------------------ 431*61c4878aSAndroid Build Coastguard WorkerCode size analysis 432*61c4878aSAndroid Build Coastguard Worker------------------ 433*61c4878aSAndroid Build Coastguard WorkerThe table below showcases the difference in size between functions returning a 434*61c4878aSAndroid Build Coastguard Worker``pw::Status`` with an output pointer, and functions returning a Result, in 435*61c4878aSAndroid Build Coastguard Workervarious situations. 436*61c4878aSAndroid Build Coastguard Worker 437*61c4878aSAndroid Build Coastguard WorkerNote that these are simplified examples which do not necessarily reflect the 438*61c4878aSAndroid Build Coastguard Workerusage of ``pw::Result`` in real code. Make sure to always run your own size 439*61c4878aSAndroid Build Coastguard Workerreports to check if ``pw::Result`` is suitable for you. 440*61c4878aSAndroid Build Coastguard Worker 441*61c4878aSAndroid Build Coastguard Worker.. include:: result_size 442