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