1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #pragma once
8 
9 #include <functional>
10 #include <rpl/consumer.h>
11 #include <rpl/lifetime.h>
12 #include <rpl/details/superset_type.h>
13 #include <rpl/details/callable.h>
14 
15 #if defined _DEBUG || defined COMPILER_MSVC
16 #define RPL_PRODUCER_TYPE_ERASED_ALWAYS
17 #endif // _DEBUG
18 
19 namespace rpl {
20 namespace details {
21 
22 template <typename Value, typename Error>
23 const consumer<Value, Error> &const_ref_consumer();
24 
25 template <typename Lambda>
26 class mutable_lambda_wrap {
27 public:
mutable_lambda_wrap(Lambda && lambda)28 	mutable_lambda_wrap(Lambda &&lambda)
29 		: _lambda(std::move(lambda)) {
30 	}
31 	mutable_lambda_wrap(const mutable_lambda_wrap &other) = default;
32 	mutable_lambda_wrap(mutable_lambda_wrap &&other) = default;
33 	mutable_lambda_wrap &operator=(
34 		const mutable_lambda_wrap &other) = default;
35 	mutable_lambda_wrap &operator=(
36 		mutable_lambda_wrap &&other) = default;
37 
38 	template <typename... Args>
operator()39 	auto operator()(Args&&... args) const {
40 		return (const_cast<mutable_lambda_wrap*>(this)->_lambda)(
41 			std::forward<Args>(args)...);
42 	}
43 
44 private:
45 	Lambda _lambda;
46 
47 };
48 
49 // Type-erased copyable mutable function using std::function.
50 template <typename Value, typename Error>
51 class type_erased_generator final {
52 public:
53 	template <typename Handlers>
54 	using consumer_type = consumer<Value, Error, Handlers>;
55 	using value_type = Value;
56 	using error_type = Error;
57 
58 	type_erased_generator(
59 		const type_erased_generator &other) = default;
60 	type_erased_generator(
61 		type_erased_generator &&other) = default;
62 	type_erased_generator &operator=(
63 		const type_erased_generator &other) = default;
64 	type_erased_generator &operator=(
65 		type_erased_generator &&other) = default;
66 
67 	type_erased_generator(std::nullptr_t = nullptr) {
68 	}
69 	type_erased_generator &operator=(std::nullptr_t) {
70 		_implementation = nullptr;
71 		return *this;
72 	}
73 
74 	template <
75 		typename Generator,
76 		typename = std::enable_if_t<
77 			std::is_convertible_v<
78 				decltype(std::declval<Generator>()(
79 					const_ref_consumer<Value, Error>())),
80 				lifetime> &&
81 			!std::is_same_v<
82 				std::decay_t<Generator>,
83 				type_erased_generator>>>
type_erased_generator(Generator other)84 	type_erased_generator(Generator other) : _implementation(
85 		mutable_lambda_wrap<Generator>(std::move(other))) {
86 	}
87 	template <
88 		typename Generator,
89 		typename = std::enable_if_t<
90 			std::is_convertible_v<
91 				decltype(std::declval<Generator>()(
92 					const_ref_consumer<Value, Error>())),
93 				lifetime> &&
94 			!std::is_same_v<
95 				std::decay_t<Generator>,
96 				type_erased_generator>>>
97 	type_erased_generator &operator=(Generator other) {
98 		_implementation = mutable_lambda_wrap<Generator>(
99 			std::move(other));
100 		return *this;
101 	}
102 
103 	template <typename Handlers>
operator()104 	lifetime operator()(const consumer_type<Handlers> &consumer) {
105 		return _implementation ? _implementation(consumer) : lifetime();
106 	}
107 
empty()108 	bool empty() const {
109 		return !_implementation;
110 	}
111 
112 private:
113 	std::function<lifetime(const consumer_type<type_erased_handlers<Value, Error>> &)> _implementation;
114 
115 };
116 
117 } // namespace details
118 
119 template <
120 	typename Value = empty_value,
121 	typename Error = no_error,
122 	typename Generator = details::type_erased_generator<
123 		Value,
124 		Error>>
125 class producer;
126 
127 template <
128 	typename Value1,
129 	typename Value2,
130 	typename Error1,
131 	typename Error2,
132 	typename Generator>
133 struct superset_type<
134 		producer<Value1, Error1, Generator>,
135 		producer<Value2, Error2, Generator>> {
136 	using type = producer<
137 		superset_type_t<Value1, Value2>,
138 		superset_type_t<Error1, Error2>,
139 		Generator>;
140 };
141 
142 template <
143 	typename Value,
144 	typename Error,
145 	typename Generator1,
146 	typename Generator2>
147 struct superset_type<
148 		producer<Value, Error, Generator1>,
149 		producer<Value, Error, Generator2>> {
150 	using type = producer<Value, Error>;
151 };
152 
153 template <
154 	typename Value,
155 	typename Error,
156 	typename Generator>
157 struct superset_type<
158 		producer<Value, Error, Generator>,
159 		producer<Value, Error, Generator>> {
160 	using type = producer<Value, Error, Generator>;
161 };
162 
163 namespace details {
164 
165 template <typename Value, typename Error, typename Generator>
166 class producer_base {
167 public:
168 	template <typename Handlers>
169 	using consumer_type = consumer<Value, Error, Handlers>;
170 	using value_type = Value;
171 	using error_type = Error;
172 
173 	template <
174 		typename OtherGenerator,
175 		typename = std::enable_if_t<
176 			std::is_constructible_v<Generator, OtherGenerator&&>>>
177 	producer_base(OtherGenerator &&generator);
178 
179 	producer_base() = default;
180 	producer_base(const producer_base &other) = default;
181 	producer_base(producer_base &&other) = default;
182 	producer_base &operator=(const producer_base &other) = default;
183 	producer_base &operator=(producer_base &&other) = default;
184 
185 	template <
186 		typename OnNext,
187 		typename OnError,
188 		typename OnDone,
189 		typename = std::enable_if_t<
190 			is_callable_v<OnNext, Value>
191 			&& is_callable_v<OnError, Error>
192 			&& is_callable_v<OnDone>>>
193 	void start(
194 		OnNext &&next,
195 		OnError &&error,
196 		OnDone &&done,
197 		lifetime &alive_while) &&;
198 
199 	template <
200 		typename OnNext,
201 		typename OnError,
202 		typename OnDone,
203 		typename = std::enable_if_t<
204 			is_callable_v<OnNext, Value>
205 			&& is_callable_v<OnError, Error>
206 			&& is_callable_v<OnDone>>>
207 	[[nodiscard]] lifetime start(
208 		OnNext &&next,
209 		OnError &&error,
210 		OnDone &&done) &&;
211 
212 	template <
213 		typename OnNext,
214 		typename OnError,
215 		typename OnDone,
216 		typename = std::enable_if_t<
217 			is_callable_v<OnNext, Value>
218 			&& is_callable_v<OnError, Error>
219 			&& is_callable_v<OnDone>>>
220 	void start_copy(
221 		OnNext &&next,
222 		OnError &&error,
223 		OnDone &&done,
224 		lifetime &alive_while) const &;
225 
226 	template <
227 		typename OnNext,
228 		typename OnError,
229 		typename OnDone,
230 		typename = std::enable_if_t<
231 			is_callable_v<OnNext, Value>
232 			&& is_callable_v<OnError, Error>
233 			&& is_callable_v<OnDone>>>
234 	[[nodiscard]] lifetime start_copy(
235 		OnNext &&next,
236 		OnError &&error,
237 		OnDone &&done) const &;
238 
239 	template <typename Handlers>
240 	void start_existing(
241 		const consumer_type<Handlers> &consumer,
242 		lifetime &alive_while) &&;
243 
244 	template <typename Handlers>
245 	[[nodiscard]] lifetime start_existing(
246 		const consumer_type<Handlers> &consumer) &&;
247 
248 private:
249 	Generator _generator;
250 
251 	template <
252 		typename OtherValue,
253 		typename OtherError,
254 		typename OtherGenerator>
255 	friend class ::rpl::producer;
256 
257 };
258 
259 template <typename Value, typename Error, typename Generator>
260 template <typename OtherGenerator, typename>
261 inline producer_base<Value, Error, Generator>::producer_base(
262 	OtherGenerator &&generator)
263 : _generator(std::forward<OtherGenerator>(generator)) {
264 }
265 
266 template <typename Value, typename Error, typename Generator>
267 template <
268 	typename OnNext,
269 	typename OnError,
270 	typename OnDone,
271 	typename>
272 inline void producer_base<Value, Error, Generator>::start(
273 		OnNext &&next,
274 		OnError &&error,
275 		OnDone &&done,
276 		lifetime &alive_while) && {
277 	return std::move(*this).start_existing(
278 		make_consumer<Value, Error>(
279 			std::forward<OnNext>(next),
280 			std::forward<OnError>(error),
281 			std::forward<OnDone>(done)),
282 		alive_while);
283 }
284 
285 template <typename Value, typename Error, typename Generator>
286 template <
287 	typename OnNext,
288 	typename OnError,
289 	typename OnDone,
290 	typename>
291 [[nodiscard]] inline lifetime producer_base<Value, Error, Generator>::start(
292 		OnNext &&next,
293 		OnError &&error,
294 		OnDone &&done) && {
295 	auto result = lifetime();
296 	std::move(*this).start_existing(
297 		make_consumer<Value, Error>(
298 			std::forward<OnNext>(next),
299 			std::forward<OnError>(error),
300 			std::forward<OnDone>(done)),
301 		result);
302 	return result;
303 }
304 
305 template <typename Value, typename Error, typename Generator>
306 template <
307 	typename OnNext,
308 	typename OnError,
309 	typename OnDone,
310 	typename>
311 inline void producer_base<Value, Error, Generator>::start_copy(
312 		OnNext &&next,
313 		OnError &&error,
314 		OnDone &&done,
315 		lifetime &alive_while) const & {
316 	auto copy = *this;
317 	return std::move(copy).start_existing(
318 		make_consumer<Value, Error>(
319 			std::forward<OnNext>(next),
320 			std::forward<OnError>(error),
321 			std::forward<OnDone>(done)),
322 		alive_while);
323 }
324 
325 template <typename Value, typename Error, typename Generator>
326 template <
327 	typename OnNext,
328 	typename OnError,
329 	typename OnDone,
330 	typename>
331 [[nodiscard]] inline lifetime producer_base<Value, Error, Generator>::start_copy(
332 		OnNext &&next,
333 		OnError &&error,
334 		OnDone &&done) const & {
335 	auto result = lifetime();
336 	auto copy = *this;
337 	std::move(copy).start_existing(
338 		make_consumer<Value, Error>(
339 			std::forward<OnNext>(next),
340 			std::forward<OnError>(error),
341 			std::forward<OnDone>(done)),
342 		result);
343 	return result;
344 }
345 
346 template <typename Value, typename Error, typename Generator>
347 template <typename Handlers>
348 inline void producer_base<Value, Error, Generator>::start_existing(
349 		const consumer_type<Handlers> &consumer,
350 		lifetime &alive_while) && {
351 	alive_while.add(consumer.terminator());
352 	consumer.add_lifetime(std::move(_generator)(consumer));
353 }
354 
355 template <typename Value, typename Error, typename Generator>
356 template <typename Handlers>
357 [[nodiscard]] inline lifetime producer_base<Value, Error, Generator>::start_existing(
358 		const consumer_type<Handlers> &consumer) && {
359 	auto result = lifetime();
360 	std::move(*this).start_existing(consumer, result);
361 	return result;
362 }
363 
364 template <typename Value, typename Error>
365 using producer_base_type_erased = producer_base<
366 	Value,
367 	Error,
368 	type_erased_generator<Value, Error>>;
369 
370 } // namespace details
371 
372 template <typename Value, typename Error, typename Generator>
373 class producer final
374 : public details::producer_base<Value, Error, Generator> {
375 	using parent_type = details::producer_base<
376 		Value,
377 		Error,
378 		Generator>;
379 
380 public:
381 	using parent_type::parent_type;
382 
383 };
384 
385 template <typename Value, typename Error>
386 class producer<
387 	Value,
388 	Error,
389 	details::type_erased_generator<Value, Error>> final
390 : public details::producer_base_type_erased<Value, Error> {
391 	using parent_type = details::producer_base_type_erased<
392 		Value,
393 		Error>;
394 
395 public:
396 	using parent_type::parent_type;
397 
398 	producer() = default;
399 	producer(const producer &other) = default;
400 	producer(producer &&other) = default;
401 	producer &operator=(const producer &other) = default;
402 	producer &operator=(producer &&other) = default;
403 
404 	template <
405 		typename Generic,
406 		typename = std::enable_if_t<!std::is_same_v<
407 			Generic,
408 			details::type_erased_generator<Value, Error>>>>
409 	producer(const details::producer_base<Value, Error, Generic> &other)
410 		: parent_type(other._generator) {
411 	}
412 
413 	template <
414 		typename Generic,
415 		typename = std::enable_if_t<!std::is_same_v<
416 			Generic,
417 			details::type_erased_generator<Value, Error>>>>
418 	producer(details::producer_base<Value, Error, Generic> &&other)
419 		: parent_type(std::move(other._generator)) {
420 	}
421 
422 	template <
423 		typename Generic,
424 		typename = std::enable_if_t<!std::is_same_v<
425 			Generic,
426 			details::type_erased_generator<Value, Error>>>>
427 	producer &operator=(
428 			const details::producer_base<Value, Error, Generic> &other) {
429 		this->_generator = other._generator;
430 		return *this;
431 	}
432 
433 	template <
434 		typename Generic,
435 		typename = std::enable_if_t<!std::is_same_v<
436 			Generic,
437 			details::type_erased_generator<Value, Error>>>>
438 	producer &operator=(
439 			details::producer_base<Value, Error, Generic> &&other) {
440 		this->_generator = std::move(other._generator);
441 		return *this;
442 	}
443 
444 	explicit operator bool() const {
445 		return !this->_generator.empty();
446 	}
447 
448 };
449 
450 template <
451 	typename Value = empty_value,
452 	typename Error = no_error,
453 	typename Generator,
454 	typename = std::enable_if_t<
455 		std::is_convertible_v<
456 			decltype(std::declval<Generator>()(
457 				details::const_ref_consumer<Value, Error>())),
458 			lifetime>>>
459 inline auto make_producer(Generator &&generator)
460 #ifdef RPL_PRODUCER_TYPE_ERASED_ALWAYS
461 -> producer<Value, Error> {
462 #else // RPL_PRODUCER_TYPE_ERASED_ALWAYS
463 -> producer<Value, Error, std::decay_t<Generator>> {
464 #endif // !RPL_PRODUCER_TYPE_ERASED_ALWAYS
465 	return std::forward<Generator>(generator);
466 }
467 
468 template <typename Value, typename Error, typename Generator>
469 inline producer<Value, Error, Generator> duplicate(
470 		const producer<Value, Error, Generator> &value) {
471 	return value;
472 }
473 
474 template <
475 	typename Value,
476 	typename Error,
477 	typename Generator,
478 	typename Method,
479 	typename = decltype(std::declval<Method>()(
480 		std::declval<producer<Value, Error, Generator>>()))>
481 inline auto operator|(
482 		producer<Value, Error, Generator> &&value,
483 		Method &&method) {
484 	return std::forward<Method>(method)(std::move(value));
485 }
486 
487 namespace details {
488 
489 struct with_none {
490 };
491 
492 struct lifetime_with_none {
493 	lifetime &alive_while;
494 };
495 
496 template <typename OnNext>
497 struct with_next {
498 	OnNext next;
499 };
500 
501 template <typename OnNext>
502 struct lifetime_with_next {
503 	lifetime &alive_while;
504 	OnNext next;
505 };
506 
507 template <typename OnError>
508 struct with_error {
509 	OnError error;
510 };
511 
512 template <typename OnError>
513 struct lifetime_with_error {
514 	lifetime &alive_while;
515 	OnError error;
516 };
517 
518 template <typename OnDone>
519 struct with_done {
520 	OnDone done;
521 };
522 
523 template <typename OnDone>
524 struct lifetime_with_done {
525 	lifetime &alive_while;
526 	OnDone done;
527 };
528 
529 template <typename OnNext, typename OnError>
530 struct with_next_error {
531 	OnNext next;
532 	OnError error;
533 };
534 
535 template <typename OnNext, typename OnError>
536 struct lifetime_with_next_error {
537 	lifetime &alive_while;
538 	OnNext next;
539 	OnError error;
540 };
541 
542 template <typename OnError, typename OnDone>
543 struct with_error_done {
544 	OnError error;
545 	OnDone done;
546 };
547 
548 template <typename OnError, typename OnDone>
549 struct lifetime_with_error_done {
550 	lifetime &alive_while;
551 	OnError error;
552 	OnDone done;
553 };
554 
555 template <typename OnNext, typename OnDone>
556 struct with_next_done {
557 	OnNext next;
558 	OnDone done;
559 };
560 
561 template <typename OnNext, typename OnDone>
562 struct lifetime_with_next_done {
563 	lifetime &alive_while;
564 	OnNext next;
565 	OnDone done;
566 };
567 
568 template <typename OnNext, typename OnError, typename OnDone>
569 struct with_next_error_done {
570 	OnNext next;
571 	OnError error;
572 	OnDone done;
573 };
574 
575 template <typename OnNext, typename OnError, typename OnDone>
576 struct lifetime_with_next_error_done {
577 	lifetime &alive_while;
578 	OnNext next;
579 	OnError error;
580 	OnDone done;
581 };
582 
583 } // namespace details
584 
585 inline auto start()
586 -> details::with_none {
587 	return {};
588 }
589 
590 inline auto start(lifetime &alive_while)
591 -> details::lifetime_with_none {
592 	return { alive_while };
593 }
594 
595 template <typename OnNext>
596 inline auto start_with_next(OnNext &&next)
597 -> details::with_next<std::decay_t<OnNext>> {
598 	return { std::forward<OnNext>(next) };
599 }
600 
601 template <typename OnNext>
602 inline auto start_with_next(OnNext &&next, lifetime &alive_while)
603 -> details::lifetime_with_next<std::decay_t<OnNext>> {
604 	return { alive_while, std::forward<OnNext>(next) };
605 }
606 
607 template <typename OnError>
608 inline auto start_with_error(OnError &&error)
609 -> details::with_error<std::decay_t<OnError>> {
610 	return { std::forward<OnError>(error) };
611 }
612 
613 template <typename OnError>
614 inline auto start_with_error(OnError &&error, lifetime &alive_while)
615 -> details::lifetime_with_error<std::decay_t<OnError>> {
616 	return { alive_while, std::forward<OnError>(error) };
617 }
618 
619 template <typename OnDone>
620 inline auto start_with_done(OnDone &&done)
621 -> details::with_done<std::decay_t<OnDone>> {
622 	return { std::forward<OnDone>(done) };
623 }
624 
625 template <typename OnDone>
626 inline auto start_with_done(OnDone &&done, lifetime &alive_while)
627 -> details::lifetime_with_done<std::decay_t<OnDone>> {
628 	return { alive_while, std::forward<OnDone>(done) };
629 }
630 
631 template <typename OnNext, typename OnError>
632 inline auto start_with_next_error(
633 	OnNext &&next,
634 	OnError &&error)
635 -> details::with_next_error<
636 		std::decay_t<OnNext>,
637 		std::decay_t<OnError>> {
638 	return {
639 		std::forward<OnNext>(next),
640 		std::forward<OnError>(error)
641 	};
642 }
643 
644 template <typename OnNext, typename OnError>
645 inline auto start_with_next_error(
646 	OnNext &&next,
647 	OnError &&error,
648 	lifetime &alive_while)
649 -> details::lifetime_with_next_error<
650 		std::decay_t<OnNext>,
651 		std::decay_t<OnError>> {
652 	return {
653 		alive_while,
654 		std::forward<OnNext>(next),
655 		std::forward<OnError>(error)
656 	};
657 }
658 
659 template <typename OnError, typename OnDone>
660 inline auto start_with_error_done(
661 	OnError &&error,
662 	OnDone &&done)
663 -> details::with_error_done<
664 		std::decay_t<OnError>,
665 		std::decay_t<OnDone>> {
666 	return {
667 		std::forward<OnError>(error),
668 		std::forward<OnDone>(done)
669 	};
670 }
671 
672 template <typename OnError, typename OnDone>
673 inline auto start_with_error_done(
674 	OnError &&error,
675 	OnDone &&done,
676 	lifetime &alive_while)
677 -> details::lifetime_with_error_done<
678 		std::decay_t<OnError>,
679 		std::decay_t<OnDone>> {
680 	return {
681 		alive_while,
682 		std::forward<OnError>(error),
683 		std::forward<OnDone>(done)
684 	};
685 }
686 
687 template <typename OnNext, typename OnDone>
688 inline auto start_with_next_done(
689 	OnNext &&next,
690 	OnDone &&done)
691 -> details::with_next_done<
692 		std::decay_t<OnNext>,
693 		std::decay_t<OnDone>> {
694 	return {
695 		std::forward<OnNext>(next),
696 		std::forward<OnDone>(done)
697 	};
698 }
699 
700 template <typename OnNext, typename OnDone>
701 inline auto start_with_next_done(
702 	OnNext &&next,
703 	OnDone &&done,
704 	lifetime &alive_while)
705 -> details::lifetime_with_next_done<
706 		std::decay_t<OnNext>,
707 		std::decay_t<OnDone>> {
708 	return {
709 		alive_while,
710 		std::forward<OnNext>(next),
711 		std::forward<OnDone>(done)
712 	};
713 }
714 
715 template <typename OnNext, typename OnError, typename OnDone>
716 inline auto start_with_next_error_done(
717 	OnNext &&next,
718 	OnError &&error,
719 	OnDone &&done)
720 -> details::with_next_error_done<
721 		std::decay_t<OnNext>,
722 		std::decay_t<OnError>,
723 		std::decay_t<OnDone>> {
724 	return {
725 		std::forward<OnNext>(next),
726 		std::forward<OnError>(error),
727 		std::forward<OnDone>(done)
728 	};
729 }
730 
731 template <typename OnNext, typename OnError, typename OnDone>
732 inline auto start_with_next_error_done(
733 	OnNext &&next,
734 	OnError &&error,
735 	OnDone &&done,
736 	lifetime &alive_while)
737 -> details::lifetime_with_next_error_done<
738 		std::decay_t<OnNext>,
739 		std::decay_t<OnError>,
740 		std::decay_t<OnDone>> {
741 	return {
742 		alive_while,
743 		std::forward<OnNext>(next),
744 		std::forward<OnError>(error),
745 		std::forward<OnDone>(done)
746 	};
747 }
748 
749 namespace details {
750 
751 template <typename Value, typename Error, typename Generator>
752 [[nodiscard]] inline lifetime operator|(
753 		producer<Value, Error, Generator> &&value,
754 		with_none &&handlers) {
755 	return std::move(value).start(
756 		[] {},
757 		[] {},
758 		[] {});
759 }
760 
761 template <typename Value, typename Error, typename Generator>
762 inline void operator|(
763 		producer<Value, Error, Generator> &&value,
764 		lifetime_with_none &&handlers) {
765 	std::move(value).start(
766 		[] {},
767 		[] {},
768 		[] {},
769 		handlers.alive_while);
770 }
771 
772 template <
773 	typename Value,
774 	typename Error,
775 	typename Generator,
776 	typename OnNext,
777 	typename = std::enable_if_t<is_callable_v<OnNext, Value>>>
778 [[nodiscard]] inline lifetime operator|(
779 		producer<Value, Error, Generator> &&value,
780 		with_next<OnNext> &&handlers) {
781 	return std::move(value).start(
782 		std::move(handlers.next),
783 		[] {},
784 		[] {});
785 }
786 
787 template <
788 	typename Value,
789 	typename Error,
790 	typename Generator,
791 	typename OnNext,
792 	typename = std::enable_if_t<is_callable_v<OnNext, Value>>>
793 inline void operator|(
794 		producer<Value, Error, Generator> &&value,
795 		lifetime_with_next<OnNext> &&handlers) {
796 	std::move(value).start(
797 		std::move(handlers.next),
798 		[] {},
799 		[] {},
800 		handlers.alive_while);
801 }
802 
803 template <
804 	typename Value,
805 	typename Error,
806 	typename Generator,
807 	typename OnError,
808 	typename = std::enable_if_t<is_callable_v<OnError, Error>>>
809 [[nodiscard]] inline lifetime operator|(
810 		producer<Value, Error, Generator> &&value,
811 		with_error<OnError> &&handlers) {
812 	return std::move(value).start(
813 		[] {},
814 		std::move(handlers.error),
815 		[] {});
816 }
817 
818 template <
819 	typename Value,
820 	typename Error,
821 	typename Generator,
822 	typename OnError,
823 	typename = std::enable_if_t<is_callable_v<OnError, Error>>>
824 inline void operator|(
825 		producer<Value, Error, Generator> &&value,
826 		lifetime_with_error<OnError> &&handlers) {
827 	std::move(value).start(
828 		[] {},
829 		std::move(handlers.error),
830 		[] {},
831 		handlers.alive_while);
832 }
833 
834 template <
835 	typename Value,
836 	typename Error,
837 	typename Generator,
838 	typename OnDone,
839 	typename = std::enable_if_t<is_callable_v<OnDone>>>
840 [[nodiscard]] inline lifetime operator|(
841 		producer<Value, Error, Generator> &&value,
842 		with_done<OnDone> &&handlers) {
843 	return std::move(value).start(
844 		[] {},
845 		[] {},
846 		std::move(handlers.done));
847 }
848 
849 template <
850 	typename Value,
851 	typename Error,
852 	typename Generator,
853 	typename OnDone,
854 	typename = std::enable_if_t<is_callable_v<OnDone>>>
855 inline void operator|(
856 		producer<Value, Error, Generator> &&value,
857 		lifetime_with_done<OnDone> &&handlers) {
858 	std::move(value).start(
859 		[] {},
860 		[] {},
861 		std::move(handlers.done),
862 		handlers.alive_while);
863 }
864 
865 template <
866 	typename Value,
867 	typename Error,
868 	typename Generator,
869 	typename OnNext,
870 	typename OnError,
871 	typename = std::enable_if_t<
872 		is_callable_v<OnNext, Value> &&
873 		is_callable_v<OnError, Error>>>
874 [[nodiscard]] inline lifetime operator|(
875 		producer<Value, Error, Generator> &&value,
876 		with_next_error<OnNext, OnError> &&handlers) {
877 	return std::move(value).start(
878 		std::move(handlers.next),
879 		std::move(handlers.error),
880 		[] {});
881 }
882 
883 template <
884 	typename Value,
885 	typename Error,
886 	typename Generator,
887 	typename OnNext,
888 	typename OnError,
889 	typename = std::enable_if_t<
890 		is_callable_v<OnNext, Value> &&
891 		is_callable_v<OnError, Error>>>
892 inline void operator|(
893 		producer<Value, Error, Generator> &&value,
894 		lifetime_with_next_error<OnNext, OnError> &&handlers) {
895 	std::move(value).start(
896 		std::move(handlers.next),
897 		std::move(handlers.error),
898 		[] {},
899 		handlers.alive_while);
900 }
901 
902 template <
903 	typename Value,
904 	typename Error,
905 	typename Generator,
906 	typename OnError,
907 	typename OnDone,
908 	typename = std::enable_if_t<
909 		is_callable_v<OnError, Error> &&
910 		is_callable_v<OnDone>>>
911 [[nodiscard]] inline lifetime operator|(
912 		producer<Value, Error, Generator> &&value,
913 		with_error_done<OnError, OnDone> &&handlers) {
914 	return std::move(value).start(
915 		[] {},
916 		std::move(handlers.error),
917 		std::move(handlers.done));
918 }
919 
920 template <
921 	typename Value,
922 	typename Error,
923 	typename Generator,
924 	typename OnError,
925 	typename OnDone,
926 	typename = std::enable_if_t<
927 		is_callable_v<OnError, Error> &&
928 		is_callable_v<OnDone>>>
929 inline void operator|(
930 		producer<Value, Error, Generator> &&value,
931 		lifetime_with_error_done<OnError, OnDone> &&handlers) {
932 	std::move(value).start(
933 		[] {},
934 		std::move(handlers.error),
935 		std::move(handlers.done),
936 		handlers.alive_while);
937 }
938 
939 template <
940 	typename Value,
941 	typename Error,
942 	typename Generator,
943 	typename OnNext,
944 	typename OnDone,
945 	typename = std::enable_if_t<
946 		is_callable_v<OnNext, Value> &&
947 		is_callable_v<OnDone>>>
948 [[nodiscard]] inline lifetime operator|(
949 		producer<Value, Error, Generator> &&value,
950 		with_next_done<OnNext, OnDone> &&handlers) {
951 	return std::move(value).start(
952 		std::move(handlers.next),
953 		[] {},
954 		std::move(handlers.done));
955 }
956 
957 template <
958 	typename Value,
959 	typename Error,
960 	typename Generator,
961 	typename OnNext,
962 	typename OnDone,
963 	typename = std::enable_if_t<
964 		is_callable_v<OnNext, Value> &&
965 		is_callable_v<OnDone>>>
966 inline void operator|(
967 		producer<Value, Error, Generator> &&value,
968 		lifetime_with_next_done<OnNext, OnDone> &&handlers) {
969 	std::move(value).start(
970 		std::move(handlers.next),
971 		[] {},
972 		std::move(handlers.done),
973 		handlers.alive_while);
974 }
975 
976 template <
977 	typename Value,
978 	typename Error,
979 	typename Generator,
980 	typename OnNext,
981 	typename OnError,
982 	typename OnDone,
983 	typename = std::enable_if_t<
984 		is_callable_v<OnNext, Value> &&
985 		is_callable_v<OnError, Error> &&
986 		is_callable_v<OnDone>>>
987 [[nodiscard]] inline lifetime operator|(
988 		producer<Value, Error, Generator> &&value,
989 		with_next_error_done<
990 			OnNext,
991 			OnError,
992 			OnDone> &&handlers) {
993 	return std::move(value).start(
994 		std::move(handlers.next),
995 		std::move(handlers.error),
996 		std::move(handlers.done));
997 }
998 
999 template <
1000 	typename Value,
1001 	typename Error,
1002 	typename Generator,
1003 	typename OnNext,
1004 	typename OnError,
1005 	typename OnDone,
1006 	typename = std::enable_if_t<
1007 		is_callable_v<OnNext, Value> &&
1008 		is_callable_v<OnError, Error> &&
1009 		is_callable_v<OnDone>>>
1010 inline void operator|(
1011 		producer<Value, Error, Generator> &&value,
1012 		lifetime_with_next_error_done<
1013 			OnNext,
1014 			OnError,
1015 			OnDone> &&handlers) {
1016 	std::move(value).start(
1017 		std::move(handlers.next),
1018 		std::move(handlers.error),
1019 		std::move(handlers.done),
1020 		handlers.alive_while);
1021 }
1022 
1023 } // namespace details
1024 } // namespace rpl
1025