aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/rust-ffi.hh
blob: a488b96d69f7ced953edd0f0bce7b65c37e9de09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "serialise.hh"

namespace rust {

// Depending on the internal representation of Rust slices is slightly
// evil...
template<typename T>
struct Slice
{
    T * ptr;
    size_t size;

    Slice(T * ptr, size_t size) : ptr(ptr), size(size)
    {
        assert(ptr);
    }
};

struct StringSlice : Slice<char>
{
    StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {}
};

struct Source
{
    size_t (*fun)(void * source_this, rust::Slice<uint8_t> data);
    nix::Source * _this;

    Source(nix::Source & _this)
        : fun(sourceWrapper), _this(&_this)
    {}

    // 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);
        return n;
    }
};

/* C++ representation of Rust's Result<T, CppException>. */
template<typename T>
struct Result
{
    unsigned int tag;

    union {
        T data;
        std::exception_ptr * exc;
    };

    /* Rethrow the wrapped exception or return the wrapped value. */
    T unwrap()
    {
        if (tag == 0)
            return data;
        else if (tag == 1)
            std::rethrow_exception(*exc);
        else
            abort();
    }
};

template<typename T>
struct CBox
{
    T * ptr;

    T * operator ->()
    {
        return ptr;
    }

    CBox(T * ptr) : ptr(ptr) { }
    CBox(const CBox &) = delete;
    CBox(CBox &&) = delete;

    ~CBox()
    {
        free(ptr);
    }
};

// Grrr, this is only needed because 'extern "C"' functions don't
// support non-POD return types (and CBox has a destructor so it's not
// POD).
template<typename T>
struct CBox2
{
    T * ptr;
    CBox<T> use()
    {
        return CBox(ptr);
    }
};

}