aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/types.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/types.hh')
-rw-r--r--src/libutil/types.hh82
1 files changed, 69 insertions, 13 deletions
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 9c85fef62..00ba567c6 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -6,26 +6,23 @@
#include <set>
#include <string>
#include <map>
+#include <variant>
#include <vector>
namespace nix {
-using std::list;
-using std::set;
-using std::vector;
-using std::string;
-
-typedef list<string> Strings;
-typedef set<string> StringSet;
-typedef std::map<string, string> StringMap;
+typedef std::list<std::string> Strings;
+typedef std::set<std::string> StringSet;
+typedef std::map<std::string, std::string> StringMap;
+typedef std::map<std::string, std::string> StringPairs;
/* Paths are just strings. */
+typedef std::string Path;
+typedef std::string_view PathView;
+typedef std::list<Path> Paths;
+typedef std::set<Path> PathSet;
-typedef string Path;
-typedef list<Path> Paths;
-typedef set<Path> PathSet;
-
-typedef vector<std::pair<string, string>> Headers;
+typedef std::vector<std::pair<std::string, std::string>> Headers;
/* Helper class to run code at startup. */
template<typename T>
@@ -46,4 +43,63 @@ struct Explicit {
}
};
+
+/* This wants to be a little bit like rust's Cow type.
+ Some parts of the evaluator benefit greatly from being able to reuse
+ existing allocations for strings, but have to be able to also use
+ newly allocated storage for values.
+
+ We do not define implicit conversions, even with ref qualifiers,
+ since those can easily become ambiguous to the reader and can degrade
+ into copying behaviour we want to avoid. */
+class BackedStringView {
+private:
+ std::variant<std::string, std::string_view> data;
+
+ /* Needed to introduce a temporary since operator-> must return
+ a pointer. Without this we'd need to store the view object
+ even when we already own a string. */
+ class Ptr {
+ private:
+ std::string_view view;
+ public:
+ Ptr(std::string_view view): view(view) {}
+ const std::string_view * operator->() const { return &view; }
+ };
+
+public:
+ BackedStringView(std::string && s): data(std::move(s)) {}
+ BackedStringView(std::string_view sv): data(sv) {}
+ template<size_t N>
+ BackedStringView(const char (& lit)[N]): data(std::string_view(lit)) {}
+
+ BackedStringView(const BackedStringView &) = delete;
+ BackedStringView & operator=(const BackedStringView &) = delete;
+
+ /* We only want move operations defined since the sole purpose of
+ this type is to avoid copies. */
+ BackedStringView(BackedStringView && other) = default;
+ BackedStringView & operator=(BackedStringView && other) = default;
+
+ bool isOwned() const
+ {
+ return std::holds_alternative<std::string>(data);
+ }
+
+ std::string toOwned() &&
+ {
+ return isOwned()
+ ? std::move(std::get<std::string>(data))
+ : std::string(std::get<std::string_view>(data));
+ }
+
+ std::string_view operator*() const
+ {
+ return isOwned()
+ ? std::get<std::string>(data)
+ : std::get<std::string_view>(data);
+ }
+ Ptr operator->() const { return Ptr(**this); }
+};
+
}