feat: remove some optional in rust and cbindgen

This commit is contained in:
yyc12345 committed 2026-05-27 13:16:51 +08:00
1 parent 77924b5937
commit 8c61aa1e1d
5 files changed
+105 -69

No files matched your search

+50 -24
View File
@@ -44,6 +44,8 @@ pub enum ParseProgramError {
pub enum ProgramError {
#[error("{0}")]
Lowlevel(#[from] lowlevel::Error),
#[error("{0}")]
LoadIconRc(#[from] concept::LoadIconRcError),
#[error("given index is invalid")]
BadIndex,
}
@@ -57,6 +59,7 @@ pub struct Program {
app_paths_key: lowlevel::AppPathsKey,
applications_key: lowlevel::ApplicationsKey,
app_path: String,
app_file_name: String,
app_dir_path: String,
name: Option<Arc<ProgramStr>>,
icon: Option<Arc<ProgramIcon>>,
@@ -254,6 +257,7 @@ impl Program {
app_paths_key,
applications_key,
app_path,
app_file_name,
app_dir_path,
name,
icon,
@@ -268,26 +272,43 @@ 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
pub fn resolve_name(&self) -> Result<String, ProgramError> {
// Fecch from user specified name first
let name = self
.name
.as_ref()
.map(|name| name.inner.extract().ok())
.flatten())
.flatten();
if let Some(name) = name {
return Ok(name);
}
// TODO:
// Fetch it from executable manifest file.
// Finally fallback to use executable name.
Ok(self.app_file_name.clone())
}
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
pub fn resolve_icon(&self) -> Result<concept::IconRc, ProgramError> {
// Fetch from user specified icon first
let icon = self
.icon
.as_ref()
.map(|icon| icon.inner.extract(concept::IconSizeKind::Small).ok())
.flatten())
.flatten();
if let Some(icon) = icon {
return Ok(icon);
}
// Fetch from the first icon of executable instead.
let icon = concept::IconRc::new(&self.app_path, 0, concept::IconSizeKind::Small).ok();
if let Some(icon) = icon {
return Ok(icon);
}
// Finally fallback to use system default executable icon.
Ok(concept::IconRc::GENERIC_APPLICATION(
concept::IconSizeKind::Small,
)?)
}
pub fn exts_len(&self) -> usize {
@@ -309,12 +330,14 @@ impl Program {
.inner
.extract()
.unwrap_or(progid_ext_key.progid_key.inner().to_string());
// Try to fetch icon
// Try to fetch icon, and fallback to system default file icon.
let icon = progid_ext_key
.icon
.inner
.extract(concept::IconSizeKind::Small)
.ok();
.unwrap_or(concept::IconRc::GENERIC_DOCUMENT(
concept::IconSizeKind::Small,
)?);
// Okey, return it
Ok(ProgramSelfExtStatus::new(
@@ -557,11 +580,14 @@ impl Program {
.flatten();
}
let name = name.unwrap_or(progid_key.inner().to_string());
// Now try to fetch icon.
// Now try to fetch icon and fallback to system default file icon.
let icon = progid_key
.get_default_icon(view)?
.map(|ico| ico.extract(concept::IconSizeKind::Small).ok())
.flatten();
.flatten()
.unwrap_or(concept::IconRc::GENERIC_DOCUMENT(
concept::IconSizeKind::Small,
)?);
// Okey, return it.
Ok(Some(ProgramExtStatus::new(name, icon)))
@@ -617,11 +643,11 @@ struct ProgramProgIdExtKey {
pub struct ProgramSelfExtStatus {
ext: concept::Ext,
name: String,
icon: Option<concept::IconRc>,
icon: concept::IconRc,
}
impl ProgramSelfExtStatus {
fn new(ext: concept::Ext, name: String, icon: Option<concept::IconRc>) -> Self {
fn new(ext: concept::Ext, name: String, icon: concept::IconRc) -> Self {
Self { ext, name, icon }
}
@@ -646,8 +672,8 @@ impl ProgramSelfExtStatus {
/// 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()
pub fn get_icon(&self) -> &concept::IconRc {
&self.icon
}
}
@@ -656,11 +682,11 @@ impl ProgramSelfExtStatus {
/// The data including the diaplay name and icon.
pub struct ProgramExtStatus {
name: String,
icon: Option<concept::IconRc>,
icon: concept::IconRc,
}
impl ProgramExtStatus {
fn new(name: String, icon: Option<concept::IconRc>) -> Self {
fn new(name: String, icon: concept::IconRc) -> Self {
Self { name, icon }
}
@@ -675,8 +701,8 @@ impl ProgramExtStatus {
/// 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()
pub fn get_icon(&self) -> &concept::IconRc {
&self.icon
}
}
+17
View File
@@ -510,6 +510,20 @@ pub struct IconRc {
icon: HICON,
}
impl IconRc {
/// Get the icon preset representing generic document.
#[allow(non_snake_case)]
pub fn GENERIC_DOCUMENT(kind: IconSizeKind) -> Result<Self, LoadIconRcError> {
Self::new("shell32.dll", 0, kind)
}
/// Get the icon preset representing generic executable.
#[allow(non_snake_case)]
pub fn GENERIC_APPLICATION(kind: IconSizeKind) -> Result<Self, LoadIconRcError> {
Self::new("imageres.dll", 0, kind)
}
}
impl IconRc {
/// Load icon from executable or `.ico` file.
///
@@ -867,16 +881,19 @@ pub struct Verb {
}
impl Verb {
/// Get the verb representing Open.
#[allow(non_snake_case)]
pub fn OPEN() -> Self {
Verb::new("open").expect("unexpected bad verb")
}
/// Get the verb representing Edit.
#[allow(non_snake_case)]
pub fn EDIT() -> Self {
Verb::new("edit").expect("unexpected bad verb")
}
/// Get the verb representing Play.
#[allow(non_snake_case)]
pub fn PLAY() -> Self {
Verb::new("play").expect("unexpected bad verb")