Remove cxx bridge & export functions from rust

This commit is contained in:
Caelan Sayler
2024-11-10 22:21:07 +00:00
committed by Caelan
parent 9dd46b450a
commit 0e593a2587
14 changed files with 1313 additions and 1046 deletions

65
Cargo.lock generated
View File

@@ -422,16 +422,6 @@ 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"
@@ -536,50 +526,6 @@ 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.87",
]
[[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.87",
]
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.11" version = "0.3.11"
@@ -1238,15 +1184,6 @@ 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"
@@ -2342,8 +2279,6 @@ name = "velopack_libc"
version = "0.0.0-local" version = "0.0.0-local"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cxx",
"cxx-build",
"lazy_static", "lazy_static",
"log", "log",
"velopack", "velopack",

View File

@@ -23,8 +23,6 @@ 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"
ureq = "2.10" ureq = "2.10"

View File

@@ -18,11 +18,7 @@ path = "src/lib.rs"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
cxx.workspace = true
velopack.workspace = true velopack.workspace = true
anyhow.workspace = true anyhow.workspace = true
lazy_static.workspace = true lazy_static.workspace = true
log.workspace = true log.workspace = true
[build-dependencies]
cxx-build.workspace = true

View File

@@ -1,19 +1,21 @@
fn main() { fn main() {
cxx_build::bridge("src/lib.rs") // cc::Build::new()
.file("src/bridge.cc") // .cpp(true)
.warnings_into_errors(true) // .static_crt(true)
.flag_if_supported("/std:c++17") // .file("src/bridge.cc")
.flag_if_supported("/EHsc") // exception unwind handling // .warnings_into_errors(true)
.flag_if_supported("-Wno-unused-function") // allow unused functions // .flag_if_supported("/std:c++17")
.define("VELOPACK_LIBC_EXPORTS", Some("1")) // .flag_if_supported("/EHsc") // exception unwind handling
.std("c++17") // .flag_if_supported("-Wno-unused-function") // allow unused functions
.compile("velopack_libc"); // .define("VELOPACK_LIBC_EXPORTS", Some("1"))
// .std("c++17")
// .compile("velopack_libc");
println!("cargo:rerun-if-changed=include/Velopack.h"); // println!("cargo:rerun-if-changed=include/Velopack.h");
println!("cargo:rerun-if-changed=src/lib.rs"); // println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=src/bridge.hpp"); // println!("cargo:rerun-if-changed=src/bridge.hpp");
println!("cargo:rerun-if-changed=src/bridge.cc"); // println!("cargo:rerun-if-changed=src/bridge.cc");
#[cfg(target_os = "windows")] // #[cfg(target_os = "windows")]
println!("cargo:rustc-link-arg=/WHOLEARCHIVE:velopack_libc.lib"); // println!("cargo:rustc-link-arg=/WHOLEARCHIVE:velopack_libc.lib");
} }

View File

@@ -20,39 +20,6 @@
#include <string.h> #include <string.h>
#endif #endif
#if defined(VELOPACK_LIBC_EXPORTS) && defined(_WIN32)
#define VPKC_EXPORT __declspec(dllexport)
#define VPKC_CALL __cdecl
#pragma comment(linker, "/EXPORT:vpkc_new_update_manager")
#pragma comment(linker, "/EXPORT:vpkc_get_current_version")
#pragma comment(linker, "/EXPORT:vpkc_get_app_id")
#pragma comment(linker, "/EXPORT:vpkc_is_portable")
#pragma comment(linker, "/EXPORT:vpkc_update_pending_restart")
#pragma comment(linker, "/EXPORT:vpkc_download_updates")
#pragma comment(linker, "/EXPORT:vpkc_wait_exit_then_apply_update")
#pragma comment(linker, "/EXPORT:vpkc_app_set_auto_apply_on_startup")
#pragma comment(linker, "/EXPORT:vpkc_app_set_args")
#pragma comment(linker, "/EXPORT:vpkc_app_set_locator")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_after_install")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_before_uninstall")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_before_update")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_after_update")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_first_run")
#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_restarted")
#pragma comment(linker, "/EXPORT:vpkc_app_run")
#pragma comment(linker, "/EXPORT:vpkc_get_last_error")
#pragma comment(linker, "/EXPORT:vpkc_set_logger")
#pragma comment(linker, "/EXPORT:vpkc_free_update_manager")
#pragma comment(linker, "/EXPORT:vpkc_free_update_info")
#pragma comment(linker, "/EXPORT:vpkc_free_asset")
#elif defined(VELOPACK_LIBC_EXPORTS) && !defined(_WIN32)
#define VPKC_EXPORT __attribute__((visibility("default"))) __attribute__((used))
#define VPKC_CALL
#else
#define VPKC_EXPORT
#define VPKC_CALL
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -63,9 +30,10 @@ typedef void (*vpkc_log_callback_t)(void* pUserData, const char* pszLevel, const
typedef void (*vpkc_hook_callback_t)(void* pUserData, const char* pszAppVersion); typedef void (*vpkc_hook_callback_t)(void* pUserData, const char* pszAppVersion);
typedef enum vpkc_update_check_t { typedef enum vpkc_update_check_t {
UPDATE_ERROR = -1,
UPDATE_AVAILABLE = 0, UPDATE_AVAILABLE = 0,
NO_UPDATE_AVAILABLE = 1, NO_UPDATE_AVAILABLE = 1,
UPDATE_ERROR = 2, REMOTE_IS_EMPTY = 2,
} vpkc_update_check_t; } vpkc_update_check_t;
// !! AUTO-GENERATED-START C_TYPES // !! AUTO-GENERATED-START C_TYPES
@@ -138,55 +106,55 @@ typedef struct vpkc_update_options_t {
/// Creates a new vpkc_update_manager_t. Free with vpkc_free_update_manager. /// Creates a new vpkc_update_manager_t. Free with vpkc_free_update_manager.
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager); bool vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion); size_t vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId); size_t vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager); bool vpkc_is_portable(vpkc_update_manager_t* pManager);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset); bool vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate); vpkc_update_check_t vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress, void* pUserData = 0); bool vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress, void* pUserData = 0);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs); bool vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager); void vpkc_free_update_manager(vpkc_update_manager_t* pManager);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo); void vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo);
/// \group UpdateManager /// \group UpdateManager
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pAsset); void vpkc_free_asset(vpkc_asset_t* pAsset);
/// Should be run at the beginning of your application to handle Velopack events. /// Should be run at the beginning of your application to handle Velopack events.
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_run(void* pUserData = 0); void vpkc_app_run(void* pUserData = 0);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_auto_apply_on_startup(bool bAutoApply); void vpkc_app_set_auto_apply_on_startup(bool bAutoApply);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs); void vpkc_app_set_args(char** pArgs, size_t cArgs);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_config_t* pLocator); void vpkc_app_set_locator(vpkc_locator_config_t* pLocator);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall); void vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cbBeforeUninstall); void vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cbBeforeUninstall);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_update(vpkc_hook_callback_t cbBeforeUpdate); void vpkc_app_set_hook_before_update(vpkc_hook_callback_t cbBeforeUpdate);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_update(vpkc_hook_callback_t cbAfterUpdate); void vpkc_app_set_hook_after_update(vpkc_hook_callback_t cbAfterUpdate);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFirstRun); void vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFirstRun);
/// \group VelopackApp /// \group VelopackApp
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted); void vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted);
/// Given a function has returned a failure, this function will return the last error message as a string. /// Given a function has returned a failure, this function will return the last error message as a string.
VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError); size_t vpkc_get_last_error(char* pszError, size_t cError);
/// Sets the callback to be used/called with log messages from Velopack. /// Sets the callback to be used/called with log messages from Velopack.
VPKC_EXPORT void VPKC_CALL vpkc_set_logger(vpkc_log_callback_t cbLog, void* pUserData = 0); void vpkc_set_logger(vpkc_log_callback_t cbLog, void* pUserData = 0);
#ifdef __cplusplus // end of extern "C" #ifdef __cplusplus // end of extern "C"
} }
@@ -594,6 +562,7 @@ public:
throw_last_error(); throw_last_error();
return std::nullopt; return std::nullopt;
case vpkc_update_check_t::NO_UPDATE_AVAILABLE: case vpkc_update_check_t::NO_UPDATE_AVAILABLE:
case vpkc_update_check_t::REMOTE_IS_EMPTY:
return std::nullopt; return std::nullopt;
case vpkc_update_check_t::UPDATE_AVAILABLE: case vpkc_update_check_t::UPDATE_AVAILABLE:
UpdateInfo cpp_info = to_cpp(update); UpdateInfo cpp_info = to_cpp(update);

View File

@@ -1,408 +1,408 @@
// Uncomment to enable debug type checking // // Uncomment to enable debug type checking
// #pragma include_alias( "velopack_libc/src/lib.rs.h", "../../../target/cxxbridge/velopack_libc/src/lib.rs.h" ) // // #pragma include_alias( "velopack_libc/src/lib.rs.h", "../../../target/cxxbridge/velopack_libc/src/lib.rs.h" )
// #pragma include_alias( "velopack_libc/include/Velopack.h", "../include/Velopack.h" ) // // #pragma include_alias( "velopack_libc/include/Velopack.h", "../include/Velopack.h" )
// #pragma include_alias( "velopack_libc/src/bridge.hpp", "bridge.hpp" ) // // #pragma include_alias( "velopack_libc/src/bridge.hpp", "bridge.hpp" )
// #pragma include_alias( "rust/cxx.h", "../../../target/cxxbridge/rust/cxx.h" ) // // #pragma include_alias( "rust/cxx.h", "../../../target/cxxbridge/rust/cxx.h" )
#include "velopack_libc/src/lib.rs.h" // #include "velopack_libc/src/lib.rs.h"
static inline std::string to_bridgestring(const char* psz) { // static inline std::string to_bridgestring(const char* psz) {
return psz == nullptr ? "" : psz; // return psz == nullptr ? "" : psz;
} // }
static inline char* to_cstring(const std::string& str) { // static inline char* to_cstring(const std::string& str) {
return const_cast<char*>(str.c_str()); // return const_cast<char*>(str.c_str());
} // }
static inline char* to_cstring_opt(const std::optional<std::string>& str) { // static inline char* to_cstring_opt(const std::optional<std::string>& str) {
return str.has_value() ? to_cstring(str.value()) : nullptr; // return str.has_value() ? to_cstring(str.value()) : nullptr;
} // }
static inline StringOption to_bridgestring_opt(const char* psz) { // static inline StringOption to_bridgestring_opt(const char* psz) {
StringOption opt; // StringOption opt;
if (psz == nullptr) { // if (psz == nullptr) {
opt.has_data = false; // opt.has_data = false;
return opt; // return opt;
} // }
opt.has_data = true; // opt.has_data = true;
opt.data = psz; // opt.data = psz;
return opt; // return opt;
} // }
static inline void allocate_string(::rust::String& str, char** ppsz) { // static inline void allocate_string(::rust::String& str, char** ppsz) {
#ifdef _WIN32 // #ifdef _WIN32
*ppsz = _strdup(str.c_str()); // *ppsz = _strdup(str.c_str());
#else // #else
*ppsz = strdup(str.c_str()); // *ppsz = strdup(str.c_str());
#endif // #endif
} // }
static inline void allocate_string_opt(StringOption str, char** ppsz) { // static inline void allocate_string_opt(StringOption str, char** ppsz) {
if (str.has_data) { // if (str.has_data) {
allocate_string(str.data, ppsz); // allocate_string(str.data, ppsz);
} else { // } else {
*ppsz = nullptr; // *ppsz = nullptr;
} // }
} // }
// !! AUTO-GENERATED-START BRIDGE_MAPPING // // !! AUTO-GENERATED-START BRIDGE_MAPPING
static inline VelopackLocatorConfigDto to_bridge(vpkc_locator_config_t* pDto) { // static inline VelopackLocatorConfigDto to_bridge(vpkc_locator_config_t* pDto) {
if (pDto == nullptr) { return {}; } // if (pDto == nullptr) { return {}; }
return { // return {
to_bridgestring(pDto->RootAppDir), // to_bridgestring(pDto->RootAppDir),
to_bridgestring(pDto->UpdateExePath), // to_bridgestring(pDto->UpdateExePath),
to_bridgestring(pDto->PackagesDir), // to_bridgestring(pDto->PackagesDir),
to_bridgestring(pDto->ManifestPath), // to_bridgestring(pDto->ManifestPath),
to_bridgestring(pDto->CurrentBinaryDir), // to_bridgestring(pDto->CurrentBinaryDir),
pDto->IsPortable, // pDto->IsPortable,
}; // };
} // }
static inline VelopackLocatorConfigDtoOption to_bridge_opt(vpkc_locator_config_t* pDto) { // static inline VelopackLocatorConfigDtoOption to_bridge_opt(vpkc_locator_config_t* pDto) {
VelopackLocatorConfigDtoOption opt; // VelopackLocatorConfigDtoOption opt;
if (pDto == nullptr) { // if (pDto == nullptr) {
opt.has_data = false; // opt.has_data = false;
return opt; // return opt;
} // }
opt.has_data = true; // opt.has_data = true;
opt.data = to_bridge(pDto); // opt.data = to_bridge(pDto);
return opt; // return opt;
} // }
static inline void allocate_velopacklocatorconfig(VelopackLocatorConfigDto bridgeDto, vpkc_locator_config_t* pDto) { // static inline void allocate_velopacklocatorconfig(VelopackLocatorConfigDto bridgeDto, vpkc_locator_config_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
allocate_string(bridgeDto.RootAppDir, &pDto->RootAppDir); // allocate_string(bridgeDto.RootAppDir, &pDto->RootAppDir);
allocate_string(bridgeDto.UpdateExePath, &pDto->UpdateExePath); // allocate_string(bridgeDto.UpdateExePath, &pDto->UpdateExePath);
allocate_string(bridgeDto.PackagesDir, &pDto->PackagesDir); // allocate_string(bridgeDto.PackagesDir, &pDto->PackagesDir);
allocate_string(bridgeDto.ManifestPath, &pDto->ManifestPath); // allocate_string(bridgeDto.ManifestPath, &pDto->ManifestPath);
allocate_string(bridgeDto.CurrentBinaryDir, &pDto->CurrentBinaryDir); // allocate_string(bridgeDto.CurrentBinaryDir, &pDto->CurrentBinaryDir);
pDto->IsPortable = bridgeDto.IsPortable; // pDto->IsPortable = bridgeDto.IsPortable;
} // }
static inline void free_velopacklocatorconfig(vpkc_locator_config_t* pDto) { // static inline void free_velopacklocatorconfig(vpkc_locator_config_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
free(pDto->RootAppDir); // free(pDto->RootAppDir);
free(pDto->UpdateExePath); // free(pDto->UpdateExePath);
free(pDto->PackagesDir); // free(pDto->PackagesDir);
free(pDto->ManifestPath); // free(pDto->ManifestPath);
free(pDto->CurrentBinaryDir); // free(pDto->CurrentBinaryDir);
} // }
static inline VelopackAssetDto to_bridge(vpkc_asset_t* pDto) { // static inline VelopackAssetDto to_bridge(vpkc_asset_t* pDto) {
if (pDto == nullptr) { return {}; } // if (pDto == nullptr) { return {}; }
return { // return {
to_bridgestring(pDto->PackageId), // to_bridgestring(pDto->PackageId),
to_bridgestring(pDto->Version), // to_bridgestring(pDto->Version),
to_bridgestring(pDto->Type), // to_bridgestring(pDto->Type),
to_bridgestring(pDto->FileName), // to_bridgestring(pDto->FileName),
to_bridgestring(pDto->SHA1), // to_bridgestring(pDto->SHA1),
to_bridgestring(pDto->SHA256), // to_bridgestring(pDto->SHA256),
pDto->Size, // pDto->Size,
to_bridgestring(pDto->NotesMarkdown), // to_bridgestring(pDto->NotesMarkdown),
to_bridgestring(pDto->NotesHtml), // to_bridgestring(pDto->NotesHtml),
}; // };
} // }
static inline VelopackAssetDtoOption to_bridge_opt(vpkc_asset_t* pDto) { // static inline VelopackAssetDtoOption to_bridge_opt(vpkc_asset_t* pDto) {
VelopackAssetDtoOption opt; // VelopackAssetDtoOption opt;
if (pDto == nullptr) { // if (pDto == nullptr) {
opt.has_data = false; // opt.has_data = false;
return opt; // return opt;
} // }
opt.has_data = true; // opt.has_data = true;
opt.data = to_bridge(pDto); // opt.data = to_bridge(pDto);
return opt; // return opt;
} // }
static inline void allocate_velopackasset(VelopackAssetDto bridgeDto, vpkc_asset_t* pDto) { // static inline void allocate_velopackasset(VelopackAssetDto bridgeDto, vpkc_asset_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
allocate_string(bridgeDto.PackageId, &pDto->PackageId); // allocate_string(bridgeDto.PackageId, &pDto->PackageId);
allocate_string(bridgeDto.Version, &pDto->Version); // allocate_string(bridgeDto.Version, &pDto->Version);
allocate_string(bridgeDto.Type, &pDto->Type); // allocate_string(bridgeDto.Type, &pDto->Type);
allocate_string(bridgeDto.FileName, &pDto->FileName); // allocate_string(bridgeDto.FileName, &pDto->FileName);
allocate_string(bridgeDto.SHA1, &pDto->SHA1); // allocate_string(bridgeDto.SHA1, &pDto->SHA1);
allocate_string(bridgeDto.SHA256, &pDto->SHA256); // allocate_string(bridgeDto.SHA256, &pDto->SHA256);
pDto->Size = bridgeDto.Size; // pDto->Size = bridgeDto.Size;
allocate_string(bridgeDto.NotesMarkdown, &pDto->NotesMarkdown); // allocate_string(bridgeDto.NotesMarkdown, &pDto->NotesMarkdown);
allocate_string(bridgeDto.NotesHtml, &pDto->NotesHtml); // allocate_string(bridgeDto.NotesHtml, &pDto->NotesHtml);
} // }
static inline void free_velopackasset(vpkc_asset_t* pDto) { // static inline void free_velopackasset(vpkc_asset_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
free(pDto->PackageId); // free(pDto->PackageId);
free(pDto->Version); // free(pDto->Version);
free(pDto->Type); // free(pDto->Type);
free(pDto->FileName); // free(pDto->FileName);
free(pDto->SHA1); // free(pDto->SHA1);
free(pDto->SHA256); // free(pDto->SHA256);
free(pDto->NotesMarkdown); // free(pDto->NotesMarkdown);
free(pDto->NotesHtml); // free(pDto->NotesHtml);
} // }
static inline UpdateInfoDto to_bridge(vpkc_update_info_t* pDto) { // static inline UpdateInfoDto to_bridge(vpkc_update_info_t* pDto) {
if (pDto == nullptr) { return {}; } // if (pDto == nullptr) { return {}; }
return { // return {
to_bridge(&pDto->TargetFullRelease), // to_bridge(&pDto->TargetFullRelease),
pDto->IsDowngrade, // pDto->IsDowngrade,
}; // };
} // }
static inline UpdateInfoDtoOption to_bridge_opt(vpkc_update_info_t* pDto) { // static inline UpdateInfoDtoOption to_bridge_opt(vpkc_update_info_t* pDto) {
UpdateInfoDtoOption opt; // UpdateInfoDtoOption opt;
if (pDto == nullptr) { // if (pDto == nullptr) {
opt.has_data = false; // opt.has_data = false;
return opt; // return opt;
} // }
opt.has_data = true; // opt.has_data = true;
opt.data = to_bridge(pDto); // opt.data = to_bridge(pDto);
return opt; // return opt;
} // }
static inline void allocate_updateinfo(UpdateInfoDto bridgeDto, vpkc_update_info_t* pDto) { // static inline void allocate_updateinfo(UpdateInfoDto bridgeDto, vpkc_update_info_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
allocate_velopackasset(bridgeDto.TargetFullRelease, &pDto->TargetFullRelease); // allocate_velopackasset(bridgeDto.TargetFullRelease, &pDto->TargetFullRelease);
pDto->IsDowngrade = bridgeDto.IsDowngrade; // pDto->IsDowngrade = bridgeDto.IsDowngrade;
} // }
static inline void free_updateinfo(vpkc_update_info_t* pDto) { // static inline void free_updateinfo(vpkc_update_info_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
free_velopackasset(&pDto->TargetFullRelease); // free_velopackasset(&pDto->TargetFullRelease);
} // }
static inline UpdateOptionsDto to_bridge(vpkc_update_options_t* pDto) { // static inline UpdateOptionsDto to_bridge(vpkc_update_options_t* pDto) {
if (pDto == nullptr) { return {}; } // if (pDto == nullptr) { return {}; }
return { // return {
pDto->AllowVersionDowngrade, // pDto->AllowVersionDowngrade,
to_bridgestring_opt(pDto->ExplicitChannel), // to_bridgestring_opt(pDto->ExplicitChannel),
}; // };
} // }
static inline UpdateOptionsDtoOption to_bridge_opt(vpkc_update_options_t* pDto) { // static inline UpdateOptionsDtoOption to_bridge_opt(vpkc_update_options_t* pDto) {
UpdateOptionsDtoOption opt; // UpdateOptionsDtoOption opt;
if (pDto == nullptr) { // if (pDto == nullptr) {
opt.has_data = false; // opt.has_data = false;
return opt; // return opt;
} // }
opt.has_data = true; // opt.has_data = true;
opt.data = to_bridge(pDto); // opt.data = to_bridge(pDto);
return opt; // return opt;
} // }
static inline void allocate_updateoptions(UpdateOptionsDto bridgeDto, vpkc_update_options_t* pDto) { // static inline void allocate_updateoptions(UpdateOptionsDto bridgeDto, vpkc_update_options_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
pDto->AllowVersionDowngrade = bridgeDto.AllowVersionDowngrade; // pDto->AllowVersionDowngrade = bridgeDto.AllowVersionDowngrade;
allocate_string_opt(bridgeDto.ExplicitChannel, &pDto->ExplicitChannel); // allocate_string_opt(bridgeDto.ExplicitChannel, &pDto->ExplicitChannel);
} // }
static inline void free_updateoptions(vpkc_update_options_t* pDto) { // static inline void free_updateoptions(vpkc_update_options_t* pDto) {
if (pDto == nullptr) { return; } // if (pDto == nullptr) { return; }
free(pDto->ExplicitChannel); // free(pDto->ExplicitChannel);
} // }
// !! AUTO-GENERATED-END BRIDGE_MAPPING // // !! AUTO-GENERATED-END BRIDGE_MAPPING
static inline size_t return_c_string(std::string& value, char* psz, size_t csz) { // static inline size_t return_c_string(std::string& value, char* psz, size_t csz) {
if (value.empty()) { // if (value.empty()) {
return 0; // return 0;
} // }
const char* c_str = value.c_str(); // const char* c_str = value.c_str();
size_t len = strlen(c_str); // size_t len = strlen(c_str);
if (psz == nullptr || csz == 0 || len == 0) { // if (psz == nullptr || csz == 0 || len == 0) {
// no buffer has been provided, return the length // // no buffer has been provided, return the length
return len; // return len;
} // }
// shorten the length if it's longer than the buffer // // shorten the length if it's longer than the buffer
if (len > csz) { // if (len > csz) {
len = csz; // len = csz;
} // }
// copy the string to the buffer // // copy the string to the buffer
memcpy(psz, c_str, len); // memcpy(psz, c_str, len);
return len; // return len;
} // }
// Error handling // // Error handling
std::string lastError; // std::string lastError;
VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError) { // VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError) {
return return_c_string(lastError, pszError, cError); // return return_c_string(lastError, pszError, cError);
} // }
static inline void set_last_error(const char* pszError) { // static inline void set_last_error(const char* pszError) {
lastError = pszError; // lastError = pszError;
} // }
static inline void clear_last_error() { // static inline void clear_last_error() {
lastError.clear(); // lastError.clear();
} // }
// Update Manager // // Update Manager
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager) { // VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager) {
clear_last_error(); // clear_last_error();
try { // try {
if (pManager == nullptr) { // if (pManager == nullptr) {
set_last_error("pManager cannot be null"); // set_last_error("pManager cannot be null");
return false; // return false;
} // }
VelopackLocatorConfigDtoOption locator = to_bridge_opt(pLocator); // VelopackLocatorConfigDtoOption locator = to_bridge_opt(pLocator);
UpdateOptionsDtoOption options = to_bridge_opt(pOptions); // UpdateOptionsDtoOption options = to_bridge_opt(pOptions);
::rust::Box<::UpdateManagerOpaque> manager = bridge_new_update_manager(pszUrlOrString, options, locator); // ::rust::Box<::UpdateManagerOpaque> manager = bridge_new_update_manager(pszUrlOrString, options, locator);
UpdateManagerOpaque* pOpaque = manager.into_raw(); // UpdateManagerOpaque* pOpaque = manager.into_raw();
*pManager = reinterpret_cast<vpkc_update_manager_t*>(pOpaque); // *pManager = reinterpret_cast<vpkc_update_manager_t*>(pOpaque);
return true; // return true;
} catch (const std::exception& e) { // } catch (const std::exception& e) {
set_last_error(e.what()); // set_last_error(e.what());
return false; // return false;
} // }
} // }
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion) { // VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
std::string version = (std::string)bridge_get_current_version(*pOpaque); // std::string version = (std::string)bridge_get_current_version(*pOpaque);
return return_c_string(version, pszVersion, cVersion); // return return_c_string(version, pszVersion, cVersion);
} // }
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId) { // VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
std::string id = (std::string)bridge_get_app_id(*pOpaque); // std::string id = (std::string)bridge_get_app_id(*pOpaque);
return return_c_string(id, pszId, cId); // return return_c_string(id, pszId, cId);
} // }
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager) { // VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
return bridge_is_portable(*pOpaque); // return bridge_is_portable(*pOpaque);
} // }
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset) { // VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
VelopackAssetDtoOption asset = bridge_update_pending_restart(*pOpaque); // VelopackAssetDtoOption asset = bridge_update_pending_restart(*pOpaque);
if (asset.has_data) { // if (asset.has_data) {
allocate_velopackasset(asset.data, pAsset); // allocate_velopackasset(asset.data, pAsset);
return true; // return true;
} // }
return false; // return false;
} // }
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate) { // VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate) {
clear_last_error(); // clear_last_error();
try { // try {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
UpdateInfoDtoOption update = bridge_check_for_updates(*pOpaque); // UpdateInfoDtoOption update = bridge_check_for_updates(*pOpaque);
if (update.has_data) { // if (update.has_data) {
allocate_updateinfo(update.data, pUpdate); // allocate_updateinfo(update.data, pUpdate);
return vpkc_update_check_t::UPDATE_AVAILABLE; // return vpkc_update_check_t::UPDATE_AVAILABLE;
} // }
return vpkc_update_check_t::NO_UPDATE_AVAILABLE; // return vpkc_update_check_t::NO_UPDATE_AVAILABLE;
} // }
catch (const std::exception& e) { // catch (const std::exception& e) {
set_last_error(e.what()); // set_last_error(e.what());
return vpkc_update_check_t::UPDATE_ERROR; // return vpkc_update_check_t::UPDATE_ERROR;
} // }
} // }
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress, void* pUserData) { // VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress, void* pUserData) {
clear_last_error(); // clear_last_error();
try { // try {
if (!pUpdate) { // if (!pUpdate) {
set_last_error("pUpdate is a required parameter"); // set_last_error("pUpdate is a required parameter");
return false; // return false;
} // }
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
UpdateInfoDto update = to_bridge(pUpdate); // UpdateInfoDto update = to_bridge(pUpdate);
DownloadCallbackManager download{}; // DownloadCallbackManager download{};
download.progress_cb = cbProgress; // download.progress_cb = cbProgress;
download.user_data = pUserData; // download.user_data = pUserData;
bridge_download_updates(*pOpaque, update, download); // bridge_download_updates(*pOpaque, update, download);
return true; // return true;
} // }
catch (const std::exception& e) { // catch (const std::exception& e) {
set_last_error(e.what()); // set_last_error(e.what());
return false; // return false;
} // }
} // }
VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs) { // VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs) {
clear_last_error(); // clear_last_error();
try { // try {
if (!pAsset) { // if (!pAsset) {
set_last_error("pAsset is a required parameter"); // set_last_error("pAsset is a required parameter");
return false; // return false;
} // }
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
VelopackAssetDto asset = to_bridge(pAsset); // VelopackAssetDto asset = to_bridge(pAsset);
::rust::Vec<::rust::String> restartArgs{}; // ::rust::Vec<::rust::String> restartArgs{};
for (size_t i = 0; i < cRestartArgs; i++) { // for (size_t i = 0; i < cRestartArgs; i++) {
restartArgs.push_back(pRestartArgs[i]); // restartArgs.push_back(pRestartArgs[i]);
} // }
bridge_wait_exit_then_apply_update(*pOpaque, asset, bSilent, bRestart, restartArgs); // bridge_wait_exit_then_apply_update(*pOpaque, asset, bSilent, bRestart, restartArgs);
return true; // return true;
} // }
catch (const std::exception& e) { // catch (const std::exception& e) {
set_last_error(e.what()); // set_last_error(e.what());
return false; // return false;
} // }
} // }
// VelopackApp // // VelopackApp
bool autoApply = true; // bool autoApply = true;
StringArrayOption args{}; // StringArrayOption args{};
VelopackLocatorConfigDtoOption locator{}; // VelopackLocatorConfigDtoOption locator{};
HookCallbackManager hooks{}; // HookCallbackManager hooks{};
VPKC_EXPORT void VPKC_CALL vpkc_app_set_auto_apply_on_startup(bool bAutoApply) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_auto_apply_on_startup(bool bAutoApply) {
autoApply = bAutoApply; // autoApply = bAutoApply;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs) {
args.has_data = true; // args.has_data = true;
args.data.clear(); // args.data.clear();
for (size_t i = 0; i < cArgs; i++) { // for (size_t i = 0; i < cArgs; i++) {
args.data.push_back(pArgs[i]); // args.data.push_back(pArgs[i]);
} // }
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_config_t* pLocator) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_config_t* pLocator) {
locator = to_bridge_opt(pLocator); // locator = to_bridge_opt(pLocator);
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall) {
hooks.after_install = cbAfterInstall; // hooks.after_install = cbAfterInstall;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cbBeforeUninstall) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cbBeforeUninstall) {
hooks.before_uninstall = cbBeforeUninstall; // hooks.before_uninstall = cbBeforeUninstall;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_update(vpkc_hook_callback_t cbBeforeUpdate) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_update(vpkc_hook_callback_t cbBeforeUpdate) {
hooks.before_update = cbBeforeUpdate; // hooks.before_update = cbBeforeUpdate;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_update(vpkc_hook_callback_t cbAfterUpdate) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_update(vpkc_hook_callback_t cbAfterUpdate) {
hooks.after_update = cbAfterUpdate; // hooks.after_update = cbAfterUpdate;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFirstRun) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFirstRun) {
hooks.first_run = cbFirstRun; // hooks.first_run = cbFirstRun;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted) { // VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted) {
hooks.restarted = cbRestarted; // hooks.restarted = cbRestarted;
} // }
VPKC_EXPORT void VPKC_CALL vpkc_app_run(void* pUserData) { // VPKC_EXPORT void VPKC_CALL vpkc_app_run(void* pUserData) {
hooks.user_data = pUserData; // hooks.user_data = pUserData;
bridge_appbuilder_run(hooks, args, locator, autoApply); // bridge_appbuilder_run(hooks, args, locator, autoApply);
} // }
// Misc functions // // Misc functions
LoggerCallbackManager logMgr{}; // LoggerCallbackManager logMgr{};
VPKC_EXPORT void VPKC_CALL vpkc_set_logger(vpkc_log_callback_t cbLog, void* pUserData) { // VPKC_EXPORT void VPKC_CALL vpkc_set_logger(vpkc_log_callback_t cbLog, void* pUserData) {
logMgr.lob_cb = cbLog; // logMgr.lob_cb = cbLog;
logMgr.user_data = pUserData; // logMgr.user_data = pUserData;
bridge_set_logger_callback(&logMgr); // bridge_set_logger_callback(&logMgr);
} // }
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager) { // VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager); // UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
auto box = ::rust::Box<::UpdateManagerOpaque>::from_raw(pOpaque); // auto box = ::rust::Box<::UpdateManagerOpaque>::from_raw(pOpaque);
// this will free when the box goes out of scope // // this will free when the box goes out of scope
} // }
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo) { // VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo) {
free_updateinfo(pUpdateInfo); // free_updateinfo(pUpdateInfo);
} // }
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pAsset) { // VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pAsset) {
free_velopackasset(pAsset); // free_velopackasset(pAsset);
} // }

View File

@@ -1,69 +1,69 @@
#pragma once // #pragma once
#include "rust/cxx.h" // #include "rust/cxx.h"
#include "velopack_libc/include/Velopack.h" // #include "velopack_libc/include/Velopack.h"
struct HookCallbackManager { // struct HookCallbackManager {
vpkc_hook_callback_t after_install = nullptr; // vpkc_hook_callback_t after_install = nullptr;
vpkc_hook_callback_t before_uninstall = nullptr; // vpkc_hook_callback_t before_uninstall = nullptr;
vpkc_hook_callback_t before_update = nullptr; // vpkc_hook_callback_t before_update = nullptr;
vpkc_hook_callback_t after_update = nullptr; // vpkc_hook_callback_t after_update = nullptr;
vpkc_hook_callback_t first_run = nullptr; // vpkc_hook_callback_t first_run = nullptr;
vpkc_hook_callback_t restarted = nullptr; // vpkc_hook_callback_t restarted = nullptr;
void* user_data = nullptr; // void* user_data = nullptr;
void install_hook(::rust::String app_version) const { // void install_hook(::rust::String app_version) const {
if (after_install) { // if (after_install) {
after_install(user_data, app_version.c_str()); // after_install(user_data, app_version.c_str());
} // }
}; // };
void update_hook(::rust::String app_version) const { // void update_hook(::rust::String app_version) const {
if (after_update) { // if (after_update) {
after_update(user_data, app_version.c_str()); // after_update(user_data, app_version.c_str());
} // }
}; // };
void obsolete_hook(::rust::String app_version) const { // void obsolete_hook(::rust::String app_version) const {
if (before_update) { // if (before_update) {
before_update(user_data, app_version.c_str()); // before_update(user_data, app_version.c_str());
} // }
}; // };
void uninstall_hook(::rust::String app_version) const { // void uninstall_hook(::rust::String app_version) const {
if (before_uninstall) { // if (before_uninstall) {
before_uninstall(user_data, app_version.c_str()); // before_uninstall(user_data, app_version.c_str());
} // }
}; // };
void firstrun_hook(::rust::String app_version) const { // void firstrun_hook(::rust::String app_version) const {
if (first_run) { // if (first_run) {
first_run(user_data, app_version.c_str()); // first_run(user_data, app_version.c_str());
} // }
}; // };
void restarted_hook(::rust::String app_version) const { // void restarted_hook(::rust::String app_version) const {
if (restarted) { // if (restarted) {
restarted(user_data, app_version.c_str()); // restarted(user_data, app_version.c_str());
} // }
}; // };
}; // };
struct DownloadCallbackManager { // struct DownloadCallbackManager {
vpkc_progress_callback_t progress_cb = nullptr; // vpkc_progress_callback_t progress_cb = nullptr;
void* user_data = nullptr; // void* user_data = nullptr;
void download_progress(int16_t progress) const { // void download_progress(int16_t progress) const {
if (progress_cb) { // if (progress_cb) {
progress_cb(user_data, progress); // progress_cb(user_data, progress);
} // }
}; // };
}; // };
struct LoggerCallbackManager { // struct LoggerCallbackManager {
vpkc_log_callback_t lob_cb = nullptr; // vpkc_log_callback_t lob_cb = nullptr;
void* user_data = nullptr; // void* user_data = nullptr;
void log(::rust::String level, ::rust::String message) const { // void log(::rust::String level, ::rust::String message) const {
if (lob_cb) { // if (lob_cb) {
lob_cb(user_data, level.c_str(), message.c_str()); // lob_cb(user_data, level.c_str(), message.c_str());
} // }
}; // };
}; // };

View File

@@ -1,143 +1,352 @@
#![allow(dead_code)] #![allow(dead_code)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(non_camel_case_types)]
mod map; mod statics;
use map::*; use statics::*;
use anyhow::{bail, Result}; mod types;
use log::{Level, Log, Metadata, Record}; use types::*;
use std::sync::atomic::{AtomicUsize, Ordering};
use anyhow::{anyhow, bail};
use std::ffi::{c_char, c_void, CString};
use velopack::{sources, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp}; use velopack::{sources, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp};
#[cxx::bridge] #[repr(C)]
mod ffi { pub enum vpkc_update_check_t {
// Shared structs with fields visible to both languages. UPDATE_ERROR = -1,
#[derive(Default)] UPDATE_AVAILABLE = 0,
pub struct StringOption { NO_UPDATE_AVAILABLE = 1,
pub data: String, REMOTE_IS_EMPTY = 2,
pub has_data: bool, }
#[no_mangle]
pub extern "C" fn vpkc_new_update_manager(
psz_url_or_string: *const c_char,
p_options: *mut vpkc_update_options_t,
p_locator: *mut vpkc_locator_config_t,
p_manager: *mut *mut c_void,
) -> bool {
wrap_error(|| {
let update_url = c_to_string_opt(psz_url_or_string).ok_or(anyhow!("URL or path is null"))?;
let source = sources::AutoSource::new(&update_url);
let options = c_to_updateoptions_opt(p_options);
let locator = c_to_velopacklocatorconfig_opt(p_locator);
let manager = UpdateManager::new(source, options, locator)?;
let opaque = Box::new(UpdateManagerOpaque::new(manager));
unsafe { *p_manager = Box::into_raw(opaque) as *mut c_void };
Ok(())
})
}
#[no_mangle]
pub extern "C" fn vpkc_get_current_version(p_manager: *mut c_void, psz_version: *mut c_char, c_version: usize) -> usize {
if p_manager.is_null() {
return 0;
} }
#[derive(Default)] let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
pub struct StringArrayOption { let version = manager.obj.get_current_version_as_string();
pub data: Vec<String>, return_cstr(psz_version, c_version, &version)
pub has_data: bool, }
#[no_mangle]
pub extern "C" fn vpkc_get_app_id(p_manager: *mut c_void, psz_id: *mut c_char, c_id: usize) -> usize {
if p_manager.is_null() {
return 0;
} }
// !! AUTO-GENERATED-START BRIDGE_DTOS let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
#[derive(Default)] let app_id = manager.obj.get_app_id();
pub struct VelopackLocatorConfigDto { return_cstr(psz_id, c_id, &app_id)
pub RootAppDir: String, }
pub UpdateExePath: String,
pub PackagesDir: String, #[no_mangle]
pub ManifestPath: String, pub extern "C" fn vpkc_is_portable(p_manager: *mut c_void) -> bool {
pub CurrentBinaryDir: String, if p_manager.is_null() {
pub IsPortable: bool, return false;
} }
#[derive(Default)] let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
pub struct VelopackLocatorConfigDtoOption { manager.obj.get_is_portable()
pub data: VelopackLocatorConfigDto, }
pub has_data: bool,
#[no_mangle]
pub extern "C" fn vpkc_update_pending_restart(p_manager: *mut c_void, p_asset: *mut vpkc_asset_t) -> bool {
if p_manager.is_null() {
return false;
} }
#[derive(Default)] let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
pub struct VelopackAssetDto { let asset_opt = manager.obj.get_update_pending_restart();
pub PackageId: String,
pub Version: String, if let Some(asset) = asset_opt {
pub Type: String, unsafe { allocate_velopackasset(asset, p_asset) };
pub FileName: String, true
pub SHA1: String, } else {
pub SHA256: String, false
pub Size: u64, }
pub NotesMarkdown: String, }
pub NotesHtml: String,
#[no_mangle]
pub extern "C" fn vpkc_check_for_updates(p_manager: *mut c_void, p_update: *mut vpkc_update_info_t) -> vpkc_update_check_t {
if p_manager.is_null() {
set_last_error("pManager must not be null");
return vpkc_update_check_t::UPDATE_ERROR;
} }
#[derive(Default)] let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
pub struct VelopackAssetDtoOption {
pub data: VelopackAssetDto, match manager.obj.check_for_updates() {
pub has_data: bool, Ok(UpdateCheck::UpdateAvailable(info)) => {
unsafe {
allocate_updateinfo(info, p_update);
}
vpkc_update_check_t::UPDATE_AVAILABLE
}
Ok(UpdateCheck::RemoteIsEmpty) => vpkc_update_check_t::REMOTE_IS_EMPTY,
Ok(UpdateCheck::NoUpdateAvailable) => vpkc_update_check_t::NO_UPDATE_AVAILABLE,
Err(e) => {
set_last_error(&format!("{:?}", e));
vpkc_update_check_t::UPDATE_ERROR
}
}
}
#[no_mangle]
pub extern "C" fn vpkc_download_updates(
p_manager: *mut c_void,
p_update: *mut vpkc_update_info_t,
cb_progress: vpkc_progress_callback_t,
p_user_data: *mut c_void,
) -> bool {
wrap_error(|| {
if p_manager.is_null() {
bail!("pManager must not be null");
}
let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
let update = c_to_updateinfo_opt(p_update).ok_or(anyhow!("pUpdate must not be null"))?;
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(&update, 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_progress(p_user_data, progress as usize);
}
_ => {
// 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");
}
}
}
})
}
#[no_mangle]
pub extern "C" fn vpkc_wait_exit_then_apply_update(
p_manager: *mut c_void,
p_asset: *mut vpkc_asset_t,
b_silent: bool,
b_restart: bool,
p_restart_args: *mut *mut c_char,
c_restart_args: usize,
) -> bool {
wrap_error(|| {
if p_manager.is_null() {
bail!("pManager must not be null");
}
let manager = unsafe { &*(p_manager as *mut UpdateManagerOpaque) };
let asset = c_to_velopackasset_opt(p_asset).ok_or(anyhow!("pAsset must not be null"))?;
let restart_args = c_to_string_array_opt(p_restart_args, c_restart_args).unwrap_or_default();
manager.obj.wait_exit_then_apply_updates(&asset, b_silent, b_restart, &restart_args)?;
Ok(())
})
}
#[no_mangle]
pub extern "C" fn vpkc_free_update_manager(p_manager: *mut c_void) {
if !p_manager.is_null() {
// Convert the raw pointer back into a Box to deallocate it properly
let _ = unsafe { Box::from_raw(p_manager as *mut UpdateManagerOpaque) };
}
}
#[no_mangle]
pub extern "C" fn vpkc_free_update_info(p_update_info: *mut vpkc_update_info_t) {
if !p_update_info.is_null() {
unsafe { free_updateinfo(p_update_info) };
}
}
#[no_mangle]
pub extern "C" fn vpkc_free_asset(p_asset: *mut vpkc_asset_t) {
if !p_asset.is_null() {
unsafe { free_velopackasset(p_asset) };
}
}
#[no_mangle]
pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) {
let app_options = VELOPACK_APP.read().unwrap();
let mut app = VelopackApp::build();
if let Some(auto_apply) = app_options.auto_apply {
app = app.set_auto_apply_on_startup(auto_apply);
} }
#[derive(Default)] if let Some(args) = &app_options.args {
pub struct UpdateInfoDto { app = app.set_args(args.clone());
pub TargetFullRelease: VelopackAssetDto,
pub IsDowngrade: bool,
} }
#[derive(Default)] if let Some(locator) = &app_options.locator {
pub struct UpdateInfoDtoOption { app = app.set_locator(locator.clone());
pub data: UpdateInfoDto,
pub has_data: bool,
} }
#[derive(Default)] if let Some(hook) = &app_options.install_hook {
pub struct UpdateOptionsDto { app = app.on_after_install_fast_callback(|version| {
pub AllowVersionDowngrade: bool, let c_string = CString::new(version.to_string()).unwrap();
pub ExplicitChannel: StringOption, hook(p_user_data, c_string.as_ptr());
});
} }
#[derive(Default)] if let Some(hook) = &app_options.uninstall_hook {
pub struct UpdateOptionsDtoOption { app = app.on_before_uninstall_fast_callback(|version| {
pub data: UpdateOptionsDto, let c_string = CString::new(version.to_string()).unwrap();
pub has_data: bool, hook(p_user_data, c_string.as_ptr());
} });
// !! AUTO-GENERATED-END BRIDGE_DTOS
// C++ types and signatures exposed to Rust.
unsafe extern "C++" {
include!("velopack_libc/include/Velopack.h");
include!("velopack_libc/src/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: String, message: String);
} }
// Rust types and signatures exposed to C++. if let Some(hook) = &app_options.obsolete_hook {
extern "Rust" { app = app.on_before_update_fast_callback(|version| {
type UpdateManagerOpaque; let c_string = CString::new(version.to_string()).unwrap();
fn bridge_new_update_manager( hook(p_user_data, c_string.as_ptr());
url_or_path: &String, });
options: &UpdateOptionsDtoOption,
locator: &VelopackLocatorConfigDtoOption,
) -> 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) -> VelopackAssetDtoOption;
fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<UpdateInfoDtoOption>;
fn bridge_download_updates(
manager: &UpdateManagerOpaque,
to_download: &UpdateInfoDto,
progress: &DownloadCallbackManager,
) -> Result<()>;
fn bridge_wait_exit_then_apply_update(
manager: &UpdateManagerOpaque,
to_apply: &VelopackAssetDto,
silent: bool,
restart: bool,
restart_args: &Vec<String>,
) -> Result<()>;
fn bridge_appbuilder_run(
cb: &HookCallbackManager,
custom_args: &StringArrayOption,
locator: &VelopackLocatorConfigDtoOption,
auto_apply: bool,
);
unsafe fn bridge_set_logger_callback(cb: *mut LoggerCallbackManager);
} }
if let Some(hook) = &app_options.update_hook {
app = app.on_after_update_fast_callback(|version| {
let c_string = CString::new(version.to_string()).unwrap();
hook(p_user_data, c_string.as_ptr());
});
}
if let Some(hook) = &app_options.firstrun_hook {
app = app.on_first_run(|version| {
let c_string = CString::new(version.to_string()).unwrap();
hook(p_user_data, c_string.as_ptr());
});
}
if let Some(hook) = &app_options.restarted_hook {
app = app.on_restarted(|version| {
let c_string = CString::new(version.to_string()).unwrap();
hook(p_user_data, c_string.as_ptr());
});
}
app.run();
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_auto_apply_on_startup(b_auto_apply: bool) {
update_app_options(|opt| {
opt.auto_apply = Some(b_auto_apply);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_args(p_args: *mut *mut c_char, c_args: usize) {
update_app_options(|opt| {
opt.args = c_to_string_array_opt(p_args, c_args);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_locator(p_locator: *mut vpkc_locator_config_t) {
update_app_options(|opt| {
opt.locator = c_to_velopacklocatorconfig_opt(p_locator);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_after_install(cb_after_install: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.install_hook = Some(cb_after_install);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_before_uninstall(cb_before_uninstall: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.uninstall_hook = Some(cb_before_uninstall);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_before_update(cb_before_update: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.obsolete_hook = Some(cb_before_update);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_after_update(cb_after_update: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.update_hook = Some(cb_after_update);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_first_run(cb_first_run: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.firstrun_hook = Some(cb_first_run);
});
}
#[no_mangle]
pub extern "C" fn vpkc_app_set_hook_restarted(cb_restarted: vpkc_hook_callback_t) {
update_app_options(|opt| {
opt.restarted_hook = Some(cb_restarted);
});
}
#[no_mangle]
pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: usize) -> usize {
let error = get_last_error();
return_cstr(psz_error, c_error, &error)
}
#[no_mangle]
pub extern "C" fn vpkc_set_logger(cb_log: vpkc_log_callback_t, p_user_data: *mut c_void) {
set_log_callback(cb_log, p_user_data);
} }
#[derive(Clone)] #[derive(Clone)]
@@ -157,185 +366,3 @@ impl Drop for UpdateManagerOpaque {
log::debug!("UpdateManagerOpaque dropped"); log::debug!("UpdateManagerOpaque dropped");
} }
} }
fn bridge_new_update_manager(
url_or_path: &String,
options: &ffi::UpdateOptionsDtoOption,
locator: &ffi::VelopackLocatorConfigDtoOption,
) -> Result<Box<UpdateManagerOpaque>> {
let source = sources::AutoSource::new(url_or_path);
let options = updateoptions_to_core_option(options);
let locator = velopacklocatorconfig_to_core_option(locator);
let update_manager = UpdateManager::new(source, options, locator)?;
Ok(Box::new(UpdateManagerOpaque::new(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::VelopackAssetDtoOption {
let asset_opt = manager.obj.get_update_pending_restart();
velopackasset_to_bridge_option(&asset_opt)
}
fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<ffi::UpdateInfoDtoOption> {
let info_opt = if let UpdateCheck::UpdateAvailable(info) = manager.obj.check_for_updates()? { Some(info) } else { None };
Ok(updateinfo_to_bridge_option(&info_opt))
}
fn bridge_download_updates(
manager: &UpdateManagerOpaque,
to_download: &ffi::UpdateInfoDto,
cb: &ffi::DownloadCallbackManager,
) -> Result<()> {
let info = updateinfo_to_core(&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_apply: &ffi::VelopackAssetDto,
silent: bool,
restart: bool,
restart_args: &Vec<String>,
) -> Result<()> {
let asset = velopackasset_to_core(&to_apply);
manager.obj.wait_exit_then_apply_updates(&asset, silent, restart, restart_args)?;
Ok(())
}
fn bridge_appbuilder_run(
cb: &ffi::HookCallbackManager,
custom_args: &ffi::StringArrayOption,
locator: &ffi::VelopackLocatorConfigDtoOption,
auto_apply: bool,
) {
let mut app = VelopackApp::build()
.set_auto_apply_on_startup(auto_apply)
.on_first_run(|v| cb.firstrun_hook(v.to_string()))
.on_restarted(|v| cb.restarted_hook(v.to_string()));
#[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 {
let locator = velopacklocatorconfig_to_core(&locator.data);
app = app.set_locator(locator);
}
if custom_args.has_data {
app = app.set_args(custom_args.data.clone());
}
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 => "error",
Level::Warn => "warn",
Level::Info => "info",
Level::Debug => "debug",
Level::Trace => "trace",
}
.to_string();
if let Some(cb) = get_logger() {
if let Some(cb) = unsafe { cb.as_mut() } {
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)
}
}
unsafe fn bridge_set_logger_callback(cb: *mut ffi::LoggerCallbackManager) {
let _ = log::set_logger(&LOGGER);
log::set_max_level(log::LevelFilter::Trace);
store_logger(cb);
}

View File

@@ -1,160 +0,0 @@
use std::path::PathBuf;
use velopack::locator::VelopackLocatorConfig;
use velopack::{UpdateInfo, UpdateOptions, VelopackAsset};
use crate::ffi::*;
fn pathbuf_to_core(dto: &String) -> PathBuf {
PathBuf::from(dto)
}
fn pathbuf_to_bridge(dto: &PathBuf) -> String {
dto.to_string_lossy().to_string()
}
fn string_to_core(dto: &String) -> String {
dto.clone()
}
fn string_to_bridge(dto: &String) -> String {
dto.clone()
}
fn bool_to_core(dto: &bool) -> bool {
*dto
}
fn bool_to_bridge(dto: &bool) -> bool {
*dto
}
fn u64_to_core(dto: &u64) -> u64 {
*dto
}
fn u64_to_bridge(dto: &u64) -> u64 {
*dto
}
// !! AUTO-GENERATED-START CORE_MAPPING
pub fn velopacklocatorconfig_to_core(dto: &VelopackLocatorConfigDto) -> VelopackLocatorConfig {
VelopackLocatorConfig {
RootAppDir: pathbuf_to_core(&dto.RootAppDir),
UpdateExePath: pathbuf_to_core(&dto.UpdateExePath),
PackagesDir: pathbuf_to_core(&dto.PackagesDir),
ManifestPath: pathbuf_to_core(&dto.ManifestPath),
CurrentBinaryDir: pathbuf_to_core(&dto.CurrentBinaryDir),
IsPortable: bool_to_core(&dto.IsPortable),
}
}
pub fn velopacklocatorconfig_to_bridge(dto: &VelopackLocatorConfig) -> VelopackLocatorConfigDto {
VelopackLocatorConfigDto {
RootAppDir: pathbuf_to_bridge(&dto.RootAppDir),
UpdateExePath: pathbuf_to_bridge(&dto.UpdateExePath),
PackagesDir: pathbuf_to_bridge(&dto.PackagesDir),
ManifestPath: pathbuf_to_bridge(&dto.ManifestPath),
CurrentBinaryDir: pathbuf_to_bridge(&dto.CurrentBinaryDir),
IsPortable: bool_to_bridge(&dto.IsPortable),
}
}
pub fn velopacklocatorconfig_to_core_option(dto: &VelopackLocatorConfigDtoOption) -> Option<VelopackLocatorConfig> {
if dto.has_data { Some(velopacklocatorconfig_to_core(&dto.data)) } else { None }
}
pub fn velopacklocatorconfig_to_bridge_option(dto: &Option<VelopackLocatorConfig>) -> VelopackLocatorConfigDtoOption {
match dto {
Some(dto) => VelopackLocatorConfigDtoOption { data: velopacklocatorconfig_to_bridge(dto), has_data: true },
None => VelopackLocatorConfigDtoOption { data: Default::default(), has_data: false },
}
}
pub fn velopackasset_to_core(dto: &VelopackAssetDto) -> VelopackAsset {
VelopackAsset {
PackageId: string_to_core(&dto.PackageId),
Version: string_to_core(&dto.Version),
Type: string_to_core(&dto.Type),
FileName: string_to_core(&dto.FileName),
SHA1: string_to_core(&dto.SHA1),
SHA256: string_to_core(&dto.SHA256),
Size: u64_to_core(&dto.Size),
NotesMarkdown: string_to_core(&dto.NotesMarkdown),
NotesHtml: string_to_core(&dto.NotesHtml),
}
}
pub fn velopackasset_to_bridge(dto: &VelopackAsset) -> VelopackAssetDto {
VelopackAssetDto {
PackageId: string_to_bridge(&dto.PackageId),
Version: string_to_bridge(&dto.Version),
Type: string_to_bridge(&dto.Type),
FileName: string_to_bridge(&dto.FileName),
SHA1: string_to_bridge(&dto.SHA1),
SHA256: string_to_bridge(&dto.SHA256),
Size: u64_to_bridge(&dto.Size),
NotesMarkdown: string_to_bridge(&dto.NotesMarkdown),
NotesHtml: string_to_bridge(&dto.NotesHtml),
}
}
pub fn velopackasset_to_core_option(dto: &VelopackAssetDtoOption) -> Option<VelopackAsset> {
if dto.has_data { Some(velopackasset_to_core(&dto.data)) } else { None }
}
pub fn velopackasset_to_bridge_option(dto: &Option<VelopackAsset>) -> VelopackAssetDtoOption {
match dto {
Some(dto) => VelopackAssetDtoOption { data: velopackasset_to_bridge(dto), has_data: true },
None => VelopackAssetDtoOption { data: Default::default(), has_data: false },
}
}
pub fn updateinfo_to_core(dto: &UpdateInfoDto) -> UpdateInfo {
UpdateInfo {
TargetFullRelease: velopackasset_to_core(&dto.TargetFullRelease),
IsDowngrade: bool_to_core(&dto.IsDowngrade),
}
}
pub fn updateinfo_to_bridge(dto: &UpdateInfo) -> UpdateInfoDto {
UpdateInfoDto {
TargetFullRelease: velopackasset_to_bridge(&dto.TargetFullRelease),
IsDowngrade: bool_to_bridge(&dto.IsDowngrade),
}
}
pub fn updateinfo_to_core_option(dto: &UpdateInfoDtoOption) -> Option<UpdateInfo> {
if dto.has_data { Some(updateinfo_to_core(&dto.data)) } else { None }
}
pub fn updateinfo_to_bridge_option(dto: &Option<UpdateInfo>) -> UpdateInfoDtoOption {
match dto {
Some(dto) => UpdateInfoDtoOption { data: updateinfo_to_bridge(dto), has_data: true },
None => UpdateInfoDtoOption { data: Default::default(), has_data: false },
}
}
pub fn updateoptions_to_core(dto: &UpdateOptionsDto) -> UpdateOptions {
UpdateOptions {
AllowVersionDowngrade: bool_to_core(&dto.AllowVersionDowngrade),
ExplicitChannel: if dto.ExplicitChannel.has_data { Some(string_to_core(&dto.ExplicitChannel.data)) } else { None },
}
}
pub fn updateoptions_to_bridge(dto: &UpdateOptions) -> UpdateOptionsDto {
UpdateOptionsDto {
AllowVersionDowngrade: bool_to_bridge(&dto.AllowVersionDowngrade),
ExplicitChannel: StringOption { data: string_to_bridge(&dto.ExplicitChannel.clone().unwrap_or_default()), has_data: dto.ExplicitChannel.is_some() },
}
}
pub fn updateoptions_to_core_option(dto: &UpdateOptionsDtoOption) -> Option<UpdateOptions> {
if dto.has_data { Some(updateoptions_to_core(&dto.data)) } else { None }
}
pub fn updateoptions_to_bridge_option(dto: &Option<UpdateOptions>) -> UpdateOptionsDtoOption {
match dto {
Some(dto) => UpdateOptionsDtoOption { data: updateoptions_to_bridge(dto), has_data: true },
None => UpdateOptionsDtoOption { data: Default::default(), has_data: false },
}
}
// !! AUTO-GENERATED-END CORE_MAPPING

119
src/lib-cpp/src/statics.rs Normal file
View File

@@ -0,0 +1,119 @@
use anyhow::Result;
use log::{Level, Log, Metadata, Record};
use std::ffi::{c_void, CString};
use std::sync::{Mutex, RwLock};
use velopack::locator::VelopackLocatorConfig;
use crate::types::*;
#[derive(Debug, Default, Clone)]
pub struct AppOptions {
pub install_hook: Option<vpkc_hook_callback_t>,
pub update_hook: Option<vpkc_hook_callback_t>,
pub obsolete_hook: Option<vpkc_hook_callback_t>,
pub uninstall_hook: Option<vpkc_hook_callback_t>,
pub firstrun_hook: Option<vpkc_hook_callback_t>,
pub restarted_hook: Option<vpkc_hook_callback_t>,
pub auto_apply: Option<bool>,
pub args: Option<Vec<String>>,
pub locator: Option<VelopackLocatorConfig>,
}
lazy_static::lazy_static! {
static ref LAST_ERROR: RwLock<String> = RwLock::new(String::new());
static ref LOG_CALLBACK: Mutex<Option<(vpkc_log_callback_t, usize)>> = Mutex::new(None);
pub static ref VELOPACK_APP: RwLock<AppOptions> = RwLock::new(Default::default());
}
pub fn update_app_options<F>(op: F)
where
F: FnOnce(&mut AppOptions),
{
let mut app_options = VELOPACK_APP.write().unwrap();
op(&mut app_options);
}
pub fn clear_last_error() {
let mut last_error = LAST_ERROR.write().unwrap();
last_error.clear();
}
pub fn get_last_error() -> String {
let last_error = LAST_ERROR.read().unwrap();
last_error.clone()
}
pub fn set_last_error(message: &str) {
let mut last_error = LAST_ERROR.write().unwrap();
*last_error = message.to_string();
}
pub fn wrap_error<F>(op: F) -> bool
where
F: FnOnce() -> Result<()>,
{
let mut last_error = LAST_ERROR.write().unwrap();
last_error.clear();
match op() {
Ok(_) => true,
Err(e) => {
*last_error = format!("{:?}", e);
false
}
}
}
pub fn set_log_callback(callback: vpkc_log_callback_t, user_data: *mut c_void) {
// Initialize the logger if it hasn't been set yet
let _ = log::set_logger(&LOGGER);
log::set_max_level(log::LevelFilter::Trace);
let mut log_callback = LOG_CALLBACK.lock().unwrap();
*log_callback = Some((callback, user_data as usize));
}
pub fn clear_log_callback() {
let mut log_callback = LOG_CALLBACK.lock().unwrap();
*log_callback = None;
}
pub fn log_message(level: &str, message: &str) {
let log_callback = LOG_CALLBACK.lock().unwrap();
if let Some((callback, user_data)) = *log_callback {
let c_level = CString::new(level).unwrap();
let c_message = CString::new(message).unwrap();
callback(user_data as *mut c_void, c_level.as_ptr(), c_message.as_ptr());
}
}
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 => "error",
Level::Warn => "warn",
Level::Info => "info",
Level::Debug => "debug",
Level::Trace => "trace",
}
.to_string();
log_message(&level, &text);
}
fn flush(&self) {}
}

274
src/lib-cpp/src/types.rs Normal file
View File

@@ -0,0 +1,274 @@
use std::ffi::{c_char, c_void, CStr, CString};
use std::path::PathBuf;
use velopack::{locator::VelopackLocatorConfig, UpdateInfo, UpdateOptions, VelopackAsset};
pub fn c_to_string_opt(psz: *const c_char) -> Option<String> {
if psz.is_null() {
return None;
}
let cstr = unsafe { CStr::from_ptr(psz) };
Some(String::from_utf8_lossy(cstr.to_bytes()).to_string())
}
pub fn c_to_string(psz: *const c_char) -> String {
c_to_string_opt(psz).unwrap_or_default()
}
pub fn c_to_pathbuf(psz: *const c_char) -> PathBuf {
PathBuf::from(c_to_string(psz))
}
pub fn string_to_cstr(s: &str) -> *mut c_char {
let cstr = CString::new(s).unwrap();
cstr.into_raw()
}
pub fn free_cstr(psz: *mut c_char) {
if !psz.is_null() {
let _ = unsafe { CString::from_raw(psz) };
}
}
pub fn allocate_string(s: String, psz: *mut *mut c_char) {
if psz.is_null() {
return;
}
unsafe { *psz = string_to_cstr(&s) };
}
pub fn allocate_string_opt(s: Option<String>, psz: *mut *mut c_char) {
if let Some(s) = s {
allocate_string(s, psz);
}
}
pub unsafe fn free_string(psz: *mut *mut c_char) {
if !psz.is_null() {
free_cstr(*psz);
}
}
pub fn allocate_pathbuf(p: PathBuf, psz: *mut *mut c_char) {
allocate_string(p.to_string_lossy().to_string(), psz);
}
pub unsafe fn free_pathbuf(psz: *mut *mut c_char) {
free_string(psz);
}
pub fn c_to_string_array_opt(p_args: *mut *mut c_char, c_args: usize) -> Option<Vec<String>> {
if p_args.is_null() || c_args == 0 {
return None;
}
let mut args = Vec::with_capacity(c_args);
for i in 0..c_args {
if let Some(arg) = c_to_string_opt(unsafe { *p_args.add(i) }) {
args.push(arg);
}
}
Some(args)
}
pub fn return_cstr(psz: *mut c_char, c: usize, s: &str) -> usize {
if !psz.is_null() && c > 0 {
let cstr = CString::new(s).unwrap();
let bytes = cstr.as_bytes_with_nul();
let len = bytes.len().min(c);
unsafe {
std::ptr::copy_nonoverlapping(bytes.as_ptr(), psz as *mut u8, len);
*psz.add(len) = 0;
}
}
return s.len();
}
pub type vpkc_progress_callback_t = extern "C" fn(p_user_data: *mut c_void, progress: usize);
pub type vpkc_log_callback_t = extern "C" fn(p_user_data: *mut c_void, psz_level: *const c_char, psz_message: *const c_char);
pub type vpkc_hook_callback_t = extern "C" fn(p_user_data: *mut c_void, psz_app_version: *const c_char);
// !! AUTO-GENERATED-START RUST_TYPES
#[rustfmt::skip]
#[repr(C)]
pub struct vpkc_locator_config_t {
pub RootAppDir: *mut c_char,
pub UpdateExePath: *mut c_char,
pub PackagesDir: *mut c_char,
pub ManifestPath: *mut c_char,
pub CurrentBinaryDir: *mut c_char,
pub IsPortable: bool,
}
#[rustfmt::skip]
pub fn c_to_velopacklocatorconfig(obj: &vpkc_locator_config_t) -> VelopackLocatorConfig {
VelopackLocatorConfig {
RootAppDir: c_to_pathbuf(obj.RootAppDir),
UpdateExePath: c_to_pathbuf(obj.UpdateExePath),
PackagesDir: c_to_pathbuf(obj.PackagesDir),
ManifestPath: c_to_pathbuf(obj.ManifestPath),
CurrentBinaryDir: c_to_pathbuf(obj.CurrentBinaryDir),
IsPortable: obj.IsPortable,
}
}
#[rustfmt::skip]
pub fn c_to_velopacklocatorconfig_opt(obj: *mut vpkc_locator_config_t) -> Option<VelopackLocatorConfig> {
if obj.is_null() { return None; }
Some(c_to_velopacklocatorconfig(unsafe { &*obj }))
}
#[rustfmt::skip]
pub unsafe fn allocate_velopacklocatorconfig(dto: VelopackLocatorConfig, obj: *mut vpkc_locator_config_t) {
if obj.is_null() { return; }
allocate_pathbuf(dto.RootAppDir, &mut (*obj).RootAppDir);
allocate_pathbuf(dto.UpdateExePath, &mut (*obj).UpdateExePath);
allocate_pathbuf(dto.PackagesDir, &mut (*obj).PackagesDir);
allocate_pathbuf(dto.ManifestPath, &mut (*obj).ManifestPath);
allocate_pathbuf(dto.CurrentBinaryDir, &mut (*obj).CurrentBinaryDir);
(*obj).IsPortable = dto.IsPortable;
}
#[rustfmt::skip]
pub unsafe fn free_velopacklocatorconfig(obj: *mut vpkc_locator_config_t) {
if obj.is_null() { return; }
free_pathbuf(&mut (*obj).RootAppDir);
free_pathbuf(&mut (*obj).UpdateExePath);
free_pathbuf(&mut (*obj).PackagesDir);
free_pathbuf(&mut (*obj).ManifestPath);
free_pathbuf(&mut (*obj).CurrentBinaryDir);
}
#[rustfmt::skip]
#[repr(C)]
pub struct vpkc_asset_t {
pub PackageId: *mut c_char,
pub Version: *mut c_char,
pub Type: *mut c_char,
pub FileName: *mut c_char,
pub SHA1: *mut c_char,
pub SHA256: *mut c_char,
pub Size: u64,
pub NotesMarkdown: *mut c_char,
pub NotesHtml: *mut c_char,
}
#[rustfmt::skip]
pub fn c_to_velopackasset(obj: &vpkc_asset_t) -> VelopackAsset {
VelopackAsset {
PackageId: c_to_string(obj.PackageId),
Version: c_to_string(obj.Version),
Type: c_to_string(obj.Type),
FileName: c_to_string(obj.FileName),
SHA1: c_to_string(obj.SHA1),
SHA256: c_to_string(obj.SHA256),
Size: obj.Size,
NotesMarkdown: c_to_string(obj.NotesMarkdown),
NotesHtml: c_to_string(obj.NotesHtml),
}
}
#[rustfmt::skip]
pub fn c_to_velopackasset_opt(obj: *mut vpkc_asset_t) -> Option<VelopackAsset> {
if obj.is_null() { return None; }
Some(c_to_velopackasset(unsafe { &*obj }))
}
#[rustfmt::skip]
pub unsafe fn allocate_velopackasset(dto: VelopackAsset, obj: *mut vpkc_asset_t) {
if obj.is_null() { return; }
allocate_string(dto.PackageId, &mut (*obj).PackageId);
allocate_string(dto.Version, &mut (*obj).Version);
allocate_string(dto.Type, &mut (*obj).Type);
allocate_string(dto.FileName, &mut (*obj).FileName);
allocate_string(dto.SHA1, &mut (*obj).SHA1);
allocate_string(dto.SHA256, &mut (*obj).SHA256);
(*obj).Size = dto.Size;
allocate_string(dto.NotesMarkdown, &mut (*obj).NotesMarkdown);
allocate_string(dto.NotesHtml, &mut (*obj).NotesHtml);
}
#[rustfmt::skip]
pub unsafe fn free_velopackasset(obj: *mut vpkc_asset_t) {
if obj.is_null() { return; }
free_string(&mut (*obj).PackageId);
free_string(&mut (*obj).Version);
free_string(&mut (*obj).Type);
free_string(&mut (*obj).FileName);
free_string(&mut (*obj).SHA1);
free_string(&mut (*obj).SHA256);
free_string(&mut (*obj).NotesMarkdown);
free_string(&mut (*obj).NotesHtml);
}
#[rustfmt::skip]
#[repr(C)]
pub struct vpkc_update_info_t {
pub TargetFullRelease: vpkc_asset_t,
pub IsDowngrade: bool,
}
#[rustfmt::skip]
pub fn c_to_updateinfo(obj: &vpkc_update_info_t) -> UpdateInfo {
UpdateInfo {
TargetFullRelease: c_to_velopackasset(&obj.TargetFullRelease),
IsDowngrade: obj.IsDowngrade,
}
}
#[rustfmt::skip]
pub fn c_to_updateinfo_opt(obj: *mut vpkc_update_info_t) -> Option<UpdateInfo> {
if obj.is_null() { return None; }
Some(c_to_updateinfo(unsafe { &*obj }))
}
#[rustfmt::skip]
pub unsafe fn allocate_updateinfo(dto: UpdateInfo, obj: *mut vpkc_update_info_t) {
if obj.is_null() { return; }
allocate_velopackasset(dto.TargetFullRelease, &mut (*obj).TargetFullRelease);
(*obj).IsDowngrade = dto.IsDowngrade;
}
#[rustfmt::skip]
pub unsafe fn free_updateinfo(obj: *mut vpkc_update_info_t) {
if obj.is_null() { return; }
free_velopackasset(&mut (*obj).TargetFullRelease);
}
#[rustfmt::skip]
#[repr(C)]
pub struct vpkc_update_options_t {
pub AllowVersionDowngrade: bool,
pub ExplicitChannel: *mut c_char,
}
#[rustfmt::skip]
pub fn c_to_updateoptions(obj: &vpkc_update_options_t) -> UpdateOptions {
UpdateOptions {
AllowVersionDowngrade: obj.AllowVersionDowngrade,
ExplicitChannel: c_to_string_opt(obj.ExplicitChannel),
}
}
#[rustfmt::skip]
pub fn c_to_updateoptions_opt(obj: *mut vpkc_update_options_t) -> Option<UpdateOptions> {
if obj.is_null() { return None; }
Some(c_to_updateoptions(unsafe { &*obj }))
}
#[rustfmt::skip]
pub unsafe fn allocate_updateoptions(dto: UpdateOptions, obj: *mut vpkc_update_options_t) {
if obj.is_null() { return; }
(*obj).AllowVersionDowngrade = dto.AllowVersionDowngrade;
allocate_string_opt(dto.ExplicitChannel, &mut (*obj).ExplicitChannel);
}
#[rustfmt::skip]
pub unsafe fn free_updateoptions(obj: *mut vpkc_update_options_t) {
if obj.is_null() { return; }
free_string(&mut (*obj).ExplicitChannel);
}
// !! AUTO-GENERATED-END RUST_TYPES

View File

@@ -47,51 +47,59 @@ if (desiredStructs.Length != availableStructs.Count) {
} }
// rust bridge code // rust bridge code
string rustCppLib = Path.Combine(libcppDir, "src", "lib.rs"); // string rustCppLib = Path.Combine(libcppDir, "src", "lib.rs");
string rustCppMap = Path.Combine(libcppDir, "src", "map.rs"); string rustTypes = Path.Combine(libcppDir, "src", "types.rs");
//string rustCppMap = Path.Combine(libcppDir, "src", "map.rs");
string rustCppInclude = Path.Combine(libcppDir, "include", "Velopack.h"); string rustCppInclude = Path.Combine(libcppDir, "include", "Velopack.h");
string rustBridgeC = Path.Combine(libcppDir, "src", "bridge.cc"); //string rustBridgeC = Path.Combine(libcppDir, "src", "bridge.cc");
Console.WriteLine("Generating bridge dtos"); //Console.WriteLine("Generating bridge dtos");
var sbBridgeDto = new IndentStringBuilder(); //var sbBridgeDto = new IndentStringBuilder();
foreach(var rs in availableStructs) { //foreach(var rs in availableStructs) {
Templates.WriteBridgeDto(desiredStructs, sbBridgeDto, rs); // Templates.WriteBridgeDto(desiredStructs, sbBridgeDto, rs);
} //}
Console.WriteLine("Generating bridge to core mappings"); //Console.WriteLine("Generating bridge to core mappings");
var sbBridgeMapping = new IndentStringBuilder(); //var sbBridgeMapping = new IndentStringBuilder();
foreach(var rs in availableStructs) { //foreach(var rs in availableStructs) {
Templates.WriteBridgeToCoreMapping(desiredStructs, sbBridgeMapping, rs); // Templates.WriteBridgeToCoreMapping(desiredStructs, sbBridgeMapping, rs);
} //}
Console.WriteLine("Generating C types"); Console.WriteLine("Generating C types");
var cTypes = new IndentStringBuilder(); var cTypes = new IndentStringBuilder();
cTypes.AppendLine(); cTypes.AppendLine();
foreach(var rs in availableStructs) { foreach (var rs in availableStructs) {
Templates.WriteBasicC(basic_libc_names, cTypes, rs); Templates.WriteBasicC(basic_libc_names, cTypes, rs);
} }
Console.WriteLine("Generating C++ types"); Console.WriteLine("Generating C++ types");
var cppTypes = new IndentStringBuilder(); var cppTypes = new IndentStringBuilder();
cppTypes.AppendLine(); cppTypes.AppendLine();
foreach(var rs in availableStructs) { foreach (var rs in availableStructs) {
Templates.WriteCPlusPlus(basic_libc_names, cppTypes, rs); Templates.WriteCPlusPlus(basic_libc_names, cppTypes, rs);
} }
foreach (var rs in availableStructs) { foreach (var rs in availableStructs) {
Templates.WriteC2CPPMapping(basic_libc_names, cppTypes, rs); Templates.WriteC2CPPMapping(basic_libc_names, cppTypes, rs);
} }
Console.WriteLine("Generating C to bridge mappings"); Console.WriteLine("Generating Rust-C types");
var cToBridgeMapping = new IndentStringBuilder(); var rustCTypes = new IndentStringBuilder();
foreach(var rs in availableStructs) { foreach (var rs in availableStructs) {
Templates.WriteCBridgeMapping(basic_libc_names, cToBridgeMapping, rs); Templates.WriteRustCRepr(basic_libc_names, rustCTypes, rs);
} }
//Console.WriteLine("Generating C to bridge mappings");
//var cToBridgeMapping = new IndentStringBuilder();
//foreach (var rs in availableStructs) {
// Templates.WriteCBridgeMapping(basic_libc_names, cToBridgeMapping, rs);
//}
Console.WriteLine("Writing all to file"); Console.WriteLine("Writing all to file");
Util.ReplaceTextInFile(rustCppLib, "BRIDGE_DTOS", sbBridgeDto.ToString()); //Util.ReplaceTextInFile(rustCppLib, "BRIDGE_DTOS", sbBridgeDto.ToString());
Util.ReplaceTextInFile(rustCppMap, "CORE_MAPPING", sbBridgeMapping.ToString()); //Util.ReplaceTextInFile(rustCppMap, "CORE_MAPPING", sbBridgeMapping.ToString());
Util.ReplaceTextInFile(rustTypes, "RUST_TYPES", rustCTypes.ToString());
Util.ReplaceTextInFile(rustCppInclude, "C_TYPES", cTypes.ToString()); Util.ReplaceTextInFile(rustCppInclude, "C_TYPES", cTypes.ToString());
Util.ReplaceTextInFile(rustCppInclude, "CPP_TYPES", cppTypes.ToString()); Util.ReplaceTextInFile(rustCppInclude, "CPP_TYPES", cppTypes.ToString());
Util.ReplaceTextInFile(rustBridgeC, "BRIDGE_MAPPING", cToBridgeMapping.ToString()); //Util.ReplaceTextInFile(rustBridgeC, "BRIDGE_MAPPING", cToBridgeMapping.ToString());
return 0; return 0;

View File

@@ -25,6 +25,103 @@
} }
} }
private static string GetBasicCTypeInRust(Dictionary<string, string> nameMap, string rustType)
{
switch (rustType) {
case "PathBuf":
case "String":
return "*mut c_char";
case "bool":
return "bool";
case "i32":
return "i32";
case "i64":
return "i64";
case "u32":
return "u32";
case "u64":
return "u64";
default:
if (nameMap.TryGetValue(rustType, out var type)) {
return type;
}
throw new NotSupportedException("Unsupported type for rust-c: " + rustType);
}
}
public static void WriteRustCRepr(Dictionary<string, string> nameMap, IndentStringBuilder sb, RustStruct rs)
{
var cName = nameMap[rs.Name];
sb.AppendLine("#[rustfmt::skip]");
sb.AppendLine($"#[repr(C)]");
sb.AppendLine($"pub struct {cName} {{");
using (sb.Indent()) {
foreach (var field in rs.Fields) {
sb.AppendLine($"pub {field.Name}: {GetBasicCTypeInRust(nameMap, field.Type)},");
}
}
sb.AppendLine("}");
sb.AppendLine();
sb.AppendLine("#[rustfmt::skip]");
sb.AppendLine($"pub fn c_to_{rs.Name.ToLower()}(obj: &{cName}) -> {rs.Name} {{");
using (sb.Indent()) {
// sb.AppendLine($"let obj = unsafe {{ &*obj }};");
sb.AppendLine($"{rs.Name} {{");
using (sb.Indent()) {
foreach (var field in rs.Fields) {
if (field.Optional || field.Type == "PathBuf" || field.Type == "String" || nameMap.ContainsKey(field.Type)) {
sb.AppendLine($"{field.Name}: c_to_{field.Type.ToLower()}{(field.Optional ? "_opt": "")}({(nameMap.ContainsKey(field.Type) ? "&" : "")}obj.{field.Name}),");
} else {
sb.AppendLine($"{field.Name}: obj.{field.Name},");
}
}
}
sb.AppendLine("}");
}
sb.AppendLine("}");
sb.AppendLine();
sb.AppendLine("#[rustfmt::skip]");
sb.AppendLine($"pub fn c_to_{rs.Name.ToLower()}_opt(obj: *mut {cName}) -> Option<{rs.Name}> {{");
using (sb.Indent()) {
sb.AppendLine("if obj.is_null() { return None; }");
sb.AppendLine($"Some(c_to_{rs.Name.ToLower()}(unsafe {{ &*obj }}))");
}
sb.AppendLine("}");
sb.AppendLine();
sb.AppendLine("#[rustfmt::skip]");
sb.AppendLine($"pub unsafe fn allocate_{rs.Name.ToLower()}(dto: {rs.Name}, obj: *mut {cName}) {{");
using (sb.Indent()) {
sb.AppendLine("if obj.is_null() { return; }");
foreach (var field in rs.Fields) {
if (field.Optional || field.Type == "PathBuf" || field.Type == "String" || nameMap.ContainsKey(field.Type)) {
sb.AppendLine($"allocate_{field.Type.ToLower()}{(field.Optional ? "_opt": "")}(dto.{field.Name}, &mut (*obj).{field.Name});");
} else {
sb.AppendLine($"(*obj).{field.Name} = dto.{field.Name};");
}
}
}
sb.AppendLine("}");
sb.AppendLine();
sb.AppendLine("#[rustfmt::skip]");
sb.AppendLine($"pub unsafe fn free_{rs.Name.ToLower()}(obj: *mut {cName}) {{");
using (sb.Indent()) {
sb.AppendLine("if obj.is_null() { return; }");
foreach (var field in rs.Fields) {
if (field.Optional || field.Type == "PathBuf" || field.Type == "String" || nameMap.ContainsKey(field.Type)) {
sb.AppendLine($"free_{field.Type.ToLower()}(&mut (*obj).{field.Name});");
}
}
}
sb.AppendLine("}");
sb.AppendLine();
}
private static string GetCPlusPlusType(string[] coreTypes, string rustType, bool optional) private static string GetCPlusPlusType(string[] coreTypes, string rustType, bool optional)
{ {
string type = rustType switch { string type = rustType switch {
@@ -100,6 +197,7 @@
: $"pDto->{field.Name} = bridgeDto.{field.Name};"); : $"pDto->{field.Name} = bridgeDto.{field.Name};");
} }
} }
sb.AppendLine($"}}"); sb.AppendLine($"}}");
sb.AppendLine(); sb.AppendLine();
@@ -115,6 +213,7 @@
} }
} }
} }
sb.AppendLine($"}}"); sb.AppendLine($"}}");
sb.AppendLine(); sb.AppendLine();
} }

View File

@@ -3,7 +3,7 @@ use std::env;
use std::process::exit; use std::process::exit;
use crate::{ use crate::{
locator::{VelopackLocatorConfig}, locator::VelopackLocatorConfig,
constants::*, constants::*,
manager, manager,
sources, sources,