1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-30 03:23:16 +02:00

Merge remote-tracking branch 'origin/master' into flakes

This commit is contained in:
Eelco Dolstra 2019-12-11 14:53:30 +01:00
commit ecb3a1afa2
119 changed files with 3905 additions and 2250 deletions

View file

@ -1,12 +1,18 @@
#include "logging.hh"
#include "rust-ffi.hh"
namespace nix {
extern "C" std::exception_ptr * make_error(rust::StringSlice s)
{
// FIXME: leak
return new std::exception_ptr(std::make_exception_ptr(Error(std::string(s.ptr, s.size))));
return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size))));
}
namespace rust {
std::ostream & operator << (std::ostream & str, const String & s)
{
str << (std::string_view) s;
return str;
}
}

View file

@ -1,16 +1,91 @@
#pragma once
#include "serialise.hh"
#include <string_view>
#include <cstring>
#include <array>
namespace rust {
// Depending on the internal representation of Rust slices is slightly
// evil...
typedef void (*DropFun)(void *);
/* A Rust value of N bytes. It can be moved but not copied. When it
goes out of scope, the C++ destructor will run the drop
function. */
template<std::size_t N, DropFun drop>
struct Value
{
protected:
std::array<char, N> raw;
~Value()
{
if (!isEvacuated()) {
drop(this);
evacuate();
}
}
// Must not be called directly.
Value()
{ }
Value(Value && other)
: raw(other.raw)
{
other.evacuate();
}
void operator =(Value && other)
{
if (!isEvacuated())
drop(this);
raw = other.raw;
other.evacuate();
}
private:
/* FIXME: optimize these (ideally in such a way that the compiler
can elide most calls to evacuate() / isEvacuated(). */
inline void evacuate()
{
for (auto & i : raw) i = 0;
}
inline bool isEvacuated()
{
for (auto & i : raw)
if (i != 0) return false;
return true;
}
};
/* A Rust vector. */
template<typename T, DropFun drop>
struct Vec : Value<3 * sizeof(void *), drop>
{
inline size_t size() const
{
return ((const size_t *) &this->raw)[2];
}
const T * data() const
{
return ((const T * *) &this->raw)[0];
}
};
/* A Rust slice. */
template<typename T>
struct Slice
{
T * ptr;
const T * ptr;
size_t size;
Slice(T * ptr, size_t size) : ptr(ptr), size(size)
Slice(const T * ptr, size_t size) : ptr(ptr), size(size)
{
assert(ptr);
}
@ -18,9 +93,44 @@ struct Slice
struct StringSlice : Slice<char>
{
StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {}
StringSlice(const std::string & s): Slice(s.data(), s.size()) {}
explicit StringSlice(std::string_view s): Slice(s.data(), s.size()) {}
StringSlice(const char * s): Slice(s, strlen(s)) {}
operator std::string_view() const
{
return std::string_view(ptr, size);
}
};
/* A Rust string. */
struct String;
extern "C" {
void ffi_String_new(StringSlice s, String * out);
void ffi_String_drop(void * s);
}
struct String : Vec<char, ffi_String_drop>
{
String(std::string_view s)
{
ffi_String_new(StringSlice(s), this);
}
String(const char * s)
: String({s, std::strlen(s)})
{
}
operator std::string_view() const
{
return std::string_view(data(), size());
}
};
std::ostream & operator << (std::ostream & str, const String & s);
struct Source
{
size_t (*fun)(void * source_this, rust::Slice<uint8_t> data);
@ -33,7 +143,7 @@ struct Source
// FIXME: how to propagate exceptions?
static size_t sourceWrapper(void * _this, rust::Slice<uint8_t> data)
{
auto n = ((nix::Source *) _this)->read(data.ptr, data.size);
auto n = ((nix::Source *) _this)->read((unsigned char *) data.ptr, data.size);
return n;
}
};
@ -49,11 +159,20 @@ struct Result
std::exception_ptr * exc;
};
~Result()
{
if (tag == 0)
data.~T();
else if (tag == 1)
// FIXME: don't leak exc
;
}
/* Rethrow the wrapped exception or return the wrapped value. */
T unwrap()
{
if (tag == 0)
return data;
return std::move(data);
else if (tag == 1)
std::rethrow_exception(*exc);
else

View file

@ -17,7 +17,7 @@ void unpackTarfile(Source & source, const Path & destDir)
void unpackTarfile(const Path & tarFile, const Path & destDir,
std::optional<std::string> baseName)
{
if (!baseName) baseName = baseNameOf(tarFile);
if (!baseName) baseName = std::string(baseNameOf(tarFile));
auto source = sinkToSource([&](Sink & sink) {
// FIXME: look at first few bytes to determine compression type.

View file

@ -189,22 +189,22 @@ Path dirOf(const Path & path)
}
string baseNameOf(const Path & path)
std::string_view baseNameOf(std::string_view path)
{
if (path.empty())
return "";
Path::size_type last = path.length() - 1;
auto last = path.size() - 1;
if (path[last] == '/' && last > 0)
last -= 1;
Path::size_type pos = path.rfind('/', last);
auto pos = path.rfind('/', last);
if (pos == string::npos)
pos = 0;
else
pos += 1;
return string(path, pos, last - pos + 1);
return path.substr(pos, last - pos + 1);
}
@ -1307,9 +1307,10 @@ bool hasPrefix(const string & s, const string & prefix)
}
bool hasSuffix(const string & s, const string & suffix)
bool hasSuffix(std::string_view s, std::string_view suffix)
{
return s.size() >= suffix.size() && string(s, s.size() - suffix.size()) == suffix;
return s.size() >= suffix.size()
&& s.substr(s.size() - suffix.size()) == suffix;
}

View file

@ -62,7 +62,7 @@ Path dirOf(const Path & path);
/* Return the base name of the given canonical path, i.e., everything
following the final `/'. */
string baseNameOf(const Path & path);
std::string_view baseNameOf(std::string_view path);
/* Check whether 'path' is a descendant of 'dir'. */
bool isInDir(const Path & path, const Path & dir);
@ -431,7 +431,7 @@ bool hasPrefix(const string & s, const string & prefix);
/* Return true iff `s' ends in `suffix'. */
bool hasSuffix(const string & s, const string & suffix);
bool hasSuffix(std::string_view s, std::string_view suffix);
/* Convert a string to lower case. */
@ -474,10 +474,10 @@ string base64Decode(const string & s);
/* Get a value for the specified key from an associate container, or a
default value if the key doesn't exist. */
template <class T>
string get(const T & map, const string & key, const string & def = "")
std::optional<std::string> get(const T & map, const std::string & key)
{
auto i = map.find(key);
return i == map.end() ? def : i->second;
return i == map.end() ? std::optional<std::string>() : i->second;
}