streams 3.5.0
A collection of useful stream primitives and implementations.
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
Streams
A collection of useful stream primitives and implementations. Streams come in two flavors:
- Input streams must define a function
StreamResult readFromStream(E[] buffer)
for reading elements from a data source and storing them inbuffer
. - Output streams must define a function
StreamResult writeToStream(E[] buffer)
for writing elements frombuffer
to a data sink.
Features:
- Full BetterC compatibility
- Simple, extensible interface
- Seamless conversion between streams and ranges
- Fully documented API
- Flexible ownership: pass a stream directly to transfer ownership, or pass a pointer to a stream to temporarily give something access to your stream.
- Many basic stream types are included:
- Array input streams for reading from arrays, and array output streams to write to an in-memory array buffer.
- Buffered input and output streams that buffer reads and writes to a wrapped stream.
- File streams that use C's
fopen
and associated functions so for BetterC compatibility. - Socket streams (only available outside of BetterC mode).
- Data serialization and deserialization streams, for reading and writing primitive values and arrays using configured endianness.
- Chunked-encoded streams for reading and writing chunked data according to RFC-9112, section 7.1. Currently doesn't support trailer fields.
Similar to Phobos' ranges, streams
are defined and type-checked using a primitives package that contains various
compile-time functions like isInputStream
and isOutputStream
.
Difference with Ranges
Phobos' concept of an Input Range relies on implicit buffering of results,
because of the contract it defines with front()
needing to return the same
result in consecutive calls without calling popFront()
. This doesn't map as
easily to many low-level resources, and also introduces additional cognitive
complexity to programmers who don't need that functionality.
This isn't to say that ranges aren't useful! They certainly are in many cases, but the argument is that a simpler stream interface is more useful in IO-heavy tasks or other cases where you simply want to read or write data to/from a buffer.
Furthermore, streams of this nature are a common feature in many other programming languages, and thus provides a bit of a "comfort zone" to help welcome programmers.
Range Compatibility
- To convert a range to a stream:
auto stream = asStream(range);
You can also useasInputStream
andasOutputStream
to be more explicit when dealing with things that behave as both an input and output range. - To convert a stream to a range:
auto range = asRange(stream);
You can also useasInputRange
andasOutputRange
to be more explicit when dealing with streams that implement both input and output functions.
Ownership
Since most streams (think sockets, files, memory buffers) have some internal state, we want to keep that state even if we hand off our stream to some other function or wrapper stream. For example:
auto buf = byteArrayOutputStream();
auto dataOut = dataOutputStreamFor(&buf);
// dataOut is borrowing buf from us.
dataOut.writeToStream!uint(42);
assert(buf.toArrayRaw().length == 4);
// uint == 4 bytes.
Sometimes though, we just want to pass a stream to a wrapper and give it complete ownership, because we won't need it anymore. In that case, just pass it directly; no reference or pointers.
auto sIn = SocketInputStream(mySocket);
auto bufIn = bufferedInputStreamFor(sIn);
// We should no longer read directly from sIn.
// Its state is controlled by bufIn, and sIn's no longer updates.
// Here's another common use case: wrapping an array stream:
ubyte[] myRawData = [1, 2, 3, 4, 5, 6, 7, 8];
auto dataIn = dataInputStreamFor(arrayInputStreamFor(myRawData));
ulong value = dataIn.readFromStreamOrDefault!ulong();
Development
Simply clone this repository, and ensure you have a recent version of D with
any compiler, and run dub test
to test the library.
For testing the library's BetterC compatibility, run dub test --config=betterC
.
Documentation can be generated with ./gen_docs.d
, which internally uses
Adrdox to generate documentation at generated-docs/
.
Tests and coverage are run automatically with GitHub Actions. See gen_coverage.d
for a look at how coverage is computed in detail, but essentially:
- We generate coverage
.lst
files using the standard compiler unittest coverage feature. - The
.lst
files are parsed, and lines with// cov-ignore
comments are ignored. - We compute the % of lines covered, and if it's below some threshold, fail.
Note for MacOSX v13 developers: run this before running tests:
export MACOSX_DEPLOYMENT_TARGET=12
- Registered by Andrew Lalis
- 3.5.0 released a year ago
- andrewlalis/streams
- MIT
- Copyright © 2023, Andrew Lalis
- Authors:
- Dependencies:
- none
- Versions:
-
3.5.0 2023-Jun-23 3.4.3 2023-Jun-22 3.4.2 2023-Jun-22 3.4.1 2023-Jun-22 3.4.0 2023-Jun-17 - Download Stats:
-
-
0 downloads today
-
27 downloads this week
-
85 downloads this month
-
6960 downloads total
-
- Score:
- 2.3
- Short URL:
- streams.dub.pm