mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +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
|
cross.log
|
||||||
*.tgz
|
*.tgz
|
||||||
*.node
|
*.node
|
||||||
|
out/
|
||||||
|
|
||||||
#################
|
#################
|
||||||
## Eclipse
|
## Eclipse
|
||||||
|
|||||||
87
Cargo.lock
generated
87
Cargo.lock
generated
@@ -422,6 +422,16 @@ dependencies = [
|
|||||||
"objc",
|
"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]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -526,6 +536,50 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@@ -1070,6 +1124,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "link-cplusplus"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@@ -1649,6 +1712,12 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"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]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.11.1"
|
version = "2.11.1"
|
||||||
@@ -2051,6 +2120,12 @@ dependencies = [
|
|||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ureq"
|
name = "ureq"
|
||||||
version = "2.10.1"
|
version = "2.10.1"
|
||||||
@@ -2170,6 +2245,18 @@ dependencies = [
|
|||||||
"winsafe",
|
"winsafe",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "velopack_libc"
|
||||||
|
version = "0.0.0-local"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"cxx",
|
||||||
|
"cxx-build",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"velopack",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "velopack_nodeffi"
|
name = "velopack_nodeffi"
|
||||||
version = "0.0.0-local"
|
version = "0.0.0-local"
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ members = [
|
|||||||
"src/bins",
|
"src/bins",
|
||||||
"src/lib-rust",
|
"src/lib-rust",
|
||||||
"src/lib-nodejs/velopack_nodeffi",
|
"src/lib-nodejs/velopack_nodeffi",
|
||||||
|
"src/lib-cpp",
|
||||||
]
|
]
|
||||||
exclude = [
|
exclude = [
|
||||||
"samples/RustIced",
|
"samples/RustIced",
|
||||||
"src/lib-cpp/generator"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
@@ -23,6 +23,8 @@ edition = "2021"
|
|||||||
rust-version = "1.75"
|
rust-version = "1.75"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
cxx = "1.0"
|
||||||
|
cxx-build = "1.0"
|
||||||
velopack = { path = "src/lib-rust" }
|
velopack = { path = "src/lib-rust" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
native-tls = "0.2"
|
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