#pragma once namespace nix { #define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_2 0x6478696f #define PROTOCOL_VERSION 0x119 #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) typedef enum { wopIsValidPath = 1, wopHasSubstitutes = 3, wopQueryPathHash = 4, // obsolete wopQueryReferences = 5, // obsolete wopQueryReferrers = 6, wopAddToStore = 7, wopAddTextToStore = 8, // obsolete since 1.25, Nix 3.0. Use wopAddToStore wopBuildPaths = 9, wopEnsurePath = 10, wopAddTempRoot = 11, wopAddIndirectRoot = 12, wopSyncWithGC = 13, wopFindRoots = 14, wopExportPath = 16, // obsolete wopQueryDeriver = 18, // obsolete wopSetOptions = 19, wopCollectGarbage = 20, wopQuerySubstitutablePathInfo = 21, wopQueryDerivationOutputs = 22, // obsolete wopQueryAllValidPaths = 23, wopQueryFailedPaths = 24, wopClearFailedPaths = 25, wopQueryPathInfo = 26, wopImportPaths = 27, // obsolete wopQueryDerivationOutputNames = 28, // obsolete wopQueryPathFromHashPart = 29, wopQuerySubstitutablePathInfos = 30, wopQueryValidPaths = 31, wopQuerySubstitutablePaths = 32, wopQueryValidDerivers = 33, wopOptimiseStore = 34, wopVerifyStore = 35, wopBuildDerivation = 36, wopAddSignatures = 37, wopNarFromPath = 38, wopAddToStoreNar = 39, wopQueryMissing = 40, wopQueryDerivationOutputMap = 41, } WorkerOp; #define STDERR_NEXT 0x6f6c6d67 #define STDERR_READ 0x64617461 // data needed from source #define STDERR_WRITE 0x64617416 // data for sink #define STDERR_LAST 0x616c7473 #define STDERR_ERROR 0x63787470 #define STDERR_START_ACTIVITY 0x53545254 #define STDERR_STOP_ACTIVITY 0x53544f50 #define STDERR_RESULT 0x52534c54 class Store; struct Source; /* To guide overloading */ template struct Phantom {}; 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(template, std::set); MAKE_WORKER_PROTO(template, std::optional); #define X_ template #define Y_ std::map MAKE_WORKER_PROTO(X_, Y_); #undef X_ #undef Y_ template std::set read(const Store & store, Source & from, Phantom> _) { std::set resSet; auto size = readNum(from); while (size--) { resSet.insert(read(store, from, Phantom {})); } return resSet; } template void write(const Store & store, Sink & out, const std::set & resSet) { out << resSet.size(); for (auto & key : resSet) { write(store, out, key); } } template std::map read(const Store & store, Source & from, Phantom> _) { std::map resMap; auto size = readNum(from); while (size--) { auto k = read(store, from, Phantom {}); auto v = read(store, from, Phantom {}); resMap.insert_or_assign(std::move(k), std::move(v)); } return resMap; } template void write(const Store & store, Sink & out, const std::map & resMap) { out << resMap.size(); for (auto & i : resMap) { write(store, out, i.first); write(store, out, i.second); } } template std::optional read(const Store & store, Source & from, Phantom> _) { auto tag = readNum(from); switch (tag) { case 0: return std::nullopt; case 1: return read(store, from, Phantom {}); default: throw Error("got an invalid tag bit for std::optional: %#04x", (size_t)tag); } } template void write(const Store & store, Sink & out, const std::optional & optVal) { out << (uint64_t) (optVal ? 1 : 0); if (optVal) nix::worker_proto::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, where <= is the compatability partial order, T is one of the types below. */ MAKE_WORKER_PROTO(, std::optional); MAKE_WORKER_PROTO(, std::optional); } }