ufotofu 0.10.1

Abstractions for lazily consuming and producing sequences
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
//! Producers — values that asynchronously yield a sequence of items.
//!
//! [`Producer`] is an asynchronous generalisation of [`Iterator`]; a producer lazily produces a sequence of items. There are three core differences between [`Iterator::next`] and the analogous [`Producer::produce`]:
//!
//! - `produce` is asynchronous;
//! - `produce` returns a result, allowing it to report fatal errors; and
//! - `produce` uses an [`Either`] to distinguish between repeated items ([`Left`]) and the final value ([`Right`]).
//!
//! ```
//! use ufotofu::prelude::*;
//! # pollster::block_on(async{
//! let mut my_first_producer = [1, 2, 4].into_producer();
//!
//! assert_eq!(my_first_producer.produce().await?, Left(1));
//! assert_eq!(my_first_producer.produce().await?, Left(2));
//! assert_eq!(my_first_producer.produce().await?, Left(4));
//! assert_eq!(my_first_producer.produce().await?, Right(()));
//! # Result::<(), Infallible>::Ok(())
//! # });
//! ```
//!
//! Whereas an *iterator* yields a sequence of arbitrarily many values of type [`Iterator::Item`] followed by up to one value of type `()`, a *producer* yields a sequence of arbitrarily many values of type [`Producer::Item`] followed by either up to one value of type [`Producer::Final`] or by up to one value of type [`Producer::Error`]. Producers with `Final = ()` and `Error = Infallible` are effectively asynchronous iterators.
//!
//! It is forbidden to call `produce` after a producer has emitted an error or its final value. Any such call may result in unspecified (but safe) behaviour.
//!
//! <br/>
//!
//! The [`consume`] macro provides a handy generalisation of `for` loop syntax. It can handle not only repeated items but optionally also final values and errors. The following example handles repeated items and the final value, and transparently propagates errors.
//!
//! ```
//! use ufotofu::prelude::*;
//! # fn main() {
//! # pollster::block_on(async{
//!
//! // The macro converts `[1, 2, 4]` into a producer.
//! consume![[1, 2, 4] {
//!     item it => print!("{it}, "),
//!     // We could remove the next line to simply ignore the final value.
//!     final () => println!("and done!"),
//!     // The following line would “catch” and print any producer error.
//!     // error err => println!({err}),
//! }];
//! // Prints `1, 2, 4, and done!`.
//! # Result::<(), Infallible>::Ok(())
//! # });
//! # }
//! ```
//!
//! The [`IntoProducer`] trait describes types which can be converted into producers. In the preceding example, this trait allowed the `consume!` macro to convert the array `[1, 2, 4]` into a producer of these three items. The standard library counterpart to `IntoProducer` is [`IntoIterator`].
//!
//! <br/>
//!
//! Every producer may eagerly perform side-effects to make subsequent `produce` calls more efficient. The classic example of a buffering producer is a producer of bytes which reads a file from disk: it should most certainly prefetch many bytes at a time instead of reading them on demand.
//!
//! The [`slurp`](Producer::slurp) method lets calling code instruct the producer to perform preparatory side-effects, even without the need to actually produce any data yet.
//!
//! <br/>
//!
//! Every producer automatically implements the [`ProducerExt`] trait, which provides useful methods for working with producers.
//!
//! <br/>Producing a sequence one item at a time can be inefficient. The [`BulkProducer`] trait extends [`Producer`] with the ability to produce multiple items at a time. This is enabled by the [`BulkProducer::expose_items_gracefully`] method. You pass to this method an async function as the sole argument. The bulk producer calls that function, passing it a non-empty slice of items. The function can process these items in any way, and then returns a pair of values: first, the number of items the producer should now consider as having been produced, and second, an arbitrary value, to be returned by the `expose_items` call.
//! If the producer returns its final value or an error on a call to `expose_items_gracefully`, the provided function is returned alongside that value.
//! ```
//! use ufotofu::prelude::*;
//! # pollster::block_on(async{
//! let mut p = [1, 2, 4].into_producer();
//!
//! assert_eq!(p.expose_items_gracefully(async |items| {
//!     assert_eq!(items, &[1, 2, 4]);
//!     return (3, "hi!");
//! }).await.ok().unwrap().left(), Some("hi!"));
//! assert_eq!(p.produce().await?, Right(()));
//!
//! // If we reported that we only processed two items, the producer would later emit the `4`:
//! let mut p2 = [1, 2, 4].into_producer();
//! assert_eq!(p2.expose_items_gracefully(async |items| {
//!     assert_eq!(items, &[1, 2, 4]);
//!     return (2, "hi!");
//! }).await.ok().unwrap().left(), Some("hi!"));
//! assert_eq!(p2.produce().await?, Left(4));
//! # Result::<(), Infallible>::Ok(())
//! # });
//! ```
//!
//! <br/>
//!
//! Every bulk producer automatically implements the [`BulkProducerExt`] trait, which provides bulk-production-based variants of several methods of [`ProducerExt`]. These bulk versions are typically more efficient and should be preferred whenever possible.
//!
//! Of particular note are the following:
//! - The [`BulkProducerExt::expose_items`] method, which behaves exactly like `expose_items_gracefully`, but simplifies working with `Final` and `Error` values by returning them without the provided function.
//! - The [`BulkProducerExt::bulk_produce`] method, which builds on `expose_items` and reimplements the way that, e.g., [`std::io::Read`] emits multiple items at a time: `bulk_produce` takes a mutable slice as its input, and the producer reports how many items it copied (cloned) into it.
//!
//! ```
//! use ufotofu::prelude::*;
//! # pollster::block_on(async{
//!
//! let mut p1 = [0, 1, 2].into_producer();
//! assert_eq!(p1.expose_items(async |items| {
//!     assert_eq!(items, &[0, 1, 2]);
//!     (3, "hi!")
//! }).await?, Left("hi!"));
//!
//! let mut p2 = [1, 2, 4].into_producer();
//! let mut buf = [0, 0];
//!
//! assert_eq!(p2.bulk_produce(&mut buf[..]).await?, Left(2));
//! assert_eq!(buf, [1, 2]);
//! assert_eq!(p2.bulk_produce(&mut buf[..]).await?, Left(1));
//! assert_eq!(buf, [4, 2]);
//! assert_eq!(p2.bulk_produce(&mut buf[..]).await?, Right(()));
//! # Result::<(), Infallible>::Ok(())
//! # });
//! ```
//!
//! <br/>The counterpart to the [`producer`] module is the [`consumer`] module.

use crate::prelude::*;

mod producer_ext;
pub use producer_ext::*;

mod clone_from_slice;
pub use clone_from_slice::*;

mod empty;
pub use empty::*;

mod error_immediately;
pub use error_immediately::*;

pub mod compat;

mod buffered;
pub use buffered::*;

mod bulk_buffered;
pub use bulk_buffered::*;

mod map_err;
pub use map_err::*;

mod map_final;
pub use map_final::*;

mod map_item;
pub use map_item::*;

mod chain;
pub use chain::*;

mod produce_while;
pub use produce_while::*;

mod limit;
pub use limit::*;

#[cfg(feature = "dev")]
mod scrambled;
#[cfg(feature = "dev")]
pub use scrambled::*;

#[cfg(feature = "dev")]
mod bulk_scrambled;
#[cfg(feature = "dev")]
pub use bulk_scrambled::*;

#[cfg(feature = "dev")]
mod test_producer;
#[cfg(feature = "dev")]
pub use test_producer::*;

/// A [`Producer`] lazily yields a sequence of items.
///
/// The sequence consists of an arbitrary number of items of type [`Producer::Item`], optionally terminated by either a value of type [`Producer::Final`] or a value of type [`Producer::Error`].
///
/// ```
/// use ufotofu::prelude::*;
/// # pollster::block_on(async{
/// let mut p = [1, 2, 4].into_producer();
///
/// assert_eq!(p.produce().await?, Left(1));
/// assert_eq!(p.produce().await?, Left(2));
/// assert_eq!(p.produce().await?, Left(4));
/// assert_eq!(p.produce().await?, Right(()));
/// # Result::<(), Infallible>::Ok(())
/// # });
/// ```
///
/// Every producer may eagerly perform side-effects to make subsequent `produce` calls more efficient. The classic example of a buffering producer is a producer of bytes which reads a file from disk: it should most certainly prefetch many bytes at a time instead of reading them on demand.
///
/// The [`slurp`](Producer::slurp) method lets calling code instruct the producer to perform preparatory side-effects, even without the need to actually produce any data yet.
///
/// Calling code must uphold the following invariants:
///
/// - Do not call trait methods after any method has yielded a final value or an error.
/// - Do not use the producer after dropping any `Future` returned by any of its methods, unless the dropped future has been polled to completion.
/// - Do not use the producer after catching an unwinding panic.
///
/// <br/>Counterpart: the [`Consumer`] trait.
#[must_use = "producers are lazy and do nothing unless consumed"]
pub trait Producer {
    /// The sequence produced by this producer starts with *arbitrarily many* values of this type.
    type Item;
    /// The sequence produced by this producer ends with *up to one* value of this type.
    type Final;
    /// The type of errors the producer can emit instead of doing its job.
    type Error;

    /// Attempts to produce the next item, which is either a regular repeated item or the final value.
    /// The method may fail, returning an `Err` instead.
    ///
    /// After this method returns the final value or after it returns an error, no further
    /// methods of this trait may be invoked.
    ///
    /// # Invariants
    ///
    /// Must not be called after any method of this trait has returned a final value or an error.
    ///
    /// <br/>Counterpart: the [`Consumer::consume`] method.
    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error>;

    /// Attempts to perform any effectful actions that might make future calls to `produce` and `bulk_produce` more efficient.
    ///
    /// This function allows the [`Producer`] to perform side-effects that it would otherwise
    /// have to do just-in-time when [`produce`](Producer::produce) gets called.
    ///
    /// After this function returns an error, no further methods of this trait may be invoked.
    ///
    /// #### Invariants
    ///
    /// Must not be called after any method of this trait has returned a final value or an error.
    ///
    /// <br/>Counterpart: the [`Consumer::flush`] method.
    async fn slurp(&mut self) -> Result<(), Self::Error>;
}

impl<P> Producer for &mut P
where
    P: Producer + ?Sized,
{
    type Item = P::Item;
    type Final = P::Final;
    type Error = P::Error;

    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
        (*self).produce().await
    }

    async fn slurp(&mut self) -> Result<(), Self::Error> {
        (*self).slurp().await
    }
}

#[cfg(feature = "alloc")]
impl<P> Producer for alloc::boxed::Box<P>
where
    P: Producer + ?Sized,
{
    type Item = P::Item;
    type Final = P::Final;
    type Error = P::Error;

    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
        self.as_mut().produce().await
    }

    async fn slurp(&mut self) -> Result<(), Self::Error> {
        self.as_mut().slurp().await
    }
}

impl Producer for Infallible {
    type Item = Infallible;
    type Final = Infallible;
    type Error = Infallible;

    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
        unreachable!()
    }

    async fn slurp(&mut self) -> Result<(), Self::Error> {
        unreachable!()
    }
}

/// Conversion into a [`Producer`].
///
/// By implementing `IntoProducer` for a type, you define how it will be
/// converted to a producer. This is common for types which describe a
/// collection of some kind.
///
/// One benefit of implementing `IntoIterator` is that your type will [work
/// with the `consume!` macro](consume).
///
/// <br/>Counterpart: the [`IntoConsumer`] trait.
pub trait IntoProducer {
    /// The type of repeated items being produced.
    type Item;

    /// The type of the final value being produced.
    type Final;

    /// The type of errors the producer may emit.
    type Error;

    /// The producer into which values of this type can be converted.
    ///
    /// <br/>Counterpart: the [`IntoConsumer::IntoConsumer`] type.
    type IntoProducer: Producer<Item = Self::Item, Final = Self::Final, Error = Self::Error>;

    /// Creates a producer from a value.
    ///
    /// <br/>Counterpart: the [`IntoConsumer::into_consumer`] method.
    fn into_producer(self) -> Self::IntoProducer;
}

impl<P: Producer> IntoProducer for P {
    type Item = P::Item;
    type Final = P::Final;
    type Error = P::Error;
    type IntoProducer = P;

    #[inline]
    fn into_producer(self) -> P {
        self
    }
}

impl IntoProducer for () {
    type Item = Infallible;
    type Final = ();
    type Error = Infallible;
    type IntoProducer = Empty<()>;

    #[inline]
    fn into_producer(self) -> Self::IntoProducer {
        empty(())
    }
}

/// A [`BulkProducer`] is a producer that can emit multiple items with a single call of the [`BulkProducer::expose_items_gracefully`] method.
///
/// This method takes an async function as its sole argument. The producer calls that function, passing it a non-empty slice of items. The function can process these items in any way, and then returns a pair of values: first, the number of items the producer should now consider as having been produced, and second, an arbitrary value, to be returned by the `expose_items_gracefully` call.
/// If the producer returns an error or a final value from `expose_items_gracefully`, the supplied function is returned alongside that value.
///
/// See [`BulkProducerExt::expose_items`] for a variant of `expose_items_gracefully` which simplifies the handling of final and error values by not returning the supplied function.
/// See [`BulkProducerExt::bulk_produce`] for using bulk producers in a way analogous to [`std::io::Read::read`].
///
/// ```
/// use ufotofu::prelude::*;
/// # pollster::block_on(async{
/// let mut p = [1, 2, 4].into_producer();
///
/// assert_eq!(p.expose_items_gracefully(async |items| {
///     assert_eq!(items, &[1, 2, 4]);
///     return (3, "hi!");
/// }).await.ok().unwrap().left(), Some("hi!"));
/// assert_eq!(p.produce().await?, Right(()));
///
/// // If we reported that we only processed two items, the producer would later emit the `4`:
/// let mut p2 = [1, 2, 4].into_producer();
/// assert_eq!(p2.expose_items_gracefully(async |items| {
///     assert_eq!(items, &[1, 2, 4]);
///     return (2, "hi!");
/// }).await.ok().unwrap().left(), Some("hi!"));
/// assert_eq!(p2.produce().await?, Left(4));
/// # Result::<(), Infallible>::Ok(())
/// # });
/// ```
///
/// Semantically, there should be no difference between bulk production or item-by-item production.
///
/// <br/>Counterpart: the [`BulkConsumer`] trait.
pub trait BulkProducer: Producer {
    /// Exposes a non-empty number of items to a given async function, the function then reports to the producer how many items should now be considered produced.
    ///
    /// When the producer needs to yield an error or its final value, it must return them immediately from this method. Otherwise, i.e., when it wants to produce regular items, it must call the passed function `f` with a non-empty slice of items as the argument, and then poll `f` to completion. When `f` has yielded `(amount, t)`, the producer must adjust its state as if `produce` had been called `amount` many times, and then return `Ok(Left(t))`. It must not return `Ok(Right(_))` or `Err(_)` when having called `f`.
    ///
    /// When passing a slice to `f`, if `f` does not report that *every* provided item was processed, then the producer must be able to produce the remaining number of items without emitting an error. For example: a producer passes a slice of five slots to `f`, and `f` returns `(3, _)`. Then the next two calls to `produce` *must* return `Ok(Left(_))`.
    ///
    /// After this function returns the final value or after it returns an error, no further methods of this trait may be invoked.
    ///
    /// Because `f` might still be needed after the producer reports an error or returns its final value, this method returns `f` alongside these values. For more convenient handling of error and final values in cases where `f` does not need to be preserved, see [`expose_items`](`BulkProducerExt::expose_items`).
    ///
    /// # Invariants
    ///
    /// Must not be called after any method of this trait has returned a final value or an error.
    ///
    /// `f` must not return an `amount` strictly greater than the length of the buffer passed to it.
    ///
    /// # Examples
    ///
    /// ```
    /// use ufotofu::prelude::*;
    /// use producer::error_immediately;
    /// # pollster::block_on(async{
    ///
    /// let mut p = [1, 2, 4].into_producer();
    ///
    /// match p.expose_items_gracefully(async |items| {
    ///     assert_eq!(items, &[1, 2, 4]);
    ///     return (3, "hi!");
    /// }).await {
    ///     Ok(value) => assert_eq!(value.left(), Some("hi!")),
    ///     Err(_) => unreachable!(),
    /// };
    ///
    /// assert_eq!(p.produce().await?, Right(()));
    ///
    /// // If we reported that we only processed two items, the producer would later emit the `4`:
    /// let mut p2 = [1, 2, 4].into_producer();
    /// match p2.expose_items_gracefully(async |items| {
    ///     assert_eq!(items, &[1, 2, 4]);
    ///     return (2, "hi!");
    /// }).await {
    ///     Ok(value) => assert_eq!(value.left(), Some("hi!")),
    ///     Err(_) => unreachable!(),
    /// };
    ///
    /// assert_eq!(p2.produce().await?, Left(4));
    ///
    /// // When we expose items gracefully, we can retrieve the supplied function when an error or final value is returned:
    ///
    /// let mut oops = error_immediately(17);
    ///
    /// let f = match oops.expose_items_gracefully(async |items| {
    ///     return (1, "oops!");
    /// }).await {
    ///     Err((f, err)) => {assert_eq!(err, 17); f},
    ///     Ok(_) => unreachable!(),
    /// };
    ///
    /// assert_eq!(f(&[]).await, (1, "oops!"));
    ///
    /// # Result::<(), Infallible>::Ok(())
    /// # });
    /// ```
    ///
    /// <br/>Counterpart: the [`BulkConsumer::expose_slots_gracefully`] method.
    async fn expose_items_gracefully<F, R>(
        &mut self,
        f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R);
}

impl<P> BulkProducer for &mut P
where
    P: BulkProducer + ?Sized,
{
    async fn expose_items_gracefully<F, R>(
        &mut self,
        f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R),
    {
        (*self).expose_items_gracefully(f).await
    }
}

#[cfg(feature = "alloc")]
impl<P> BulkProducer for alloc::boxed::Box<P>
where
    P: BulkProducer + ?Sized,
{
    async fn expose_items_gracefully<F, R>(
        &mut self,
        f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R),
    {
        self.as_mut().expose_items_gracefully(f).await
    }
}

impl BulkProducer for Infallible {
    async fn expose_items_gracefully<F, R>(
        &mut self,
        _f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R),
    {
        unreachable!()
    }
}

/// Conversion into a [`BulkProducer`].
///
/// This trait is automatically implemented by implementing [`IntoProducer`] with the associated producer being a bulk producer.
///
/// <br/>Counterpart: the [`IntoBulkConsumer`] trait.
pub trait IntoBulkProducer: IntoProducer<IntoProducer: BulkProducer> {}

impl<P> IntoBulkProducer for P where P: IntoProducer<IntoProducer: BulkProducer> {}