1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_stream: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::stream 4*61c4878aSAndroid Build Coastguard Worker 5*61c4878aSAndroid Build Coastguard Worker========= 6*61c4878aSAndroid Build Coastguard Workerpw_stream 7*61c4878aSAndroid Build Coastguard Worker========= 8*61c4878aSAndroid Build Coastguard Worker``pw_stream`` provides a foundational interface for streaming data from one part 9*61c4878aSAndroid Build Coastguard Workerof a system to another. In the simplest use cases, this is basically a memcpy 10*61c4878aSAndroid Build Coastguard Workerbehind a reusable interface that can be passed around the system. On the other 11*61c4878aSAndroid Build Coastguard Workerhand, the flexibility of this interface means a ``pw_stream`` could terminate is 12*61c4878aSAndroid Build Coastguard Workersomething more complex, like a UART stream or flash memory. 13*61c4878aSAndroid Build Coastguard Worker 14*61c4878aSAndroid Build Coastguard Worker-------- 15*61c4878aSAndroid Build Coastguard WorkerOverview 16*61c4878aSAndroid Build Coastguard Worker-------- 17*61c4878aSAndroid Build Coastguard WorkerAt the most basic level, ``pw_stream``'s interfaces provide very simple handles 18*61c4878aSAndroid Build Coastguard Workerto enabling streaming data from one location in a system to an endpoint. 19*61c4878aSAndroid Build Coastguard Worker 20*61c4878aSAndroid Build Coastguard WorkerExample: 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard Worker Status DumpSensorData(pw::stream::Writer& writer) { 25*61c4878aSAndroid Build Coastguard Worker static char temp[64]; 26*61c4878aSAndroid Build Coastguard Worker ImuSample imu_sample; 27*61c4878aSAndroid Build Coastguard Worker imu.GetSample(&info); 28*61c4878aSAndroid Build Coastguard Worker size_t bytes_written = imu_sample.AsCsv(temp, sizeof(temp)); 29*61c4878aSAndroid Build Coastguard Worker return writer.Write(temp, bytes_written); 30*61c4878aSAndroid Build Coastguard Worker } 31*61c4878aSAndroid Build Coastguard Worker 32*61c4878aSAndroid Build Coastguard WorkerIn this example, ``DumpSensorData()`` only cares that it has access to a 33*61c4878aSAndroid Build Coastguard Worker:cpp:class:`Writer` that it can use to stream data to using ``Writer::Write()``. 34*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`Writer` itself can be backed by anything that can act as a data 35*61c4878aSAndroid Build Coastguard Worker"sink." 36*61c4878aSAndroid Build Coastguard Worker 37*61c4878aSAndroid Build Coastguard Worker--------------------- 38*61c4878aSAndroid Build Coastguard Workerpw::stream Interfaces 39*61c4878aSAndroid Build Coastguard Worker--------------------- 40*61c4878aSAndroid Build Coastguard WorkerThere are three basic capabilities of a stream: 41*61c4878aSAndroid Build Coastguard Worker 42*61c4878aSAndroid Build Coastguard Worker* Reading -- Bytes can be read from the stream. 43*61c4878aSAndroid Build Coastguard Worker* Writing -- Bytes can be written to the stream. 44*61c4878aSAndroid Build Coastguard Worker* Seeking -- The position in the stream can be changed. 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard Worker``pw_stream`` provides a family of stream classes with different capabilities. 47*61c4878aSAndroid Build Coastguard WorkerThe most basic class, :cpp:class:`Stream` guarantees no functionality, while the 48*61c4878aSAndroid Build Coastguard Workermost capable class, :cpp:class:`SeekableReaderWriter` supports reading, writing, 49*61c4878aSAndroid Build Coastguard Workerand seeking. 50*61c4878aSAndroid Build Coastguard Worker 51*61c4878aSAndroid Build Coastguard WorkerUsage overview 52*61c4878aSAndroid Build Coastguard Worker============== 53*61c4878aSAndroid Build Coastguard Worker.. list-table:: 54*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 55*61c4878aSAndroid Build Coastguard Worker 56*61c4878aSAndroid Build Coastguard Worker * - pw::stream Interfaces 57*61c4878aSAndroid Build Coastguard Worker - Accept in APIs? 58*61c4878aSAndroid Build Coastguard Worker - Extend to create new stream? 59*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::stream::Stream` 60*61c4878aSAndroid Build Coastguard Worker - ❌ 61*61c4878aSAndroid Build Coastguard Worker - ❌ 62*61c4878aSAndroid Build Coastguard Worker * - | :cpp:class:`pw::stream::Reader` 63*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::Writer` 64*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::ReaderWriter` 65*61c4878aSAndroid Build Coastguard Worker - ✅ 66*61c4878aSAndroid Build Coastguard Worker - ❌ 67*61c4878aSAndroid Build Coastguard Worker * - | :cpp:class:`pw::stream::SeekableReader` 68*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::SeekableWriter` 69*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::SeekableReaderWriter` 70*61c4878aSAndroid Build Coastguard Worker - ✅ 71*61c4878aSAndroid Build Coastguard Worker - ✅ 72*61c4878aSAndroid Build Coastguard Worker * - | :cpp:class:`pw::stream::RelativeSeekableReader` 73*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::RelativeSeekableWriter` 74*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::RelativeSeekableReaderWriter` 75*61c4878aSAndroid Build Coastguard Worker - ✅ (rarely) 76*61c4878aSAndroid Build Coastguard Worker - ✅ 77*61c4878aSAndroid Build Coastguard Worker * - | :cpp:class:`pw::stream::NonSeekableReader` 78*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::NonSeekableWriter` 79*61c4878aSAndroid Build Coastguard Worker | :cpp:class:`pw::stream::NonSeekableReaderWriter` 80*61c4878aSAndroid Build Coastguard Worker - ❌ 81*61c4878aSAndroid Build Coastguard Worker - ✅ 82*61c4878aSAndroid Build Coastguard Worker 83*61c4878aSAndroid Build Coastguard Worker 84*61c4878aSAndroid Build Coastguard WorkerInterface documentation 85*61c4878aSAndroid Build Coastguard Worker======================= 86*61c4878aSAndroid Build Coastguard WorkerSummary documentation for the ``pw_stream`` interfaces is below. See the API 87*61c4878aSAndroid Build Coastguard Workercomments in `pw_stream/public/pw_stream/stream.h 88*61c4878aSAndroid Build Coastguard Worker<https://cs.pigweed.dev/pigweed/+/main:pw_stream/public/pw_stream/stream.h>`_ 89*61c4878aSAndroid Build Coastguard Workerfor full details. 90*61c4878aSAndroid Build Coastguard Worker 91*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::Stream 92*61c4878aSAndroid Build Coastguard Worker :members: 93*61c4878aSAndroid Build Coastguard Worker :private-members: 94*61c4878aSAndroid Build Coastguard Worker 95*61c4878aSAndroid Build Coastguard WorkerReader interfaces 96*61c4878aSAndroid Build Coastguard Worker----------------- 97*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::Reader 98*61c4878aSAndroid Build Coastguard Worker :members: 99*61c4878aSAndroid Build Coastguard Worker 100*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::SeekableReader 101*61c4878aSAndroid Build Coastguard Worker :members: 102*61c4878aSAndroid Build Coastguard Worker 103*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::RelativeSeekableReader 104*61c4878aSAndroid Build Coastguard Worker :members: 105*61c4878aSAndroid Build Coastguard Worker 106*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::NonSeekableReader 107*61c4878aSAndroid Build Coastguard Worker :members: 108*61c4878aSAndroid Build Coastguard Worker 109*61c4878aSAndroid Build Coastguard WorkerWriter interfaces 110*61c4878aSAndroid Build Coastguard Worker----------------- 111*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::Writer 112*61c4878aSAndroid Build Coastguard Worker :members: 113*61c4878aSAndroid Build Coastguard Worker 114*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::SeekableWriter 115*61c4878aSAndroid Build Coastguard Worker :members: 116*61c4878aSAndroid Build Coastguard Worker 117*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::RelativeSeekableWriter 118*61c4878aSAndroid Build Coastguard Worker :members: 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::NonSeekableWriter 121*61c4878aSAndroid Build Coastguard Worker :members: 122*61c4878aSAndroid Build Coastguard Worker 123*61c4878aSAndroid Build Coastguard Worker 124*61c4878aSAndroid Build Coastguard WorkerReaderWriter interfaces 125*61c4878aSAndroid Build Coastguard Worker----------------------- 126*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::ReaderWriter 127*61c4878aSAndroid Build Coastguard Worker :members: 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::SeekableReaderWriter 130*61c4878aSAndroid Build Coastguard Worker :members: 131*61c4878aSAndroid Build Coastguard Worker 132*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::RelativeSeekableReaderWriter 133*61c4878aSAndroid Build Coastguard Worker :members: 134*61c4878aSAndroid Build Coastguard Worker 135*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::stream::NonSeekableReaderWriter 136*61c4878aSAndroid Build Coastguard Worker :members: 137*61c4878aSAndroid Build Coastguard Worker 138*61c4878aSAndroid Build Coastguard Worker--------------- 139*61c4878aSAndroid Build Coastguard WorkerImplementations 140*61c4878aSAndroid Build Coastguard Worker--------------- 141*61c4878aSAndroid Build Coastguard Worker``pw_stream`` includes a few stream implementations for general use. 142*61c4878aSAndroid Build Coastguard Worker 143*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: MemoryWriter : public SeekableWriter 144*61c4878aSAndroid Build Coastguard Worker 145*61c4878aSAndroid Build Coastguard Worker The ``MemoryWriter`` class implements the :cpp:class:`Writer` interface by 146*61c4878aSAndroid Build Coastguard Worker backing the data destination with an **externally-provided** memory buffer. 147*61c4878aSAndroid Build Coastguard Worker ``MemoryWriterBuffer`` extends ``MemoryWriter`` to internally provide a memory 148*61c4878aSAndroid Build Coastguard Worker buffer. 149*61c4878aSAndroid Build Coastguard Worker 150*61c4878aSAndroid Build Coastguard Worker The ``MemoryWriter`` can be accessed like a standard C++ container. The 151*61c4878aSAndroid Build Coastguard Worker contents grow as data is written. 152*61c4878aSAndroid Build Coastguard Worker 153*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: MemoryReader : public SeekableReader 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard Worker The ``MemoryReader`` class implements the :cpp:class:`Reader` interface by 156*61c4878aSAndroid Build Coastguard Worker backing the data source with an **externally-provided** memory buffer. 157*61c4878aSAndroid Build Coastguard Worker 158*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: NullStream : public SeekableReaderWriter 159*61c4878aSAndroid Build Coastguard Worker 160*61c4878aSAndroid Build Coastguard Worker ``NullStream`` is a no-op stream implementation, similar to ``/dev/null``. 161*61c4878aSAndroid Build Coastguard Worker Writes are always dropped. Reads always return ``OUT_OF_RANGE``. Seeks have no 162*61c4878aSAndroid Build Coastguard Worker effect. 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: CountingNullStream : public SeekableReaderWriter 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker ``CountingNullStream`` is a no-op stream implementation, like 167*61c4878aSAndroid Build Coastguard Worker :cpp:class:`NullStream`, that counts the number of bytes written. 168*61c4878aSAndroid Build Coastguard Worker 169*61c4878aSAndroid Build Coastguard Worker .. cpp:function:: size_t bytes_written() const 170*61c4878aSAndroid Build Coastguard Worker 171*61c4878aSAndroid Build Coastguard Worker Returns the number of bytes provided to previous ``Write()`` calls. 172*61c4878aSAndroid Build Coastguard Worker 173*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: StdFileWriter : public SeekableWriter 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard Worker ``StdFileWriter`` wraps an ``std::ofstream`` with the :cpp:class:`Writer` 176*61c4878aSAndroid Build Coastguard Worker interface. 177*61c4878aSAndroid Build Coastguard Worker 178*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: StdFileReader : public SeekableReader 179*61c4878aSAndroid Build Coastguard Worker 180*61c4878aSAndroid Build Coastguard Worker ``StdFileReader`` wraps an ``std::ifstream`` with the :cpp:class:`Reader` 181*61c4878aSAndroid Build Coastguard Worker interface. 182*61c4878aSAndroid Build Coastguard Worker 183*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: SocketStream : public NonSeekableReaderWriter 184*61c4878aSAndroid Build Coastguard Worker 185*61c4878aSAndroid Build Coastguard Worker ``SocketStream`` wraps posix-style TCP sockets with the :cpp:class:`Reader` 186*61c4878aSAndroid Build Coastguard Worker and :cpp:class:`Writer` interfaces. It can be used to connect to a TCP server, 187*61c4878aSAndroid Build Coastguard Worker or to communicate with a client via the ``ServerSocket`` class. 188*61c4878aSAndroid Build Coastguard Worker 189*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: ServerSocket 190*61c4878aSAndroid Build Coastguard Worker 191*61c4878aSAndroid Build Coastguard Worker ``ServerSocket`` wraps a posix server socket, and produces a 192*61c4878aSAndroid Build Coastguard Worker :cpp:class:`SocketStream` for each accepted client connection. 193*61c4878aSAndroid Build Coastguard Worker 194*61c4878aSAndroid Build Coastguard Worker------------------ 195*61c4878aSAndroid Build Coastguard WorkerWhy use pw_stream? 196*61c4878aSAndroid Build Coastguard Worker------------------ 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard WorkerStandard API 199*61c4878aSAndroid Build Coastguard Worker============ 200*61c4878aSAndroid Build Coastguard Worker``pw_stream`` provides a standard way for classes to express that they have the 201*61c4878aSAndroid Build Coastguard Workerability to write data. Writing to one sink versus another sink is a matter of 202*61c4878aSAndroid Build Coastguard Workerjust passing a reference to the appropriate :cpp:class:`Writer`. 203*61c4878aSAndroid Build Coastguard Worker 204*61c4878aSAndroid Build Coastguard WorkerAs an example, imagine dumping sensor data. If written against a random HAL 205*61c4878aSAndroid Build Coastguard Workeror one-off class, there's porting work required to write to a different sink 206*61c4878aSAndroid Build Coastguard Worker(imagine writing over UART vs dumping to flash memory). Building a "dumping" 207*61c4878aSAndroid Build Coastguard Workerimplementation against the :cpp:class:`Writer` interface prevents a dependency 208*61c4878aSAndroid Build Coastguard Workeron a bespoke API that would require porting work. 209*61c4878aSAndroid Build Coastguard Worker 210*61c4878aSAndroid Build Coastguard WorkerSimilarly, after building a :cpp:class:`Writer` implementation for a Sink that 211*61c4878aSAndroid Build Coastguard Workerdata could be dumped to, that same :cpp:class:`Writer` can be reused for other 212*61c4878aSAndroid Build Coastguard Workercontexts that already write data to the :cpp:class:`pw::stream::Writer` 213*61c4878aSAndroid Build Coastguard Workerinterface. 214*61c4878aSAndroid Build Coastguard Worker 215*61c4878aSAndroid Build Coastguard WorkerBefore: 216*61c4878aSAndroid Build Coastguard Worker 217*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 218*61c4878aSAndroid Build Coastguard Worker 219*61c4878aSAndroid Build Coastguard Worker // Not reusable, depends on `Uart`. 220*61c4878aSAndroid Build Coastguard Worker void DumpSensorData(Uart& uart) { 221*61c4878aSAndroid Build Coastguard Worker static char temp[64]; 222*61c4878aSAndroid Build Coastguard Worker ImuSample imu_sample; 223*61c4878aSAndroid Build Coastguard Worker imu.GetSample(&info); 224*61c4878aSAndroid Build Coastguard Worker size_t bytes_written = imu_sample.AsCsv(temp, sizeof(temp)); 225*61c4878aSAndroid Build Coastguard Worker uart.Transmit(temp, bytes_written, /*timeout_ms=*/ 200); 226*61c4878aSAndroid Build Coastguard Worker } 227*61c4878aSAndroid Build Coastguard Worker 228*61c4878aSAndroid Build Coastguard WorkerAfter: 229*61c4878aSAndroid Build Coastguard Worker 230*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 231*61c4878aSAndroid Build Coastguard Worker 232*61c4878aSAndroid Build Coastguard Worker // Reusable; no more Uart dependency! 233*61c4878aSAndroid Build Coastguard Worker Status DumpSensorData(Writer& writer) { 234*61c4878aSAndroid Build Coastguard Worker static char temp[64]; 235*61c4878aSAndroid Build Coastguard Worker ImuSample imu_sample; 236*61c4878aSAndroid Build Coastguard Worker imu.GetSample(&info); 237*61c4878aSAndroid Build Coastguard Worker size_t bytes_written = imu_sample.AsCsv(temp, sizeof(temp)); 238*61c4878aSAndroid Build Coastguard Worker return writer.Write(temp, bytes_written); 239*61c4878aSAndroid Build Coastguard Worker } 240*61c4878aSAndroid Build Coastguard Worker 241*61c4878aSAndroid Build Coastguard WorkerReduce intermediate buffers 242*61c4878aSAndroid Build Coastguard Worker=========================== 243*61c4878aSAndroid Build Coastguard WorkerOften functions that write larger blobs of data request a buffer is passed as 244*61c4878aSAndroid Build Coastguard Workerthe destination that data should be written to. This *requires* a buffer to be 245*61c4878aSAndroid Build Coastguard Workerallocated, even if the data only exists in that buffer for a very short period 246*61c4878aSAndroid Build Coastguard Workerof time before it's written somewhere else. 247*61c4878aSAndroid Build Coastguard Worker 248*61c4878aSAndroid Build Coastguard WorkerIn situations where data read from somewhere will immediately be written 249*61c4878aSAndroid Build Coastguard Workersomewhere else, a :cpp:class:`Writer` interface can cut out the middleman 250*61c4878aSAndroid Build Coastguard Workerbuffer. 251*61c4878aSAndroid Build Coastguard Worker 252*61c4878aSAndroid Build Coastguard WorkerBefore: 253*61c4878aSAndroid Build Coastguard Worker 254*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 255*61c4878aSAndroid Build Coastguard Worker 256*61c4878aSAndroid Build Coastguard Worker // Requires an intermediate buffer to write the data as CSV. 257*61c4878aSAndroid Build Coastguard Worker void DumpSensorData(Uart& uart) { 258*61c4878aSAndroid Build Coastguard Worker char temp[64]; 259*61c4878aSAndroid Build Coastguard Worker ImuSample imu_sample; 260*61c4878aSAndroid Build Coastguard Worker imu.GetSample(&info); 261*61c4878aSAndroid Build Coastguard Worker size_t bytes_written = imu_sample.AsCsv(temp, sizeof(temp)); 262*61c4878aSAndroid Build Coastguard Worker uart.Transmit(temp, bytes_written, /*timeout_ms=*/ 200); 263*61c4878aSAndroid Build Coastguard Worker } 264*61c4878aSAndroid Build Coastguard Worker 265*61c4878aSAndroid Build Coastguard WorkerAfter: 266*61c4878aSAndroid Build Coastguard Worker 267*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 268*61c4878aSAndroid Build Coastguard Worker 269*61c4878aSAndroid Build Coastguard Worker // Both DumpSensorData() and RawSample::AsCsv() use a Writer, eliminating the 270*61c4878aSAndroid Build Coastguard Worker // need for an intermediate buffer. 271*61c4878aSAndroid Build Coastguard Worker Status DumpSensorData(Writer& writer) { 272*61c4878aSAndroid Build Coastguard Worker RawSample imu_sample; 273*61c4878aSAndroid Build Coastguard Worker imu.GetSample(&info); 274*61c4878aSAndroid Build Coastguard Worker return imu_sample.AsCsv(writer); 275*61c4878aSAndroid Build Coastguard Worker } 276*61c4878aSAndroid Build Coastguard Worker 277*61c4878aSAndroid Build Coastguard WorkerPrevent buffer overflow 278*61c4878aSAndroid Build Coastguard Worker======================= 279*61c4878aSAndroid Build Coastguard WorkerWhen copying data from one buffer to another, there must be checks to ensure the 280*61c4878aSAndroid Build Coastguard Workercopy does not overflow the destination buffer. As this sort of logic is 281*61c4878aSAndroid Build Coastguard Workerduplicated throughout a codebase, there's more opportunities for bound-checking 282*61c4878aSAndroid Build Coastguard Workerbugs to sneak in. ``Writers`` manage this logic internally rather than pushing 283*61c4878aSAndroid Build Coastguard Workerthe bounds checking to the code that is moving or writing the data. 284*61c4878aSAndroid Build Coastguard Worker 285*61c4878aSAndroid Build Coastguard WorkerSimilarly, since only the :cpp:class:`Writer` has access to any underlying 286*61c4878aSAndroid Build Coastguard Workerbuffers, it's harder for functions that share a :cpp:class:`Writer` to 287*61c4878aSAndroid Build Coastguard Workeraccidentally clobber data written by others using the same buffer. 288*61c4878aSAndroid Build Coastguard Worker 289*61c4878aSAndroid Build Coastguard WorkerBefore: 290*61c4878aSAndroid Build Coastguard Worker 291*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 292*61c4878aSAndroid Build Coastguard Worker 293*61c4878aSAndroid Build Coastguard Worker Status BuildPacket(Id dest, span<const std::byte> payload, 294*61c4878aSAndroid Build Coastguard Worker span<std::byte> dest) { 295*61c4878aSAndroid Build Coastguard Worker Header header; 296*61c4878aSAndroid Build Coastguard Worker if (dest.size_bytes() + payload.size_bytes() < sizeof(Header)) { 297*61c4878aSAndroid Build Coastguard Worker return Status::ResourceExhausted(); 298*61c4878aSAndroid Build Coastguard Worker } 299*61c4878aSAndroid Build Coastguard Worker header.dest = dest; 300*61c4878aSAndroid Build Coastguard Worker header.src = DeviceId(); 301*61c4878aSAndroid Build Coastguard Worker header.payload_size = payload.size_bytes(); 302*61c4878aSAndroid Build Coastguard Worker 303*61c4878aSAndroid Build Coastguard Worker memcpy(dest.data(), &header, sizeof(header)); 304*61c4878aSAndroid Build Coastguard Worker // Forgetting this line would clobber buffer contents. Also, using 305*61c4878aSAndroid Build Coastguard Worker // a temporary span instead could leave `dest` to be misused elsewhere in 306*61c4878aSAndroid Build Coastguard Worker // the function. 307*61c4878aSAndroid Build Coastguard Worker dest = dest.subspan(sizeof(header)); 308*61c4878aSAndroid Build Coastguard Worker memcpy(dest.data(), payload.data(), payload.size_bytes()); 309*61c4878aSAndroid Build Coastguard Worker } 310*61c4878aSAndroid Build Coastguard Worker 311*61c4878aSAndroid Build Coastguard WorkerAfter: 312*61c4878aSAndroid Build Coastguard Worker 313*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 314*61c4878aSAndroid Build Coastguard Worker 315*61c4878aSAndroid Build Coastguard Worker Status BuildPacket(Id dest, span<const std::byte> payload, Writer& writer) { 316*61c4878aSAndroid Build Coastguard Worker Header header; 317*61c4878aSAndroid Build Coastguard Worker header.dest = dest; 318*61c4878aSAndroid Build Coastguard Worker header.src = DeviceId(); 319*61c4878aSAndroid Build Coastguard Worker header.payload_size = payload.size_bytes(); 320*61c4878aSAndroid Build Coastguard Worker 321*61c4878aSAndroid Build Coastguard Worker writer.Write(header); 322*61c4878aSAndroid Build Coastguard Worker return writer.Write(payload); 323*61c4878aSAndroid Build Coastguard Worker } 324*61c4878aSAndroid Build Coastguard Worker 325*61c4878aSAndroid Build Coastguard Worker------------ 326*61c4878aSAndroid Build Coastguard WorkerDesign notes 327*61c4878aSAndroid Build Coastguard Worker------------ 328*61c4878aSAndroid Build Coastguard Worker 329*61c4878aSAndroid Build Coastguard WorkerSync & Flush 330*61c4878aSAndroid Build Coastguard Worker============ 331*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`pw::stream::Stream` API does not include ``Sync()`` or 332*61c4878aSAndroid Build Coastguard Worker``Flush()`` functions. There no mechanism in the :cpp:class:`Stream` API to 333*61c4878aSAndroid Build Coastguard Workersynchronize a :cpp:class:`Reader`'s potentially buffered input with its 334*61c4878aSAndroid Build Coastguard Workerunderlying data source. This must be handled by the implementation if required. 335*61c4878aSAndroid Build Coastguard WorkerSimilarly, the :cpp:class:`Writer` implementation is responsible for flushing 336*61c4878aSAndroid Build Coastguard Workerany buffered data to the sink. 337*61c4878aSAndroid Build Coastguard Worker 338*61c4878aSAndroid Build Coastguard Worker``Flush()`` and ``Sync()`` were excluded from :cpp:class:`Stream` for a few 339*61c4878aSAndroid Build Coastguard Workerreasons: 340*61c4878aSAndroid Build Coastguard Worker 341*61c4878aSAndroid Build Coastguard Worker* The semantics of when to call ``Flush()``/``Sync()`` on the stream are 342*61c4878aSAndroid Build Coastguard Worker unclear. The presence of these methods complicates using a :cpp:class:`Reader` 343*61c4878aSAndroid Build Coastguard Worker or :cpp:class:`Writer`. 344*61c4878aSAndroid Build Coastguard Worker* Adding one or two additional virtual calls increases the size of all 345*61c4878aSAndroid Build Coastguard Worker :cpp:class:`Stream` vtables. 346*61c4878aSAndroid Build Coastguard Worker 347*61c4878aSAndroid Build Coastguard Worker.. _module-pw_stream-class-hierarchy: 348*61c4878aSAndroid Build Coastguard Worker 349*61c4878aSAndroid Build Coastguard WorkerClass hierarchy 350*61c4878aSAndroid Build Coastguard Worker=============== 351*61c4878aSAndroid Build Coastguard WorkerAll ``pw_stream`` classes inherit from a single, common base with all possible 352*61c4878aSAndroid Build Coastguard Workerfunctionality: :cpp:class:`pw::stream::Stream`. This structure has 353*61c4878aSAndroid Build Coastguard Workersome similarities with Python's `io module 354*61c4878aSAndroid Build Coastguard Worker<https://docs.python.org/3/library/io.html>`_ and C#'s `Stream class 355*61c4878aSAndroid Build Coastguard Worker<https://docs.microsoft.com/en-us/dotnet/api/system.io.stream>`_. 356*61c4878aSAndroid Build Coastguard Worker 357*61c4878aSAndroid Build Coastguard WorkerAn alternative approach is to have the reading, writing, and seeking portions of 358*61c4878aSAndroid Build Coastguard Workerthe interface provided by different entities. This is how Go's `io 359*61c4878aSAndroid Build Coastguard Workerpackage <https://pkg.go.dev/io>`_ and C++'s `input/output library 360*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/io>`_ are structured. 361*61c4878aSAndroid Build Coastguard Worker 362*61c4878aSAndroid Build Coastguard WorkerWe chose to use a single base class for a few reasons: 363*61c4878aSAndroid Build Coastguard Worker 364*61c4878aSAndroid Build Coastguard Worker* The inheritance hierarchy is simple and linear. Despite the linear 365*61c4878aSAndroid Build Coastguard Worker hierarchy, combining capabilities is natural with classes like 366*61c4878aSAndroid Build Coastguard Worker :cpp:class:`ReaderWriter`. 367*61c4878aSAndroid Build Coastguard Worker 368*61c4878aSAndroid Build Coastguard Worker In C++, separate interfaces for each capability requires either a complex 369*61c4878aSAndroid Build Coastguard Worker virtual inheritance hierarchy or entirely separate hierarchies for each 370*61c4878aSAndroid Build Coastguard Worker capability. Separate hierarchies can become cumbersome when trying to 371*61c4878aSAndroid Build Coastguard Worker combine multiple capabilities. A :cpp:class:`SeekableReaderWriter` would 372*61c4878aSAndroid Build Coastguard Worker have to implement three different interfaces, which means three different 373*61c4878aSAndroid Build Coastguard Worker vtables and three vtable pointers in each instance. 374*61c4878aSAndroid Build Coastguard Worker* Stream capabilities are clearly expressed in the type system, while 375*61c4878aSAndroid Build Coastguard Worker naturally supporting optional functionality. A :cpp:class:`Reader` may 376*61c4878aSAndroid Build Coastguard Worker or may not support :cpp:func:`Stream::Seek`. Applications that can handle 377*61c4878aSAndroid Build Coastguard Worker seek failures gracefully way use seek on any :cpp:class:`Reader`. If seeking 378*61c4878aSAndroid Build Coastguard Worker is strictly necessary, an API can accept a :cpp:class:`SeekableReader` 379*61c4878aSAndroid Build Coastguard Worker instead. 380*61c4878aSAndroid Build Coastguard Worker 381*61c4878aSAndroid Build Coastguard Worker Expressing optional functionality in the type system is cumbersome when 382*61c4878aSAndroid Build Coastguard Worker there are distinct interfaces for each capability. ``Reader``, ``Writer``, 383*61c4878aSAndroid Build Coastguard Worker and ``Seeker`` interfaces would not be sufficient. To match the flexibility 384*61c4878aSAndroid Build Coastguard Worker of the current structure, there would have to be separate optional versions 385*61c4878aSAndroid Build Coastguard Worker of each interface, and classes for various combinations. :cpp:class:`Stream` 386*61c4878aSAndroid Build Coastguard Worker would be an "OptionalReaderOptionalWriterOptionalSeeker" in this model. 387*61c4878aSAndroid Build Coastguard Worker* Code reuse is maximized. For example, a single 388*61c4878aSAndroid Build Coastguard Worker :cpp:func:`Stream::ConservativeLimit` implementation supports many stream 389*61c4878aSAndroid Build Coastguard Worker implementations. 390*61c4878aSAndroid Build Coastguard Worker 391*61c4878aSAndroid Build Coastguard WorkerVirtual interfaces 392*61c4878aSAndroid Build Coastguard Worker================== 393*61c4878aSAndroid Build Coastguard Worker``pw_stream`` uses virtual functions. Virtual functions enable runtime 394*61c4878aSAndroid Build Coastguard Workerpolymorphism. The same code can be used with any stream implementation. 395*61c4878aSAndroid Build Coastguard Worker 396*61c4878aSAndroid Build Coastguard WorkerVirtual functions have inherently has more overhead than a regular function 397*61c4878aSAndroid Build Coastguard Workercall. However, this is true of any polymorphic API. Using a C-style ``struct`` 398*61c4878aSAndroid Build Coastguard Workerof function pointers makes different trade-offs but still has more overhead than 399*61c4878aSAndroid Build Coastguard Workera regular function call. 400*61c4878aSAndroid Build Coastguard Worker 401*61c4878aSAndroid Build Coastguard WorkerFor many use cases, the overhead of virtual calls insignificant. However, in 402*61c4878aSAndroid Build Coastguard Workersome extremely performance-sensitive contexts, the flexibility of the virtual 403*61c4878aSAndroid Build Coastguard Workerinterface may not justify the performance cost. 404*61c4878aSAndroid Build Coastguard Worker 405*61c4878aSAndroid Build Coastguard WorkerAsynchronous APIs 406*61c4878aSAndroid Build Coastguard Worker================= 407*61c4878aSAndroid Build Coastguard WorkerAt present, ``pw_stream`` is synchronous. All :cpp:class:`Stream` API calls are 408*61c4878aSAndroid Build Coastguard Workerexpected to block until the operation is complete. This might be undesirable 409*61c4878aSAndroid Build Coastguard Workerfor slow operations, like writing to NOR flash. 410*61c4878aSAndroid Build Coastguard Worker 411*61c4878aSAndroid Build Coastguard WorkerPigweed has not yet established a pattern for asynchronous C++ APIs. The 412*61c4878aSAndroid Build Coastguard Worker:cpp:class:`Stream` class may be extended in the future to add asynchronous 413*61c4878aSAndroid Build Coastguard Workercapabilities, or a separate ``AsyncStream`` could be created. 414*61c4878aSAndroid Build Coastguard Worker 415*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 416*61c4878aSAndroid Build Coastguard Worker 417*61c4878aSAndroid Build Coastguard Worker------------ 418*61c4878aSAndroid Build Coastguard WorkerDependencies 419*61c4878aSAndroid Build Coastguard Worker------------ 420*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_assert` 421*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_preprocessor` 422*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_status` 423*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_span` 424*61c4878aSAndroid Build Coastguard Worker 425*61c4878aSAndroid Build Coastguard Worker------ 426*61c4878aSAndroid Build Coastguard WorkerZephyr 427*61c4878aSAndroid Build Coastguard Worker------ 428*61c4878aSAndroid Build Coastguard WorkerTo enable ``pw_stream`` for Zephyr add ``CONFIG_PIGWEED_STREAM=y`` to the 429*61c4878aSAndroid Build Coastguard Workerproject's configuration. 430*61c4878aSAndroid Build Coastguard Worker 431*61c4878aSAndroid Build Coastguard Worker---- 432*61c4878aSAndroid Build Coastguard WorkerRust 433*61c4878aSAndroid Build Coastguard Worker---- 434*61c4878aSAndroid Build Coastguard WorkerPigweed centric analogs to Rust ``std``'s ``Read``, ``Write``, ``Seek`` traits 435*61c4878aSAndroid Build Coastguard Workeras well as a basic ``Cursor`` implementation are provided by the 436*61c4878aSAndroid Build Coastguard Worker`pw_stream crate </rustdoc/pw_stream/>`_. 437*61c4878aSAndroid Build Coastguard Worker 438*61c4878aSAndroid Build Coastguard Worker 439*61c4878aSAndroid Build Coastguard Worker.. toctree:: 440*61c4878aSAndroid Build Coastguard Worker :hidden: 441*61c4878aSAndroid Build Coastguard Worker :maxdepth: 1 442*61c4878aSAndroid Build Coastguard Worker 443*61c4878aSAndroid Build Coastguard Worker Backends <backends> 444*61c4878aSAndroid Build Coastguard Worker 445*61c4878aSAndroid Build Coastguard Worker------ 446*61c4878aSAndroid Build Coastguard WorkerPython 447*61c4878aSAndroid Build Coastguard Worker------ 448*61c4878aSAndroid Build Coastguard WorkerThere are legacy Python utilities used for reading and writing a serial device 449*61c4878aSAndroid Build Coastguard Workerfor RPC purposes. 450*61c4878aSAndroid Build Coastguard Worker 451*61c4878aSAndroid Build Coastguard Worker.. toctree:: 452*61c4878aSAndroid Build Coastguard Worker :hidden: 453*61c4878aSAndroid Build Coastguard Worker 454*61c4878aSAndroid Build Coastguard Worker Python <py/docs> 455