1
0

feat: remove useless win32 concept for clear code

This commit is contained in:
2026-04-12 16:39:15 +08:00
parent 6b7019e640
commit 69c7592f41
7 changed files with 509 additions and 838 deletions

16
Cargo.lock generated
View File

@@ -187,12 +187,6 @@ dependencies = [
"litrs",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -255,15 +249,6 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.15"
@@ -752,7 +737,6 @@ name = "wfassoc"
version = "0.1.0"
dependencies = [
"indexmap",
"itertools",
"regex",
"thiserror",
"uuid",

View File

@@ -1,4 +1,4 @@
# Wfassoc
# WFAssoc
**W**indows **F**ile **Assoc**iation Library

View File

@@ -20,6 +20,5 @@ windows-sys = { version = "0.60.2", features = [
winreg = { version = "0.55.0", features = ["transactions"] }
widestring = "1.2.1"
indexmap = "2.11.4"
itertools = "0.14.0"
regex = "1.11.3"
uuid = { version = "1.18.1", features = ["v4"] }

File diff suppressed because it is too large Load Diff

View File

@@ -5,95 +5,98 @@
compile_error!("Crate wfassoc is only supported on Windows.");
pub mod utilities;
pub mod winconcept;
pub mod win32ext;
pub mod winregext;
pub mod concept;
use std::collections::HashMap;
use thiserror::Error as TeError;
// pub mod utilities;
// pub mod winconcept;
// pub mod win32ext;
// pub mod winregext;
/// Error occurs in this module.
#[derive(Debug, TeError)]
pub enum Error {}
// use std::collections::HashMap;
// use thiserror::Error as TeError;
/// Result type used in this module.
type Result<T> = std::result::Result<T, Error>;
// /// Error occurs in this module.
// #[derive(Debug, TeError)]
// pub enum Error {}
/// Schema is the sketchpad of complete Program.
///
/// We will create a Schema first, fill some properties, add file extensions,
/// then convert it into immutable Program for following using.
#[derive(Debug)]
pub struct Schema {
identifier: String,
path: String,
clsid: String,
icons: HashMap<String, String>,
behaviors: HashMap<String, String>,
exts: HashMap<String, SchemaExt>,
}
// /// Result type used in this module.
// type Result<T> = std::result::Result<T, Error>;
/// Internal used struct as the Schema file extensions hashmap value type.
#[derive(Debug)]
struct SchemaExt {
name: String,
icon: String,
behavior: String,
}
// /// Schema is the sketchpad of complete Program.
// ///
// /// We will create a Schema first, fill some properties, add file extensions,
// /// then convert it into immutable Program for following using.
// #[derive(Debug)]
// pub struct Schema {
// identifier: String,
// path: String,
// clsid: String,
// icons: HashMap<String, String>,
// behaviors: HashMap<String, String>,
// exts: HashMap<String, SchemaExt>,
// }
impl Schema {
pub fn new() -> Self {
Self {
identifier: String::new(),
path: String::new(),
clsid: String::new(),
icons: HashMap::new(),
behaviors: HashMap::new(),
exts: HashMap::new(),
}
}
// /// Internal used struct as the Schema file extensions hashmap value type.
// #[derive(Debug)]
// struct SchemaExt {
// name: String,
// icon: String,
// behavior: String,
// }
pub fn set_identifier(&mut self, identifier: &str) -> Result<()> {}
// impl Schema {
// pub fn new() -> Self {
// Self {
// identifier: String::new(),
// path: String::new(),
// clsid: String::new(),
// icons: HashMap::new(),
// behaviors: HashMap::new(),
// exts: HashMap::new(),
// }
// }
pub fn set_path(&mut self, exe_path: &str) -> Result<()> {}
// pub fn set_identifier(&mut self, identifier: &str) -> Result<()> {}
pub fn set_clsid(&mut self, clsid: &str) -> Result<()> {}
// pub fn set_path(&mut self, exe_path: &str) -> Result<()> {}
pub fn add_icon(&mut self, name: &str, value: &str) -> Result<()> {}
// pub fn set_clsid(&mut self, clsid: &str) -> Result<()> {}
pub fn add_behavior(&mut self, name: &str, value: &str) -> Result<()> {}
// pub fn add_icon(&mut self, name: &str, value: &str) -> Result<()> {}
pub fn add_ext(
&mut self,
ext: &str,
ext_name: &str,
ext_icon: &str,
ext_behavior: &str,
) -> Result<()> {
}
// pub fn add_behavior(&mut self, name: &str, value: &str) -> Result<()> {}
pub fn into_program(self) -> Result<Program> {
Program::new(self)
}
}
// pub fn add_ext(
// &mut self,
// ext: &str,
// ext_name: &str,
// ext_icon: &str,
// ext_behavior: &str,
// ) -> Result<()> {
// }
/// Program is a complete and immutable program representer
pub struct Program {}
// pub fn into_program(self) -> Result<Program> {
// Program::new(self)
// }
// }
impl TryFrom<Schema> for Program {
type Error = Error;
// /// Program is a complete and immutable program representer
// pub struct Program {}
fn try_from(value: Schema) -> std::result::Result<Self, Self::Error> {
Self::new(value)
}
}
// impl TryFrom<Schema> for Program {
// type Error = Error;
impl Program {
pub fn new(schema: Schema) -> Result<Self> {}
}
// fn try_from(value: Schema) -> std::result::Result<Self, Self::Error> {
// Self::new(value)
// }
// }
// impl Program {
// pub fn new(schema: Schema) -> Result<Self> {}
// }
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ExtKey {
inner: winconcept::Ext
}
// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
// pub struct ExtKey {
// inner: winconcept::Ext
// }

View File

@@ -12,13 +12,13 @@ macro_rules! debug_println {
// For no argument.
() => {
if cfg!(debug_assertions) {
println!();
eprintln!();
}
};
// For one or more arguments like println!.
($($arg:tt)*) => {
if cfg!(debug_assertions) {
println!($($arg)*);
eprintln!($($arg)*);
}
};
}
@@ -27,7 +27,7 @@ macro_rules! debug_println {
/// The error occurs when casting `OsStr` into `str`.
#[derive(Debug, TeError)]
#[error("failed when casting OS string into string")]
#[error("fail to cast OS string into string")]
pub struct CastOsStrError {}
impl CastOsStrError {

View File

@@ -1,8 +1,10 @@
use std::{path::Path, str::FromStr};
use wfassoc::winconcept::*;
use std::str::FromStr;
use wfassoc::concept::*;
// region: File Extension
#[test]
fn test_ex_new() {
fn test_ext_new() {
fn ok_tester(s: &str, probe: &str) {
let rv = Ext::new(s);
assert!(rv.is_ok());
@@ -37,6 +39,10 @@ fn test_ext_parse() {
err_tester("jar");
}
// endregion
// region: Programmatic Identifiers
#[test]
fn test_prog_id_new() {
fn ok_tester(vendor: &str, component: &str, version: Option<u32>, probe: &str) {
@@ -50,6 +56,7 @@ fn test_prog_id_new() {
assert!(rv.is_err());
}
ok_tester("VSCode", "c++", None, "VSCode.c++");
ok_tester("PowerPoint", "Template", Some(12), "PowerPoint.Template.12");
err_tester("", "MyApp", None);
err_tester("Me", "", None);
@@ -79,11 +86,17 @@ fn test_prog_id_parse() {
err_tester("What the f*ck?");
}
// endregion
// region: CLSID
#[test]
fn test_clsid() {
fn ok_tester(s: &str) {
let rv = Clsid::from_str(s);
assert!(rv.is_ok());
let rv = rv.unwrap();
assert_eq!(s.to_lowercase(), rv.to_string().to_lowercase());
}
fn err_tester(s: &str) {
let rv = Clsid::from_str(s);
@@ -96,6 +109,12 @@ fn test_clsid() {
err_tester("{26EE0668A00A-44D7-9371-BEB064C98683}");
}
// endregion
// region: Windows Resource Reference String
// region: Icon Reference String
#[test]
fn test_icon_ref_str() {
fn ok_tester(s: &str, probe: (&str, u32)) {
@@ -115,9 +134,14 @@ fn test_icon_ref_str() {
(r#"%SystemRoot%\System32\imageres.dll"#, 72),
);
err_tester(r#"C:\Windows\Cursors\aero_arrow.cur"#);
err_tester(r#"This is my application, OK?"#);
err_tester(r#"@%SystemRoot%\System32\shell32.dll,-30596"#);
}
// endregion
// region: String Reference String
#[test]
fn test_str_ref_str() {
fn ok_tester(s: &str, probe: (&str, u32)) {
@@ -140,29 +164,57 @@ fn test_str_ref_str() {
err_tester(r#"%SystemRoot%\System32\imageres.dll,-72"#);
}
// endregion
// endregion
// region: Windows Resource
// region: Icon Resource
#[test]
fn test_icon_rc() {
fn tester(file: &str, index: u32) {
let icon = IconRc::new(Path::new(file), index, IconSizeKind::Small);
fn ok_tester(file: &str, index: u32) {
let icon = IconRc::new(file, index, IconSizeKind::Small);
assert!(icon.is_ok())
}
fn err_tester(file: &str, index: u32) {
let icon = IconRc::new(file, index, IconSizeKind::Small);
assert!(icon.is_err())
}
// We pick it from "jpegfile" ProgId
tester("imageres.dll", 72);
tester("notepad.exe", 0);
ok_tester("imageres.dll", 72);
ok_tester("notepad.exe", 0);
err_tester("this-executable-must-inexisting.exe", 114514);
}
// endregion
// region: String Resource
#[test]
fn test_str_rc() {
fn tester(file: &str, index: u32) {
let rv = StrRc::new(Path::new(file), index);
fn ok_tester(file: &str, index: u32) {
let rv = StrRc::new(file, index);
assert!(rv.is_ok());
}
fn err_tester(file: &str, index: u32) {
let rv = StrRc::new(file, index);
assert!(rv.is_err());
}
// We pick from "jpegfile" ProgId
tester("shell32.dll", 30596);
// We pick it from "jpegfile" ProgId
ok_tester("shell32.dll", 30596);
err_tester("this-executable-must-inexisting.exe", 114514);
}
// endregion
// endregion
// region: Expand String
#[test]
fn test_expand_string() {
fn tester(s: &str) {
@@ -177,91 +229,4 @@ fn test_expand_string() {
tester(r#"%SystemRoot%\System32\shell32.dll"#);
}
#[test]
fn test_cmd_args() {
// Declare tester
fn tester(s: &str, probe: &[&'static str]) {
let rv = CmdArgs::new(s);
let inner = rv.get_inner();
assert_eq!(inner.len(), probe.len());
let n = inner.len();
for i in 0..n {
assert_eq!(inner[i].get_inner(), probe[i]);
}
}
// Normal cases
tester(
"MyApp.exe --config ppic.toml",
&["MyApp.exe", "--config", "ppic.toml"],
);
tester(
r#""C:\Program Files\MyApp\MyApp.exe" --config ppic.toml"#,
&[
r#"C:\Program Files\MyApp\MyApp.exe"#,
"--config",
"ppic.toml",
],
);
// Microsoft shitty cases.
tester(r#""abc" d e"#, &[r#"abc"#, r#"d"#, r#"e"#]);
tester(r#"a\\b d"e f"g h"#, &[r#"a\\b"#, r#"de fg"#, r#"h"#]);
tester(r#"a\\\"b c d"#, &[r#"a\"b"#, r#"c"#, r#"d"#]);
tester(r#"a\\\\"b c" d e"#, &[r#"a\\b c"#, r#"d"#, r#"e"#]);
tester(r#"a"b"" c d"#, &[r#"ab" c d"#]);
}
#[test]
fn test_cmd_arg() {
// Declare tester
fn ok_tester(s: &str, probe: &str) {
let rv = CmdArg::new(s);
assert!(rv.is_ok());
let rv = rv.unwrap();
assert_eq!(rv.get_inner(), probe);
}
fn err_tester(s: &str) {
let rv = CmdArg::new(s);
assert!(rv.is_err());
}
// Normal test
ok_tester(
r#""C:\Program Files\MyApp\MyApp.exe""#,
r#"C:\Program Files\MyApp\MyApp.exe"#,
);
err_tester("MyApp.exe --config ppic.toml");
err_tester("");
}
#[test]
fn test_cmd_arg_quoted_string() {
fn tester(s: &str, probe: &str) {
let rv = CmdArg::with_inner(s);
assert_eq!(rv.to_quoted_string(true), probe);
}
tester(
r#"C:\Program Files\MyApp\MyApp.exe"#,
r#""C:\Program Files\MyApp\MyApp.exe""#,
);
}
#[test]
fn test_cmd_args_quoted_string() {
fn tester(args: &[&str], probe: &str) {
let rv = CmdArgs::with_inner(args.iter().map(|s| CmdArg::with_inner(s)));
assert_eq!(rv.to_quoted_string(), probe);
}
tester(
&[
r#"C:\Program Files\MyApp\MyApp.exe"#,
"--config",
"ppic.toml",
],
r#""C:\Program Files\MyApp\MyApp.exe" --config ppic.toml"#,
);
}
// endregion