• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_span:
2
3=======
4pw_span
5=======
6.. pigweed-module::
7   :name: pw_span
8
9* **Standardized**: :cpp:class:`pw::span` matches C++20's `std::span
10  <https://en.cppreference.com/w/cpp/container/span>`_ as closely as possible.
11* **Zero-cost**: If ``std::span`` is available, ``pw::span`` is simply an alias
12  of it.
13
14.. pw_span-example-start
15
16.. code-block:: cpp
17
18   #include <span>
19
20   // With pw::span, a buffer is passed as a single argument.
21   // No need to handle pointer and size arguments.
22   bool ProcessBuffer(pw::span<uint8_t> buffer);
23
24   bool DoStuff() {
25     // ...
26     ProcessBuffer(c_array);
27     ProcessBuffer(array_object);
28     ProcessBuffer(pw::span(data_pointer, data_size));
29   }
30
31.. pw_span-example-end
32
33:cpp:class:`pw::span` is a convenient abstraction that wraps a pointer and a
34size. It's especially useful in APIs. Spans support implicit conversions from
35C arrays, ``std::array``, or any STL-style container, such as
36``std::string_view``.
37
38.. _module-pw_span-start:
39
40-----------
41Get started
42-----------
43.. repository: https://bazel.build/concepts/build-ref#repositories
44
45.. tab-set::
46
47   .. tab-item:: Bazel
48
49      Add ``@pigweed//pw_span`` to the ``deps`` list in your Bazel target:
50
51      .. code-block::
52
53         cc_library("...") {
54           # ...
55           deps = [
56             # ...
57             "@pigweed//pw_span",
58             # ...
59           ]
60         }
61
62      This assumes that your Bazel ``WORKSPACE`` has a `repository
63      <https://bazel.build/concepts/build-ref#repositories>`_ named ``@pigweed``
64      that points to the upstream Pigweed repository.
65
66   .. tab-item:: GN
67
68      Add ``$dir_pw_span`` to the ``deps`` list in your ``pw_executable()``
69      build target:
70
71      .. code-block::
72
73         pw_executable("...") {
74           # ...
75           deps = [
76             # ...
77             "$dir_pw_span",
78             # ...
79           ]
80         }
81
82   .. tab-item:: CMake
83
84      Add ``pw_span`` to your ``pw_add_library`` or similar CMake target:
85
86      .. code-block::
87
88         pw_add_library(my_library STATIC
89           HEADERS
90             ...
91           PRIVATE_DEPS
92             # ...
93             pw_span
94             # ...
95         )
96
97   .. tab-item:: Zephyr
98
99      There are two ways to use ``pw_span`` from a Zephyr project:
100
101      #. Depend on ``pw_span`` in your CMake target (see CMake tab). This is
102         Pigweed Team's suggested approach since it enables precise CMake
103         dependency analysis.
104
105      #. Add ``CONFIG_PIGWEED_SPAN=y`` to the Zephyr project's configuration,
106         which causes ``pw_span`` to become a global dependency and have the
107         includes exposed to all targets. Pigweed team does not recommend this
108         approach, though it is the typical Zephyr solution.
109
110------
111Guides
112------
113
114.. _module-pw_span-start-params:
115
116``pw::span`` as a function parameter
117====================================
118``pw::span`` objects should be passed by value.
119
120.. admonition:: **Yes**: Accept ``pw::span`` object by value:
121   :class: checkmark
122
123   .. code-block:: cpp
124
125      bool ProcessBuffer(pw::span<uint8_t> buffer);
126
127.. admonition:: **No**: Accept ``pw::span`` object by reference:
128   :class: error
129
130   .. code-block:: cpp
131
132      bool ProcessBuffer(const pw::span<uint8_t>& buffer);
133
134
135Rationale: Since a ``pw::span`` object is essentially a pointer and a size,
136references to ``pw::span`` objects are almost always unnecessary indirection.
137
138See also: https://abseil.io/tips/93#as-function-parameters
139
140Operating on arrays of bytes
141============================
142When operating on an array of bytes you typically need pointer and size
143arguments:
144
145.. code-block:: cpp
146
147   bool ProcessBuffer(char* buffer, size_t buffer_size);
148
149   bool DoStuff() {
150     ProcessBuffer(c_array, sizeof(c_array));
151     ProcessBuffer(array_object.data(), array_object.size());
152     ProcessBuffer(data_pointer, data_size);
153   }
154
155With ``pw::span`` you can pass the buffer as a single argument instead:
156
157.. include:: docs.rst
158   :start-after: .. pw_span-example-start
159   :end-before: .. pw_span-example-end
160
161Working with spans of binary data
162=================================
163Use ``pw::span<std::byte>`` or ``pw::span<const std::byte>`` to represent
164spans of binary data. Convert spans to byte spans with ``pw::as_bytes`` or
165``pw::as_writable_bytes``.
166
167.. code-block:: cpp
168
169   void ProcessData(pw::span<const std::byte> data);
170
171   void DoStuff() {
172     std::array<AnyType, 7> data = { ... };
173     ProcessData(pw::as_bytes(pw::span(data)));
174   }
175
176``pw_bytes/span.h`` provides ``ByteSpan`` and ``ConstByteSpan`` aliases for
177these types.
178
179Convert byte spans back to their original type, or to spans of other 1-byte
180types using ``pw::span_cast<T>``.
181
182.. literalinclude:: cast_test.cc
183   :language: cpp
184   :start-after: [start-pw_span-cast-example]
185   :end-before: [end-pw_span-cast-example]
186
187.. warning::
188
189   ``pw::span_cast<T>`` is only safe to use if the underlying data is actually
190   of the specified type, or if ``T`` is another 1-byte type (e.g.
191   ``uint8_t``). You cannot safely use this function to reinterpret e.g. a raw
192   byte array from ``malloc()`` as a span of integers.
193
194
195----------
196References
197----------
198
199pw_span/span.h
200==============
201See `std::span <https://en.cppreference.com/w/cpp/container/span>`_.
202The ``pw::span`` API is designed to match the ``std::span`` API.
203
204pw_span/cast.h
205==============
206This header provides functions for casting between ``pw::span`` types, and is
207not part of the ``std::span`` interface.
208
209..
210   TODO: https://pwbug.dev/396493663 - Doxygen thinks the const/non-const
211   versions of span_cast are the same function and merges their docs together.
212
213   .. doxygengroup:: pw_span_cast
214      :content-only:
215
216.. cpp:function:: span<T> pw::span_cast(std::span<std::byte> bytes)
217
218   Casts a ``pw::span<std::byte>`` (``ByteSpan``) to a span of a
219   different type.
220
221   This function is only safe to use if the underlying data is actually of the
222   specified type. You cannot safely use this function to reinterpret e.g. a
223   raw byte array from ``malloc()`` as a span of integers.
224
225   This function is essentially the inverse of ``pw::as_writable_bytes``.
226
227   If ``kSourceExtentBytes`` is ``dynamic_extent``, the returned span also has
228   a dynamic extent.  Otherwise, the returned span has a static extent of
229   ``kSourceExtentBytes / sizeof(ResultT)``.
230
231.. cpp:function:: span<const T> pw::span_cast(std::span<const std::byte> bytes)
232
233   Casts a ``pw::span<const std::byte>`` (``ConstByteSpan``) to a span of a
234   different const type.
235
236   This function is only safe to use if the underlying data is actually of the
237   specified type. You cannot safely use this function to reinterpret e.g. a
238   raw byte array from ``malloc()`` as a span of integers.
239
240   This function is essentially the inverse of ``pw::as_bytes``.
241
242   If ``kSourceExtentBytes`` is ``dynamic_extent``, the returned span also has
243   a dynamic extent.  Otherwise, the returned span has a static extent of
244   ``kSourceExtentBytes / sizeof(ResultT)``.
245
246Configuration options
247=====================
248The following configurations can be adjusted via compile-time configuration of
249this module, see the
250:ref:`module documentation <module-structure-compile-time-configuration>` for
251more details.
252
253.. doxygendefine:: PW_SPAN_ENABLE_ASSERTS
254