libkazv
Loading...
Searching...
No Matches
immer-utils.hpp
Go to the documentation of this file.
1/*
2 * This file is part of libkazv.
3 * SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
4 * SPDX-License-Identifier: AGPL-3.0-or-later
5 */
6
7#pragma once
8#include "libkazv-config.hpp"
9
10#include <tuple>
11#include <optional>
12
13namespace Kazv
14{
15 template<class T>
16 [[nodiscard]] auto getIn(T &&item)
17 {
18 return std::forward<T>(item);
19 }
20
21 template<class ImmerT, class K, class ...Keys>
22 [[nodiscard]] auto getIn(ImmerT &&container, K &&key, Keys &&...keys)
23 {
24 return getIn(std::forward<ImmerT>(container)[std::forward<K>(key)], std::forward<Keys>(keys)...);
25 }
26
27 template<class T>
28 [[nodiscard]] auto setIn(T, T newVal)
29 {
30 return newVal;
31 }
32
33 template<class ImmerT, class K>
34 [[nodiscard]] auto setIn(ImmerT container, std::decay_t<decltype(getIn(std::declval<ImmerT>(), std::declval<K>()))> newVal, K &&key) -> std::decay_t<ImmerT>
35 {
36 return std::move(container).set(std::forward<K>(key), std::move(newVal));
37 }
38
39 template<class ImmerT, class K, class ...Keys>
40 [[nodiscard]] auto setIn(ImmerT container, std::decay_t<decltype(getIn(std::declval<ImmerT>(), std::declval<K>(), std::declval<Keys>()...))> newVal, K &&key, Keys &&...keys) -> std::decay_t<ImmerT>
41 {
42 auto oldItem = getIn(container, key);
43 return std::move(container).set(
44 std::forward<K>(key),
45 setIn(oldItem, std::move(newVal), std::forward<Keys>(keys)...)
46 );
47 }
48
49 template<class T, class Func>
50 [[nodiscard]] auto updateIn(T oldVal, Func func) -> T
51 {
52 return std::move(func)(oldVal);
53 }
54
55 template<class ImmerT, class Func, class ...Keys>
56 [[nodiscard]] auto updateIn(ImmerT container, Func func, Keys &&...keys) -> ImmerT
57 {
58 auto oldVal = getIn(container, keys...);
59 auto newVal = std::move(func)(std::move(oldVal));
60 return setIn(std::move(container), std::move(newVal), std::forward<Keys>(keys)...);
61 }
62
72 template<class ImmerT, class Func, class ValueT = typename ImmerT::value_type>
73 auto withBox(ImmerT &box, Func &&func) -> std::decay_t<std::invoke_result_t<Func &&, ValueT &>>
74 {
75 using ResT = std::decay_t<std::invoke_result_t<Func &&, ValueT &>>;
76 if constexpr (std::is_same_v<ResT, void>) {
77 box = std::move(box)
78 .update([f=std::forward<Func>(func)](ValueT v) mutable {
79 std::forward<Func>(f)(v);
80 return v;
81 });
82 } else {
83 std::optional<ResT> res;
84 box = std::move(box)
85 .update([f=std::forward<Func>(func), &res](ValueT v) mutable {
86 res = std::forward<Func>(f)(v);
87 return v;
88 });
89 return std::move(res).value();
90 }
91 }
92
93 template<
94 class ImmerT,
95 class Key,
96 class Func,
97 class BoxT = typename ImmerT::mapped_type,
98 class ValueT = typename BoxT::value_type
99 >
100 auto withMapBox(ImmerT &map, Key &&k, Func &&func) -> std::decay_t<std::invoke_result_t<Func &&, ValueT &>>
101 {
102 using ResT = std::decay_t<std::invoke_result_t<Func &&, ValueT &>>;
103 if constexpr (std::is_same_v<ResT, void>) {
104 map = std::move(map)
105 .update(std::forward<Key>(k), [f=std::forward<Func>(func)](BoxT v) mutable {
106 withBox(v, std::forward<Func>(f));
107 return v;
108 });
109 } else {
110 std::optional<ResT> res;
111 map = std::move(map)
112 .update(std::forward<Key>(k), [f=std::forward<Func>(func), &res](BoxT v) mutable {
113 res = withBox(v, std::forward<Func>(f));
114 return v;
115 });
116 return std::move(res).value();
117 }
118 }
119}
Definition location.hpp:10
auto setIn(T, T newVal)
Definition immer-utils.hpp:28
auto withMapBox(ImmerT &map, Key &&k, Func &&func) -> std::decay_t< std::invoke_result_t< Func &&, ValueT & > >
Definition immer-utils.hpp:100
auto updateIn(T oldVal, Func func) -> T
Definition immer-utils.hpp:50
auto getIn(T &&item)
Definition immer-utils.hpp:16
auto withBox(ImmerT &box, Func &&func) -> std::decay_t< std::invoke_result_t< Func &&, ValueT & > >
Do something with the box, updating its value, then return the return value of the function.
Definition immer-utils.hpp:73