mirror of
https://github.com/velopack/velopack.git
synced 2025-10-24 15:19:23 +00:00
wip new C++ library
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,6 +11,7 @@ cargo.log
|
||||
cross.log
|
||||
*.tgz
|
||||
*.node
|
||||
out/
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
|
||||
87
Cargo.lock
generated
87
Cargo.lock
generated
@@ -422,6 +422,16 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
@@ -526,6 +536,50 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbdc8cca144dce1c4981b5c9ab748761619979e515c3d53b5df385c677d1d007"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5764c3142ab44fcf857101d12c0ddf09c34499900557c764f5ad0597159d1fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d422aff542b4fa28c2ce8e5cc202d42dbf24702345c1fba3087b2d3f8a1b90ff"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1719100f31492cd6adeeab9a0f46cdbc846e615fdb66d7b398aa46ec7fdd06f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
@@ -1070,6 +1124,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
@@ -1649,6 +1712,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
@@ -2051,6 +2120,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.10.1"
|
||||
@@ -2170,6 +2245,18 @@ dependencies = [
|
||||
"winsafe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "velopack_libc"
|
||||
version = "0.0.0-local"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"velopack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "velopack_nodeffi"
|
||||
version = "0.0.0-local"
|
||||
|
||||
@@ -4,10 +4,10 @@ members = [
|
||||
"src/bins",
|
||||
"src/lib-rust",
|
||||
"src/lib-nodejs/velopack_nodeffi",
|
||||
"src/lib-cpp",
|
||||
]
|
||||
exclude = [
|
||||
"samples/RustIced",
|
||||
"src/lib-cpp/generator"
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
@@ -23,6 +23,8 @@ edition = "2021"
|
||||
rust-version = "1.75"
|
||||
|
||||
[workspace.dependencies]
|
||||
cxx = "1.0"
|
||||
cxx-build = "1.0"
|
||||
velopack = { path = "src/lib-rust" }
|
||||
log = "0.4"
|
||||
native-tls = "0.2"
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
project(velopack_cpp)
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/api)
|
||||
|
||||
if(WIN32)
|
||||
set(RUST_STATIC_LIB "velopack_cpp_bridge.lib")
|
||||
link_libraries(ntdll)
|
||||
foreach(flag_var
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag_var} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
endif()
|
||||
endforeach()
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(RUST_STATIC_LIB "velopack_cpp_bridge.a")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
elseif(APPLE)
|
||||
set(RUST_STATIC_LIB "velopack_cpp_bridge.a")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
|
||||
endif()
|
||||
|
||||
# Full path for the library
|
||||
set(RUST_STATIC_LIB_PATH "${CMAKE_SOURCE_DIR}/../../target/release/${RUST_STATIC_LIB}")
|
||||
|
||||
# Custom command to build the library
|
||||
add_custom_command(OUTPUT ${RUST_STATIC_LIB_PATH}
|
||||
COMMAND cargo build --release
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/generator
|
||||
COMMENT "Running pre-build command")
|
||||
|
||||
# Custom target to handle the build of the library
|
||||
add_custom_target(build_rust_lib DEPENDS ${RUST_STATIC_LIB_PATH})
|
||||
|
||||
# Main executable
|
||||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
|
||||
# Ensure the library is built before the main project
|
||||
add_dependencies(${PROJECT_NAME} build_rust_lib)
|
||||
|
||||
# Link the library after it has been built
|
||||
target_link_libraries(${PROJECT_NAME} ${RUST_STATIC_LIB_PATH})
|
||||
28
src/lib-cpp/Cargo.toml
Normal file
28
src/lib-cpp/Cargo.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
[package]
|
||||
name = "velopack_libc"
|
||||
publish = false
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
documentation.workspace = true
|
||||
keywords.workspace = true
|
||||
categories.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
cxx.workspace = true
|
||||
velopack.workspace = true
|
||||
anyhow.workspace = true
|
||||
lazy_static.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
cxx-build.workspace = true
|
||||
@@ -1,108 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
//for assert
|
||||
#include <cassert>
|
||||
//for std::abort
|
||||
#include <cstdlib>
|
||||
//for std::move
|
||||
#include <utility>
|
||||
//for std::conditional
|
||||
#include <type_traits>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "c_Foo.h"
|
||||
|
||||
namespace velopack_cpp {
|
||||
|
||||
template<bool>
|
||||
class FooWrapper;
|
||||
using Foo = FooWrapper<true>;
|
||||
using FooRef = FooWrapper<false>;
|
||||
|
||||
|
||||
template<bool OWN_DATA>
|
||||
class FooWrapper {
|
||||
public:
|
||||
using value_type = FooWrapper<true>;
|
||||
friend class FooWrapper<true>;
|
||||
friend class FooWrapper<false>;
|
||||
|
||||
using SelfType = typename std::conditional<OWN_DATA, FooOpaque *, const FooOpaque *>::type;
|
||||
using CForeignType = FooOpaque;
|
||||
|
||||
FooWrapper(FooWrapper &&o) noexcept: self_(o.self_)
|
||||
{
|
||||
o.self_ = nullptr;
|
||||
}
|
||||
FooWrapper &operator=(FooWrapper &&o) noexcept
|
||||
{
|
||||
assert(this != &o);
|
||||
free_mem(this->self_);
|
||||
self_ = o.self_;
|
||||
o.self_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
explicit FooWrapper(SelfType o) noexcept: self_(o) {}
|
||||
FooOpaque *release() noexcept
|
||||
{
|
||||
FooOpaque *ret = self_;
|
||||
self_ = nullptr;
|
||||
return ret;
|
||||
}
|
||||
explicit operator SelfType() const noexcept { return self_; }
|
||||
FooWrapper<false> as_rref() const noexcept { return FooWrapper<false>{ self_ }; }
|
||||
const FooWrapper<true> &as_cref() const noexcept { return reinterpret_cast<const FooWrapper<true> &>(*this); }
|
||||
|
||||
FooWrapper(const FooWrapper&) = delete;
|
||||
FooWrapper &operator=(const FooWrapper&) = delete;
|
||||
|
||||
FooWrapper(int32_t val) noexcept
|
||||
{
|
||||
|
||||
this->self_ = Foo_new(val);
|
||||
if (this->self_ == nullptr) {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t f(int32_t a, int32_t b) const noexcept;
|
||||
//Custom doc comment
|
||||
void setField(int32_t v) noexcept;
|
||||
|
||||
private:
|
||||
static void free_mem(SelfType &p) noexcept
|
||||
{
|
||||
if (OWN_DATA && p != nullptr) {
|
||||
Foo_delete(p);
|
||||
}
|
||||
p = nullptr;
|
||||
}
|
||||
public:
|
||||
~FooWrapper() noexcept
|
||||
{
|
||||
free_mem(this->self_);
|
||||
}
|
||||
|
||||
private:
|
||||
SelfType self_;
|
||||
};
|
||||
|
||||
|
||||
template<bool OWN_DATA>
|
||||
inline int32_t FooWrapper<OWN_DATA>::f(int32_t a, int32_t b) const noexcept
|
||||
{
|
||||
|
||||
int32_t ret = Foo_f(this->self_, a, b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<bool OWN_DATA>
|
||||
inline void FooWrapper<OWN_DATA>::setField(int32_t v) noexcept
|
||||
{
|
||||
|
||||
Foo_setField(this->self_, v);
|
||||
}
|
||||
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,9 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
namespace velopack_cpp {
|
||||
template<bool>
|
||||
class FooWrapper;
|
||||
using Foo = FooWrapper<true>;
|
||||
using FooRef = FooWrapper<false>;
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,28 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
|
||||
#pragma once
|
||||
|
||||
//for (u)intX_t types
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(uintptr_t) == sizeof(uint8_t) * 8,
|
||||
"our conversion usize <-> uintptr_t is wrong");
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct FooOpaque FooOpaque;
|
||||
|
||||
FooOpaque *Foo_new(int32_t val);
|
||||
|
||||
int32_t Foo_f(const FooOpaque * const self, int32_t a, int32_t b);
|
||||
//Custom doc comment
|
||||
void Foo_setField(FooOpaque * const self, int32_t v);
|
||||
|
||||
void Foo_delete(const FooOpaque *self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "rust_foreign_slice_iter.hpp"
|
||||
|
||||
namespace velopack_cpp {
|
||||
template <class ForeignClassRef, typename CContainerType>
|
||||
class RustForeignSlice final : public CContainerType {
|
||||
public:
|
||||
using const_reference = ForeignClassRef;
|
||||
using CForeignType = typename ForeignClassRef::CForeignType;
|
||||
using value_type = typename ForeignClassRef::value_type;
|
||||
using iterator = RustForeignSliceIterator<ForeignClassRef>;
|
||||
using const_iterator = RustForeignSliceIterator<ForeignClassRef>;
|
||||
|
||||
RustForeignSlice() noexcept { reset(); }
|
||||
explicit RustForeignSlice(const CContainerType &o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->step = o.step;
|
||||
}
|
||||
RustForeignSlice(const RustForeignSlice &) = delete;
|
||||
RustForeignSlice &operator=(const RustForeignSlice &) = delete;
|
||||
RustForeignSlice(RustForeignSlice &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->step = o.step;
|
||||
o.reset();
|
||||
}
|
||||
RustForeignSlice &operator=(RustForeignSlice &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->step = o.step;
|
||||
o.reset();
|
||||
return *this;
|
||||
}
|
||||
~RustForeignSlice() noexcept {}
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
ForeignClassRef operator[](size_t i) const noexcept
|
||||
{
|
||||
assert(i < this->len);
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += this->step * i;
|
||||
auto elem_ptr = static_cast<const CForeignType *>(static_cast<const void *>(p));
|
||||
return ForeignClassRef{ elem_ptr };
|
||||
}
|
||||
iterator begin() noexcept { return iterator{ this->data, this->step }; }
|
||||
|
||||
const_iterator begin() const noexcept { return const_iterator{ this->data, this->step }; }
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += this->step * this->len;
|
||||
return iterator{ p, this->step };
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += this->step * this->len;
|
||||
return const_iterator{ p, this->step };
|
||||
}
|
||||
|
||||
private:
|
||||
void reset()
|
||||
{
|
||||
this->step = 0;
|
||||
this->len = 0;
|
||||
this->data = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,131 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> //ptrdiff_t
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
template <typename T> class RustForeignSliceIterator final {
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const T *;
|
||||
using reference = T;
|
||||
|
||||
using CForeignType = typename T::CForeignType;
|
||||
|
||||
RustForeignSliceIterator() noexcept
|
||||
: ptr(nullptr)
|
||||
, step(0)
|
||||
{
|
||||
}
|
||||
RustForeignSliceIterator(const void *p, size_t s) noexcept
|
||||
: ptr(p)
|
||||
, step(s)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \defgroup Forward iterator requirements
|
||||
*/
|
||||
/*@{*/
|
||||
T operator*() const noexcept
|
||||
{
|
||||
auto elem_ptr = static_cast<const CForeignType *>(this->ptr);
|
||||
return T{ elem_ptr };
|
||||
}
|
||||
|
||||
RustForeignSliceIterator &operator++() noexcept
|
||||
{
|
||||
this->ptr = static_cast<const uint8_t *>(this->ptr) + this->step;
|
||||
return *this;
|
||||
}
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \defgroup Bidirectional iterator requirements
|
||||
*/
|
||||
/*@{*/
|
||||
RustForeignSliceIterator &operator--() noexcept
|
||||
{
|
||||
this->ptr = static_cast<const uint8_t *>(this->ptr) - this->step;
|
||||
return *this;
|
||||
}
|
||||
/*@}*/
|
||||
/**
|
||||
* \defgroup Random access iterator requirements
|
||||
*/
|
||||
/*@{*/
|
||||
T operator[](ptrdiff_t n) const noexcept
|
||||
{
|
||||
auto p = static_cast<const uint8_t *>(this->ptr) + n * this->step;
|
||||
auto elem_ptr = static_cast<const CForeignType *>(p);
|
||||
return T{ elem_ptr };
|
||||
}
|
||||
|
||||
RustForeignSliceIterator &operator+=(ptrdiff_t n) noexcept
|
||||
{
|
||||
this->ptr = static_cast<const uint8_t *>(this->ptr) + n * this->step;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RustForeignSliceIterator operator+(ptrdiff_t n) const noexcept
|
||||
{
|
||||
const void *p = static_cast<const uint8_t *>(this->ptr) + n * this->step;
|
||||
return RustForeignSliceIterator(p, this->step);
|
||||
}
|
||||
|
||||
RustForeignSliceIterator &operator-=(ptrdiff_t n) noexcept
|
||||
{
|
||||
this->ptr = static_cast<const uint8_t *>(this->ptr) - n * this->step;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RustForeignSliceIterator operator-(ptrdiff_t n) const noexcept
|
||||
{
|
||||
const void *p = static_cast<const uint8_t *>(this->ptr) - n * this->step;
|
||||
return RustForeignSliceIterator(p, this->step);
|
||||
}
|
||||
|
||||
ptrdiff_t operator-(const RustForeignSliceIterator &o) const noexcept
|
||||
{
|
||||
assert(this->step == o.step);
|
||||
ptrdiff_t diff
|
||||
= static_cast<const uint8_t *>(this->ptr) - static_cast<const uint8_t *>(o.ptr);
|
||||
// if container empty step may be 0, to prevent div by 0
|
||||
if (diff != 0) {
|
||||
return diff / this->step;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const RustForeignSliceIterator &o) const noexcept
|
||||
{
|
||||
assert(this->step == o.step);
|
||||
return this->ptr < o.ptr;
|
||||
}
|
||||
|
||||
bool operator>(const RustForeignSliceIterator &o) const noexcept
|
||||
{
|
||||
assert(this->step == o.step);
|
||||
return this->ptr > o.ptr;
|
||||
}
|
||||
|
||||
bool operator<=(const RustForeignSliceIterator &o) const noexcept { return !operator>(o); }
|
||||
|
||||
bool operator>=(const RustForeignSliceIterator &o) const noexcept { return !operator<(o); }
|
||||
/*@}*/
|
||||
|
||||
bool operator==(const RustForeignSliceIterator<T> &o) const noexcept
|
||||
{
|
||||
assert(this->step == o.step);
|
||||
return this->ptr == o.ptr;
|
||||
}
|
||||
bool operator!=(const RustForeignSliceIterator<T> &o) const noexcept { return !operator==(o); }
|
||||
|
||||
private:
|
||||
const void *ptr;
|
||||
uintptr_t step;
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "rust_foreign_slice_impl.hpp"
|
||||
#include "rust_foreign_slice_iter.hpp"
|
||||
#include "rust_slice.h"
|
||||
#include "rust_slice_mut.h"
|
||||
|
||||
namespace velopack_cpp {
|
||||
|
||||
template <class ForeignClassRef, typename CContainerType, void (*FreeFunc)(CContainerType),
|
||||
void (*PushFunc)(CContainerType *, void *),
|
||||
void *(*RemoveFunc)(CContainerType *, uintptr_t), const uintptr_t &ELEM_SIZE>
|
||||
class RustForeignVec final : private CContainerType {
|
||||
public:
|
||||
using const_reference = ForeignClassRef;
|
||||
using CForeignType = typename ForeignClassRef::CForeignType;
|
||||
using value_type = typename ForeignClassRef::value_type;
|
||||
using iterator = RustForeignSliceIterator<ForeignClassRef>;
|
||||
using const_iterator = RustForeignSliceIterator<ForeignClassRef>;
|
||||
|
||||
RustForeignVec() noexcept { reset(*this); }
|
||||
explicit RustForeignVec(const CContainerType &o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
}
|
||||
RustForeignVec(const RustForeignVec &) = delete;
|
||||
RustForeignVec &operator=(const RustForeignVec &) = delete;
|
||||
RustForeignVec(RustForeignVec &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
reset(o);
|
||||
}
|
||||
RustForeignVec &operator=(RustForeignVec &&o) noexcept
|
||||
{
|
||||
free_mem();
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
reset(o);
|
||||
return *this;
|
||||
}
|
||||
~RustForeignVec() noexcept { free_mem(); }
|
||||
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
|
||||
ForeignClassRef operator[](size_t i) const noexcept
|
||||
{
|
||||
assert(i < this->len);
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += ELEM_SIZE * i;
|
||||
auto elem_ptr = static_cast<const CForeignType *>(static_cast<const void *>(p));
|
||||
return ForeignClassRef{ elem_ptr };
|
||||
}
|
||||
|
||||
void push(value_type o) noexcept { PushFunc(this, o.release()); }
|
||||
|
||||
value_type remove(size_t idx) noexcept
|
||||
{
|
||||
auto p = static_cast<CForeignType *>(RemoveFunc(this, idx));
|
||||
return value_type{ p };
|
||||
}
|
||||
|
||||
iterator begin() noexcept { return iterator{ this->data, ELEM_SIZE }; }
|
||||
|
||||
const_iterator begin() const noexcept { return const_iterator{ this->data, ELEM_SIZE }; }
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += ELEM_SIZE * this->len;
|
||||
return iterator{ p, ELEM_SIZE };
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
auto p = static_cast<const uint8_t *>(this->data);
|
||||
p += ELEM_SIZE * this->len;
|
||||
return const_iterator{ p, ELEM_SIZE };
|
||||
}
|
||||
|
||||
RustForeignSlice<ForeignClassRef, CRustObjectSlice> as_slice() const noexcept
|
||||
{
|
||||
return RustForeignSlice<ForeignClassRef, CRustObjectSlice>{ CRustObjectSlice{
|
||||
this->data, this->len, ELEM_SIZE } };
|
||||
}
|
||||
|
||||
RustForeignSlice<ForeignClassRef, CRustObjectMutSlice> as_slice_mut() noexcept
|
||||
{
|
||||
return RustForeignSlice<ForeignClassRef, CRustObjectMutSlice>{ CRustObjectMutSlice{
|
||||
this->data, this->len, ELEM_SIZE } };
|
||||
}
|
||||
|
||||
void clear() noexcept { free_mem(); }
|
||||
|
||||
CContainerType release() noexcept
|
||||
{
|
||||
CContainerType ret{ this->data, this->len, this->capacity };
|
||||
reset(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
void free_mem() noexcept
|
||||
{
|
||||
FreeFunc(*this);
|
||||
reset(*this);
|
||||
}
|
||||
static void reset(RustForeignVec &o) noexcept
|
||||
{
|
||||
// Rust Vec::new uses NonNull::danling with similar value
|
||||
o.data = reinterpret_cast<value_type *>(std::alignment_of<value_type>::value);
|
||||
o.len = 0;
|
||||
o.capacity = 0;
|
||||
}
|
||||
};
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,46 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
//for (u)intX_t types
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(uintptr_t) == sizeof(uint8_t) * 8,
|
||||
"our conversion usize <-> uintptr_t is wrong");
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustObjectSlice {
|
||||
/*const*/void * data;
|
||||
uintptr_t len;
|
||||
uintptr_t step;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "rust_foreign_slice_impl.hpp"
|
||||
|
||||
namespace velopack_cpp {
|
||||
template<typename T>
|
||||
using RustForeignSliceConst = RustForeignSlice<T, CRustObjectSlice>;
|
||||
}
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustSliceAccess {
|
||||
/*const*/void * data;
|
||||
uintptr_t len;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include "rust_slice.h"
|
||||
|
||||
namespace velopack_cpp {
|
||||
template <typename IndexAccess> class RustSliceAccess final : public CRustSliceAccess {
|
||||
public:
|
||||
using ReturnType = typename IndexAccess::ReturnType;
|
||||
|
||||
RustSliceAccess() noexcept { reset(); }
|
||||
explicit RustSliceAccess(CRustSliceAccess o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
}
|
||||
RustSliceAccess(const RustSliceAccess &) = delete;
|
||||
RustSliceAccess &operator=(const RustSliceAccess &) = delete;
|
||||
RustSliceAccess(RustSliceAccess &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
o.reset();
|
||||
}
|
||||
RustSliceAccess &operator=(RustSliceAccess &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
o.reset();
|
||||
return *this;
|
||||
}
|
||||
~RustSliceAccess() noexcept {}
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
ReturnType operator[](size_t i) const noexcept
|
||||
{
|
||||
assert(i < this->len);
|
||||
return IndexAccess::index(*this, i);
|
||||
}
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
this->data = nullptr;
|
||||
this->len = 0;
|
||||
}
|
||||
};
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,33 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
//for (u)intX_t types
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(uintptr_t) == sizeof(uint8_t) * 8,
|
||||
"our conversion usize <-> uintptr_t is wrong");
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustObjectMutSlice {
|
||||
void * data;
|
||||
uintptr_t len;
|
||||
uintptr_t step;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "rust_foreign_slice_impl.hpp"
|
||||
|
||||
namespace velopack_cpp {
|
||||
template<typename T>
|
||||
using RustForeignSliceMut = RustForeignSlice<T, CRustObjectMutSlice>;
|
||||
}
|
||||
#endif
|
||||
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace velopack_cpp {
|
||||
|
||||
template <typename value_type> class RustSlice final {
|
||||
public:
|
||||
using iterator = value_type *;
|
||||
using const_iterator = const value_type *;
|
||||
|
||||
explicit RustSlice(value_type *p, size_t n) noexcept
|
||||
{
|
||||
this->data = p;
|
||||
this->len = n;
|
||||
}
|
||||
RustSlice(const RustSlice &) = delete;
|
||||
RustSlice &operator=(const RustSlice &) = delete;
|
||||
RustSlice(RustSlice &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
|
||||
reset(o);
|
||||
}
|
||||
RustSlice &operator=(RustSlice &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
|
||||
reset(o);
|
||||
return *this;
|
||||
}
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
const value_type &operator[](size_t i) const noexcept { return this->data[i]; }
|
||||
value_type &operator[](size_t i) noexcept { return this->data[i]; }
|
||||
iterator begin() noexcept { return this->data; }
|
||||
const_iterator begin() const noexcept { return this->data; }
|
||||
iterator end() noexcept { return this->data + this->len; }
|
||||
const_iterator end() const noexcept { return this->data + this->len; }
|
||||
template <typename CContainerType> CContainerType as_c() const noexcept
|
||||
{
|
||||
return CContainerType{ this->data, this->len };
|
||||
}
|
||||
|
||||
private:
|
||||
value_type *data;
|
||||
uintptr_t len;
|
||||
|
||||
static void reset(RustSlice &o) noexcept
|
||||
{
|
||||
o.data = nullptr;
|
||||
o.len = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,127 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
//for (u)intX_t types
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(uintptr_t) == sizeof(uint8_t) * 8,
|
||||
"our conversion usize <-> uintptr_t is wrong");
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustStrView {
|
||||
const char * data;
|
||||
uintptr_t len;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustString {
|
||||
const char * data;
|
||||
uintptr_t len;
|
||||
uintptr_t capacity;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void crust_string_free(struct CRustString x);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustString crust_string_clone(struct CRustString x);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace velopack_cpp {
|
||||
class RustString final : private CRustString {
|
||||
public:
|
||||
explicit RustString(const CRustString &o) noexcept
|
||||
{
|
||||
data = o.data;
|
||||
len = o.len;
|
||||
capacity = o.capacity;
|
||||
}
|
||||
RustString() noexcept { reset(*this); }
|
||||
RustString(const RustString &o) noexcept
|
||||
: RustString(crust_string_clone(o))
|
||||
{
|
||||
}
|
||||
RustString &operator=(const RustString &o) noexcept
|
||||
{
|
||||
if (this != &o) {
|
||||
free_mem();
|
||||
auto copy = crust_string_clone(o);
|
||||
data = copy.data;
|
||||
len = copy.len;
|
||||
capacity = copy.capacity;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
RustString(RustString &&o) noexcept
|
||||
{
|
||||
data = o.data;
|
||||
len = o.len;
|
||||
capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
}
|
||||
RustString &operator=(RustString &&o) noexcept
|
||||
{
|
||||
free_mem();
|
||||
data = o.data;
|
||||
len = o.len;
|
||||
capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
return *this;
|
||||
}
|
||||
~RustString() noexcept { free_mem(); }
|
||||
std::string to_std_string() const { return std::string(data, len); }
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
|
||||
std::string_view to_string_view() const { return std::string_view(data, len); }
|
||||
|
||||
private:
|
||||
void free_mem() noexcept
|
||||
{
|
||||
if (data != nullptr) {
|
||||
crust_string_free(*this);
|
||||
reset(*this);
|
||||
}
|
||||
}
|
||||
static void reset(RustString &o) noexcept
|
||||
{
|
||||
o.data = nullptr;
|
||||
o.len = 0;
|
||||
o.capacity = 0;
|
||||
}
|
||||
};
|
||||
} // namespace velopack_cpp
|
||||
#endif // __cplusplus
|
||||
@@ -1,38 +0,0 @@
|
||||
// Automatically generated by flapigen
|
||||
#pragma once
|
||||
|
||||
//for (u)intX_t types
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(uintptr_t) == sizeof(uint8_t) * 8,
|
||||
"our conversion usize <-> uintptr_t is wrong");
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustVecAccess {
|
||||
/*const*/void * data;
|
||||
uintptr_t len;
|
||||
uintptr_t capacity;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct CRustForeignVec {
|
||||
/*const*/void * data;
|
||||
uintptr_t len;
|
||||
uintptr_t capacity;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C" {
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace velopack_cpp {
|
||||
template <typename VectorTrait, typename CContainerType>
|
||||
class RustVecAccess final : private CContainerType {
|
||||
public:
|
||||
using ElemType = typename VectorTrait::ElemType;
|
||||
|
||||
explicit RustVecAccess(const CContainerType &o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
}
|
||||
RustVecAccess() noexcept { reset(*this); }
|
||||
RustVecAccess(const RustVecAccess &) = delete;
|
||||
RustVecAccess &operator=(const RustVecAccess &) = delete;
|
||||
RustVecAccess(RustVecAccess &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
}
|
||||
RustVecAccess &operator=(RustVecAccess &&o) noexcept
|
||||
{
|
||||
free_mem();
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
return *this;
|
||||
}
|
||||
~RustVecAccess() noexcept { free_mem(); }
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
ElemType operator[](size_t i) const noexcept { return VectorTrait::index(*this, i); }
|
||||
|
||||
private:
|
||||
void free_mem() noexcept
|
||||
{
|
||||
if (this->data != nullptr) {
|
||||
VectorTrait::free(*this);
|
||||
reset(*this);
|
||||
}
|
||||
}
|
||||
static void reset(RustVecAccess &o) noexcept
|
||||
{
|
||||
o.data = nullptr;
|
||||
o.len = 0;
|
||||
o.capacity = 0;
|
||||
}
|
||||
};
|
||||
} // namespace velopack_cpp
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace velopack_cpp {
|
||||
|
||||
namespace internal {
|
||||
template <typename T, typename E> E field_type(E T::*);
|
||||
}
|
||||
|
||||
template <typename CContainerType, void (*FreeFunc)(CContainerType)>
|
||||
class RustVec final : private CContainerType {
|
||||
public:
|
||||
using value_type =
|
||||
typename std::remove_const<typename std::remove_reference<decltype(*internal::field_type(
|
||||
&CContainerType::data))>::type>::type;
|
||||
using iterator = value_type *;
|
||||
using const_iterator = const value_type *;
|
||||
|
||||
explicit RustVec(const CContainerType &o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
}
|
||||
RustVec() noexcept { reset(*this); }
|
||||
RustVec(const RustVec &) = delete;
|
||||
RustVec &operator=(const RustVec &) = delete;
|
||||
RustVec(RustVec &&o) noexcept
|
||||
{
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
}
|
||||
RustVec &operator=(RustVec &&o) noexcept
|
||||
{
|
||||
free_mem();
|
||||
this->data = o.data;
|
||||
this->len = o.len;
|
||||
this->capacity = o.capacity;
|
||||
|
||||
reset(o);
|
||||
return *this;
|
||||
}
|
||||
~RustVec() noexcept { free_mem(); }
|
||||
size_t size() const noexcept { return this->len; }
|
||||
bool empty() const noexcept { return this->len == 0; }
|
||||
const value_type &operator[](size_t i) const noexcept { return this->data[i]; }
|
||||
iterator begin() noexcept { return this->data; }
|
||||
const_iterator begin() const noexcept { return this->data; }
|
||||
iterator end() noexcept { return this->data + this->len; }
|
||||
const_iterator end() const noexcept { return this->data + this->len; }
|
||||
void clear() noexcept { free_mem(); }
|
||||
CContainerType release() noexcept
|
||||
{
|
||||
CContainerType ret{ this->data, this->len, this->capacity };
|
||||
reset(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
void free_mem() noexcept
|
||||
{
|
||||
FreeFunc(*this);
|
||||
reset(*this);
|
||||
}
|
||||
static void reset(RustVec &o) noexcept
|
||||
{
|
||||
// Rust Vec::new uses NonNull::danling with similar value
|
||||
o.data = reinterpret_cast<value_type *>(std::alignment_of<value_type>::value);
|
||||
o.len = 0;
|
||||
o.capacity = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace velopack_cpp
|
||||
11
src/lib-cpp/build.rs
Normal file
11
src/lib-cpp/build.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
fn main() {
|
||||
cxx_build::bridge("src/lib.rs")
|
||||
// .file("src/blobstore.cc")
|
||||
.flag_if_supported("/std:c++17")
|
||||
.std("c++17")
|
||||
.compile("velopack_libc");
|
||||
|
||||
println!("cargo:rerun-if-changed=src/lib.rs");
|
||||
println!("cargo:rerun-if-changed=include/Velopack.hpp");
|
||||
println!("cargo:rerun-if-changed=include/bridge.hpp");
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
[package]
|
||||
name = "velopack_cpp_bridge"
|
||||
version = "0.0.0-local"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "velopack_cpp_bridge"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
rifgen = "*"
|
||||
velopack = { path = "../../lib-rust" }
|
||||
|
||||
[build-dependencies]
|
||||
flapigen = "*"
|
||||
rifgen = "*"
|
||||
@@ -1,19 +0,0 @@
|
||||
use flapigen::{CppConfig, CppOptional, CppStrView, CppVariant, LanguageConfig};
|
||||
use std::{env, path::Path, process::Command};
|
||||
|
||||
fn main() {
|
||||
use rifgen::{Generator, Language, TypeCases};
|
||||
let source_folder = "./src";
|
||||
let out_file = "./src/cpp_glue.rs.in";
|
||||
Generator::new(TypeCases::CamelCase, Language::Cpp, source_folder).generate_interface(out_file);
|
||||
|
||||
let cpp_cfg = CppConfig::new(Path::new("..").join("api"), "velopack_cpp".into())
|
||||
.cpp_optional(CppOptional::Std17)
|
||||
.cpp_variant(CppVariant::Std17)
|
||||
.cpp_str_view(CppStrView::Std17);
|
||||
|
||||
let swig_gen = flapigen::Generator::new(LanguageConfig::CppConfig(cpp_cfg));
|
||||
swig_gen.expand("velopack_cpp", Path::new("./src/cpp_glue.rs.in"), &Path::new("src").join("cpp_glue.rs"));
|
||||
|
||||
Command::new("rustfmt").arg("src/cpp_glue.rs").status().unwrap();
|
||||
}
|
||||
@@ -1,440 +0,0 @@
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! swig_c_str {
|
||||
($ lit : expr) => {
|
||||
concat!($lit, "\0").as_ptr() as *const ::std::os::raw::c_char
|
||||
};
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub trait SwigForeignClass {
|
||||
fn c_class_name() -> *const ::std::os::raw::c_char;
|
||||
fn box_object(x: Self) -> *mut ::std::os::raw::c_void;
|
||||
fn unbox_object(p: *mut ::std::os::raw::c_void) -> Self;
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub trait SwigForeignEnum {
|
||||
fn as_u32(&self) -> u32;
|
||||
fn from_u32(_: u32) -> Self;
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[doc = ""]
|
||||
trait SwigFrom<T> {
|
||||
fn swig_from(_: T) -> Self;
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CRustStrView {
|
||||
data: *const ::std::os::raw::c_char,
|
||||
len: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
impl CRustStrView {
|
||||
fn from_str(s: &str) -> CRustStrView {
|
||||
CRustStrView { data: s.as_ptr() as *const ::std::os::raw::c_char, len: s.len() }
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct CRustString {
|
||||
data: *const ::std::os::raw::c_char,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
impl CRustString {
|
||||
pub fn from_string(s: String) -> CRustString {
|
||||
let data = s.as_ptr() as *const ::std::os::raw::c_char;
|
||||
let len = s.len();
|
||||
let capacity = s.capacity();
|
||||
::std::mem::forget(s);
|
||||
CRustString { data, len, capacity }
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CRustObjectSlice {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
step: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
pub struct CRustObjectMutSlice {
|
||||
data: *mut ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
step: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CRustSliceAccess {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
impl CRustSliceAccess {
|
||||
pub fn from_slice<T>(sl: &[T]) -> Self {
|
||||
Self { data: sl.as_ptr() as *const ::std::os::raw::c_void, len: sl.len() }
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct CRustVecAccess {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
impl CRustVecAccess {
|
||||
pub fn from_vec<T>(mut v: Vec<T>) -> Self {
|
||||
let data = v.as_mut_ptr() as *const ::std::os::raw::c_void;
|
||||
let len = v.len();
|
||||
let capacity = v.capacity();
|
||||
::std::mem::forget(v);
|
||||
Self { data, len, capacity }
|
||||
}
|
||||
pub fn to_slice<'a, T>(cs: Self) -> &'a [T] {
|
||||
unsafe { ::std::slice::from_raw_parts(cs.data as *const T, cs.len) }
|
||||
}
|
||||
pub fn to_vec<T>(cs: Self) -> Vec<T> {
|
||||
unsafe { Vec::from_raw_parts(cs.data as *mut T, cs.len, cs.capacity) }
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct CRustForeignVec {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
impl CRustForeignVec {
|
||||
pub fn from_vec<T: SwigForeignClass>(mut v: Vec<T>) -> CRustForeignVec {
|
||||
let data = v.as_mut_ptr() as *const ::std::os::raw::c_void;
|
||||
let len = v.len();
|
||||
let capacity = v.capacity();
|
||||
::std::mem::forget(v);
|
||||
CRustForeignVec { data, len, capacity }
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn push_foreign_class_to_vec<T: SwigForeignClass>(vec: *mut CRustForeignVec, elem: *mut ::std::os::raw::c_void) {
|
||||
assert!(!vec.is_null());
|
||||
let vec: &mut CRustForeignVec = unsafe { &mut *vec };
|
||||
let mut v = unsafe { Vec::from_raw_parts(vec.data as *mut T, vec.len, vec.capacity) };
|
||||
v.push(T::unbox_object(elem));
|
||||
vec.data = v.as_mut_ptr() as *const ::std::os::raw::c_void;
|
||||
vec.len = v.len();
|
||||
vec.capacity = v.capacity();
|
||||
::std::mem::forget(v);
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn remove_foreign_class_from_vec<T: SwigForeignClass>(vec: *mut CRustForeignVec, index: usize) -> *mut ::std::os::raw::c_void {
|
||||
assert!(!vec.is_null());
|
||||
let vec: &mut CRustForeignVec = unsafe { &mut *vec };
|
||||
let mut v = unsafe { Vec::from_raw_parts(vec.data as *mut T, vec.len, vec.capacity) };
|
||||
let elem: T = v.remove(index);
|
||||
vec.data = v.as_mut_ptr() as *const ::std::os::raw::c_void;
|
||||
vec.len = v.len();
|
||||
vec.capacity = v.capacity();
|
||||
::std::mem::forget(v);
|
||||
T::box_object(elem)
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
fn drop_foreign_class_vec<T: SwigForeignClass>(v: CRustForeignVec) {
|
||||
let v = unsafe { Vec::from_raw_parts(v.data as *mut T, v.len, v.capacity) };
|
||||
drop(v);
|
||||
}
|
||||
use crate::*;
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustStrView_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustStrView {
|
||||
data: *const ::std::os::raw::c_char,
|
||||
len: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustStrView>(), ::std::mem::size_of::<CRustStrView>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustStrView>(), ::std::mem::align_of::<CRustStrView>());
|
||||
let our_s: MyCRustStrView = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustStrView = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustStrView_data_type_fn(s: &CRustStrView) -> &*const ::std::os::raw::c_char {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_char) as usize) - ((&our_s as *const MyCRustStrView) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_char) as usize) - ((&user_s as *const CRustStrView) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustStrView_len_type_fn(s: &CRustStrView) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustStrView) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustStrView) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustString_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustString {
|
||||
data: *const ::std::os::raw::c_char,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustString>(), ::std::mem::size_of::<CRustString>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustString>(), ::std::mem::align_of::<CRustString>());
|
||||
let our_s: MyCRustString = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustString = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustString_data_type_fn(s: &CRustString) -> &*const ::std::os::raw::c_char {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_char) as usize) - ((&our_s as *const MyCRustString) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_char) as usize) - ((&user_s as *const CRustString) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustString_len_type_fn(s: &CRustString) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustString) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustString) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustString_capacity_type_fn(s: &CRustString) -> &usize {
|
||||
&s.capacity
|
||||
}
|
||||
let offset_our = ((&our_s.capacity as *const usize) as usize) - ((&our_s as *const MyCRustString) as usize);
|
||||
let offset_user = ((&user_s.capacity as *const usize) as usize) - ((&user_s as *const CRustString) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crust_string_free(x: CRustString) {
|
||||
let s = unsafe { String::from_raw_parts(x.data as *mut u8, x.len, x.capacity) };
|
||||
drop(s);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crust_string_clone(x: CRustString) -> CRustString {
|
||||
let s = unsafe { String::from_raw_parts(x.data as *mut u8, x.len, x.capacity) };
|
||||
let ret = CRustString::from_string(s.clone());
|
||||
::std::mem::forget(s);
|
||||
ret
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustObjectSlice_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustObjectSlice {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
step: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustObjectSlice>(), ::std::mem::size_of::<CRustObjectSlice>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustObjectSlice>(), ::std::mem::align_of::<CRustObjectSlice>());
|
||||
let our_s: MyCRustObjectSlice = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustObjectSlice = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectSlice_data_type_fn(s: &CRustObjectSlice) -> &*const ::std::os::raw::c_void {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&our_s as *const MyCRustObjectSlice) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&user_s as *const CRustObjectSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectSlice_len_type_fn(s: &CRustObjectSlice) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustObjectSlice) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustObjectSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectSlice_step_type_fn(s: &CRustObjectSlice) -> &usize {
|
||||
&s.step
|
||||
}
|
||||
let offset_our = ((&our_s.step as *const usize) as usize) - ((&our_s as *const MyCRustObjectSlice) as usize);
|
||||
let offset_user = ((&user_s.step as *const usize) as usize) - ((&user_s as *const CRustObjectSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustObjectMutSlice_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustObjectMutSlice {
|
||||
data: *mut ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
step: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustObjectMutSlice>(), ::std::mem::size_of::<CRustObjectMutSlice>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustObjectMutSlice>(), ::std::mem::align_of::<CRustObjectMutSlice>());
|
||||
let our_s: MyCRustObjectMutSlice = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustObjectMutSlice = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectMutSlice_data_type_fn(s: &CRustObjectMutSlice) -> &*mut ::std::os::raw::c_void {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *mut ::std::os::raw::c_void) as usize) - ((&our_s as *const MyCRustObjectMutSlice) as usize);
|
||||
let offset_user = ((&user_s.data as *const *mut ::std::os::raw::c_void) as usize) - ((&user_s as *const CRustObjectMutSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectMutSlice_len_type_fn(s: &CRustObjectMutSlice) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustObjectMutSlice) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustObjectMutSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustObjectMutSlice_step_type_fn(s: &CRustObjectMutSlice) -> &usize {
|
||||
&s.step
|
||||
}
|
||||
let offset_our = ((&our_s.step as *const usize) as usize) - ((&our_s as *const MyCRustObjectMutSlice) as usize);
|
||||
let offset_user = ((&user_s.step as *const usize) as usize) - ((&user_s as *const CRustObjectMutSlice) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustSliceAccess_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustSliceAccess {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustSliceAccess>(), ::std::mem::size_of::<CRustSliceAccess>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustSliceAccess>(), ::std::mem::align_of::<CRustSliceAccess>());
|
||||
let our_s: MyCRustSliceAccess = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustSliceAccess = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustSliceAccess_data_type_fn(s: &CRustSliceAccess) -> &*const ::std::os::raw::c_void {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&our_s as *const MyCRustSliceAccess) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&user_s as *const CRustSliceAccess) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustSliceAccess_len_type_fn(s: &CRustSliceAccess) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustSliceAccess) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustSliceAccess) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustVecAccess_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustVecAccess {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustVecAccess>(), ::std::mem::size_of::<CRustVecAccess>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustVecAccess>(), ::std::mem::align_of::<CRustVecAccess>());
|
||||
let our_s: MyCRustVecAccess = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustVecAccess = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustVecAccess_data_type_fn(s: &CRustVecAccess) -> &*const ::std::os::raw::c_void {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&our_s as *const MyCRustVecAccess) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&user_s as *const CRustVecAccess) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustVecAccess_len_type_fn(s: &CRustVecAccess) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustVecAccess) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustVecAccess) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustVecAccess_capacity_type_fn(s: &CRustVecAccess) -> &usize {
|
||||
&s.capacity
|
||||
}
|
||||
let offset_our = ((&our_s.capacity as *const usize) as usize) - ((&our_s as *const MyCRustVecAccess) as usize);
|
||||
let offset_user = ((&user_s.capacity as *const usize) as usize) - ((&user_s as *const CRustVecAccess) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_CRustForeignVec_layout() {
|
||||
#[repr(C)]
|
||||
struct MyCRustForeignVec {
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
capacity: usize,
|
||||
}
|
||||
assert_eq!(::std::mem::size_of::<MyCRustForeignVec>(), ::std::mem::size_of::<CRustForeignVec>());
|
||||
assert_eq!(::std::mem::align_of::<MyCRustForeignVec>(), ::std::mem::align_of::<CRustForeignVec>());
|
||||
let our_s: MyCRustForeignVec = unsafe { ::std::mem::zeroed() };
|
||||
let user_s: CRustForeignVec = unsafe { ::std::mem::zeroed() };
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustForeignVec_data_type_fn(s: &CRustForeignVec) -> &*const ::std::os::raw::c_void {
|
||||
&s.data
|
||||
}
|
||||
let offset_our = ((&our_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&our_s as *const MyCRustForeignVec) as usize);
|
||||
let offset_user = ((&user_s.data as *const *const ::std::os::raw::c_void) as usize) - ((&user_s as *const CRustForeignVec) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustForeignVec_len_type_fn(s: &CRustForeignVec) -> &usize {
|
||||
&s.len
|
||||
}
|
||||
let offset_our = ((&our_s.len as *const usize) as usize) - ((&our_s as *const MyCRustForeignVec) as usize);
|
||||
let offset_user = ((&user_s.len as *const usize) as usize) - ((&user_s as *const CRustForeignVec) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
#[allow(dead_code)]
|
||||
fn check_CRustForeignVec_capacity_type_fn(s: &CRustForeignVec) -> &usize {
|
||||
&s.capacity
|
||||
}
|
||||
let offset_our = ((&our_s.capacity as *const usize) as usize) - ((&our_s as *const MyCRustForeignVec) as usize);
|
||||
let offset_user = ((&user_s.capacity as *const usize) as usize) - ((&user_s as *const CRustForeignVec) as usize);
|
||||
assert_eq!(offset_our, offset_user);
|
||||
}
|
||||
impl SwigForeignClass for Foo {
|
||||
fn c_class_name() -> *const ::std::os::raw::c_char {
|
||||
swig_c_str!(stringify!(Foo))
|
||||
}
|
||||
fn box_object(this: Self) -> *mut ::std::os::raw::c_void {
|
||||
let this: Box<Foo> = Box::new(this);
|
||||
let this: *mut Foo = Box::into_raw(this);
|
||||
this as *mut ::std::os::raw::c_void
|
||||
}
|
||||
fn unbox_object(p: *mut ::std::os::raw::c_void) -> Self {
|
||||
let p = p as *mut Foo;
|
||||
let p: Box<Foo> = unsafe { Box::from_raw(p) };
|
||||
let p: Foo = *p;
|
||||
p
|
||||
}
|
||||
}
|
||||
#[allow(unused_variables, unused_mut, non_snake_case, unused_unsafe)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Foo_new(val: i32) -> *const ::std::os::raw::c_void {
|
||||
let this: Foo = Foo::new(val);
|
||||
let this: Box<Foo> = Box::new(this);
|
||||
let this: *mut Foo = Box::into_raw(this);
|
||||
this as *const ::std::os::raw::c_void
|
||||
}
|
||||
#[allow(non_snake_case, unused_variables, unused_mut, unused_unsafe)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Foo_f(this: *mut Foo, a: i32, b: i32) -> i32 {
|
||||
let this: &Foo = unsafe { this.as_mut().unwrap() };
|
||||
let mut ret: i32 = Foo::f(this, a, b);
|
||||
ret
|
||||
}
|
||||
#[allow(non_snake_case, unused_variables, unused_mut, unused_unsafe)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Foo_setField(this: *mut Foo, v: i32) -> () {
|
||||
let this: &mut Foo = unsafe { this.as_mut().unwrap() };
|
||||
let mut ret: () = Foo::set_field(this, v);
|
||||
ret
|
||||
}
|
||||
#[allow(unused_variables, unused_mut, non_snake_case, unused_unsafe)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Foo_delete(this: *mut Foo) {
|
||||
let this: Box<Foo> = unsafe { Box::from_raw(this) };
|
||||
drop(this);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
//Automatically generated by rifgen
|
||||
use crate::*;
|
||||
foreign_class!(
|
||||
class Foo {
|
||||
self_type Foo;
|
||||
constructor Foo::new(val : i32)->Foo;
|
||||
fn Foo::f(& self , a : i32 , b : i32)->i32; alias f;
|
||||
# [doc = "Custom doc comment"]
|
||||
fn Foo::set_field(& mut self , v : i32); alias setField;
|
||||
}
|
||||
);
|
||||
@@ -1,45 +0,0 @@
|
||||
mod cpp_glue;
|
||||
pub use crate::cpp_glue::*;
|
||||
|
||||
use rifgen::rifgen_attr::*;
|
||||
|
||||
extern crate velopack;
|
||||
|
||||
velopack::
|
||||
|
||||
pub struct Foo {
|
||||
data: i32,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
#[generate_interface(constructor)]
|
||||
fn new(val: i32) -> Foo {
|
||||
Foo { data: val }
|
||||
}
|
||||
#[generate_interface]
|
||||
fn f(&self, a: i32, b: i32) -> i32 {
|
||||
self.data + a + b
|
||||
}
|
||||
|
||||
///Custom doc comment
|
||||
#[generate_interface]
|
||||
fn set_field(&mut self, v: i32) {
|
||||
self.data = v;
|
||||
}
|
||||
}
|
||||
|
||||
fn f2(a: i32) -> i32 {
|
||||
a * 2
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let foo = Foo::new(5);
|
||||
assert_eq!(8, foo.f(1, 2));
|
||||
}
|
||||
}
|
||||
|
||||
7
src/lib-cpp/include/Velopack.hpp
Normal file
7
src/lib-cpp/include/Velopack.hpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef VELOPACK_HPP
|
||||
#define VELOPACK_HPP
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // VELOPACK_HPP
|
||||
20
src/lib-cpp/include/bridge.hpp
Normal file
20
src/lib-cpp/include/bridge.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "rust/cxx.h"
|
||||
|
||||
struct HookCallbackManager {
|
||||
void install_hook(::rust::String app_version) const {};
|
||||
void update_hook(::rust::String app_version) const {};
|
||||
void obsolete_hook(::rust::String app_version) const {};
|
||||
void uninstall_hook(::rust::String app_version) const {};
|
||||
void firstrun_hook(::rust::String app_version) const {};
|
||||
void restarted_hook(::rust::String app_version) const {};
|
||||
};
|
||||
|
||||
struct DownloadCallbackManager {
|
||||
void download_progress(int16_t progress) const {};
|
||||
};
|
||||
|
||||
struct LoggerCallbackManager {
|
||||
void log(::LogLevel level, ::rust::String message) const {};
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "Foo.hpp"
|
||||
using namespace velopack_cpp;
|
||||
|
||||
int main()
|
||||
{
|
||||
// ANCHOR: call_rust
|
||||
Foo foo(5);
|
||||
int res = foo.f(1, 2);
|
||||
// ANCHOR_END: call_rust
|
||||
if (res == 8) {
|
||||
std::cout << "All works fine\n";
|
||||
}
|
||||
else {
|
||||
std::cout << "Something really BAD!!!\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
369
src/lib-cpp/src/lib.rs
Normal file
369
src/lib-cpp/src/lib.rs
Normal file
@@ -0,0 +1,369 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use lazy_static::lazy_static;
|
||||
use log::{Level, Log, Metadata, Record};
|
||||
use velopack::{
|
||||
locator::VelopackLocatorConfig,
|
||||
UpdateManager,
|
||||
UpdateCheck,
|
||||
UpdateOptions as VelopackUpdateOptions,
|
||||
UpdateInfo as VelopackUpdateInfo,
|
||||
VelopackAsset,
|
||||
VelopackApp,
|
||||
Error as VelopackError,
|
||||
sources,
|
||||
};
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
// Shared structs with fields visible to both languages.
|
||||
#[derive(Default)]
|
||||
pub struct Asset {
|
||||
pub PackageId: String,
|
||||
pub Version: String,
|
||||
pub Type: String,
|
||||
pub FileName: String,
|
||||
pub SHA1: String,
|
||||
pub SHA256: String,
|
||||
pub Size: u64,
|
||||
pub NotesMarkdown: String,
|
||||
pub NotesHtml: String,
|
||||
}
|
||||
|
||||
pub struct AssetOption {
|
||||
pub data: Asset,
|
||||
pub has_data: bool,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UpdateInfo {
|
||||
pub TargetFullRelease: Asset,
|
||||
pub IsDowngrade: bool,
|
||||
}
|
||||
|
||||
pub struct UpdateInfoOption {
|
||||
pub data: UpdateInfo,
|
||||
pub has_data: bool,
|
||||
}
|
||||
|
||||
pub struct LocatorConfig<'a> {
|
||||
pub RootAppDir: &'a CxxString,
|
||||
pub UpdateExePath: &'a CxxString,
|
||||
pub PackagesDir: &'a CxxString,
|
||||
pub ManifestPath: &'a CxxString,
|
||||
pub CurrentBinaryDir: &'a CxxString,
|
||||
pub IsPortable: bool,
|
||||
}
|
||||
|
||||
pub struct LocatorConfigOption<'a> {
|
||||
pub data: LocatorConfig<'a>,
|
||||
pub has_data: bool,
|
||||
}
|
||||
|
||||
pub struct UpdateOptions<'a> {
|
||||
pub AllowVersionDowngrade: bool,
|
||||
pub ExplicitChannel: &'a CxxString,
|
||||
}
|
||||
|
||||
pub struct StringArrayOption {
|
||||
pub data: Vec<String>,
|
||||
pub has_data: bool,
|
||||
}
|
||||
|
||||
pub enum LogLevel {
|
||||
Trace = 0,
|
||||
Debug = 1,
|
||||
Info = 2,
|
||||
Warn = 3,
|
||||
Error = 4,
|
||||
}
|
||||
|
||||
// C++ types and signatures exposed to Rust.
|
||||
unsafe extern "C++" {
|
||||
include!("velopack_libc/include/bridge.hpp");
|
||||
type HookCallbackManager;
|
||||
fn install_hook(self: &HookCallbackManager, app_version: String);
|
||||
fn update_hook(self: &HookCallbackManager, app_version: String);
|
||||
fn obsolete_hook(self: &HookCallbackManager, app_version: String);
|
||||
fn uninstall_hook(self: &HookCallbackManager, app_version: String);
|
||||
fn firstrun_hook(self: &HookCallbackManager, app_version: String);
|
||||
fn restarted_hook(self: &HookCallbackManager, app_version: String);
|
||||
type DownloadCallbackManager;
|
||||
fn download_progress(self: &DownloadCallbackManager, progress: i16);
|
||||
type LoggerCallbackManager;
|
||||
fn log(self: &LoggerCallbackManager, level: LogLevel, message: String);
|
||||
}
|
||||
|
||||
// Rust types and signatures exposed to C++.
|
||||
extern "Rust" {
|
||||
type UpdateManagerOpaque;
|
||||
fn bridge_new_update_manager(url_or_path: &CxxString, options: UpdateOptions, locator: LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>>;
|
||||
fn bridge_get_current_version(manager: &UpdateManagerOpaque) -> String;
|
||||
fn bridge_get_app_id(manager: &UpdateManagerOpaque) -> String;
|
||||
fn bridge_is_portable(manager: &UpdateManagerOpaque) -> bool;
|
||||
fn bridge_update_pending_restart(manager: &UpdateManagerOpaque) -> AssetOption;
|
||||
fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<UpdateInfoOption>;
|
||||
fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: UpdateInfo, progress: UniquePtr<DownloadCallbackManager>) -> Result<()>;
|
||||
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download: Asset, silent: bool, restart: bool, restart_args: Vec<String>) -> Result<()>;
|
||||
fn bridge_appbuilder_run(cb: UniquePtr<HookCallbackManager>, custom_args: StringArrayOption, locator: LocatorConfigOption, auto_apply: bool);
|
||||
fn bridge_set_logger_callback(cb: UniquePtr<LoggerCallbackManager>);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct UpdateManagerOpaque {
|
||||
obj: UpdateManager,
|
||||
}
|
||||
|
||||
fn to_locator_config(locator: &ffi::LocatorConfig) -> VelopackLocatorConfig {
|
||||
VelopackLocatorConfig {
|
||||
RootAppDir: PathBuf::from(locator.RootAppDir.to_string_lossy().to_string()),
|
||||
UpdateExePath: PathBuf::from(locator.UpdateExePath.to_string_lossy().to_string()),
|
||||
PackagesDir: PathBuf::from(locator.PackagesDir.to_string_lossy().to_string()),
|
||||
ManifestPath: PathBuf::from(locator.ManifestPath.to_string_lossy().to_string()),
|
||||
CurrentBinaryDir: PathBuf::from(locator.CurrentBinaryDir.to_string_lossy().to_string()),
|
||||
IsPortable: locator.IsPortable,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_update_options(options: &ffi::UpdateOptions) -> VelopackUpdateOptions {
|
||||
let channel = options.ExplicitChannel.to_string_lossy().to_string();
|
||||
VelopackUpdateOptions {
|
||||
AllowVersionDowngrade: options.AllowVersionDowngrade,
|
||||
ExplicitChannel: if channel.is_empty() { None } else { Some(channel) },
|
||||
}
|
||||
}
|
||||
|
||||
fn from_asset(asset: &VelopackAsset) -> ffi::Asset {
|
||||
ffi::Asset {
|
||||
PackageId: asset.PackageId.clone(),
|
||||
Version: asset.Version.clone(),
|
||||
Type: asset.Type.clone(),
|
||||
FileName: asset.FileName.clone(),
|
||||
SHA1: asset.SHA1.clone(),
|
||||
SHA256: asset.SHA256.clone(),
|
||||
Size: asset.Size,
|
||||
NotesMarkdown: asset.NotesMarkdown.clone(),
|
||||
NotesHtml: asset.NotesHtml.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_asset(asset: &ffi::Asset) -> VelopackAsset {
|
||||
VelopackAsset {
|
||||
PackageId: asset.PackageId.clone(),
|
||||
Version: asset.Version.clone(),
|
||||
Type: asset.Type.clone(),
|
||||
FileName: asset.FileName.clone(),
|
||||
SHA1: asset.SHA1.clone(),
|
||||
SHA256: asset.SHA256.clone(),
|
||||
Size: asset.Size,
|
||||
NotesMarkdown: asset.NotesMarkdown.clone(),
|
||||
NotesHtml: asset.NotesHtml.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_update_info(info: &VelopackUpdateInfo) -> ffi::UpdateInfo {
|
||||
ffi::UpdateInfo {
|
||||
TargetFullRelease: from_asset(&info.TargetFullRelease),
|
||||
IsDowngrade: info.IsDowngrade,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_update_info(info: &ffi::UpdateInfo) -> VelopackUpdateInfo {
|
||||
VelopackUpdateInfo {
|
||||
TargetFullRelease: to_asset(&info.TargetFullRelease),
|
||||
IsDowngrade: info.IsDowngrade,
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_new_update_manager(url_or_path: &cxx::CxxString, options: ffi::UpdateOptions, locator: ffi::LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>> {
|
||||
let url = url_or_path.to_string_lossy();
|
||||
let source = sources::AutoSource::new(&url);
|
||||
let update_options = to_update_options(&options);
|
||||
|
||||
if locator.has_data {
|
||||
let locator_config = to_locator_config(&locator.data);
|
||||
let update_manager = UpdateManager::new(source, Some(update_options), Some(locator_config))?;
|
||||
Ok(Box::new(UpdateManagerOpaque { obj: update_manager }))
|
||||
} else {
|
||||
let update_manager = UpdateManager::new(source, Some(update_options), None)?;
|
||||
Ok(Box::new(UpdateManagerOpaque { obj: update_manager }))
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_get_current_version(manager: &UpdateManagerOpaque) -> String {
|
||||
manager.obj.get_current_version_as_string()
|
||||
}
|
||||
|
||||
fn bridge_get_app_id(manager: &UpdateManagerOpaque) -> String {
|
||||
manager.obj.get_app_id()
|
||||
}
|
||||
|
||||
fn bridge_is_portable(manager: &UpdateManagerOpaque) -> bool {
|
||||
manager.obj.get_is_portable()
|
||||
}
|
||||
|
||||
fn bridge_update_pending_restart(manager: &UpdateManagerOpaque) -> ffi::AssetOption {
|
||||
if let Some(info) = manager.obj.get_update_pending_restart() {
|
||||
let update = from_asset(&info);
|
||||
ffi::AssetOption { data: update, has_data: true }
|
||||
} else {
|
||||
let default = ffi::Asset::default();
|
||||
ffi::AssetOption { data: default, has_data: false }
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<ffi::UpdateInfoOption> {
|
||||
if let UpdateCheck::UpdateAvailable(info) = manager.obj.check_for_updates()? {
|
||||
let update = from_update_info(&info);
|
||||
Ok(ffi::UpdateInfoOption { data: update, has_data: true })
|
||||
} else {
|
||||
let default = ffi::UpdateInfo::default();
|
||||
Ok(ffi::UpdateInfoOption { data: default, has_data: false })
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: ffi::UpdateInfo, cb: cxx::UniquePtr<ffi::DownloadCallbackManager>) -> Result<()> {
|
||||
// let info = to_update_info(&to_download);
|
||||
//
|
||||
// let (sender, receiver) = std::sync::mpsc::channel::<i16>();
|
||||
// std::thread::spawn(move || {
|
||||
// while let Ok(progress) = receiver.recv() {
|
||||
// cb.download_progress(progress);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// manager.obj.download_updates(&info, Some(sender))?;
|
||||
// Ok(())
|
||||
|
||||
let info = to_update_info(&to_download);
|
||||
|
||||
let (progress_sender, progress_receiver) = std::sync::mpsc::channel::<i16>();
|
||||
let (completion_sender, completion_receiver) = std::sync::mpsc::channel::<std::result::Result<(), VelopackError>>();
|
||||
|
||||
// Move the download_updates call into a new thread
|
||||
let manager = manager.clone();
|
||||
std::thread::spawn(move || {
|
||||
let result = manager.obj.download_updates(&info, Some(progress_sender));
|
||||
let _ = completion_sender.send(result);
|
||||
});
|
||||
|
||||
// Process progress updates on the caller's thread
|
||||
loop {
|
||||
// Try to receive progress updates without blocking
|
||||
match progress_receiver.try_recv() {
|
||||
Ok(progress) => {
|
||||
cb.download_progress(progress);
|
||||
}
|
||||
_ => {
|
||||
// No progress updates available, sleep for a short time to avoid busy-waiting
|
||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if download is complete
|
||||
match completion_receiver.try_recv() {
|
||||
Ok(result) => {
|
||||
// Download is complete, return the result (propagating any errors)
|
||||
result?;
|
||||
return Ok(());
|
||||
}
|
||||
Err(std::sync::mpsc::TryRecvError::Empty) => {
|
||||
// Download is still in progress, continue processing progress updates
|
||||
}
|
||||
Err(std::sync::mpsc::TryRecvError::Disconnected) => {
|
||||
bail!("Download thread disconnected unexpectedly without returning a result");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download: ffi::Asset, silent: bool, restart: bool, restart_args: Vec<String>) -> Result<()> {
|
||||
let asset = to_asset(&to_download);
|
||||
manager.obj.wait_exit_then_apply_updates(&asset, silent, restart, restart_args)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bridge_appbuilder_run(cb: cxx::UniquePtr<ffi::HookCallbackManager>, custom_args: ffi::StringArrayOption, locator: ffi::LocatorConfigOption, auto_apply: bool) {
|
||||
let mut app = VelopackApp::build()
|
||||
.on_first_run(|v| cb.firstrun_hook(v.to_string()))
|
||||
.on_restarted(|v| cb.restarted_hook(v.to_string()))
|
||||
.set_auto_apply_on_startup(auto_apply);
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
app = app.on_after_install_fast_callback(|v| cb.install_hook(v.to_string()))
|
||||
.on_after_update_fast_callback(|v| cb.update_hook(v.to_string()))
|
||||
.on_before_update_fast_callback(|v| cb.obsolete_hook(v.to_string()))
|
||||
.on_before_uninstall_fast_callback(|v| cb.uninstall_hook(v.to_string()));
|
||||
}
|
||||
|
||||
if locator.has_data {
|
||||
app = app.set_locator(to_locator_config(&locator.data));
|
||||
}
|
||||
|
||||
if custom_args.has_data {
|
||||
app = app.set_args(custom_args.data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
struct LoggerImpl {}
|
||||
static LOGGER: LoggerImpl = LoggerImpl {};
|
||||
|
||||
impl Log for LoggerImpl {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= log::max_level()
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if !self.enabled(record.metadata()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let text = format!("{}", record.args());
|
||||
|
||||
let level = match record.level() {
|
||||
Level::Error => ffi::LogLevel::Error,
|
||||
Level::Warn => ffi::LogLevel::Warn,
|
||||
Level::Info => ffi::LogLevel::Info,
|
||||
Level::Debug => ffi::LogLevel::Debug,
|
||||
Level::Trace => ffi::LogLevel::Trace,
|
||||
};
|
||||
|
||||
if let Some(cb) = get_logger() {
|
||||
cb.log(level, text);
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref LOGGER_CB: AtomicUsize = AtomicUsize::new(0);
|
||||
}
|
||||
|
||||
fn store_logger(ptr: *mut ffi::LoggerCallbackManager) {
|
||||
LOGGER_CB.store(ptr as usize, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn get_logger() -> Option<*mut ffi::LoggerCallbackManager> {
|
||||
let ptr = LOGGER_CB.load(Ordering::SeqCst);
|
||||
if ptr == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ptr as *mut ffi::LoggerCallbackManager)
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_set_logger_callback(cb: cxx::UniquePtr<ffi::LoggerCallbackManager>) {
|
||||
let cb = cb.into_raw();
|
||||
store_logger(cb);
|
||||
}
|
||||
Reference in New Issue
Block a user