xref: /aosp_15_r20/external/pigweed/pw_result/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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