Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:27

0001 // Copyright (c) 2023 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef BOOST_COBALT_RESULT_HPP
0006 #define BOOST_COBALT_RESULT_HPP
0007 
0008 #include <boost/cobalt/concepts.hpp>
0009 
0010 #include <boost/core/no_exceptions_support.hpp>
0011 #include <boost/system/result.hpp>
0012 
0013 namespace boost::cobalt
0014 {
0015 
0016 
0017 namespace detail
0018 {
0019 
0020 template<typename T>
0021 concept result_error =
0022   requires (const T & t, const source_location & loc)
0023   {
0024     system::throw_exception_from_error(t, loc);
0025   }
0026   || // ADL
0027   requires (const T & t, const source_location & loc)
0028   {
0029     throw_exception_from_error(t, loc);
0030   }
0031 ;
0032 
0033 }
0034 
0035 inline constexpr auto interpret_as_result(std::tuple<> &&)
0036 {
0037   return system::result<void>();
0038 }
0039 
0040 template<typename Arg>
0041 auto interpret_as_result(std::tuple<Arg> && args)
0042 {
0043   if constexpr (detail::result_error<Arg>)
0044   {
0045     if (std::get<0>(args))
0046       return system::result<void, Arg>(system::in_place_error, std::get<0>(args));
0047     else
0048       return system::result<void, Arg>(system::in_place_value);
0049   }
0050 
0051   else
0052     return system::result<Arg>(std::move(std::get<0>(args)));
0053 }
0054 
0055 template<typename First, typename ... Args>
0056   requires (!detail::result_error<First> && sizeof...(Args) > 0u)
0057 auto interpret_as_result(std::tuple<First, Args...> && args) -> system::result<std::tuple<First, Args...>>
0058 {
0059   return std::move(args);
0060 }
0061 
0062 template<detail::result_error Error, typename  ... Args>
0063   requires (sizeof...(Args) > 1u)
0064 auto interpret_as_result(std::tuple<Error, Args...> && args) -> system::result<std::tuple<Args...>, Error>
0065 {
0066   if (std::get<0>(args))
0067     return {system::in_place_error, std::move(std::get<0>(args))};
0068   return {
0069       system::in_place_value,
0070       std::apply([](auto, auto && ... rest) {return std::make_tuple(std::move(rest)...);}, std::move(args))
0071   };
0072 }
0073 
0074 template<detail::result_error Error, typename Arg>
0075 auto interpret_as_result(std::tuple<Error, Arg> && args) -> system::result<Arg, Error>
0076 {
0077   if (std::get<0>(args))
0078     return {system::in_place_error, std::get<0>(args)};
0079 
0080   return {system::in_place_value, std::get<1>(std::move(args))};
0081 }
0082 
0083 struct as_result_tag {};
0084 struct as_tuple_tag {};
0085 
0086 template<awaitable_type Aw>
0087 struct as_result_t
0088 {
0089   as_result_t(Aw && aw) : aw_(std::forward<Aw>(aw)) {}
0090 
0091   template<typename Aw_>
0092     requires requires (Aw_ && aw) {{std::forward<Aw_>(aw).operator co_await()} -> awaitable_type;}
0093   as_result_t(Aw_ && aw) : aw_(std::forward<Aw_>(aw).operator co_await()) {}
0094 
0095   template<typename Aw_>
0096     requires requires (Aw_ && aw) {{operator co_await(std::forward<Aw_>(aw))} -> awaitable_type;}
0097   as_result_t(Aw_ && aw) : aw_(operator co_await(std::forward<Aw_>(aw))) {}
0098 
0099   bool await_ready() { return aw_.await_ready();}
0100   template<typename T>
0101   auto await_suspend(std::coroutine_handle<T> h) { return aw_.await_suspend(h);}
0102 
0103   auto await_resume()
0104   {
0105     if constexpr (requires {aw_.await_resume(as_result_tag{});})
0106       return aw_.await_resume(as_result_tag{});
0107     else
0108     {
0109       using type = decltype(aw_.await_resume());
0110       if constexpr (std::is_void_v<type>)
0111       {
0112         using res_t = system::result<type, std::exception_ptr>;
0113         BOOST_TRY
0114         {
0115           aw_.await_resume();
0116           return res_t{system::in_place_value};
0117         }
0118         BOOST_CATCH (...)
0119         {
0120           return res_t{system::in_place_error, std::current_exception()};
0121         }
0122         BOOST_CATCH_END
0123       }
0124       else
0125       {
0126         using res_t = system::result<type, std::exception_ptr>;
0127         BOOST_TRY
0128         {
0129           return res_t{system::in_place_value, aw_.await_resume()};
0130         }
0131         BOOST_CATCH (...)
0132         {
0133           return res_t{system::in_place_error, std::current_exception()};
0134         }
0135         BOOST_CATCH_END
0136       }
0137     }
0138   }
0139  private:
0140   Aw aw_;
0141 };
0142 
0143 
0144 template<awaitable_type Aw>
0145 as_result_t(Aw &&) -> as_result_t<Aw>;
0146 
0147 template<typename Aw_>
0148   requires requires (Aw_ && aw) {{std::forward<Aw_>(aw).operator co_await()} -> awaitable_type;}
0149 as_result_t(Aw_ && aw) -> as_result_t<decltype(std::forward<Aw_>(aw).operator co_await())>;
0150 
0151 template<typename Aw_>
0152   requires requires (Aw_ && aw) {{operator co_await(std::forward<Aw_>(aw))} -> awaitable_type;}
0153 as_result_t(Aw_ && aw) -> as_result_t<decltype(operator co_await(std::forward<Aw_>(aw)))>;
0154 
0155 template<awaitable_type Aw>
0156 auto as_result(Aw && aw) -> as_result_t<Aw>
0157 {
0158   return as_result_t<Aw>(std::forward<Aw>(aw));
0159 }
0160 
0161 template<typename Aw>
0162   requires requires (Aw && aw)
0163   {
0164     {std::forward<Aw>(aw).operator co_await()} -> awaitable_type;
0165   }
0166 auto as_result(Aw && aw)
0167 {
0168   struct lazy_tuple
0169   {
0170     Aw aw;
0171     auto operator co_await ()
0172     {
0173       return as_result_t(std::forward<Aw>(aw));
0174     }
0175   };
0176   return lazy_tuple{std::forward<Aw>(aw)};
0177 }
0178 
0179 template<typename Aw>
0180   requires requires (Aw && aw)
0181   {
0182     {operator co_await(std::forward<Aw>(aw))} -> awaitable_type;
0183   }
0184 auto as_result(Aw && aw)
0185 {
0186   struct lazy_tuple
0187   {
0188     Aw aw;
0189     auto operator co_await ()
0190     {
0191       return as_result_t(std::forward<Aw>(aw));
0192     }
0193   };
0194   return lazy_tuple{std::forward<Aw>(aw)};
0195 }
0196 
0197 
0198 
0199 template<awaitable Aw>
0200 struct as_tuple_t
0201 {
0202   as_tuple_t(Aw && aw) : aw_(std::forward<Aw>(aw)) {}
0203 
0204   template<typename Aw_>
0205     requires requires (Aw_ && aw) {{std::forward<Aw_>(aw).operator co_await()} -> awaitable_type;}
0206   as_tuple_t(Aw_ && aw) : aw_(std::forward<Aw_>(aw).operator co_await()) {}
0207 
0208   template<typename Aw_>
0209     requires requires (Aw_ && aw) {{operator co_await(std::forward<Aw_>(aw))} -> awaitable_type;}
0210   as_tuple_t(Aw_ && aw) : aw_(operator co_await(std::forward<Aw_>(aw))) {}
0211 
0212 
0213   bool await_ready() { return aw_.await_ready();}
0214   template<typename T>
0215   auto await_suspend(std::coroutine_handle<T> h) { return aw_.await_suspend(h);}
0216 
0217   auto await_resume()
0218   {
0219     using type = decltype(aw_.await_resume());
0220     if constexpr (requires {aw_.await_resume(as_tuple_tag{});})
0221       return aw_.await_resume(as_tuple_tag{});
0222     else if constexpr (noexcept(aw_.await_resume()))
0223     {
0224       if constexpr (std::is_void_v<type>)
0225       {
0226         aw_.await_resume();
0227         return std::make_tuple();
0228       }
0229       else
0230         return std::make_tuple(aw_.await_resume());
0231 
0232     }
0233     else
0234     {
0235       if constexpr (std::is_void_v<type>)
0236       {
0237         BOOST_TRY
0238         {
0239           aw_.await_resume();
0240           return std::make_tuple(std::exception_ptr());
0241         }
0242         BOOST_CATCH (...)
0243         {
0244           return std::make_tuple(std::current_exception());
0245         }
0246         BOOST_CATCH_END
0247       }
0248       else
0249       {
0250         BOOST_TRY
0251         {
0252           return make_tuple_(std::exception_ptr(), aw_.await_resume());
0253         }
0254         BOOST_CATCH (...)
0255         {
0256           return make_tuple_(std::current_exception(), type());
0257         }
0258         BOOST_CATCH_END
0259       }
0260     }
0261   }
0262  private:
0263   template<typename ... Args>
0264   std::tuple<std::exception_ptr, Args...> make_tuple_(std::exception_ptr ep, std::tuple<Args...> && tup)
0265   {
0266     return std::apply(
0267         [&](auto ... args)
0268         {
0269           return std::make_tuple(std::move(ep), std::move(args)...);
0270         }, std::move(tup));
0271   }
0272 
0273   template<typename Arg>
0274   std::tuple<std::exception_ptr, Arg> make_tuple_(std::exception_ptr ep, Arg && arg)
0275   {
0276     return std::make_tuple(std::move(ep), std::move(arg));
0277   }
0278 
0279 private:
0280 
0281   Aw aw_;
0282 };
0283 
0284 
0285 template<awaitable_type Aw>
0286 as_tuple_t(Aw &&) -> as_tuple_t<Aw>;
0287 
0288 template<typename Aw_>
0289   requires requires (Aw_ && aw) {{std::forward<Aw_>(aw).operator co_await()} -> awaitable_type;}
0290 as_tuple_t(Aw_ && aw) -> as_tuple_t<decltype(std::forward<Aw_>(aw).operator co_await())>;
0291 
0292 template<typename Aw_>
0293   requires requires (Aw_ && aw) {{operator co_await(std::forward<Aw_>(aw))} -> awaitable_type;}
0294 as_tuple_t(Aw_ && aw) -> as_tuple_t<decltype(operator co_await(std::forward<Aw_>(aw)))>;
0295 
0296 
0297 template<awaitable_type Aw>
0298 auto as_tuple(Aw && aw) -> as_tuple_t<Aw>
0299 {
0300   return as_tuple_t<Aw>(std::forward<Aw>(aw));
0301 }
0302 
0303 template<typename Aw>
0304   requires requires (Aw && aw)
0305   {
0306     {std::forward<Aw>(aw).operator co_await()} -> awaitable_type;
0307   }
0308 auto as_tuple(Aw && aw)
0309 {
0310   struct lazy_tuple
0311   {
0312     Aw aw;
0313     auto operator co_await ()
0314     {
0315       return as_tuple_t(std::forward<Aw>(aw));
0316     }
0317   };
0318   return lazy_tuple{std::forward<Aw>(aw)};
0319 }
0320 
0321 template<typename Aw>
0322   requires requires (Aw && aw)
0323   {
0324     {operator co_await(std::forward<Aw>(aw))} -> awaitable_type;
0325   }
0326 auto as_tuple(Aw && aw)
0327 {
0328   struct lazy_tuple
0329   {
0330     Aw aw;
0331     auto operator co_await ()
0332     {
0333       return as_tuple_t(std::forward<Aw>(aw));
0334     }
0335   };
0336   return lazy_tuple{std::forward<Aw>(aw)};
0337 }
0338 
0339 
0340 }
0341 
0342 #endif //BOOST_COBALT_RESULT_HPP