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 // region: Icon Reference String
/// Error occurs when given string is not a valid Icon Reference String.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
#[error("given string \"{inner}\" is not a valid Icon Reference String")] #[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, inner: String,
} }
impl ParseIconRcError { impl ParseIconRefStrError {
/// Create new error instance.
fn new(s: &str) -> Self { fn new(s: &str) -> Self {
Self { Self {
inner: s.to_string(), inner: s.to_string(),
@ -30,19 +33,27 @@ impl ParseIconRcError {
} }
} }
#[derive(Debug, TeError)] /// The struct representing an Icon Reference String
#[error("fail to load icon")] /// looks like `%SystemRoot%\System32\imageres.dll,-72`.
pub struct FetchIconError {} pub struct IconRefStr {
/// The path part of this reference string.
pub struct IconRc { /// And it can be expandable.
path: String, path: String,
/// The index part of this reference string.
index: u32, index: u32,
} }
impl IconRc { impl IconRefStr {
/// Create a new Icon Reference String. /// 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. /// `index` is the index of the icon in the resource file.
pub fn new(path: &str, index: u32) -> Self { pub fn new(path: &str, index: u32) -> Self {
Self { Self {
@ -51,34 +62,41 @@ impl IconRc {
} }
} }
pub fn fetch_icon(&self) -> Result<Icon, FetchIconError> { /// Get the path part of this reference string.
todo!() ///
/// 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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{},-{}", self.path, self.index) write!(f, "{},-{}", self.path, self.index)
} }
} }
impl FromStr for IconRc { impl FromStr for IconRefStr {
type Err = ParseIconRcError; type Err = ParseIconRefStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
static RE: LazyLock<Regex> = 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); let caps = RE.captures(s);
if let Some(caps) = caps { if let Some(caps) = caps {
let path = &caps[1]; let path = &caps[1];
let index = caps.get(2).ok_or(ParseIconRcError::new(s)).and_then(|sv| { let index = caps
sv.as_str() .get(2)
.parse::<u32>() .and_then(|sv| sv.as_str().parse::<u32>().ok())
.map_err(|_| ParseIconRcError::new(s)) .ok_or(ParseIconRefStrError::new(s))?;
})?;
Ok(Self::new(path, index)) Ok(Self::new(path, index))
} else { } else {
Err(ParseIconRcError::new(s)) Err(ParseIconRefStrError::new(s))
} }
} }
} }
@ -87,13 +105,16 @@ impl FromStr for IconRc {
// region: String Reference String // region: String Reference String
/// Error occurs when given string is not a valid String Reference String.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
#[error("given string \"{inner}\" is not a valid String Reference String")] #[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, inner: String,
} }
impl ParseStrRcError { impl ParseStrRefStrError {
/// Create new error instance.
fn new(s: &str) -> Self { fn new(s: &str) -> Self {
Self { Self {
inner: s.to_string(), inner: s.to_string(),
@ -101,20 +122,22 @@ impl ParseStrRcError {
} }
} }
#[derive(Debug, TeError)] /// The struct representing an String Reference String
#[error("fail to load string")] /// looks like `@%SystemRoot%\System32\shell32.dll,-30596`.
pub struct FetchStrError{} pub struct StrRefStr {
/// The path part of this reference string.
pub struct StrRc { /// And it can be expandable.
path: String, path: String,
/// The index part of this reference string.
index: u32, index: u32,
} }
impl StrRc { impl StrRefStr {
/// Create a new String Reference String. /// 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. /// `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 { pub fn new(path: &str, index: u32) -> Self {
Self { Self {
path: path.to_string(), path: path.to_string(),
@ -122,33 +145,40 @@ impl StrRc {
} }
} }
pub fn fetch_string(&self) -> Result<String, FetchStrError> { /// Get the path part of this reference string.
todo!() ///
/// 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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "@{},-{}", self.path, self.index) write!(f, "@{},-{}", self.path, self.index)
} }
} }
impl FromStr for StrRc { impl FromStr for StrRefStr {
type Err = ParseStrRcError; type Err = ParseStrRefStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> { 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); let caps = RE.captures(s);
if let Some(caps) = caps { if let Some(caps) = caps {
let path = &caps[1]; let path = &caps[1];
let index = caps.get(2).ok_or(ParseStrRcError::new(s)).and_then(|sv| { let index = caps
sv.as_str() .get(2)
.parse::<u32>() .and_then(|sv| sv.as_str().parse::<u32>().ok())
.map_err(|_| ParseStrRcError::new(s)) .ok_or(ParseStrRefStrError::new(s))?;
})?;
Ok(Self::new(path, index)) Ok(Self::new(path, index))
} else { } else {
Err(ParseStrRcError::new(s)) Err(ParseStrRefStrError::new(s))
} }
} }
} }