Skip to content

Commit

Permalink
Merge pull request #4120 from obsidiansystems/no-poly-sum-worker-proto
Browse files Browse the repository at this point in the history
Remove generic std::optional<T> suppport from worker proto
  • Loading branch information
edolstra committed Oct 7, 2020
2 parents d761485 + 57d960d commit 5257a25
Showing 1 changed file with 16 additions and 32 deletions.
48 changes: 16 additions & 32 deletions src/libstore/worker-protocol.hh
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,29 @@ MAKE_WORKER_PROTO(, StorePath);
MAKE_WORKER_PROTO(, ContentAddress);

MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
MAKE_WORKER_PROTO(template<typename T>, std::optional<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.
*/
MAKE_WORKER_PROTO(, std::optional<StorePath>);
MAKE_WORKER_PROTO(, std::optional<ContentAddress>);

template<typename T>
std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _)
{
Expand Down Expand Up @@ -134,37 +149,6 @@ void write(const Store & store, Sink & out, const std::map<K, V> & resMap)
}
}

template<typename T>
std::optional<T> read(const Store & store, Source & from, Phantom<std::optional<T>> _)
{
auto tag = readNum<uint8_t>(from);
switch (tag) {
case 0:
return std::nullopt;
case 1:
return read(store, from, Phantom<T> {});
default:
throw Error("got an invalid tag bit for std::optional: %#04x", (size_t)tag);
}
}

template<typename T>
void write(const Store & store, Sink & out, const std::optional<T> & optVal)
{
out << (uint64_t) (optVal ? 1 : 0);
if (optVal)
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<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>);

}

}

0 comments on commit 5257a25

Please sign in to comment.