diff options
author | Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> | 2023-05-22 09:34:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-22 09:34:34 +0200 |
commit | 673fe85976b00a6324697b2db4a5d12a7ef57829 (patch) | |
tree | 323d9ae0cd54ec82c3316d0f29845fc21f03c3ec /src/libstore/worker-protocol.hh | |
parent | 3305fd0cb199d1c5e9e53971769960e629493211 (diff) | |
parent | cb5052d98fa9a5d64d1700fe434c1c37a72e45d1 (diff) |
Merge pull request #8365 from obsidiansystems/proto-structs
Revert "Revert "Use template structs instead of phantoms""
Diffstat (limited to 'src/libstore/worker-protocol.hh')
-rw-r--r-- | src/libstore/worker-protocol.hh | 115 |
1 files changed, 73 insertions, 42 deletions
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index fa7202ae6..f06332d17 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -88,40 +88,71 @@ enum TrustedFlag : bool; /** - * Used to guide overloading + * Data type for canonical pairs of serializers for the worker protocol. * * See https://en.cppreference.com/w/cpp/language/adl for the broader * concept of what is going on here. */ template<typename T> -struct Phantom {}; +struct WorkerProto { + static T read(const Store & store, Source & from); + static void write(const Store & store, Sink & out, const T & t); +}; +/** + * Wrapper function around `WorkerProto<T>::write` that allows us to + * infer the type instead of having to write it down explicitly. + */ +template<typename T> +void workerProtoWrite(const Store & store, Sink & out, const T & t) +{ + WorkerProto<T>::write(store, out, t); +} -namespace worker_proto { -/* FIXME maybe move more stuff inside here */ - -#define MAKE_WORKER_PROTO(TEMPLATE, T) \ - TEMPLATE T read(const Store & store, Source & from, Phantom< T > _); \ - TEMPLATE void write(const Store & store, Sink & out, const T & str) - -MAKE_WORKER_PROTO(, std::string); -MAKE_WORKER_PROTO(, StorePath); -MAKE_WORKER_PROTO(, ContentAddress); -MAKE_WORKER_PROTO(, DerivedPath); -MAKE_WORKER_PROTO(, Realisation); -MAKE_WORKER_PROTO(, DrvOutput); -MAKE_WORKER_PROTO(, BuildResult); -MAKE_WORKER_PROTO(, KeyedBuildResult); -MAKE_WORKER_PROTO(, std::optional<TrustedFlag>); +/** + * Declare a canonical serializer pair for the worker protocol. + * + * We specialize the struct merely to indicate that we are implementing + * the function for the given type. + * + * Some sort of `template<...>` must be used with the caller for this to + * be legal specialization syntax. See below for what that looks like in + * practice. + */ +#define MAKE_WORKER_PROTO(T) \ + struct WorkerProto< T > { \ + static T read(const Store & store, Source & from); \ + static void write(const Store & store, Sink & out, const T & t); \ + }; + +template<> +MAKE_WORKER_PROTO(std::string); +template<> +MAKE_WORKER_PROTO(StorePath); +template<> +MAKE_WORKER_PROTO(ContentAddress); +template<> +MAKE_WORKER_PROTO(DerivedPath); +template<> +MAKE_WORKER_PROTO(Realisation); +template<> +MAKE_WORKER_PROTO(DrvOutput); +template<> +MAKE_WORKER_PROTO(BuildResult); +template<> +MAKE_WORKER_PROTO(KeyedBuildResult); +template<> +MAKE_WORKER_PROTO(std::optional<TrustedFlag>); -MAKE_WORKER_PROTO(template<typename T>, std::vector<T>); -MAKE_WORKER_PROTO(template<typename T>, std::set<T>); +template<typename T> +MAKE_WORKER_PROTO(std::vector<T>); +template<typename T> +MAKE_WORKER_PROTO(std::set<T>); -#define X_ template<typename K, typename V> -#define Y_ std::map<K, V> -MAKE_WORKER_PROTO(X_, Y_); +template<typename K, typename V> +#define X_ std::map<K, V> +MAKE_WORKER_PROTO(X_); #undef X_ -#undef Y_ /** * These use the empty string for the null case, relying on the fact @@ -137,72 +168,72 @@ MAKE_WORKER_PROTO(X_, Y_); * worker protocol harder to implement in other languages where such * specializations may not be allowed. */ -MAKE_WORKER_PROTO(, std::optional<StorePath>); -MAKE_WORKER_PROTO(, std::optional<ContentAddress>); +template<> +MAKE_WORKER_PROTO(std::optional<StorePath>); +template<> +MAKE_WORKER_PROTO(std::optional<ContentAddress>); template<typename T> -std::vector<T> read(const Store & store, Source & from, Phantom<std::vector<T>> _) +std::vector<T> WorkerProto<std::vector<T>>::read(const Store & store, Source & from) { std::vector<T> resSet; auto size = readNum<size_t>(from); while (size--) { - resSet.push_back(read(store, from, Phantom<T> {})); + resSet.push_back(WorkerProto<T>::read(store, from)); } return resSet; } template<typename T> -void write(const Store & store, Sink & out, const std::vector<T> & resSet) +void WorkerProto<std::vector<T>>::write(const Store & store, Sink & out, const std::vector<T> & resSet) { out << resSet.size(); for (auto & key : resSet) { - write(store, out, key); + WorkerProto<T>::write(store, out, key); } } template<typename T> -std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _) +std::set<T> WorkerProto<std::set<T>>::read(const Store & store, Source & from) { std::set<T> resSet; auto size = readNum<size_t>(from); while (size--) { - resSet.insert(read(store, from, Phantom<T> {})); + resSet.insert(WorkerProto<T>::read(store, from)); } return resSet; } template<typename T> -void write(const Store & store, Sink & out, const std::set<T> & resSet) +void WorkerProto<std::set<T>>::write(const Store & store, Sink & out, const std::set<T> & resSet) { out << resSet.size(); for (auto & key : resSet) { - write(store, out, key); + WorkerProto<T>::write(store, out, key); } } template<typename K, typename V> -std::map<K, V> read(const Store & store, Source & from, Phantom<std::map<K, V>> _) +std::map<K, V> WorkerProto<std::map<K, V>>::read(const Store & store, Source & from) { std::map<K, V> resMap; auto size = readNum<size_t>(from); while (size--) { - auto k = read(store, from, Phantom<K> {}); - auto v = read(store, from, Phantom<V> {}); + auto k = WorkerProto<K>::read(store, from); + auto v = WorkerProto<V>::read(store, from); resMap.insert_or_assign(std::move(k), std::move(v)); } return resMap; } template<typename K, typename V> -void write(const Store & store, Sink & out, const std::map<K, V> & resMap) +void WorkerProto<std::map<K, V>>::write(const Store & store, Sink & out, const std::map<K, V> & resMap) { out << resMap.size(); for (auto & i : resMap) { - write(store, out, i.first); - write(store, out, i.second); + WorkerProto<K>::write(store, out, i.first); + WorkerProto<V>::write(store, out, i.second); } } } - -} |