xref: /aosp_15_r20/external/pigweed/pw_status/guide.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_status-guide:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker====================
4*61c4878aSAndroid Build Coastguard WorkerGet started & guides
5*61c4878aSAndroid Build Coastguard Worker====================
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_status
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker.. _module-pw_status-get-started:
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker-----------
12*61c4878aSAndroid Build Coastguard WorkerGet started
13*61c4878aSAndroid Build Coastguard Worker-----------
14*61c4878aSAndroid Build Coastguard WorkerTo deploy ``pw_status``, depend on the library:
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker.. tab-set::
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: Bazel
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard Worker      Add ``@pigweed//pw_status`` to the ``deps`` list in your Bazel target:
21*61c4878aSAndroid Build Coastguard Worker
22*61c4878aSAndroid Build Coastguard Worker      .. code-block::
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Worker         cc_library("...") {
25*61c4878aSAndroid Build Coastguard Worker           # ...
26*61c4878aSAndroid Build Coastguard Worker           deps = [
27*61c4878aSAndroid Build Coastguard Worker             # ...
28*61c4878aSAndroid Build Coastguard Worker             "@pigweed//pw_status",
29*61c4878aSAndroid Build Coastguard Worker             # ...
30*61c4878aSAndroid Build Coastguard Worker           ]
31*61c4878aSAndroid Build Coastguard Worker         }
32*61c4878aSAndroid Build Coastguard Worker
33*61c4878aSAndroid Build Coastguard Worker      This assumes that your Bazel ``WORKSPACE`` has a `repository
34*61c4878aSAndroid Build Coastguard Worker      <https://bazel.build/concepts/build-ref#repositories>`_ named ``@pigweed``
35*61c4878aSAndroid Build Coastguard Worker      that points to the upstream Pigweed repository.
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: GN
38*61c4878aSAndroid Build Coastguard Worker
39*61c4878aSAndroid Build Coastguard Worker      Add ``$dir_pw_status`` to the ``deps`` list in your ``pw_executable()``
40*61c4878aSAndroid Build Coastguard Worker      build target:
41*61c4878aSAndroid Build Coastguard Worker
42*61c4878aSAndroid Build Coastguard Worker      .. code-block::
43*61c4878aSAndroid Build Coastguard Worker
44*61c4878aSAndroid Build Coastguard Worker         pw_executable("...") {
45*61c4878aSAndroid Build Coastguard Worker           # ...
46*61c4878aSAndroid Build Coastguard Worker           deps = [
47*61c4878aSAndroid Build Coastguard Worker             # ...
48*61c4878aSAndroid Build Coastguard Worker             "$dir_pw_status",
49*61c4878aSAndroid Build Coastguard Worker             # ...
50*61c4878aSAndroid Build Coastguard Worker           ]
51*61c4878aSAndroid Build Coastguard Worker         }
52*61c4878aSAndroid Build Coastguard Worker
53*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: CMake
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker      Add ``pw_status`` to your ``pw_add_library`` or similar CMake target:
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker      .. code-block::
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker         pw_add_library(my_library STATIC
60*61c4878aSAndroid Build Coastguard Worker           HEADERS
61*61c4878aSAndroid Build Coastguard Worker             ...
62*61c4878aSAndroid Build Coastguard Worker           PRIVATE_DEPS
63*61c4878aSAndroid Build Coastguard Worker             # ...
64*61c4878aSAndroid Build Coastguard Worker             pw_status
65*61c4878aSAndroid Build Coastguard Worker             # ...
66*61c4878aSAndroid Build Coastguard Worker         )
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: Zephyr
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard Worker      There are two ways to use ``pw_status`` from a Zephyr project:
71*61c4878aSAndroid Build Coastguard Worker
72*61c4878aSAndroid Build Coastguard Worker      * Depend on ``pw_status`` in your CMake target (see CMake tab). This is
73*61c4878aSAndroid Build Coastguard Worker        the Pigweed team's suggested approach since it enables precise CMake
74*61c4878aSAndroid Build Coastguard Worker        dependency analysis.
75*61c4878aSAndroid Build Coastguard Worker
76*61c4878aSAndroid Build Coastguard Worker      * Add ``CONFIG_PIGWEED_STATUS=y`` to the Zephyr project's configuration,
77*61c4878aSAndroid Build Coastguard Worker        which causes ``pw_status`` to become a global dependency and have the
78*61c4878aSAndroid Build Coastguard Worker        includes exposed to all targets. The Pigweed team does not recommend
79*61c4878aSAndroid Build Coastguard Worker        this approach, though it is the typical Zephyr solution.
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard WorkerThen use the status object or try macros:
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/try.h"
86*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status.h"
87*61c4878aSAndroid Build Coastguard Worker
88*61c4878aSAndroid Build Coastguard Worker   pw::Status MyOperation() {
89*61c4878aSAndroid Build Coastguard Worker     PW_TRY(SubOp1());
90*61c4878aSAndroid Build Coastguard Worker     PW_TRY(SubOp2());
91*61c4878aSAndroid Build Coastguard Worker     // ...
92*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
93*61c4878aSAndroid Build Coastguard Worker   }
94*61c4878aSAndroid Build Coastguard Worker
95*61c4878aSAndroid Build Coastguard Worker------
96*61c4878aSAndroid Build Coastguard WorkerGuides
97*61c4878aSAndroid Build Coastguard Worker------
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard WorkerTracking the first error encountered
100*61c4878aSAndroid Build Coastguard Worker------------------------------------
101*61c4878aSAndroid Build Coastguard WorkerIn some contexts it is useful to track the first error encountered while
102*61c4878aSAndroid Build Coastguard Workerallowing execution to continue. Manually writing out ``if`` statements to check
103*61c4878aSAndroid Build Coastguard Workerand then assign quickly becomes verbose, and doesn't explicitly highlight the
104*61c4878aSAndroid Build Coastguard Workerintended behavior of "latching" to the first error.
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker.. admonition:: **No**: Track status manually across calls
107*61c4878aSAndroid Build Coastguard Worker   :class: error
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard Worker   .. code-block:: cpp
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker      Status overall_status;
112*61c4878aSAndroid Build Coastguard Worker      for (Sector& sector : sectors) {
113*61c4878aSAndroid Build Coastguard Worker        Status erase_status = sector.Erase();
114*61c4878aSAndroid Build Coastguard Worker        if (!overall_status.ok()) {
115*61c4878aSAndroid Build Coastguard Worker          overall_status = erase_status;
116*61c4878aSAndroid Build Coastguard Worker        }
117*61c4878aSAndroid Build Coastguard Worker
118*61c4878aSAndroid Build Coastguard Worker        if (erase_status.ok()) {
119*61c4878aSAndroid Build Coastguard Worker          Status header_write_status = sector.WriteHeader();
120*61c4878aSAndroid Build Coastguard Worker          if (!overall_status.ok()) {
121*61c4878aSAndroid Build Coastguard Worker            overall_status = header_write_status;
122*61c4878aSAndroid Build Coastguard Worker          }
123*61c4878aSAndroid Build Coastguard Worker        }
124*61c4878aSAndroid Build Coastguard Worker      }
125*61c4878aSAndroid Build Coastguard Worker      return overall_status;
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::Status` has a :cpp:func:`pw::Status::Update()` helper function
128*61c4878aSAndroid Build Coastguard Workerthat does exactly this to reduce visual clutter and succinctly highlight the
129*61c4878aSAndroid Build Coastguard Workerintended behavior.
130*61c4878aSAndroid Build Coastguard Worker
131*61c4878aSAndroid Build Coastguard Worker.. admonition:: **Yes**: Track status with :cpp:func:`pw::Status::Update()`
132*61c4878aSAndroid Build Coastguard Worker   :class: checkmark
133*61c4878aSAndroid Build Coastguard Worker
134*61c4878aSAndroid Build Coastguard Worker   .. code-block:: cpp
135*61c4878aSAndroid Build Coastguard Worker
136*61c4878aSAndroid Build Coastguard Worker      Status overall_status;
137*61c4878aSAndroid Build Coastguard Worker      for (Sector& sector : sectors) {
138*61c4878aSAndroid Build Coastguard Worker        Status erase_status = sector.Erase();
139*61c4878aSAndroid Build Coastguard Worker        overall_status.Update(erase_status);
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard Worker        if (erase_status.ok()) {
142*61c4878aSAndroid Build Coastguard Worker          overall_status.Update(sector.WriteHeader());
143*61c4878aSAndroid Build Coastguard Worker        }
144*61c4878aSAndroid Build Coastguard Worker      }
145*61c4878aSAndroid Build Coastguard Worker      return overall_status;
146*61c4878aSAndroid Build Coastguard Worker
147*61c4878aSAndroid Build Coastguard Worker.. _module-pw_status-guide-status-with-size:
148*61c4878aSAndroid Build Coastguard Worker
149*61c4878aSAndroid Build Coastguard Worker----------------------------------
150*61c4878aSAndroid Build Coastguard WorkerJointly reporting status with size
151*61c4878aSAndroid Build Coastguard Worker----------------------------------
152*61c4878aSAndroid Build Coastguard Worker``pw::StatusWithSize`` (``pw_status/status_with_size.h``) is a convenient,
153*61c4878aSAndroid Build Coastguard Workerefficient class for reporting a status along with an unsigned integer value.
154*61c4878aSAndroid Build Coastguard WorkerIt is similar to the ``pw::Result<T>`` class, but it stores both a size and a
155*61c4878aSAndroid Build Coastguard Workerstatus, regardless of the status value, and only supports a limited range (27
156*61c4878aSAndroid Build Coastguard Workerbits).
157*61c4878aSAndroid Build Coastguard Worker
158*61c4878aSAndroid Build Coastguard Worker``pw::StatusWithSize`` values may be created with functions similar to
159*61c4878aSAndroid Build Coastguard Worker``pw::Status``. For example:
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status_with_size.h"
164*61c4878aSAndroid Build Coastguard Worker
165*61c4878aSAndroid Build Coastguard Worker   // An OK StatusWithSize with a size of 123.
166*61c4878aSAndroid Build Coastguard Worker   StatusWithSize(123)
167*61c4878aSAndroid Build Coastguard Worker
168*61c4878aSAndroid Build Coastguard Worker   // A NOT_FOUND StatusWithSize with a size of 0.
169*61c4878aSAndroid Build Coastguard Worker   StatusWithSize::NotFound()
170*61c4878aSAndroid Build Coastguard Worker
171*61c4878aSAndroid Build Coastguard Worker   // A RESOURCE_EXHAUSTED StatusWithSize with a size of 10.
172*61c4878aSAndroid Build Coastguard Worker   StatusWithSize::ResourceExhausted(10)
173*61c4878aSAndroid Build Coastguard Worker
174*61c4878aSAndroid Build Coastguard Worker``pw::StatusWithSize`` is useful for cases where an operation may partially
175*61c4878aSAndroid Build Coastguard Workercomplete - for example read operations may read some number of bytes into an
176*61c4878aSAndroid Build Coastguard Workeroutput buffer, but not all.
177*61c4878aSAndroid Build Coastguard Worker
178*61c4878aSAndroid Build Coastguard Worker-----------------------------------
179*61c4878aSAndroid Build Coastguard WorkerReducing error handling boilerplate
180*61c4878aSAndroid Build Coastguard Worker-----------------------------------
181*61c4878aSAndroid Build Coastguard WorkerManual error handling through return codes is easy to understand and
182*61c4878aSAndroid Build Coastguard Workerstraightforward to write, but leads to verbose code. To reduce boilerplate,
183*61c4878aSAndroid Build Coastguard WorkerPigweed has the ``PW_TRY`` (``pw_status/try.h``) macro, easing development of
184*61c4878aSAndroid Build Coastguard Workerfunctions checking or returning ``pw::Status`` and ``pw::StatusWithSize``
185*61c4878aSAndroid Build Coastguard Workerobjects. The ``PW_TRY`` and ``PW_TRY_WITH_SIZE`` macros call a function and do
186*61c4878aSAndroid Build Coastguard Workeran early return if the function's return status is not :c:enumerator:`OK`.
187*61c4878aSAndroid Build Coastguard Worker
188*61c4878aSAndroid Build Coastguard WorkerExample:
189*61c4878aSAndroid Build Coastguard Worker
190*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
191*61c4878aSAndroid Build Coastguard Worker
192*61c4878aSAndroid Build Coastguard Worker   Status PwTryExample() {
193*61c4878aSAndroid Build Coastguard Worker     PW_TRY(FunctionThatReturnsStatus());
194*61c4878aSAndroid Build Coastguard Worker     PW_TRY(FunctionThatReturnsStatusWithSize());
195*61c4878aSAndroid Build Coastguard Worker
196*61c4878aSAndroid Build Coastguard Worker     // Do something, only executed if both functions above return OK.
197*61c4878aSAndroid Build Coastguard Worker   }
198*61c4878aSAndroid Build Coastguard Worker
199*61c4878aSAndroid Build Coastguard Worker   StatusWithSize PwTryWithSizeExample() {
200*61c4878aSAndroid Build Coastguard Worker     PW_TRY_WITH_SIZE(FunctionThatReturnsStatus());
201*61c4878aSAndroid Build Coastguard Worker     PW_TRY_WITH_SIZE(FunctionThatReturnsStatusWithSize());
202*61c4878aSAndroid Build Coastguard Worker
203*61c4878aSAndroid Build Coastguard Worker     // Do something, only executed if both functions above return OK.
204*61c4878aSAndroid Build Coastguard Worker   }
205*61c4878aSAndroid Build Coastguard Worker
206*61c4878aSAndroid Build Coastguard Worker``PW_TRY_ASSIGN`` is for working with ``pw::StatusWithSize`` objects in in
207*61c4878aSAndroid Build Coastguard Workerfunctions that return Status. It is similar to ``PW_TRY`` with the addition of
208*61c4878aSAndroid Build Coastguard Workerassigning the size from the ``pw::StatusWithSize`` on ok.
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
211*61c4878aSAndroid Build Coastguard Worker
212*61c4878aSAndroid Build Coastguard Worker   Status PwTryAssignExample() {
213*61c4878aSAndroid Build Coastguard Worker     size_t size_value
214*61c4878aSAndroid Build Coastguard Worker     PW_TRY_ASSIGN(size_value, FunctionThatReturnsStatusWithSize());
215*61c4878aSAndroid Build Coastguard Worker
216*61c4878aSAndroid Build Coastguard Worker     // Do something that uses size_value. size_value is only assigned and this
217*61c4878aSAndroid Build Coastguard Worker     // following code executed if the PW_TRY_ASSIGN function above returns OK.
218*61c4878aSAndroid Build Coastguard Worker   }
219