diff --git a/wfassoc/src/assoc.rs b/wfassoc/src/assoc.rs index 24d27fb..a461272 100644 --- a/wfassoc/src/assoc.rs +++ b/wfassoc/src/assoc.rs @@ -4,7 +4,6 @@ use crate::extra::windows::{Ext, ProgId}; use crate::extra::winreg as winreg_extra; use crate::utilities; -use std::convert::Infallible; use std::fmt::Display; use std::str::FromStr; use thiserror::Error as TeError; @@ -25,7 +24,9 @@ pub enum Error { #[error("{0}")] ParseProgId(#[from] crate::extra::windows::ParseProgIdError), #[error("{0}")] - BlankPath(#[from] crate::extra::winreg::BlankStringError), + ParseProgIdKind(#[from] ParseProgIdKindError), + #[error("{0}")] + BlankPath(#[from] crate::extra::winreg::BlankPathError), } /// The result type used in this crate. @@ -113,6 +114,15 @@ impl From for View { // region: ProgId Kind +/// The error occurs when parsing ProgId kind. +#[derive(Debug, TeError)] +pub enum ParseProgIdKindError { + #[error("{0}")] + FromStd(#[from] crate::extra::windows::ParseProgIdError), + #[error("given ProgId is blank")] + BlankProgId, +} + /// The variant of ProgId for the compatibility /// with those software which do not follow Microsoft suggestions. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -133,13 +143,17 @@ impl Display for ProgIdKind { } impl FromStr for ProgIdKind { - type Err = Infallible; + type Err = ParseProgIdKindError; fn from_str(s: &str) -> std::result::Result { - Ok(match s.parse::() { - Ok(v) => Self::Std(v), - Err(_) => Self::Other(s.to_string()), - }) + if s.is_empty() { + Err(ParseProgIdKindError::BlankProgId) + } else { + Ok(match s.parse::() { + Ok(v) => Self::Std(v), + Err(_) => Self::Other(s.to_string()), + }) + } } } @@ -231,6 +245,20 @@ pub struct ExtKey { ext: Ext, } +impl ExtKey { + /// Create new file extension registry key representer. + pub fn new(s: &str) -> Result { + Ok(Self { + ext: Ext::from_str(s)?, + }) + } + + /// Fetch the reference to inner extension representer. + pub fn as_inner(&self) -> &Ext { + &self.ext + } +} + impl ExtKey { /// Set the default "Open With" of this file extension to given ProgId. pub fn link(&self, prog_id: &ProgIdKey, scope: Scope) -> Result<()> { @@ -243,7 +271,7 @@ impl ExtKey { let (subkey, _) = classes.create_subkey_with_flags(blank_path_guard(self.ext.to_string())?, KEY_WRITE)?; // Set the default way to open this file extension - subkey.set_value("", &prog_id.to_string())?; + subkey.set_value("", &prog_id.as_inner().to_string())?; // Okey Ok(()) @@ -268,7 +296,7 @@ impl ExtKey { )? { // Only delete the default key if it is equal to our ProgId if let Some(value) = try_get_value::(&subkey, "")? { - if value == prog_id.to_string() { + if value == prog_id.as_inner().to_string() { // Delete the default key. subkey.delete_value("")?; } @@ -297,9 +325,7 @@ impl ExtKey { Some(subkey) => { // Try get associated ProgId if possible match try_get_value::(&subkey, "")? { - Some(value) => { - Some(ProgIdKey::from_str(value.as_str()).expect("unexpected Infallable")) - } + Some(value) => Some(ProgIdKey::new(value.as_str())?), None => None, } } @@ -311,22 +337,6 @@ impl ExtKey { } } -impl Display for ExtKey { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.ext) - } -} - -impl FromStr for ExtKey { - type Err = ::Err; - - fn from_str(s: &str) -> std::result::Result { - Ok(Self { - ext: Ext::from_str(s)?, - }) - } -} - // endregion // region: ProgId Registry Key @@ -336,6 +346,20 @@ pub struct ProgIdKey { prog_id: ProgIdKind, } +impl ProgIdKey { + /// Create new ProgId registry representer. + pub fn new(s: &str) -> Result { + Ok(Self { + prog_id: ProgIdKind::from_str(s)?, + }) + } + + /// Fetch the reference to inner ProgId. + pub fn as_inner(&self) -> &ProgIdKind { + &self.prog_id + } +} + impl ProgIdKey { /// Create ProgId into Registry in given scope with given parameters pub fn create(&self, scope: Scope, command: &str) -> Result<()> { @@ -364,20 +388,4 @@ impl ProgIdKey { } } -impl Display for ProgIdKey { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.prog_id) - } -} - -impl FromStr for ProgIdKey { - type Err = ::Err; - - fn from_str(s: &str) -> std::result::Result { - Ok(Self { - prog_id: ProgIdKind::from_str(s)?, - }) - } -} - // endregion diff --git a/wfassoc/src/extra/winreg.rs b/wfassoc/src/extra/winreg.rs index 014cb84..f56df09 100644 --- a/wfassoc/src/extra/winreg.rs +++ b/wfassoc/src/extra/winreg.rs @@ -62,14 +62,14 @@ pub fn try_get_value>( // endregion -// region: Blank String Guard +// region: Blank Path Guard -/// The error occurs when given string is empty. +/// The error occurs when given registry path is empty. #[derive(Debug, TeError)] -#[error("unexpected empty string")] -pub struct BlankStringError {} +#[error("unexpected empty registry path")] +pub struct BlankPathError {} -impl BlankStringError { +impl BlankPathError { fn new() -> Self { Self {} } @@ -82,9 +82,9 @@ impl BlankStringError { /// Because it will cause unexpected behavior that returning key self, rather than subkey. /// This is VERY dangerous especially for those registry delete functions. /// So I create this function to prevent any harmful blank path was passed into registry function. -pub fn blank_path_guard>(path: P) -> std::result::Result { +pub fn blank_path_guard>(path: P) -> std::result::Result { if path.as_ref().is_empty() { - Err(BlankStringError::new()) + Err(BlankPathError::new()) } else { Ok(path) }