Bridge C++ bytes with Rust &[u8]

This commit is contained in:
topjohnwu
2023-06-07 16:49:40 -07:00
parent 5e2ef1b7f4
commit ee4dad7a13
7 changed files with 145 additions and 132 deletions
+94 -9
View File
@@ -7,10 +7,18 @@
#include <bitset>
#include <random>
#include "xwrap.hpp"
#define DISALLOW_COPY_AND_MOVE(clazz) \
clazz(const clazz &) = delete; \
clazz(const clazz &) = delete; \
clazz(clazz &&) = delete;
#define ALLOW_MOVE_ONLY(clazz) \
clazz() = default; \
clazz(const clazz&) = delete; \
clazz(clazz &&o) { swap(o); } \
clazz& operator=(clazz &&o) { swap(o); return *this; }
class mutex_guard {
DISALLOW_COPY_AND_MOVE(mutex_guard)
public:
@@ -119,15 +127,92 @@ struct StringCmp {
bool operator()(std::string_view a, std::string_view b) const { return a < b; }
};
template<typename T>
rust::Slice<uint8_t> u8_mut_slice(T *buf, size_t sz) {
return rust::Slice(reinterpret_cast<uint8_t *>(buf), sz);
}
struct heap_data;
template<typename T>
rust::Slice<const uint8_t> u8_slice(T *buf, size_t sz) {
return rust::Slice(reinterpret_cast<const uint8_t *>(buf), sz);
}
// Interchangeable as `&[u8]` in Rust
struct byte_view {
byte_view() : _buf(nullptr), _sz(0) {}
byte_view(const void *buf, size_t sz) : _buf((uint8_t *) buf), _sz(sz) {}
// byte_view, or any of its subclass, can be copied as byte_view
byte_view(const byte_view &o) : _buf(o._buf), _sz(o._sz) {}
// Bridging to Rust slice
byte_view(rust::Slice<const uint8_t> o) : byte_view(o.data(), o.size()) {}
operator rust::Slice<const uint8_t>() { return rust::Slice<const uint8_t>(_buf, _sz); }
// String as bytes
byte_view(const char *s, bool with_nul = true)
: byte_view(std::string_view(s), with_nul, false) {}
byte_view(const std::string &s, bool with_nul = true)
: byte_view(std::string_view(s), with_nul, false) {}
byte_view(std::string_view s, bool with_nul = true)
: byte_view(s, with_nul, true /* string_view is not guaranteed to null terminate */ ) {}
// Vector as bytes
byte_view(const std::vector<uint8_t> &v) : byte_view(v.data(), v.size()) {}
const uint8_t *buf() const { return _buf; }
size_t sz() const { return _sz; }
bool contains(byte_view pattern) const;
bool equals(byte_view o) const;
heap_data clone() const;
protected:
uint8_t *_buf;
size_t _sz;
private:
byte_view(std::string_view s, bool with_nul, bool check_nul)
: byte_view(static_cast<const void *>(s.data()), s.length()) {
if (with_nul) {
if (check_nul && s[s.length()] != '\0')
return;
++_sz;
}
}
};
// Interchangeable as `&mut [u8]` in Rust
struct byte_data : public byte_view {
byte_data() = default;
byte_data(void *buf, size_t sz) : byte_view(buf, sz) {}
// We don't want mutable references to be copied or moved around; pass bytes as byte_view
// Subclasses are free to implement their own constructors
byte_data(const byte_data &) = delete;
byte_data(byte_data &&) = delete;
// Transparent conversion from common C++ types to mutable byte references
byte_data(std::string &s, bool with_nul = true)
: byte_data(s.data(), with_nul ? s.length() + 1 : s.length()) {}
byte_data(std::vector<uint8_t> &v) : byte_data(v.data(), v.size()) {}
// Bridging to Rust slice
byte_data(rust::Slice<uint8_t> o) : byte_data(o.data(), o.size()) {}
operator rust::Slice<uint8_t>() { return rust::Slice<uint8_t>(_buf, _sz); }
using byte_view::buf;
using byte_view::sz;
uint8_t *buf() { return _buf; }
size_t &sz() { return _sz; }
void swap(byte_data &o);
std::vector<size_t> patch(byte_view from, byte_view to);
};
class byte_channel;
struct heap_data : public byte_data {
ALLOW_MOVE_ONLY(heap_data)
explicit heap_data(size_t sz) : byte_data(malloc(sz), sz) {}
~heap_data() { free(_buf); }
// byte_channel needs to reallocate the internal buffer
friend byte_channel;
};
uint64_t parse_uint64_hex(std::string_view s);
int parse_int(std::string_view s);