1
0

feat: write some highlevel code

This commit is contained in:
2026-04-23 13:17:25 +08:00
parent fed02ad9bc
commit 6ff42928f1
4 changed files with 166 additions and 8 deletions

View File

@@ -1,5 +1,8 @@
use crate::lowlevel; use crate::{lowlevel, utilities, win32};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsStr;
use std::rc::Rc;
use std::path::Path;
use thiserror::Error as TeError; use thiserror::Error as TeError;
pub use lowlevel::{Scope, View}; pub use lowlevel::{Scope, View};
@@ -15,7 +18,16 @@ pub enum SchemaError {
/// Error occurs when trying converting `Schema` into `Program`. /// Error occurs when trying converting `Schema` into `Program`.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
pub enum ParseProgramError {} pub enum ParseProgramError {
#[error("{0}")]
BadFileName(#[from] win32::concept::BadFileNameError),
#[error("{0}")]
CastOsStr(#[from] utilities::CastOsStrError),
#[error("given path doesn't has legal file name part")]
NoFileNamePart,
#[error("given path doesn't has legal directory part")]
NoDirNamePart,
}
/// Error occurs when operating with `Program`. /// Error occurs when operating with `Program`.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
@@ -161,7 +173,20 @@ impl SchemaExt {
/// Program is a complete and immutable program representer /// Program is a complete and immutable program representer
pub struct Program { pub struct Program {
app_paths_key: lowlevel::AppPathsKey,
applications_key: lowlevel::ApplicationsKey,
file_name: String,
dir_name: String,
name: Rc<ProgramStr>,
icon: Rc<ProgramIcon>,
behavior: Rc<ProgramBehavior>,
strs: Vec<Rc<ProgramStr>>,
icons: Vec<Rc<ProgramIcon>>,
behaviors: Vec<Rc<ProgramBehavior>>,
progid_keys: Vec<Rc<ProgramProgIdKey>>,
ext_keys: Vec<ProgramExtKey>,
} }
impl TryFrom<Schema> for Program { impl TryFrom<Schema> for Program {
@@ -173,9 +198,43 @@ impl TryFrom<Schema> for Program {
} }
impl Program { impl Program {
/// Extract the file name part from full path to application,
/// which was used in Registry path component.
fn extract_file_name(full_path: &Path) -> Result<&OsStr, ParseProgramError> {
full_path
.file_name()
.ok_or(ParseProgramError::NoFileNamePart)
}
/// Extract the start in path from full path to application,
/// which basically is the stem of full path.
fn extract_dir_name(full_path: &Path) -> Result<&OsStr, ParseProgramError> {
full_path
.parent()
.map(|p| p.as_os_str())
.ok_or(ParseProgramError::NoDirNamePart)
}
/// Try creating Program from Schema. /// Try creating Program from Schema.
pub fn new(schema: Schema) -> Result<Self, ParseProgramError> { pub fn new(schema: Schema) -> Result<Self, ParseProgramError> {
todo!() // Extract file name part and directory name part respectively.
let schema_path = Path::new(&schema.path);
let file_name = Self::extract_file_name(schema_path)?;
let file_name = String::from(utilities::osstr_to_str(file_name)?);
let dir_name = Self::extract_dir_name(schema_path)?;
let dir_name = String::from(utilities::osstr_to_str(dir_name)?);
// Build app paths key and applications key respectively
let key = win32::concept::FileName::new(&file_name)?;
let app_paths_key = lowlevel::AppPathsKey::new(key.clone());
let applications_key = lowlevel::ApplicationsKey::new(key.clone());
todo!();
// Ok(Self {
// app_paths_key,
// applications_key,
// file_name,
// dir_name,
// })
} }
} }
@@ -199,6 +258,8 @@ impl Program {
/// Check whether this application has been registered in given view. /// Check whether this application has been registered in given view.
/// ///
/// Please note that this is a rough check and do not validate any data. /// Please note that this is a rough check and do not validate any data.
///
/// The return value only ensures the pre-requirement of `register` and `unregister`.
pub fn is_registered(&self, view: View) -> Result<bool, ProgramError> { pub fn is_registered(&self, view: View) -> Result<bool, ProgramError> {
todo!() todo!()
} }
@@ -208,6 +269,41 @@ impl Program {
// region: Program Internals // region: Program Internals
/// Internal used enum presenting a Program string resource.
#[derive(Debug)]
enum ProgramStr {
Plain(String),
RefStr(win32::concept::StrRefStr)
}
/// Internal used enum presenting a Program icon resource.
#[derive(Debug)]
enum ProgramIcon {
Plain(String),
RefStr(win32::concept::IconRefStr)
}
/// Internal used enum presenting a Program behavior (command line setups).
#[derive(Debug)]
struct ProgramBehavior {
inner: String,
}
/// Internal used struct presenting a Program ProgId.
#[derive(Debug)]
struct ProgramProgIdKey {
key: lowlevel::ProgIdKey,
name: Rc<ProgramStr>,
icon: Rc<ProgramIcon>,
behavior: Rc<ProgramBehavior>,
}
/// Internal used struct presenting a Program file extension.
#[derive(Debug)]
struct ProgramExtKey {
key: lowlevel::ExtKey,
assoc: Rc<ProgramProgIdKey>
}
// endregion // endregion

View File

@@ -88,16 +88,44 @@ impl Scope {
// endregion // endregion
// region: App Paths Key
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AppPathsKey { pub struct AppPathsKey {
key: win32::concept::FileName, key: win32::concept::FileName,
} }
impl AppPathsKey {
pub fn new(inner: win32::concept::FileName) -> Self {
Self { key: inner }
}
pub fn inner(&self) -> &win32::concept::FileName {
&self.key
}
}
// endregion
// region: Applications Key
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ApplicationsKey { pub struct ApplicationsKey {
key: win32::concept::FileName, key: win32::concept::FileName,
} }
impl ApplicationsKey {
pub fn new(inner: win32::concept::FileName) -> Self {
Self { key: inner }
}
pub fn inner(&self) -> &win32::concept::FileName {
&self.key
}
}
// endregion
// region: File Extension Key // region: File Extension Key
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -156,6 +184,16 @@ impl ExtKey {
} }
impl ExtKey {
pub fn new(inner: win32::concept::Ext) -> Self {
Self { ext: inner }
}
pub fn inner(&self) -> &win32::concept::Ext {
&self.ext
}
}
// endregion // endregion
// region: ProgId Key // region: ProgId Key
@@ -164,11 +202,11 @@ impl ExtKey {
/// The enum representing a losse Programmatic Identifiers (ProgId). /// The enum representing a losse Programmatic Identifiers (ProgId).
/// ///
/// In real world, not all software developers are willing to following Microsoft suggestions to use ProgId, /// In real world, not all software developers are willing to following Microsoft suggestions to use ProgId.
/// They use string which do not have any regulation as ProgId. /// They use string which do not have any regulation as ProgId.
/// This enum is designed for handling this scenario. /// This enum is designed for handling this scenario.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum LosseProgId { pub enum LosseProgId {
Plain(String), Plain(String),
Strict(win32::concept::ProgId), Strict(win32::concept::ProgId),
} }
@@ -203,6 +241,16 @@ pub struct ProgIdKey {
progid: LosseProgId, progid: LosseProgId,
} }
impl ProgIdKey {
pub fn new(inner: LosseProgId) -> Self {
Self { progid: inner }
}
pub fn inner(&self) -> &LosseProgId {
&self.progid
}
}
// endregion // endregion
// endregion // endregion

View File

@@ -321,6 +321,7 @@ impl ParseIconRefStrError {
/// ///
/// As far as I know, the minus token `-` does nothing in this string. /// As far as I know, the minus token `-` does nothing in this string.
/// The following number is just the index. /// The following number is just the index.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IconRefStr { pub struct IconRefStr {
/// The path part of this reference string. /// The path part of this reference string.
/// And it can be expandable. /// And it can be expandable.
@@ -414,6 +415,7 @@ impl ParseStrRefStrError {
/// ///
/// As far as I know, the minus token `-` does nothing in this string. /// As far as I know, the minus token `-` does nothing in this string.
/// The following number is just the index. /// The following number is just the index.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StrRefStr { pub struct StrRefStr {
/// The path part of this reference string. /// The path part of this reference string.
/// And it can be expandable. /// And it can be expandable.
@@ -503,6 +505,7 @@ pub enum IconSizeKind {
} }
/// The struct representing a loaded icon resource. /// The struct representing a loaded icon resource.
#[derive(Debug)]
pub struct IconRc { pub struct IconRc {
icon: HICON, icon: HICON,
} }
@@ -593,6 +596,7 @@ pub enum LoadStrRcError {
} }
/// The struct representing a loaded string resource. /// The struct representing a loaded string resource.
#[derive(Debug)]
pub struct StrRc { pub struct StrRc {
inner: String, inner: String,
} }
@@ -686,6 +690,7 @@ pub enum ExpandEnvVarError {
/// The struct representing an Expand String, /// The struct representing an Expand String,
/// which contain environment variable in string, /// which contain environment variable in string,
/// like `%LOCALAPPDATA%\SomeApp.exe`. /// like `%LOCALAPPDATA%\SomeApp.exe`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExpandString { pub struct ExpandString {
inner: String, inner: String,
} }
@@ -800,6 +805,8 @@ pub enum ParseFileNameError {
EmbeddedNul(#[from] widestring::error::ContainsNul<WideChar>), EmbeddedNul(#[from] widestring::error::ContainsNul<WideChar>),
/// Given string has illegal char as Windows file name. /// Given string has illegal char as Windows file name.
InvalidChar, InvalidChar,
/// Given string is empty.
EmptyStr,
} }
impl Display for FileName { impl Display for FileName {
@@ -814,7 +821,12 @@ impl FromStr for FileName {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
use windows_sys::Win32::UI::Shell::PathCleanupSpec; use windows_sys::Win32::UI::Shell::PathCleanupSpec;
// Make buffer and call function. // If given string is empty, it must be illegal.
if s.is_empty() {
return Err(ParseFileNameError::EmptyStr);
}
// Make buffer and call Win32 function for checking.
let mut spec = WideCString::from_str(s)?; let mut spec = WideCString::from_str(s)?;
let rv = unsafe { PathCleanupSpec(std::ptr::null(), spec.as_mut_ptr()) }; let rv = unsafe { PathCleanupSpec(std::ptr::null(), spec.as_mut_ptr()) };
if rv != 0 { if rv != 0 {

View File

@@ -35,6 +35,7 @@ fn test_ext_parse() {
} }
ok_tester(".jpg", "jpg"); ok_tester(".jpg", "jpg");
err_tester(".");
err_tester(".jar.disabled"); err_tester(".jar.disabled");
err_tester("jar"); err_tester("jar");
} }
@@ -247,6 +248,7 @@ fn test_file_name() {
} }
ok_tester("GoodExecutable.exe"); ok_tester("GoodExecutable.exe");
err_tester("");
err_tester("*.?xaml"); err_tester("*.?xaml");
err_tester(r#"\\\lol///"#); err_tester(r#"\\\lol///"#);
} }