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