mod cstr_ffi; mod last_error; mod object_pool; use object_pool::ObjectPool; use std::ffi::{CString, c_char}; use std::sync::{LazyLock, PoisonError, RwLock}; use thiserror::Error as TeError; use wfassoc::highlevel::{Program, Schema}; pub use object_pool::Token; // region: Error /// Error occurs in this crate. #[derive(Debug, TeError)] enum Error { /// Error when operating Schema. #[error("{0}")] Schema(#[from] wfassoc::highlevel::SchemaError), /// Error when parsing Schema into Program. #[error("{0}")] ParseProgram(#[from] wfassoc::highlevel::ParseProgramError), /// Error when operating Program. #[error("{0}")] Program(#[from] wfassoc::highlevel::ProgramError), /// Error when manipulating with C-style string. #[error("{0}")] CStrFfi(#[from] cstr_ffi::Error), /// Error when manipulating with object pool. #[error("{0}")] ObjectPool(#[from] object_pool::Error), /// Error when manipulating with poison RwLock #[error("RwLock is poisoning")] PoisonRwLock, } /// Result type used in this crate. type Result = std::result::Result; // endregion // region: Macros // endregion // region: Exposed Functions // region: Facilities #[unsafe(no_mangle)] pub extern "C" fn WFStartup() -> bool { true } #[unsafe(no_mangle)] pub extern "C" fn WFShutdown() -> bool { true } #[unsafe(no_mangle)] pub extern "C" fn WFGetLastError() -> *const c_char { last_error::get_last_error() } #[unsafe(no_mangle)] pub extern "C" fn WFHasPrivilege() -> bool { wfassoc::win32::utilities::has_privilege() } #[unsafe(no_mangle)] pub extern "C" fn WFAdd(left: u32, right: u32, rv: *mut u32) -> bool { unsafe { *rv = left + right; } return true; } // endregion // region: Schema const SCHEMA_POOL: LazyLock>> = LazyLock::new(|| RwLock::new(ObjectPool::new())); #[unsafe(no_mangle)] pub extern "C" fn WFSchemaCreate(out_token: *mut Token) -> bool { fn inner() -> Result { let binding = &SCHEMA_POOL; let mut pool = binding.write().map_err(|_| Error::PoisonRwLock)?; Ok(pool.allocate(Schema::new())?) } match inner() { Ok(rv) => { unsafe { *out_token = rv }; true } Err(e) => { last_error::set_last_error(e.to_string().as_str()); false } } } #[unsafe(no_mangle)] pub extern "C" fn WFSchemaIntoProgram(in_token: Token, out_token: *mut Token) -> bool { fn inner(in_token: Token) -> Result { let binding = &SCHEMA_POOL; let mut pool = binding.write().map_err(|_| Error::PoisonRwLock)?; let schema = pool.pop(in_token)?; let binding = &PROGRAM_POOL; let mut pool = binding.write().map_err(|_| Error::PoisonRwLock)?; let program = schema.into_program()?; Ok(pool.allocate(program)?) } match inner(in_token) { Ok(rv) => { unsafe { *out_token = rv }; true } Err(e) => { last_error::set_last_error(e.to_string().as_str()); false } } } #[unsafe(no_mangle)] pub extern "C" fn WFSchemaDestroy(in_token: Token) -> bool { fn inner(in_token: Token) -> Result<()> { let binding = &SCHEMA_POOL; let mut pool = binding.write().map_err(|_| Error::PoisonRwLock)?; Ok(pool.free(in_token)?) } match inner(in_token) { Ok(_) => true, Err(e) => { last_error::set_last_error(e.to_string().as_str()); false } } } // endregion // region: Program const PROGRAM_POOL: LazyLock>> = LazyLock::new(|| RwLock::new(ObjectPool::new())); // endregion // endregion