// Copyright (c) 2023, QuantStack and Mamba Contributors // // Distributed under the terms of the BSD 3-Clause License. // // The full license is in the file LICENSE, distributed with this software. #ifndef MAMBA_CORE_SOLUTION_HPP #define MAMBA_CORE_SOLUTION_HPP #include #include #include #include "package_info.hpp" namespace mamba { namespace detail { template inline constexpr bool is_any_of_v = std::disjunction_v...>; } struct Solution { struct Omit { PackageInfo what; }; struct Upgrade { PackageInfo remove; PackageInfo install; }; struct Downgrade { PackageInfo remove; PackageInfo install; }; struct Change { PackageInfo remove; PackageInfo install; }; struct Reinstall { PackageInfo what; }; struct Remove { PackageInfo remove; }; struct Install { PackageInfo install; }; template inline static constexpr bool has_remove_v = detail::is_any_of_v; template inline static constexpr bool has_install_v = detail::is_any_of_v; using Action = std::variant; using action_list = std::vector; action_list actions = {}; }; template void for_each_to_remove(Iter first, Iter last, UnaryFunc&& func); template void for_each_to_remove(Range&& actions, UnaryFunc&& func); template void for_each_to_install(Iter first, Iter last, UnaryFunc&& func); template void for_each_to_install(Range&& actions, UnaryFunc&& func); template void for_each_to_omit(Iter first, Iter last, UnaryFunc&& func); template void for_each_to_omit(Range&& actions, UnaryFunc&& func); /******************************** * Implementation of Solution * ********************************/ namespace detail { template auto to_remove_ptr(Action& action) { using PackageInfoPtr = std::conditional_t, const PackageInfo*, PackageInfo*>; return std::visit( [](auto& a) -> PackageInfoPtr { using A = std::decay_t; if constexpr (Solution::has_remove_v) { return &(a.remove); } else if constexpr (std::is_same_v) { return &(a.what); } return nullptr; }, action ); } } template void for_each_to_remove(Iter first, Iter last, UnaryFunc&& func) { for (; first != last; ++first) { if (auto* const ptr = detail::to_remove_ptr(*first)) { func(*ptr); } } } template void for_each_to_remove(Range&& actions, UnaryFunc&& func) { return for_each_to_remove(actions.begin(), actions.end(), std::forward(func)); } namespace detail { template auto to_install_ptr(Action& action) { using PackageInfoPtr = std::conditional_t, const PackageInfo*, PackageInfo*>; return std::visit( [](auto& a) -> PackageInfoPtr { using A = std::decay_t; if constexpr (Solution::has_install_v) { return &(a.install); } else if constexpr (std::is_same_v) { return &(a.what); } return nullptr; }, action ); } } template void for_each_to_install(Iter first, Iter last, UnaryFunc&& func) { for (; first != last; ++first) { if (auto* const ptr = detail::to_install_ptr(*first)) { func(*ptr); } } } template void for_each_to_install(Range&& actions, UnaryFunc&& func) { return for_each_to_install(actions.begin(), actions.end(), std::forward(func)); } namespace detail { template auto to_omit_ptr(Action& action) { using PackageInfoPtr = std::conditional_t, const PackageInfo*, PackageInfo*>; return std::visit( [](auto& a) -> PackageInfoPtr { using A = std::decay_t; if constexpr (std::is_same_v) { return &(a.what); } return nullptr; }, action ); } } template void for_each_to_omit(Iter first, Iter last, UnaryFunc&& func) { for (; first != last; ++first) { if (auto* const ptr = detail::to_omit_ptr(*first)) { func(*ptr); } } } template void for_each_to_omit(Range&& actions, UnaryFunc&& func) { return for_each_to_omit(actions.begin(), actions.end(), std::forward(func)); } } #endif