diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libutil/rust-ffi.cc | 6 | ||||
-rw-r--r-- | src/libutil/rust-ffi.hh | 31 |
2 files changed, 30 insertions, 7 deletions
diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc index accc5e22b..6f36b3192 100644 --- a/src/libutil/rust-ffi.cc +++ b/src/libutil/rust-ffi.cc @@ -3,10 +3,14 @@ extern "C" std::exception_ptr * make_error(rust::StringSlice s) { - // FIXME: leak return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size)))); } +extern "C" void destroy_error(std::exception_ptr * ex) +{ + free(ex); +} + namespace rust { std::ostream & operator << (std::ostream & str, const String & s) diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index 1466eabec..4fecce606 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -152,28 +152,47 @@ struct Source template<typename T> struct Result { - unsigned int tag; + enum { Ok = 0, Err = 1, Uninit = 2 } tag; union { T data; std::exception_ptr * exc; }; + Result() : tag(Uninit) { }; // FIXME: remove + + Result(const Result &) = delete; + + Result(Result && other) + : tag(other.tag) + { + other.tag = Uninit; + if (tag == Ok) + data = std::move(other.data); + else if (tag == Err) + exc = other.exc; + } + ~Result() { - if (tag == 0) + if (tag == Ok) data.~T(); - else if (tag == 1) - // FIXME: don't leak exc + else if (tag == Err) + free(exc); + else if (tag == Uninit) ; + else + abort(); } /* Rethrow the wrapped exception or return the wrapped value. */ T unwrap() { - if (tag == 0) + if (tag == Ok) { + tag = Uninit; return std::move(data); - else if (tag == 1) + } + else if (tag == Err) std::rethrow_exception(*exc); else abort(); |