1
0

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
This commit is contained in:
2025-10-26 22:16:48 +08:00
parent 23d0a79c0b
commit cc79951ee6

View File

@ -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<Icon, FetchIconError> {
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<Self, Self::Err> {
static RE: LazyLock<Regex> =
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::<u32>()
.map_err(|_| ParseIconRcError::new(s))
})?;
let index = caps
.get(2)
.and_then(|sv| sv.as_str().parse::<u32>().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<String, FetchStrError> {
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<Self, Self::Err> {
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^@([^,]+),-([0-9]+)$").unwrap());
static RE: LazyLock<Regex> = 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::<u32>()
.map_err(|_| ParseStrRcError::new(s))
})?;
let index = caps
.get(2)
.and_then(|sv| sv.as_str().parse::<u32>().ok())
.ok_or(ParseStrRefStrError::new(s))?;
Ok(Self::new(path, index))
} else {
Err(ParseStrRcError::new(s))
Err(ParseStrRefStrError::new(s))
}
}
}