diff options
Diffstat (limited to 'src/libstore/worker-protocol.hh')
-rw-r--r-- | src/libstore/worker-protocol.hh | 108 |
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>); } |