From cc79951ee6db69af4bcc5ac6efe633117f9b57f5 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 26 Oct 2025 22:16:48 +0800 Subject: [PATCH] refactor(windows): improve resource string parsing and documentation - Rename structs to be more descriptive (IconRefStr, StrRefStr) - Add comprehensive documentation for all public items - Simplify error handling in FromStr implementations - Add getter methods for path and index fields --- wfassoc/src/extra/windows.rs | 118 ++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/wfassoc/src/extra/windows.rs b/wfassoc/src/extra/windows.rs index d8af7bd..a0a4106 100644 --- a/wfassoc/src/extra/windows.rs +++ b/wfassoc/src/extra/windows.rs @@ -16,13 +16,16 @@ use windows_sys::Win32::UI::WindowsAndMessaging::HICON; // region: Icon Reference String +/// Error occurs when given string is not a valid Icon Reference String. #[derive(Debug, TeError)] #[error("given string \"{inner}\" is not a valid Icon Reference String")] -pub struct ParseIconRcError { +pub struct ParseIconRefStrError { + /// The clone of string which is not a valid Icon Reference String inner: String, } -impl ParseIconRcError { +impl ParseIconRefStrError { + /// Create new error instance. fn new(s: &str) -> Self { Self { inner: s.to_string(), @@ -30,19 +33,27 @@ impl ParseIconRcError { } } -#[derive(Debug, TeError)] -#[error("fail to load icon")] -pub struct FetchIconError {} - -pub struct IconRc { +/// The struct representing an Icon Reference String +/// looks like `%SystemRoot%\System32\imageres.dll,-72`. +pub struct IconRefStr { + /// The path part of this reference string. + /// And it can be expandable. path: String, + /// The index part of this reference string. index: u32, } -impl IconRc { +impl IconRefStr { /// Create a new Icon Reference String. /// - /// `path` is the path to the icon resource file and it can be Expand String. + /// `path` is the path to the icon resource file and it can be one of following types: + /// + /// * Absolute path: `C:\Windows\System32\imageres.dll` + /// * Relative path: `imageres.dll` + /// * Expandable Path: `%SystemRoot%\System32\imageres.dll` + /// + /// And it also can be quoted like: `"C:\Program Files\MyApp\MyApp.dll"` + /// /// `index` is the index of the icon in the resource file. pub fn new(path: &str, index: u32) -> Self { Self { @@ -50,35 +61,42 @@ impl IconRc { index, } } - - pub fn fetch_icon(&self) -> Result { - todo!() + + /// Get the path part of this reference string. + /// + /// This path can be absolute path, relative path or expandable path. + pub fn get_path(&self) -> &str { + &self.path + } + + /// Get the index part of this reference string. + pub fn get_index(&self) -> u32 { + self.index } } -impl Display for IconRc { +impl Display for IconRefStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{},-{}", self.path, self.index) } } -impl FromStr for IconRc { - type Err = ParseIconRcError; +impl FromStr for IconRefStr { + type Err = ParseIconRefStrError; fn from_str(s: &str) -> Result { static RE: LazyLock = - LazyLock::new(|| Regex::new(r"^([^,@][^,]*),-([0-9]+)$").unwrap()); + LazyLock::new(|| Regex::new(r"^([^,@].*),-([0-9]+)$").unwrap()); let caps = RE.captures(s); if let Some(caps) = caps { let path = &caps[1]; - let index = caps.get(2).ok_or(ParseIconRcError::new(s)).and_then(|sv| { - sv.as_str() - .parse::() - .map_err(|_| ParseIconRcError::new(s)) - })?; + let index = caps + .get(2) + .and_then(|sv| sv.as_str().parse::().ok()) + .ok_or(ParseIconRefStrError::new(s))?; Ok(Self::new(path, index)) } else { - Err(ParseIconRcError::new(s)) + Err(ParseIconRefStrError::new(s)) } } } @@ -87,13 +105,16 @@ impl FromStr for IconRc { // region: String Reference String +/// Error occurs when given string is not a valid String Reference String. #[derive(Debug, TeError)] #[error("given string \"{inner}\" is not a valid String Reference String")] -pub struct ParseStrRcError { +pub struct ParseStrRefStrError { + /// The clone of string which is not a valid String Reference String inner: String, } -impl ParseStrRcError { +impl ParseStrRefStrError { + /// Create new error instance. fn new(s: &str) -> Self { Self { inner: s.to_string(), @@ -101,20 +122,22 @@ impl ParseStrRcError { } } -#[derive(Debug, TeError)] -#[error("fail to load string")] -pub struct FetchStrError{} - -pub struct StrRc { +/// The struct representing an String Reference String +/// looks like `@%SystemRoot%\System32\shell32.dll,-30596`. +pub struct StrRefStr { + /// The path part of this reference string. + /// And it can be expandable. path: String, + /// The index part of this reference string. index: u32, } -impl StrRc { - /// Create a new String Reference String. +impl StrRefStr { + /// Create a new Icon Reference String. /// - /// `path` is the path to the string resource file and it can be Expand String. + /// `path` is the path to the string resource file. /// `index` is the index of the string in the resource file. + /// For the detail of these parameters, please see IconRefStr. pub fn new(path: &str, index: u32) -> Self { Self { path: path.to_string(), @@ -122,33 +145,40 @@ impl StrRc { } } - pub fn fetch_string(&self) -> Result { - todo!() + /// Get the path part of this reference string. + /// + /// This path can be absolute path, relative path or expandable path. + pub fn get_path(&self) -> &str { + &self.path + } + + /// Get the index part of this reference string. + pub fn get_index(&self) -> u32 { + self.index } } -impl Display for StrRc { +impl Display for StrRefStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "@{},-{}", self.path, self.index) } } -impl FromStr for StrRc { - type Err = ParseStrRcError; +impl FromStr for StrRefStr { + type Err = ParseStrRefStrError; fn from_str(s: &str) -> Result { - static RE: LazyLock = LazyLock::new(|| Regex::new(r"^@([^,]+),-([0-9]+)$").unwrap()); + static RE: LazyLock = LazyLock::new(|| Regex::new(r"^@(.+),-([0-9]+)$").unwrap()); let caps = RE.captures(s); if let Some(caps) = caps { let path = &caps[1]; - let index = caps.get(2).ok_or(ParseStrRcError::new(s)).and_then(|sv| { - sv.as_str() - .parse::() - .map_err(|_| ParseStrRcError::new(s)) - })?; + let index = caps + .get(2) + .and_then(|sv| sv.as_str().parse::().ok()) + .ok_or(ParseStrRefStrError::new(s))?; Ok(Self::new(path, index)) } else { - Err(ParseStrRcError::new(s)) + Err(ParseStrRefStrError::new(s)) } } }