diff options
Diffstat (limited to 'src/libstore/worker-protocol.hh')
-rw-r--r-- | src/libstore/worker-protocol.hh | 109 |
1 files changed, 55 insertions, 54 deletions
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 13cf8d4ab..b3705578e 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -6,7 +6,7 @@ namespace nix { #define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_2 0x6478696f -#define PROTOCOL_VERSION 0x118 +#define PROTOCOL_VERSION 0x11a #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) @@ -18,7 +18,7 @@ typedef enum { wopQueryReferences = 5, // obsolete wopQueryReferrers = 6, wopAddToStore = 7, - wopAddTextToStore = 8, + wopAddTextToStore = 8, // obsolete since 1.25, Nix 3.0. Use wopAddToStore wopBuildPaths = 9, wopEnsurePath = 10, wopAddTempRoot = 11, @@ -66,10 +66,6 @@ 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); - /* To guide overloading */ template<typename T> struct Phantom {}; @@ -78,76 +74,81 @@ struct Phantom {}; namespace worker_proto { /* FIXME maybe move more stuff inside here */ -StorePath read(const Store & store, Source & from, Phantom<StorePath> _); -void write(const Store & store, Sink & out, const StorePath & storePath); +#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) -template<typename T> -std::map<std::string, T> read(const Store & store, Source & from, Phantom<std::map<std::string, T>> _); -template<typename T> -void write(const Store & store, Sink & out, const std::map<string, T> & resMap); -template<typename T> -std::optional<T> read(const Store & store, Source & from, Phantom<std::optional<T>> _); -template<typename T> -void write(const Store & store, Sink & out, const std::optional<T> & optVal); +MAKE_WORKER_PROTO(, std::string); +MAKE_WORKER_PROTO(, StorePath); +MAKE_WORKER_PROTO(, ContentAddress); -/* Specialization which uses and empty string for the empty case, taking - advantage of the fact StorePaths always serialize to a non-empty string. - This is done primarily for backwards compatability, so that StorePath <= - std::optional<StorePath>, where <= is the compatability partial order. +MAKE_WORKER_PROTO(template<typename T>, std::set<T>); + +#define X_ template<typename K, typename V> +#define Y_ std::map<K, V> +MAKE_WORKER_PROTO(X_, Y_); +#undef X_ +#undef Y_ + +/* These use the empty string for the null case, relying on the fact + that the underlying types never serialize to the empty string. + + We do this instead of a generic std::optional<T> instance because + ordinal tags (0 or 1, here) are a bit of a compatability hazard. For + the same reason, we don't have a std::variant<T..> instances (ordinal + tags 0...n). + + We could the generic instances and then these as specializations for + compatability, but that's proven a bit finnicky, and also makes the + worker protocol harder to implement in other languages where such + specializations may not be allowed. */ -template<> -void write(const Store & store, Sink & out, const std::optional<StorePath> & optVal); +MAKE_WORKER_PROTO(, std::optional<StorePath>); +MAKE_WORKER_PROTO(, std::optional<ContentAddress>); template<typename T> -std::map<std::string, T> read(const Store & store, Source & from, Phantom<std::map<std::string, T>> _) +std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _) { - std::map<string, T> resMap; - auto size = (size_t)readInt(from); + std::set<T> resSet; + auto size = readNum<size_t>(from); while (size--) { - auto thisKey = readString(from); - resMap.insert_or_assign(std::move(thisKey), nix::worker_proto::read(store, from, Phantom<T> {})); + resSet.insert(read(store, from, Phantom<T> {})); } - return resMap; + return resSet; } template<typename T> -void write(const Store & store, Sink & out, const std::map<string, T> & resMap) +void write(const Store & store, Sink & out, const std::set<T> & resSet) { - out << resMap.size(); - for (auto & i : resMap) { - out << i.first; - nix::worker_proto::write(store, out, i.second); + out << resSet.size(); + for (auto & key : resSet) { + write(store, out, key); } } -template<typename T> -std::optional<T> read(const Store & store, Source & from, Phantom<std::optional<T>> _) +template<typename K, typename V> +std::map<K, V> read(const Store & store, Source & from, Phantom<std::map<K, V>> _) { - auto tag = readNum<uint8_t>(from); - switch (tag) { - case 0: - return std::nullopt; - case 1: - return nix::worker_proto::read(store, from, Phantom<T> {}); - default: - throw Error("got an invalid tag bit for std::optional: %#04x", tag); + 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> {}); + resMap.insert_or_assign(std::move(k), std::move(v)); } + return resMap; } -template<typename T> -void write(const Store & store, Sink & out, const std::optional<T> & optVal) +template<typename K, typename V> +void write(const Store & store, Sink & out, const std::map<K, V> & resMap) { - out << (optVal ? 1 : 0); - if (optVal) - nix::worker_proto::write(store, out, *optVal); + out << resMap.size(); + for (auto & i : resMap) { + write(store, out, i.first); + write(store, out, i.second); + } } - } - -StorePathCAMap readStorePathCAMap(const Store & store, Source & from); - -void writeStorePathCAMap(const Store & store, Sink & out, const StorePathCAMap & paths); - } |