diff --git a/src/libutil/fmt.cc b/src/libutil/fmt.cc new file mode 100644 index 000000000..400fb7ea0 --- /dev/null +++ b/src/libutil/fmt.cc @@ -0,0 +1,14 @@ +#include "fmt.hh" // IWYU pragma: keep + +template class boost::basic_format; + +namespace nix { + +// Explicit instantiation saves about 30 cpu-seconds of compile time +template HintFmt::HintFmt(const std::string &, const Uncolored &s); +template HintFmt::HintFmt(const std::string &, const std::string &s); +template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &); + +HintFmt::HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {} + +} diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh index d015f7e5f..7589e51e2 100644 --- a/src/libutil/fmt.hh +++ b/src/libutil/fmt.hh @@ -3,7 +3,6 @@ #include #include -#include #include // Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace. #if __APPLE__ || __FreeBSD__ @@ -12,6 +11,9 @@ #include #include "ansicolor.hh" +// Explicit instantiation in fmt.cc +extern template class boost::basic_format; + namespace nix { /** @@ -157,7 +159,9 @@ public: * Format the given string literally, without interpolating format * placeholders. */ - HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {} + // Moved out of line because it was instantiating the template below in + // every file in the project. + HintFmt(const std::string & literal); /** * Interpolate the given arguments into the format string. @@ -193,6 +197,11 @@ public: } }; +// Explicit instantiations in fmt.cc +extern template HintFmt::HintFmt(const std::string &, const Uncolored &s); +extern template HintFmt::HintFmt(const std::string &, const std::string &s); +extern template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * const &); + std::ostream & operator<<(std::ostream & os, const HintFmt & hf); } diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 7c0e45e4b..e7f986363 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -17,6 +17,7 @@ libutil_sources = files( 'experimental-features.cc', 'file-descriptor.cc', 'file-system.cc', + 'fmt.cc', 'git.cc', 'hash.cc', 'hilite.cc', diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index a6dd7e200..4eda1b7e7 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -9,6 +9,31 @@ namespace nix { +template +T readNum(Source & source) +{ + unsigned char buf[8]; + source(charptr_cast(buf), sizeof(buf)); + + auto n = readLittleEndian(buf); + + if (n > (uint64_t) std::numeric_limits::max()) + throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name()); + + return (T) n; +} + +template bool readNum(Source & source); + +template unsigned char readNum(Source & source); + +template unsigned int readNum(Source & source); + +template unsigned long readNum(Source & source); +template long readNum(Source & source); + +template unsigned long long readNum(Source & source); +template long long readNum(Source & source); void BufferedSink::operator () (std::string_view data) { diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index d6a22b3e9..9ad8018d0 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -450,19 +450,7 @@ inline Sink & operator<<(Sink & sink, const Error & ex) MakeError(SerialisationError, Error); template -T readNum(Source & source) -{ - unsigned char buf[8]; - source(charptr_cast(buf), sizeof(buf)); - - auto n = readLittleEndian(buf); - - if (n > (uint64_t) std::numeric_limits::max()) - throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name()); - - return (T) n; -} - +T readNum(Source & source); inline unsigned int readInt(Source & source) {