Skip to content

Commit 5d01a0b

Browse files
author
James Gober
committed
Milestone Update v0.7.0
1 parent 80d6fa6 commit 5d01a0b

10 files changed

Lines changed: 562 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,52 @@ the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html
66

77
## [Unreleased]
88

9+
## [0.7.0] - 2026-05-19
10+
11+
Driver trait release. Closes the third (and last) deferral from
12+
the `0.3.0` design lock. All locked surfaces from the original
13+
design lock are now shipped.
14+
15+
### Added
16+
17+
- `pub trait Driver` in `pipe_io::driver`, re-exported as
18+
`pipe_io::Driver`. Generic executor abstraction with `Send`
19+
bounds on the source and its item/error types. Not sealed;
20+
external executors (tokio, rayon, custom thread farms) can
21+
implement it.
22+
- `impl Driver for SyncDriver` and (under `std`)
23+
`impl Driver for ThreadedDriver`. Both delegate to their existing
24+
inherent `run` methods.
25+
- `Pipeline::run_with<D: Driver>(driver: D)` builder-terminal
26+
method. Lets callers select any `Driver` impl explicitly.
27+
- 6 integration tests in `tests/driver_trait.rs`: sync via trait,
28+
threaded via trait, `run_with(SyncDriver)`, `run_with(ThreadedDriver)`,
29+
a custom `CountingDriver` impl, and a static check that the
30+
built-in and custom drivers all satisfy `Driver`.
31+
32+
### Changed
33+
34+
- `REPS.md` section 4.8 un-defers the `Driver` trait; the
35+
trait-based abstraction is now part of the locked surface.
36+
- `docs/API.md` documents the trait and the `Pipeline::run_with`
37+
method.
38+
- `SyncDriver::run` (inherent method) keeps its looser bound (no
39+
`Send` requirement on the source). The trait impl uses the
40+
stricter bound. Both compile to the same call.
41+
42+
### Notes
43+
44+
- The trait deliberately carries the stricter `Send` bound so
45+
that any `Driver` impl can be a threaded executor. To drive a
46+
non-`Send` source on the calling thread, call
47+
`SyncDriver::run` directly (inherent method); the trait method
48+
is unavailable for non-`Send` sources by design.
49+
- This is the last design-lock deferral. The locked `1.0.0`
50+
surface in `REPS.md` is now fully implemented except for
51+
`PipelineBuilder::buffer(capacity)`, which was listed in §4.9
52+
but is not yet shipped; it lands in a future release alongside
53+
per-stage threading or as a separate `0.8.x` slot.
54+
955
## [0.6.0] - 2026-05-19
1056

1157
Dead-letter routing release. Wires up `ErrorPolicy::DeadLetter`
@@ -216,7 +262,8 @@ public surface.
216262
`.dev/` planning structure (DIRECTIVES, ROADMAP, PROMPTS).
217263
- Crate name reserved on crates.io.
218264

219-
[Unreleased]: https://github.com/jamesgober/pipe-io/compare/v0.6.0...HEAD
265+
[Unreleased]: https://github.com/jamesgober/pipe-io/compare/v0.7.0...HEAD
266+
[0.7.0]: https://github.com/jamesgober/pipe-io/compare/v0.6.0...v0.7.0
220267
[0.6.0]: https://github.com/jamesgober/pipe-io/compare/v0.5.0...v0.6.0
221268
[0.5.0]: https://github.com/jamesgober/pipe-io/compare/v0.4.0...v0.5.0
222269
[0.4.0]: https://github.com/jamesgober/pipe-io/compare/v0.3.0...v0.4.0

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pipe-io"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
edition = "2021"
55
rust-version = "1.75"
66
readme = "README.md"

REPS.md

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -221,27 +221,39 @@ arriving items will not close until end-of-stream.
221221

222222
### 4.8 `pipe_io::driver`
223223

224-
A trait-based driver abstraction is deferred past `0.3.0` because
225-
`SyncDriver` and `ThreadedDriver` have different `Send` bounds on
226-
the source and item types, and exposing a single unified trait
227-
locks in the stricter bounds for both. The trait will land once
228-
the bound difference is reconciled (likely via a sealed
229-
helper-trait pattern or two separate trait surfaces).
230-
231-
`0.3.x` ships:
232-
233-
- `SyncDriver` - zero-sized marker. Pumps the pipeline on the
234-
caller's thread. `no_std`-compatible.
235-
- `ThreadedDriver` **(std)** - zero-sized marker. Pumps the
236-
pipeline on a single background thread; the calling thread
237-
blocks on `join`. Per-stage threading is a future enhancement.
224+
- `trait Driver` - generic executor abstraction. The trait carries
225+
`Send` bounds on the source and its item/error types (matching
226+
`ThreadedDriver`'s natural requirements). External executors
227+
(tokio runtime, rayon pool, custom thread farm, ...) implement
228+
this trait. The trait is *not* sealed; consumers can plug in
229+
their own drivers.
230+
231+
```text
232+
trait Driver {
233+
fn run<S>(self, pipeline: Pipeline<S>) -> Result<RunStats>
234+
where
235+
S: Source + Send + 'static,
236+
S::Item: Send + 'static,
237+
S::Error: Send + 'static;
238+
}
239+
```
240+
241+
- `SyncDriver` - pumps the pipeline on the caller's thread.
242+
Implements [`Driver`] and additionally exposes an inherent
243+
`run` method with looser bounds (no `Send` requirement on the
244+
source). Use the inherent method when driving a non-`Send`
245+
source on the current thread.
246+
- `ThreadedDriver` **(std)** - pumps the pipeline on a single
247+
background thread; the calling thread blocks on `join`.
248+
Implements [`Driver`].
238249
- `RunStats` - statistics returned by a successful run.
239250

240251
`Pipeline` exposes:
241252

242-
- `.run()` - synchronous; equivalent to `SyncDriver::default().run(...)`.
253+
- `.run()` - synchronous; equivalent to `SyncDriver::new().run(...)`.
243254
- `.run_threaded()` **(std)** - threaded; equivalent to
244-
`ThreadedDriver::default().run(...)`.
255+
`ThreadedDriver::new().run(...)`.
256+
- `.run_with(driver)` - generic over any `Driver` impl.
245257

246258
### 4.9 Builder surface (full)
247259

docs/API.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
| `pipe_io::Sink` | trait | Re-export from `pipe_io::sink`. |
4040
| `pipe_io::Emit` | trait | Re-export from `pipe_io::emit`. |
4141
| `pipe_io::EmitError` | enum | Re-export from `pipe_io::emit`. |
42+
| `pipe_io::Driver` | trait | Re-export from `pipe_io::driver`. |
4243
| `pipe_io::Batch<T>` | struct | Owned group of items emitted by `.batch()`. |
4344
| `pipe_io::BatchPolicy` | struct | Batch trigger configuration. |
4445
| `pipe_io::ByteSize` | trait | Opt-in for byte-aware batching. |
@@ -244,13 +245,24 @@ pub struct RunStats {
244245
pub duration: Duration, // std only
245246
}
246247

248+
pub trait Driver {
249+
fn run<S>(self, pipeline: Pipeline<S>) -> Result<RunStats>
250+
where
251+
S: Source + Send + 'static,
252+
S::Item: Send + 'static,
253+
S::Error: Send + 'static;
254+
}
255+
247256
#[derive(Default, Clone, Copy)]
248257
pub struct SyncDriver;
249258

250259
impl SyncDriver {
251260
pub const fn new() -> Self;
261+
// Inherent method with looser bound (no Send required); use this
262+
// when driving a non-Send source on the current thread.
252263
pub fn run<S: Source>(self, pipeline: Pipeline<S>) -> Result<RunStats>;
253264
}
265+
impl Driver for SyncDriver { /* delegates to inherent run */ }
254266

255267
#[derive(Default, Clone, Copy)]
256268
pub struct ThreadedDriver; // std only
@@ -263,11 +275,13 @@ impl ThreadedDriver {
263275
S::Item: Send + 'static,
264276
S::Error: Send + 'static;
265277
}
278+
impl Driver for ThreadedDriver { /* delegates to inherent run */ }
266279
```
267280

268-
A unified `Driver` trait is deferred past `0.3.0`; consumers
269-
select a driver by calling `Pipeline::run` (sync) or
270-
`Pipeline::run_threaded` (std).
281+
Consumers select a driver by calling `Pipeline::run` (sync),
282+
`Pipeline::run_threaded` (std), or `Pipeline::run_with(driver)`
283+
for any `Driver` impl. The trait is not sealed; external
284+
executors (tokio, rayon, custom thread farm) can implement it.
271285

272286
## `pipe_io::emit`
273287

@@ -293,6 +307,8 @@ impl<S: Source> Pipeline<S> {
293307

294308
pub fn run(self) -> Result<RunStats>;
295309
pub fn run_threaded(self) -> Result<RunStats>; // std only
310+
pub fn run_with<D: Driver>(self, driver: D) -> Result<RunStats>
311+
where S: Send, S::Item: Send, S::Error: Send;
296312
}
297313

298314
impl<T, S, Acc> PipelineBuilder<T, S, Acc>

0 commit comments

Comments
 (0)