LeechCraft  0.6.70-18450-gabe19ee3b0
Modular cross-platform feature rich live environment.
either.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <source_location>
12 #include <QtDebug>
13 #include <util/sll/either.h>
14 #include <util/sll/void.h>
15 #include "task.h"
16 
17 namespace LC::Util
18 {
19  struct IgnoreLeft {};
20 
21  namespace detail
22  {
23  template<typename Promise>
24  [[noreturn]]
25  void TerminateLeftyCoroutine (std::coroutine_handle<Promise> handle, const auto& error)
26  {
27  auto& promise = handle.promise ();
28  if constexpr (Promise::IsVoid)
29  promise.return_void ();
30  else
31  promise.return_value (Left { error });
32 
33  throw EitherFailureAbort {};
34  }
35 
36  template<typename L, typename R, typename ErrorHandler>
38  {
40  ErrorHandler Handler_;
41 
42  using HandlerReturn_t = decltype (Handler_ (Either_.GetLeft ()));
43 
45  {
46  if (Either_.IsRight ())
47  return true;
48 
49  if constexpr (std::is_same_v<IgnoreLeft, HandlerReturn_t>)
50  {
51  static_assert (std::is_default_constructible_v<R>);
52  Handler_ (Either_.GetLeft ());
53  Either_ = R {};
54  return true;
55  }
56 
57  return false;
58  }
59 
60  auto await_suspend (auto handle)
61  {
62  if constexpr (std::is_same_v<void, HandlerReturn_t>)
63  {
64  Handler_ (Either_.GetLeft ());
65  TerminateLeftyCoroutine (handle, Either_.GetLeft ());
66  }
67  else if constexpr (std::is_same_v<IgnoreLeft, HandlerReturn_t>)
68  qFatal () << "shall never suspend when ignoring left";
69  else
70  TerminateLeftyCoroutine (handle, Handler_ (Either_.GetLeft ()));
71  }
72 
74  {
75  return Either_.GetRight ();
76  }
77  };
78  }
79 
80  template<typename L, typename R, typename F>
81  requires std::invocable<F, const L&>
82  detail::EitherAwaiter<L, R, F> WithHandler (const Either<L, R>& either, F&& errorHandler)
83  {
84  return { either, std::forward<F> (errorHandler) };
85  }
86 
87  template<typename L, typename R>
88  auto WithHandler (const Either<L, R>& either, IgnoreLeft)
89  {
90  return WithHandler (either, [] (const auto&) { return IgnoreLeft {}; });
91  }
92 
93  template<typename T>
94  Either<Void, T> NonEmpty (const T& t, auto&& msg, std::source_location loc = std::source_location::current ())
95  {
96  if (t)
97  return t;
98 
99  QMessageLogger { loc.file_name (), static_cast<int> (loc.line ()), loc.function_name () }.warning () << msg;
100  return { AsLeft, Void {} };
101  }
102 
103  template<typename T, typename... Msgs>
104  Either<Void, T> NonEmpty (const T& t, const std::tuple<Msgs...>& msgsTuple,
105  std::source_location loc = std::source_location::current ())
106  {
107  if (t)
108  return t;
109 
110  std::apply ([&]<typename... AMsgs> (AMsgs&&... amsgs)
111  {
112  const QMessageLogger log { loc.file_name (), static_cast<int> (loc.line ()), loc.function_name () };
113  (log.warning () << ... << std::forward<AMsgs> (amsgs));
114  }, msgsTuple);
115  return { AsLeft, Void {} };
116  }
117 }
118 
119 namespace LC
120 {
121  template<typename L, typename R>
123  {
124  return { either, {} };
125  }
126 }
Either< L, R > Either_
Definition: either.h:39
requires std::invocable< F, const L & > detail::EitherAwaiter< L, R, F > WithHandler(const Either< L, R > &either, F &&errorHandler)
Definition: either.h:82
std::source_location loc
Either< Void, T > NonEmpty(const T &t, auto &&msg, std::source_location loc=std::source_location::current())
Definition: either.h:94
decltype(Handler_(Either_.GetLeft())) HandlerReturn_t
Definition: either.h:42
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
auto await_suspend(auto handle)
Definition: either.h:60
constexpr auto AsLeft
Definition: either.h:27
bool await_ready() noexcept
Definition: either.h:44
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:68
void TerminateLeftyCoroutine(std::coroutine_handle< Promise > handle, const auto &error)
Definition: either.h:25
R await_resume() const noexcept
Definition: either.h:73
A proper void type, akin to unit (or ()) type in functional languages.
Definition: void.h:20