From 6a737e90e0685ca403dbb9d710e70fc0d1135e26 Mon Sep 17 00:00:00 2001 From: marcbull <31337222+marcbull@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:22:01 +0200 Subject: [PATCH] chore: allow closure as license callback --- examples/license-activation.rs | 40 +++++++++++++------------------ src/lib.rs | 44 +++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/examples/license-activation.rs b/examples/license-activation.rs index 4dd9431..5d7f8ff 100644 --- a/examples/license-activation.rs +++ b/examples/license-activation.rs @@ -2,28 +2,6 @@ use std::io::{self, BufRead}; // for user input (pause) use lexactivator::*; -pub type CallbackType = extern "C" fn(LexActivatorCode); - -extern "C" fn license_callback(code: LexActivatorCode) { - match code { - LexActivatorCode::Status(status) => { - match status { - LexActivatorStatus::LA_OK => println!("License is active!"), - LexActivatorStatus::LA_EXPIRED => println!("License has expired!"), - LexActivatorStatus::LA_SUSPENDED => println!("License has been suspended!"), - LexActivatorStatus::LA_GRACE_PERIOD_OVER => println!("License grace period is over!"), - _ => println!("Unknown license status"), - } - } - LexActivatorCode::Error(error) => { - match error { - LexActivatorError::LA_E_ACTIVATION_NOT_FOUND => println!("The license activation was deleted on the server."), - _ => println!("Unknown error"), - } - } - } -} - fn main() { let product_data: String = "Product.dat_content".to_string(); let product_id: String = "Product_id".to_string(); @@ -53,7 +31,23 @@ fn main() { } } let callback_result: Result<(), LexActivatorError> = - lexactivator::set_license_callback(license_callback); + lexactivator::set_license_callback(|code| match code { + LexActivatorCode::Status(status) => match status { + LexActivatorStatus::LA_OK => println!("License is active!"), + LexActivatorStatus::LA_EXPIRED => println!("License has expired!"), + LexActivatorStatus::LA_SUSPENDED => println!("License has been suspended!"), + LexActivatorStatus::LA_GRACE_PERIOD_OVER => { + println!("License grace period is over!") + } + _ => println!("Unknown license status"), + }, + LexActivatorCode::Error(error) => match error { + LexActivatorError::LA_E_ACTIVATION_NOT_FOUND => { + println!("The license activation was deleted on the server.") + } + _ => println!("Error: {}", error), + }, + }); println!("SetLicenseCallback: {:?}", callback_result); let validation_result: Result = diff --git a/src/lib.rs b/src/lib.rs index f8ae077..b8b6545 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ use std::ffi::*; use serde::Deserialize; +use std::sync::{LazyLock, Mutex}; mod extern_functions; use extern_functions::*; @@ -10,16 +11,16 @@ pub use error_codes::*; mod string_utils; use string_utils::*; -static mut CALLBACK_FUNCTION: Option = None; +type LicenseCallback = dyn Fn(LexActivatorCode) + Send + 'static; -pub type CallbackType = extern "C" fn(LexActivatorCode); +static CALLBACK_FUNCTION: LazyLock>>> = + LazyLock::new(|| Mutex::new(None)); extern "C" fn wrapper(code: i32) { let callback_status = LexActivatorCode::from_i32(code); - unsafe { - if let Some(callback) = CALLBACK_FUNCTION { - callback(callback_status); - } + let callback = CALLBACK_FUNCTION.lock().unwrap(); + if let Some(callback) = callback.as_ref() { + callback(callback_status); } } @@ -334,26 +335,28 @@ pub fn set_license_user_credential(email: String, password: String) -> Result<() } } -/// Sets the license callback function. -/// -/// Whenever the server sync occurs in a separate thread, and server returns the response, -/// license callback function gets invoked with the following status codes: +/// Sets the license closure callback. +/// +/// Whenever the server sync occurs in a separate thread, and server returns the response, +/// license closure callback gets invoked with the following status codes: /// LA_OK, LA_EXPIRED, LA_SUSPENDED, LA_E_REVOKED, LA_E_ACTIVATION_NOT_FOUND, LA_E_MACHINE_FINGERPRINT -/// LA_E_AUTHENTICATION_FAILED, LA_E_COUNTRY, LA_E_INET, LA_E_SERVER,LA_E_RATE_LIMIT, LA_E_IP, +/// LA_E_AUTHENTICATION_FAILED, LA_E_COUNTRY, LA_E_INET, LA_E_SERVER,LA_E_RATE_LIMIT, LA_E_IP, /// LA_E_RELEASE_VERSION_NOT_ALLOWED, LA_E_RELEASE_VERSION_FORMAT /// /// # Arguments /// -/// * `callback` - The callback function to be set. +/// * `closure` - The closure callback to be set e.g. |code| { println!("{:?}", code) } /// /// # Returns /// -/// Returns `Ok(())` if the license callback is set successfully, If an error occurs, an `Err` containing the `LexActivatorError`is returned. +/// Returns `Ok(())` if the license closure callback is set successfully, If an error occurs, an `Err` containing the `LexActivatorError`is returned. -pub fn set_license_callback(callback: CallbackType) -> Result<(), LexActivatorError> { - unsafe { - CALLBACK_FUNCTION = Some(callback); - } +pub fn set_license_callback(closure: F) -> Result<(), LexActivatorError> +where + F: Fn(LexActivatorCode) + Clone + Send + 'static, +{ + let mut callback_function = CALLBACK_FUNCTION.lock().unwrap(); + callback_function.replace(Box::new(closure)); let status: i32 = unsafe { SetLicenseCallback(wrapper) }; if status == 0 { @@ -363,6 +366,13 @@ pub fn set_license_callback(callback: CallbackType) -> Result<(), LexActivatorEr } } +/// Unset the current license closure callback. + +pub fn unset_license_callback() { + let mut callback_function = CALLBACK_FUNCTION.lock().unwrap(); + *callback_function = None; +} + /// Sets the activation lease duration. /// /// # Arguments