feat: finish highlevel convertion
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
use crate::{lowlevel, utilities, win32::concept};
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::sync::LazyLock;
|
||||
use thiserror::Error as TeError;
|
||||
|
||||
pub use lowlevel::{Scope, View};
|
||||
@@ -19,6 +21,10 @@ pub enum SchemaError {
|
||||
/// Error occurs when trying converting `Schema` into `Program`.
|
||||
#[derive(Debug, TeError)]
|
||||
pub enum ParseProgramError {
|
||||
#[error("{0}")]
|
||||
BadExtBody(#[from] concept::BadExtBodyError),
|
||||
#[error("{0}")]
|
||||
BadProgIdPart(#[from] concept::BadProgIdPartError),
|
||||
#[error("{0}")]
|
||||
BadFileName(#[from] concept::BadFileNameError),
|
||||
#[error("{0}")]
|
||||
@@ -31,6 +37,10 @@ pub enum ParseProgramError {
|
||||
NoDirNamePart,
|
||||
#[error("given identifier is not presented in dict")]
|
||||
NoSuchIdentifier,
|
||||
#[error("extension name should not be empty")]
|
||||
EmptyExtension,
|
||||
#[error("given program identifier is not allowed")]
|
||||
BadIdentifier,
|
||||
}
|
||||
|
||||
/// Error occurs when operating with `Program`.
|
||||
@@ -124,6 +134,9 @@ impl Schema {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// The passed `ext` string should be without leading dot `.`.
|
||||
pub fn add_ext(
|
||||
&mut self,
|
||||
ext: &str,
|
||||
@@ -241,14 +254,39 @@ impl Program {
|
||||
index_map: &HashMap<String, usize>,
|
||||
) -> Result<Rc<T>, ParseProgramError> {
|
||||
match index_map.get(key) {
|
||||
Some(index) => match vector.get(*index) {
|
||||
Some(value) => Ok(value.clone()),
|
||||
None => Err(ParseProgramError::NoSuchIdentifier),
|
||||
},
|
||||
Some(index) => Ok(vector
|
||||
.get(*index)
|
||||
.expect("unexpected invalid index")
|
||||
.clone()),
|
||||
None => Err(ParseProgramError::NoSuchIdentifier),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build ProgId from identifier and given file extension.
|
||||
fn build_progid(
|
||||
identifier: &str,
|
||||
ext: &str,
|
||||
) -> Result<lowlevel::LosseProgId, ParseProgramError> {
|
||||
// Use Regex to check identifier
|
||||
static RE: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^[a-zA-Z][a-zA-Z0-9_-]*$").expect("unexpected bad regex pattern string")
|
||||
});
|
||||
let identifier = match RE.captures(identifier) {
|
||||
Some(_) => identifier,
|
||||
None => return Err(ParseProgramError::BadIdentifier),
|
||||
};
|
||||
|
||||
// Capitalize first ASCII of ext
|
||||
let ext = utilities::capitalize_first_ascii(ext);
|
||||
|
||||
// Build strict ProgId
|
||||
let progid = concept::ProgId::new(identifier, &ext, None)?;
|
||||
// Then build losse ProgId
|
||||
let losse_progid: lowlevel::LosseProgId = progid.into();
|
||||
// Return built result
|
||||
Ok(losse_progid)
|
||||
}
|
||||
|
||||
/// Try creating Program from Schema.
|
||||
pub fn new(schema: Schema) -> Result<Self, ParseProgramError> {
|
||||
// Extract file name part and directory name part respectively.
|
||||
@@ -301,16 +339,60 @@ impl Program {
|
||||
.map(|behavior| Self::resolve_index(&behavior, &behaviors, &behaviors_index_map))
|
||||
.transpose()?;
|
||||
|
||||
// Process file extensions.
|
||||
// We need create ProgIds list and Exts list at the same time.
|
||||
// We build ProgIdKey and ExtKey list at the same time
|
||||
let mut progid_keys: Vec<Rc<ProgramProgIdKey>> = Vec::with_capacity(schema.exts.len());
|
||||
let mut ext_keys: Vec<ProgramExtKey> = Vec::with_capacity(schema.exts.len());
|
||||
for (key, value) in &schema.exts {
|
||||
// Build ProgId first.
|
||||
let progid = Self::build_progid(&schema.identifier, key.as_str())?;
|
||||
// Then build ProgId key.
|
||||
let progid_key = lowlevel::ProgIdKey::new(progid);
|
||||
|
||||
todo!();
|
||||
// Ok(Self {
|
||||
// app_paths_key,
|
||||
// applications_key,
|
||||
// file_name,
|
||||
// dir_name,
|
||||
// })
|
||||
// Build essential fields for program ProgId key struct.
|
||||
let name = Self::resolve_index(&value.name, &strs, &strs_index_map)?;
|
||||
let icon = Self::resolve_index(&value.icon, &icons, &icons_index_map)?;
|
||||
let behavior = Self::resolve_index(&value.behavior, &behaviors, &behaviors_index_map)?;
|
||||
|
||||
// Create program ProgId key struct
|
||||
let progid_key = ProgramProgIdKey {
|
||||
key: progid_key,
|
||||
name,
|
||||
icon,
|
||||
behavior,
|
||||
};
|
||||
// Create Rc style
|
||||
let progid_key = Rc::new(progid_key);
|
||||
|
||||
// Build Ext.
|
||||
let ext = concept::Ext::new(key.as_str())?;
|
||||
let ext_key = lowlevel::ExtKey::new(ext);
|
||||
|
||||
// Create program Ext key struct
|
||||
let ext_key = ProgramExtKey {
|
||||
key: ext_key,
|
||||
assoc: progid_key.clone(),
|
||||
};
|
||||
|
||||
// Add them into list
|
||||
progid_keys.push(progid_key);
|
||||
ext_keys.push(ext_key);
|
||||
}
|
||||
|
||||
// Everything is okey
|
||||
Ok(Self {
|
||||
app_paths_key,
|
||||
applications_key,
|
||||
file_name,
|
||||
dir_name,
|
||||
name,
|
||||
icon,
|
||||
behavior,
|
||||
strs,
|
||||
icons,
|
||||
behaviors,
|
||||
progid_keys,
|
||||
ext_keys,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user