1 #ifndef INCLUDED_IMPORTEXPORT_H
2 #define INCLUDED_IMPORTEXPORT_H
4 #include "generic/callback.h"
5 #include "string/string.h"
9 // todo: just return T, don't use continuation passing style
10 Callback<void(const Callback<void(T)> &returnz)> get;
11 Callback<void(T value)> set;
16 template<class Self, class T = Self>
18 static void Export(const Self &self, const Callback<void(T)> &returnz) {
22 static void Import(Self &self, T value) {
30 using propertyimpl_self = typename std::remove_reference<get_argument<decltype(&I::Import), 0>>::type;
33 using propertyimpl_other = get_argument<decltype(&I::Import), 1>;
36 using propertyimpl_other_free = get_argument<decltype(&I::Import), 0>;
45 class I = PropertyImpl<Self, T>
47 struct PropertyAdaptor {
51 using Get = ConstReferenceCaller<Self, void(const Callback<void(T)> &), I::Export>;
52 using Set = ReferenceCaller<Self, void(T), I::Import>;
59 struct PropertyAdaptorFree {
62 using Get = FreeCaller<void(const Callback<void(T)> &), I::Export>;
63 using Set = FreeCaller<void(T), I::Import>;
69 Property<typename A::Other> make_property(typename A::Type &self) {
70 return {typename A::Get(self), typename A::Set(self)};
74 Property<typename A::Other> make_property() {
75 return {typename A::Get(), typename A::Set()};
80 template<class I, class Self = detail::propertyimpl_self<I>, class T = detail::propertyimpl_other<I>>
81 using property_impl = PropertyAdaptor<Self, T, I>;
83 template<class I, class Self, class T = detail::propertyimpl_other<I>>
84 Property<T> make_property(Self &self) {
85 return make_property<property_impl<I>>(self);
88 template<class I, class T = detail::propertyimpl_other_free<I>>
89 using property_impl_free = PropertyAdaptorFree<T, I>;
91 template<class I, class T = detail::propertyimpl_other_free<I>>
92 Property<T> make_property() {
93 return make_property<property_impl_free<I>>();
98 template<class Self, class T = Self>
99 Property<T> make_property(Self &self) {
100 return make_property<PropertyAdaptor<Self, T>>(self);
105 template<typename DST, typename SRC, typename X, typename A>
106 struct make_property_chain_I_1 {
107 static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
108 PropertyImpl<SRC, DST>::Export(value, self);
111 static void Export(const X &self, const Callback<void(DST)> &returnz) {
112 A::Get::thunk_(self, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
115 static void Import(X &self, DST value) {
117 PropertyImpl<SRC, DST>::Import(out, value);
118 A::Set::thunk_(self, out);
122 template<class I_Outer, class I_Inner>
123 Property<detail::propertyimpl_other<I_Outer>> make_property_chain(detail::propertyimpl_self<I_Inner> &it) {
124 using DST = detail::propertyimpl_other<I_Outer>;
125 using SRC = detail::propertyimpl_self<I_Outer>;
126 using X = detail::propertyimpl_self<I_Inner>;
128 using A = property_impl<I_Inner>;
129 using I = make_property_chain_I_1<DST, SRC, X, A>;
130 return make_property<PropertyAdaptor<X, DST, I>>(it);
133 template<typename DST, typename SRC, typename A>
134 struct make_property_chain_I_2 {
135 static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
136 PropertyImpl<SRC, DST>::Export(value, self);
139 static void Export(const Callback<void(DST)> &returnz) {
140 A::Get::thunk_(nullptr, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
143 static void Import(DST value) {
145 PropertyImpl<SRC, DST>::Import(out, value);
146 A::Set::thunk_(nullptr, out);
150 template<class I_Outer, class I_Inner>
151 Property<detail::propertyimpl_other<I_Outer>> make_property_chain() {
152 using DST = detail::propertyimpl_other<I_Outer>;
153 using SRC = detail::propertyimpl_self<I_Outer>;
155 using A = property_impl_free<I_Inner>;
156 using I = make_property_chain_I_2<DST, SRC, A>;
158 return make_property<PropertyAdaptorFree<DST, I>>();
164 struct PropertyImpl<CopiedString, const char *> {
165 static void Export(const CopiedString &self, const Callback<void(const char *)> &returnz) {
166 returnz(self.c_str());
169 static void Import(CopiedString &self, const char *value) {