aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/worker-protocol.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/worker-protocol.hh')
-rw-r--r--src/libstore/worker-protocol.hh108
1 files changed, 99 insertions, 9 deletions
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 5eddaff56..2c8cb2e77 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -66,14 +66,104 @@ typedef enum {
class Store;
struct Source;
-template<class T> T readStorePaths(const Store & store, Source & from);
-
-void writeStorePaths(const Store & store, Sink & out, const StorePathSet & paths);
-
-StorePathCAMap readStorePathCAMap(const Store & store, Source & from);
-
-void writeStorePathCAMap(const Store & store, Sink & out, const StorePathCAMap & paths);
-
-void writeOutputPathMap(const Store & store, Sink & out, const OutputPathMap & paths);
+template<typename T>
+struct WorkerProto {
+ static T read(const Store & store, Source & from);
+ static void write(const Store & store, Sink & out, const T & t);
+};
+
+#define MAKE_WORKER_PROTO(T) \
+ template<> \
+ struct WorkerProto< T > { \
+ static T read(const Store & store, Source & from); \
+ static void write(const Store & store, Sink & out, const T & t); \
+ }
+
+MAKE_WORKER_PROTO(std::string);
+MAKE_WORKER_PROTO(StorePath);
+MAKE_WORKER_PROTO(ContentAddress);
+
+template<typename T>
+struct WorkerProto<std::set<T>> {
+
+ static std::set<T> read(const Store & store, Source & from)
+ {
+ std::set<T> resSet;
+ auto size = readNum<size_t>(from);
+ while (size--) {
+ resSet.insert(WorkerProto<T>::read(store, from));
+ }
+ return resSet;
+ }
+
+ static void write(const Store & store, Sink & out, const std::set<T> & resSet)
+ {
+ out << resSet.size();
+ for (auto & key : resSet) {
+ WorkerProto<T>::write(store, out, key);
+ }
+ }
+
+};
+
+template<typename K, typename V>
+struct WorkerProto<std::map<K, V>> {
+
+ static 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 = WorkerProto<K>::read(store, from);
+ auto v = WorkerProto<V>::read(store, from);
+ resMap.insert_or_assign(std::move(k), std::move(v));
+ }
+ return resMap;
+ }
+
+ static void write(const Store & store, Sink & out, const std::map<K, V> & resMap)
+ {
+ out << resMap.size();
+ for (auto & i : resMap) {
+ WorkerProto<K>::write(store, out, i.first);
+ WorkerProto<V>::write(store, out, i.second);
+ }
+ }
+
+};
+
+template<typename T>
+struct WorkerProto<std::optional<T>> {
+
+ static std::optional<T> read(const Store & store, Source & from)
+ {
+ auto tag = readNum<uint8_t>(from);
+ switch (tag) {
+ case 0:
+ return std::nullopt;
+ case 1:
+ return WorkerProto<T>::read(store, from);
+ default:
+ throw Error("got an invalid tag bit for std::optional: %#04x", (size_t)tag);
+ }
+ }
+
+ static void write(const Store & store, Sink & out, const std::optional<T> & optVal)
+ {
+ out << (uint64_t) (optVal ? 1 : 0);
+ if (optVal)
+ WorkerProto<T>::write(store, out, *optVal);
+ }
+
+};
+
+/* Specialization which uses and empty string for the empty case, taking
+ advantage of the fact these types always serialize to non-empty strings.
+ This is done primarily for backwards compatability, so that T <=
+ std::optional<T>, where <= is the compatability partial order, T is one of
+ the types below.
+ */
+MAKE_WORKER_PROTO(std::optional<StorePath>);
+MAKE_WORKER_PROTO(std::optional<ContentAddress>);
}