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