LeviLamina
Loading...
Searching...
No Matches
DataStore.h
1#pragma once
2
3#include <memory>
4#include <string>
5#include <string_view>
6#include <utility>
7
8#include "ll/api/Expected.h"
9#include "ll/api/base/Macro.h"
10#include "ll/api/base/Meta.h"
11
12#include "mc/deps/cereal/schema/dynamic/DynamicValue.h"
13#include "mc/platform/brstd/move_only_function.h"
14
15namespace ll::ui {
16
17// Property, Binding, and Subscription operations must run on the server thread,
18// including releasing the final session-owned handle.
19
20namespace detail {
21class ScreenSessionImpl;
22class BindingHandle;
23struct BindingSlot;
24struct PropertySlot;
25} // namespace detail
26
27using BindingValueTypes = meta::TypeList<double, bool, std::string, cereal::DynamicValue>;
28
29template <class T>
30concept BindingValue = BindingValueTypes::contains<T>;
31
32class Subscription {
33 struct Impl;
34 std::unique_ptr<Impl> impl;
35
36 explicit Subscription(std::unique_ptr<Impl>);
37 friend class detail::ScreenSessionImpl;
38
39public:
40 LLAPI Subscription() noexcept;
41 LLAPI ~Subscription();
42
43 Subscription(Subscription const&) = delete;
44 Subscription& operator=(Subscription const&) = delete;
45
46 LLAPI Subscription(Subscription&&) noexcept;
47 LLAPI Subscription& operator=(Subscription&&) noexcept;
48
49 LLAPI void reset() noexcept;
50
51 [[nodiscard]] LLAPI explicit operator bool() const noexcept;
52};
53
54template <BindingValue T>
55class Binding;
56class Property;
57
58namespace detail {
59
60class BindingHandle {
61 std::weak_ptr<BindingSlot> impl;
62
63 explicit BindingHandle(std::weak_ptr<BindingSlot>);
64 friend class ::ll::ui::Property;
65 friend struct ::ll::ui::detail::BindingSlot;
66 template <BindingValue>
67 friend class ::ll::ui::Binding;
68
69 LLNDAPI Expected<bool> get(bool*) const;
70 LLNDAPI Expected<double> get(double*) const;
71 LLNDAPI Expected<std::string> get(std::string*) const;
72 LLNDAPI Expected<cereal::DynamicValue> get(cereal::DynamicValue*) const;
73
74 LLNDAPI Expected<> set(bool value) const;
75 LLNDAPI Expected<> set(double value) const;
76 LLNDAPI Expected<> set(std::string value) const;
77 LLNDAPI Expected<> set(cereal::DynamicValue value) const;
78
79 LLNDAPI Expected<Subscription> listen(brstd::move_only_function<void(bool const&)> callback) const;
80 LLNDAPI Expected<Subscription> listen(brstd::move_only_function<void(double const&)> callback) const;
81 LLNDAPI Expected<Subscription> listen(brstd::move_only_function<void(std::string const&)> callback) const;
82 LLNDAPI Expected<Subscription> listen(brstd::move_only_function<void(cereal::DynamicValue const&)> callback) const;
83
84public:
85 LLAPI BindingHandle() noexcept;
86 LLAPI ~BindingHandle();
87
88 LLAPI BindingHandle(BindingHandle const&);
89 LLAPI BindingHandle& operator=(BindingHandle const&);
90 LLAPI BindingHandle(BindingHandle&&) noexcept;
91 LLAPI BindingHandle& operator=(BindingHandle&&) noexcept;
92
93 LLNDAPI Expected<> setClientWritable(bool writable) const;
94 LLNDAPI bool isClientWritable() const noexcept;
95
96 [[nodiscard]] LLAPI explicit operator bool() const noexcept;
97};
98
99} // namespace detail
100
101template <BindingValue T>
102class Binding {
104
105 explicit Binding(detail::BindingHandle value) : handle(std::move(value)) {}
106 friend class Property;
107
108public:
109 using Value = T;
110 using Callback = brstd::move_only_function<void(T const&)>;
111
112 Binding() noexcept = default;
113
114 [[nodiscard]] Expected<T> get() const { return handle.get(static_cast<T*>(nullptr)); }
115 [[nodiscard]] Expected<> set(T value) const { return handle.set(std::move(value)); }
116
117 [[nodiscard]] Expected<Subscription> listen(Callback callback) const { return handle.listen(std::move(callback)); }
118
119 [[nodiscard]] Expected<> setClientWritable(bool writable) const { return handle.setClientWritable(writable); }
120 [[nodiscard]] bool isClientWritable() const noexcept { return handle.isClientWritable(); }
121
122 [[nodiscard]] explicit operator bool() const noexcept { return static_cast<bool>(handle); }
123};
124
125class Property {
126 std::weak_ptr<detail::PropertySlot> impl;
127
128 explicit Property(std::weak_ptr<detail::PropertySlot>);
129 LLNDAPI Expected<detail::BindingHandle> bindErased(std::string path, bool*) const;
130 LLNDAPI Expected<detail::BindingHandle> bindErased(std::string path, double*) const;
131 LLNDAPI Expected<detail::BindingHandle> bindErased(std::string path, std::string*) const;
132 LLNDAPI Expected<detail::BindingHandle> bindErased(std::string path, cereal::DynamicValue*) const;
133 Expected<detail::BindingHandle> bindErasedImpl(std::string path, std::size_t type) const;
134
135 friend class detail::ScreenSessionImpl;
136 friend struct detail::PropertySlot;
137 friend class ScreenSession;
138
139public:
140 LLAPI Property() noexcept;
141 LLAPI ~Property();
142
143 LLAPI Property(Property const&);
144 LLAPI Property& operator=(Property const&);
145 LLAPI Property(Property&&) noexcept;
146 LLAPI Property& operator=(Property&&) noexcept;
147
148 LLNDAPI Expected<> set(cereal::DynamicValue const& value) const;
149 LLNDAPI Expected<> setJson(std::string const& json) const;
150 LLNDAPI Expected<> erase() const;
151
152 template <BindingValue T>
153 [[nodiscard]] Expected<Binding<T>> bind(std::string path) const {
154 auto result = bindErased(std::move(path), static_cast<T*>(nullptr));
155 if (!result) {
156 return forwardError(result.error());
157 }
158 return Binding<T>{std::move(result.value())};
159 }
160
161 template <BindingValue T>
162 [[nodiscard]] Expected<Binding<T>> bindClientWritable(std::string path) const {
163 auto result = bind<T>(std::move(path));
164 if (!result) {
165 return forwardError(result.error());
166 }
167 auto binding = std::move(result.value());
168 if (auto writable = binding.setClientWritable(true); !writable) {
169 return forwardError(writable.error());
170 }
171 return binding;
172 }
173
174 [[nodiscard]] LLAPI explicit operator bool() const noexcept;
175};
176
177} // namespace ll::ui
Definition move_only_function.h:9
Definition DynamicValue.h:14
Definition DataStore.h:102
Definition DataStore.h:125
Definition DataStore.h:60
Definition DataStore.h:30