feat: update program and cdylib exposed interface
This commit is contained in:
@@ -191,10 +191,11 @@ static PROGRAM_POOL: LazyLock<RwLock<ObjectPool<Program>>> =
|
||||
static EXT_STATUS_POOL: LazyLock<RwLock<ObjectPool<wfassoc::highlevel::ProgramExtStatus>>> =
|
||||
LazyLock::new(|| RwLock::new(ObjectPool::new()));
|
||||
|
||||
static ICON_RC_POOL: LazyLock<RwLock<ObjectPool<wfassoc::win32::concept::IconRc>>> =
|
||||
LazyLock::new(|| RwLock::new(ObjectPool::new()));
|
||||
static SELF_EXT_STATUS_POOL: LazyLock<
|
||||
RwLock<ObjectPool<wfassoc::highlevel::ProgramSelfExtStatus>>,
|
||||
> = LazyLock::new(|| RwLock::new(ObjectPool::new()));
|
||||
|
||||
static EXT_POOL: LazyLock<RwLock<ObjectPool<wfassoc::win32::concept::Ext>>> =
|
||||
static ICON_RC_POOL: LazyLock<RwLock<ObjectPool<wfassoc::win32::concept::IconRc>>> =
|
||||
LazyLock::new(|| RwLock::new(ObjectPool::new()));
|
||||
|
||||
// endregion
|
||||
@@ -218,8 +219,8 @@ pub extern "C" fn WFStartup() -> bool {
|
||||
let _pool = pull_writer!(SCHEMA_POOL)?;
|
||||
let _pool = pull_writer!(PROGRAM_POOL)?;
|
||||
let _pool = pull_writer!(EXT_STATUS_POOL)?;
|
||||
let _pool = pull_writer!(SELF_EXT_STATUS_POOL)?;
|
||||
let _pool = pull_writer!(ICON_RC_POOL)?;
|
||||
let _pool = pull_writer!(EXT_POOL)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -234,9 +235,9 @@ pub extern "C" fn WFShutdown() -> bool {
|
||||
pool.clear();
|
||||
let mut pool = pull_writer!(EXT_STATUS_POOL)?;
|
||||
pool.clear();
|
||||
let mut pool = pull_writer!(ICON_RC_POOL)?;
|
||||
let mut pool = pull_writer!(SELF_EXT_STATUS_POOL)?;
|
||||
pool.clear();
|
||||
let mut pool = pull_writer!(EXT_POOL)?;
|
||||
let mut pool = pull_writer!(ICON_RC_POOL)?;
|
||||
pool.clear();
|
||||
Ok(())
|
||||
})
|
||||
@@ -539,23 +540,6 @@ pub extern "C" fn WFProgramExtsLen(
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFProgramGetExt(
|
||||
in_program: in_param_ty!(Token),
|
||||
in_index: in_param_ty!(usize),
|
||||
out_ext: out_param_ty!(Token),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_program: Token, in_index: usize| -> (out_ext: Token) {
|
||||
let mut pool = pull_writer!(PROGRAM_POOL)?;
|
||||
let program = pool.get_mut(in_program)?;
|
||||
|
||||
let ext = program.get_ext(in_index)?;
|
||||
let mut pool = pull_writer!(EXT_POOL)?;
|
||||
let token = pool.allocate(ext.clone())?;
|
||||
Ok(token)
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFProgramFindExt(
|
||||
in_program: in_param_ty!(Token),
|
||||
@@ -575,6 +559,23 @@ pub extern "C" fn WFProgramFindExt(
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFProgramResolveExt(
|
||||
in_program: in_param_ty!(Token),
|
||||
in_index: in_param_ty!(usize),
|
||||
out_self_ext_status: out_param_ty!(Token),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_program: Token, in_index: usize| -> (out_self_ext_status: Token) {
|
||||
let mut pool = pull_writer!(PROGRAM_POOL)?;
|
||||
let program = pool.get_mut(in_program)?;
|
||||
|
||||
let self_ext_status = program.resolve_ext(in_index)?;
|
||||
let mut pool = pull_writer!(SELF_EXT_STATUS_POOL)?;
|
||||
let token = pool.allocate(self_ext_status)?;
|
||||
Ok(token)
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFProgramRegister(
|
||||
in_program: in_param_ty!(Token),
|
||||
@@ -716,6 +717,77 @@ pub extern "C" fn WFExtStatusGetIcon(
|
||||
|
||||
// endregion
|
||||
|
||||
// region: Self Extension Status
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFSelfExtStatusDestroy(in_self_ext_status: in_param_ty!(Token)) -> bool {
|
||||
cffi_wrapper!(|in_self_ext_status: Token| {
|
||||
let mut pool = pull_writer!(SELF_EXT_STATUS_POOL)?;
|
||||
Ok(pool.free(in_self_ext_status)?)
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFSelfExtStatusGetName(
|
||||
in_self_ext_status: in_param_ty!(Token),
|
||||
out_name: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_self_ext_status: Token| -> (out_name: CStyleString) {
|
||||
let pool = pull_reader!(SELF_EXT_STATUS_POOL)?;
|
||||
let self_ext_status = pool.get(in_self_ext_status)?;
|
||||
|
||||
cstr_ffi::set_ffi_string(self_ext_status.get_name())?;
|
||||
Ok(cstr_ffi::get_ffi_string())
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFSelfExtStatusGetIcon(
|
||||
in_self_ext_status: in_param_ty!(Token),
|
||||
out_icon: out_param_ty!(HICON),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_self_ext_status: Token| -> (out_icon: HICON) {
|
||||
let pool = pull_reader!(SELF_EXT_STATUS_POOL)?;
|
||||
let self_ext_status = pool.get(in_self_ext_status)?;
|
||||
|
||||
let icon = match self_ext_status.get_icon() {
|
||||
Some(icon) => icon.get_icon(),
|
||||
None => ffi_types::INVALID_HICON,
|
||||
};
|
||||
Ok(icon)
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFSelfExtStatusGetExt(
|
||||
in_self_ext_status: in_param_ty!(Token),
|
||||
out_inner: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_self_ext_status: Token| -> (out_inner: CStyleString) {
|
||||
let pool = pull_reader!(SELF_EXT_STATUS_POOL)?;
|
||||
let self_ext_status = pool.get(in_self_ext_status)?;
|
||||
|
||||
cstr_ffi::set_ffi_string(self_ext_status.get_ext())?;
|
||||
Ok(cstr_ffi::get_ffi_string())
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFSelfExtStatusGetDottedExt(
|
||||
in_self_ext_status: in_param_ty!(Token),
|
||||
out_inner: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_self_ext_status: Token| -> (out_inner: CStyleString) {
|
||||
let pool = pull_reader!(SELF_EXT_STATUS_POOL)?;
|
||||
let self_ext_status = pool.get(in_self_ext_status)?;
|
||||
|
||||
cstr_ffi::set_ffi_string(self_ext_status.get_dotted_ext().as_str())?;
|
||||
Ok(cstr_ffi::get_ffi_string())
|
||||
})
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region: Icon Resource
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -740,41 +812,3 @@ pub extern "C" fn WFIconRcGetIcon(
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region: File Extension
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFExtDestroy(in_ext: in_param_ty!(Token)) -> bool {
|
||||
cffi_wrapper!(|in_ext: Token| {
|
||||
let mut pool = pull_writer!(EXT_POOL)?;
|
||||
Ok(pool.free(in_ext)?)
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFExtGetInner(
|
||||
in_ext: in_param_ty!(Token),
|
||||
out_inner: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_ext: Token| -> (out_inner: CStyleString) {
|
||||
let pool = pull_reader!(EXT_POOL)?;
|
||||
let ext = pool.get(in_ext)?;
|
||||
cstr_ffi::set_ffi_string(ext.inner())?;
|
||||
Ok(cstr_ffi::get_ffi_string())
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFExtGetDottedInner(
|
||||
in_ext: in_param_ty!(Token),
|
||||
out_inner: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
cffi_wrapper!(|in_ext: Token| -> (out_inner: CStyleString) {
|
||||
let pool = pull_reader!(EXT_POOL)?;
|
||||
let ext = pool.get(in_ext)?;
|
||||
cstr_ffi::set_ffi_string(&ext.dotted_inner())?;
|
||||
Ok(cstr_ffi::get_ffi_string())
|
||||
})
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -126,7 +126,7 @@ fn run_ext_unlink(
|
||||
for index in exts {
|
||||
program.link_ext(scope, index)?;
|
||||
}
|
||||
|
||||
|
||||
println!("File extension now is unlinked.");
|
||||
Ok(())
|
||||
}
|
||||
@@ -139,9 +139,12 @@ fn run_ext_list(
|
||||
// Fetch info
|
||||
let mut ext_list: HashMap<String, Option<String>> = HashMap::new();
|
||||
for index in 0..program.exts_len() {
|
||||
let ext = program.get_ext(index)?;
|
||||
let self_ext_status = program.resolve_ext(index)?;
|
||||
let status = program.query_ext(view, index)?;
|
||||
ext_list.insert(ext.dotted_inner(), status.map(|s| s.get_name().to_string()));
|
||||
ext_list.insert(
|
||||
self_ext_status.get_dotted_ext(),
|
||||
status.map(|s| s.get_name().to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
// Output by styles
|
||||
|
||||
@@ -27,7 +27,7 @@ mod schema;
|
||||
mod program;
|
||||
|
||||
pub use schema::{Schema, SchemaError};
|
||||
pub use program::{Program, ParseProgramError, ProgramError, ProgramExtStatus};
|
||||
pub use program::{Program, ParseProgramError, ProgramError, ProgramSelfExtStatus, ProgramExtStatus};
|
||||
pub use lowlevel::{Scope, View};
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -269,6 +269,9 @@ impl Program {
|
||||
|
||||
impl Program {
|
||||
pub fn resolve_name(&self) -> Result<Option<String>, ProgramError> {
|
||||
// TODO:
|
||||
// Add fallback: fetch it from executable manifest file.
|
||||
// Add fallback: use executable name directly.
|
||||
Ok(self
|
||||
.name
|
||||
.as_ref()
|
||||
@@ -277,6 +280,9 @@ impl Program {
|
||||
}
|
||||
|
||||
pub fn resolve_icon(&self) -> Result<Option<concept::IconRc>, ProgramError> {
|
||||
// TODO:
|
||||
// Add fallback: fetch it from the first icon of executable.
|
||||
// Add fallback: use system default executable icon.
|
||||
Ok(self
|
||||
.icon
|
||||
.as_ref()
|
||||
@@ -288,19 +294,35 @@ impl Program {
|
||||
self.ext_keys.len()
|
||||
}
|
||||
|
||||
pub fn get_ext(&self, index: usize) -> Result<&concept::Ext, ProgramError> {
|
||||
match self.ext_keys.get(index) {
|
||||
Some(program_key) => {
|
||||
let ext_key = &program_key.ext_key;
|
||||
Ok(ext_key.inner())
|
||||
}
|
||||
None => Err(ProgramError::BadIndex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_ext(&self, body: &str) -> Option<usize> {
|
||||
self.ext_keys_map.get(body).copied()
|
||||
}
|
||||
|
||||
pub fn resolve_ext(&self, index: usize) -> Result<ProgramSelfExtStatus, ProgramError> {
|
||||
// Fetch data
|
||||
let progid_ext_key = self.ext_keys.get(index).ok_or(ProgramError::BadIndex)?;
|
||||
|
||||
// Try resolving name with string resource first,
|
||||
// and fallback to ProgId verbatim.
|
||||
let name = progid_ext_key
|
||||
.name
|
||||
.inner
|
||||
.extract()
|
||||
.unwrap_or(progid_ext_key.progid_key.inner().to_string());
|
||||
// Try to fetch icon
|
||||
let icon = progid_ext_key
|
||||
.icon
|
||||
.inner
|
||||
.extract(concept::IconSizeKind::Small)
|
||||
.ok();
|
||||
|
||||
// Okey, return it
|
||||
Ok(ProgramSelfExtStatus::new(
|
||||
progid_ext_key.ext_key.inner().clone(),
|
||||
name,
|
||||
icon,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Program {
|
||||
@@ -589,6 +611,46 @@ struct ProgramProgIdExtKey {
|
||||
|
||||
// region: Exposed Stuff
|
||||
|
||||
/// Exposed struct representing this program provided method for opening specific file extension.
|
||||
///
|
||||
/// The data including the extension name, diaplay name and icon.
|
||||
pub struct ProgramSelfExtStatus {
|
||||
ext: concept::Ext,
|
||||
name: String,
|
||||
icon: Option<concept::IconRc>,
|
||||
}
|
||||
|
||||
impl ProgramSelfExtStatus {
|
||||
fn new(ext: concept::Ext, name: String, icon: Option<concept::IconRc>) -> Self {
|
||||
Self { ext, name, icon }
|
||||
}
|
||||
|
||||
/// Get the extension name without leading dot like `jpg`.
|
||||
pub fn get_ext(&self) -> &str {
|
||||
self.ext.inner()
|
||||
}
|
||||
|
||||
/// Get the extension name with leading dot like `.jpg`.
|
||||
pub fn get_dotted_ext(&self) -> String {
|
||||
self.ext.dotted_inner()
|
||||
}
|
||||
|
||||
/// Get the display name of this program.
|
||||
///
|
||||
/// The program provided display name will be used firstly.
|
||||
/// If this program has no display name, the stringified ProgId will be used instead.
|
||||
pub fn get_name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
/// Get the icon of this program.
|
||||
///
|
||||
/// Due to the icon is optional, if there is no icon, return None.
|
||||
pub fn get_icon(&self) -> Option<&concept::IconRc> {
|
||||
self.icon.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// Exposed struct representing the default associated program of specific file extension.
|
||||
///
|
||||
/// The data including the diaplay name and icon.
|
||||
|
||||
Reference in New Issue
Block a user