doc: add docstring for highlevel functions
This commit is contained in:
@@ -24,6 +24,8 @@ pub enum ParseProgramError {
|
|||||||
#[error("parsing into Program error: {0}")]
|
#[error("parsing into Program error: {0}")]
|
||||||
BadFileName(#[from] concept::BadFileNameError),
|
BadFileName(#[from] concept::BadFileNameError),
|
||||||
#[error("parsing into Program error: {0}")]
|
#[error("parsing into Program error: {0}")]
|
||||||
|
ParseClsid(#[from] concept::ParseClsidError),
|
||||||
|
#[error("parsing into Program error: {0}")]
|
||||||
ParseCmdLine(#[from] concept::ParseCmdLineError),
|
ParseCmdLine(#[from] concept::ParseCmdLineError),
|
||||||
#[error("parsing into Program error: {0}")]
|
#[error("parsing into Program error: {0}")]
|
||||||
CastOsStr(#[from] utilities::CastOsStrError),
|
CastOsStr(#[from] utilities::CastOsStrError),
|
||||||
@@ -61,6 +63,11 @@ pub struct Program {
|
|||||||
app_path: String,
|
app_path: String,
|
||||||
app_file_name: String,
|
app_file_name: String,
|
||||||
app_dir_path: String,
|
app_dir_path: String,
|
||||||
|
|
||||||
|
// TODO: Remove this dead_code attribute once we start to use CLSID.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
clsid: concept::Clsid,
|
||||||
|
|
||||||
name: Option<Arc<ProgramStr>>,
|
name: Option<Arc<ProgramStr>>,
|
||||||
icon: Option<Arc<ProgramIcon>>,
|
icon: Option<Arc<ProgramIcon>>,
|
||||||
behavior: Option<Arc<ProgramBehavior>>,
|
behavior: Option<Arc<ProgramBehavior>>,
|
||||||
@@ -102,6 +109,8 @@ impl Program {
|
|||||||
.ok_or(ParseProgramError::NoDirNamePart)
|
.ok_or(ParseProgramError::NoDirNamePart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flatten a `HashMap<String, V>` into a `Vec<U>` with a reverse index map,
|
||||||
|
/// by applying the given transformation function `f` to each value.
|
||||||
fn flat_hashmap<V, U, F>(
|
fn flat_hashmap<V, U, F>(
|
||||||
hashmap: &HashMap<String, V>,
|
hashmap: &HashMap<String, V>,
|
||||||
f: F,
|
f: F,
|
||||||
@@ -118,6 +127,8 @@ impl Program {
|
|||||||
Ok((vector, indexmap))
|
Ok((vector, indexmap))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve a key string to an `Arc<T>` by looking it up in the index map,
|
||||||
|
/// then indexing into the vector.
|
||||||
fn resolve_index<T>(
|
fn resolve_index<T>(
|
||||||
key: &str,
|
key: &str,
|
||||||
vector: &Vec<Arc<T>>,
|
vector: &Vec<Arc<T>>,
|
||||||
@@ -175,6 +186,9 @@ impl Program {
|
|||||||
let app_paths_key = lowlevel::AppPathsKey::new(key.clone());
|
let app_paths_key = lowlevel::AppPathsKey::new(key.clone());
|
||||||
let applications_key = lowlevel::ApplicationsKey::new(key.clone());
|
let applications_key = lowlevel::ApplicationsKey::new(key.clone());
|
||||||
|
|
||||||
|
// Parse CLSID
|
||||||
|
let clsid = schema.get_clsid().parse::<concept::Clsid>()?;
|
||||||
|
|
||||||
// Build string, icon and behavior list,
|
// Build string, icon and behavior list,
|
||||||
// and build mapper at the same time.
|
// and build mapper at the same time.
|
||||||
let (strs, strs_index_map) = Self::flat_hashmap(schema.get_strs(), |entry| {
|
let (strs, strs_index_map) = Self::flat_hashmap(schema.get_strs(), |entry| {
|
||||||
@@ -259,6 +273,7 @@ impl Program {
|
|||||||
app_path,
|
app_path,
|
||||||
app_file_name,
|
app_file_name,
|
||||||
app_dir_path,
|
app_dir_path,
|
||||||
|
clsid,
|
||||||
name,
|
name,
|
||||||
icon,
|
icon,
|
||||||
behavior,
|
behavior,
|
||||||
@@ -272,6 +287,10 @@ impl Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Program {
|
impl Program {
|
||||||
|
/// Resolve the display name of this application.
|
||||||
|
///
|
||||||
|
/// Returns the user-specified display name first.
|
||||||
|
/// Falls back to the executable file name if no display name is configured.
|
||||||
pub fn resolve_name(&self) -> Result<String, ProgramError> {
|
pub fn resolve_name(&self) -> Result<String, ProgramError> {
|
||||||
// Fecch from user specified name first
|
// Fecch from user specified name first
|
||||||
let name = self
|
let name = self
|
||||||
@@ -290,6 +309,10 @@ impl Program {
|
|||||||
Ok(self.app_file_name.clone())
|
Ok(self.app_file_name.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve the icon of this application.
|
||||||
|
///
|
||||||
|
/// Returns the user-specified icon first, then falls back to the first icon from the executable,
|
||||||
|
/// and finally to the system default executable icon.
|
||||||
pub fn resolve_icon(&self) -> Result<concept::IconRc, ProgramError> {
|
pub fn resolve_icon(&self) -> Result<concept::IconRc, ProgramError> {
|
||||||
// Fetch from user specified icon first
|
// Fetch from user specified icon first
|
||||||
let icon = self
|
let icon = self
|
||||||
@@ -311,14 +334,23 @@ impl Program {
|
|||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the number of file extensions associated with this program.
|
||||||
pub fn exts_len(&self) -> usize {
|
pub fn exts_len(&self) -> usize {
|
||||||
self.ext_keys.len()
|
self.ext_keys.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the index of a file extension by its body (without leading dot).
|
||||||
|
///
|
||||||
|
/// Returns `None` if the given extension is not associated with this program.
|
||||||
pub fn find_ext(&self, body: &str) -> Option<usize> {
|
pub fn find_ext(&self, body: &str) -> Option<usize> {
|
||||||
self.ext_keys_map.get(body).copied()
|
self.ext_keys_map.get(body).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve the extension status for the extension at the given index.
|
||||||
|
/// This status including the ProgId associated with this file extension,
|
||||||
|
/// and the display name and icon for this file extension.
|
||||||
|
///
|
||||||
|
/// Returns the fetched status, or the error occurs when fetching.
|
||||||
pub fn resolve_ext(&self, index: usize) -> Result<ProgramSelfExtStatus, ProgramError> {
|
pub fn resolve_ext(&self, index: usize) -> Result<ProgramSelfExtStatus, ProgramError> {
|
||||||
// Fetch data
|
// Fetch data
|
||||||
let progid_ext_key = self
|
let progid_ext_key = self
|
||||||
@@ -461,8 +493,7 @@ 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-requirements of [Self::register] and [Self::unregister].
|
||||||
/// The return value only ensures the pre-requirement of `register` and `unregister`.
|
|
||||||
pub fn is_registered(&self, scope: Scope) -> Result<bool, ProgramError> {
|
pub fn is_registered(&self, scope: Scope) -> Result<bool, ProgramError> {
|
||||||
// Check App Paths subkey.
|
// Check App Paths subkey.
|
||||||
debug_println!("Checking App Paths subkey...");
|
debug_println!("Checking App Paths subkey...");
|
||||||
@@ -494,6 +525,7 @@ impl Program {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set this program as the default handler for the file extension at the given index.
|
||||||
pub fn link_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
|
pub fn link_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
|
||||||
match self.ext_keys.get_mut(index) {
|
match self.ext_keys.get_mut(index) {
|
||||||
Some(program_key) => {
|
Some(program_key) => {
|
||||||
@@ -518,6 +550,7 @@ impl Program {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove this program as the default handler for the file extension at the given index.
|
||||||
pub fn unlink_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
|
pub fn unlink_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
|
||||||
match self.ext_keys.get_mut(index) {
|
match self.ext_keys.get_mut(index) {
|
||||||
Some(program_key) => {
|
Some(program_key) => {
|
||||||
@@ -540,6 +573,10 @@ impl Program {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Query the current default association for the file extension at the given index.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(None)` if the extension is not associated with any program,
|
||||||
|
/// or if the associated program's registration data is missing.
|
||||||
pub fn query_ext(
|
pub fn query_ext(
|
||||||
&self,
|
&self,
|
||||||
view: View,
|
view: View,
|
||||||
@@ -655,6 +692,7 @@ pub struct ProgramSelfExtStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProgramSelfExtStatus {
|
impl ProgramSelfExtStatus {
|
||||||
|
/// Create a new `ProgramSelfExtStatus`.
|
||||||
fn new(ext: concept::Ext, name: String, icon: concept::IconRc) -> Self {
|
fn new(ext: concept::Ext, name: String, icon: concept::IconRc) -> Self {
|
||||||
Self { ext, name, icon }
|
Self { ext, name, icon }
|
||||||
}
|
}
|
||||||
@@ -695,6 +733,7 @@ pub struct ProgramExtStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProgramExtStatus {
|
impl ProgramExtStatus {
|
||||||
|
/// Create a new `ProgramExtStatus`.
|
||||||
fn new(name: String, icon: concept::IconRc) -> Self {
|
fn new(name: String, icon: concept::IconRc) -> Self {
|
||||||
Self { name, icon }
|
Self { name, icon }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ pub struct Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Schema {
|
impl Schema {
|
||||||
|
/// Create an empty `Schema` with all fields set to their defaults.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
identifier: String::new(),
|
identifier: String::new(),
|
||||||
@@ -76,22 +77,40 @@ impl Schema {
|
|||||||
self.path = exe_path.to_string();
|
self.path = exe_path.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the CLSID (Class Identifier) of the application.
|
||||||
|
///
|
||||||
|
/// # Todo
|
||||||
|
///
|
||||||
|
/// Currently this field is not used by this crate,
|
||||||
|
/// but you still need to fill it with a legal CLSID for future expanding.
|
||||||
pub fn set_clsid(&mut self, clsid: &str) -> () {
|
pub fn set_clsid(&mut self, clsid: &str) -> () {
|
||||||
self.clsid = clsid.to_string();
|
self.clsid = clsid.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the key referencing a named string resource for the application display name.
|
||||||
|
///
|
||||||
|
/// This field is optional and can pass `None` to clear it.
|
||||||
pub fn set_name(&mut self, name: Option<&str>) -> () {
|
pub fn set_name(&mut self, name: Option<&str>) -> () {
|
||||||
self.name = name.map(|n| n.to_string());
|
self.name = name.map(|n| n.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the key referencing a named icon resource for the application default icon.
|
||||||
|
///
|
||||||
|
/// This field is optional and can pass `None` to clear it.
|
||||||
pub fn set_icon(&mut self, icon: Option<&str>) -> () {
|
pub fn set_icon(&mut self, icon: Option<&str>) -> () {
|
||||||
self.icon = icon.map(|i| i.to_string());
|
self.icon = icon.map(|i| i.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the key referencing a named behavior resource for the application default execution behavior.
|
||||||
|
///
|
||||||
|
/// This field is optional and can pass `None` to clear it.
|
||||||
pub fn set_behavior(&mut self, behavior: Option<&str>) -> () {
|
pub fn set_behavior(&mut self, behavior: Option<&str>) -> () {
|
||||||
self.behavior = behavior.map(|b| b.to_string());
|
self.behavior = behavior.map(|b| b.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a named string resource entry.
|
||||||
|
///
|
||||||
|
/// Returns error if the name already exists.
|
||||||
pub fn add_str(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
pub fn add_str(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
||||||
match self.strs.insert(name.to_string(), value.to_string()) {
|
match self.strs.insert(name.to_string(), value.to_string()) {
|
||||||
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
||||||
@@ -99,6 +118,9 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a named icon resource entry.
|
||||||
|
///
|
||||||
|
/// Returns error if the name already exists.
|
||||||
pub fn add_icon(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
pub fn add_icon(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
||||||
match self.icons.insert(name.to_string(), value.to_string()) {
|
match self.icons.insert(name.to_string(), value.to_string()) {
|
||||||
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
||||||
@@ -106,6 +128,9 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a named behavior (command line) entry.
|
||||||
|
///
|
||||||
|
/// Returns error if the name already exists.
|
||||||
pub fn add_behavior(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
pub fn add_behavior(&mut self, name: &str, value: &str) -> Result<(), SchemaError> {
|
||||||
match self.behaviors.insert(name.to_string(), value.to_string()) {
|
match self.behaviors.insert(name.to_string(), value.to_string()) {
|
||||||
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
Some(_) => Err(SchemaError::DuplicateKey(name.to_string())),
|
||||||
@@ -116,6 +141,8 @@ impl Schema {
|
|||||||
/// Add a file extension to the schema.
|
/// Add a file extension to the schema.
|
||||||
///
|
///
|
||||||
/// The parameter `ext` is the file extension without leading dot `.`.
|
/// The parameter `ext` is the file extension without leading dot `.`.
|
||||||
|
/// And the parameter `ext_name`, `ext_icon` and `ext_behavior` are the key
|
||||||
|
/// referencing a named string resource, icon resource and behavior resource respectively.
|
||||||
pub fn add_ext(
|
pub fn add_ext(
|
||||||
&mut self,
|
&mut self,
|
||||||
ext: &str,
|
ext: &str,
|
||||||
@@ -135,42 +162,55 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Schema {
|
impl Schema {
|
||||||
|
/// Get the identifier of the schema.
|
||||||
pub(super) fn get_identifier(&self) -> &str {
|
pub(super) fn get_identifier(&self) -> &str {
|
||||||
&self.identifier
|
&self.identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the absolute path to the executable file.
|
||||||
pub(super) fn get_path(&self) -> &str {
|
pub(super) fn get_path(&self) -> &str {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the CLSID (Class Identifier) of the application.
|
||||||
pub(super) fn get_clsid(&self) -> &str {
|
pub(super) fn get_clsid(&self) -> &str {
|
||||||
&self.clsid
|
&self.clsid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the key referencing the named string resource for the display name.
|
||||||
|
/// Return `None` if user doesn't specify this.
|
||||||
pub(super) fn get_name(&self) -> Option<&str> {
|
pub(super) fn get_name(&self) -> Option<&str> {
|
||||||
self.name.as_ref().map(|v| v.as_str())
|
self.name.as_ref().map(|v| v.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the key referencing the named icon resource for the default icon.
|
||||||
|
/// Return `None` if user doesn't specify this.
|
||||||
pub(super) fn get_icon(&self) -> Option<&str> {
|
pub(super) fn get_icon(&self) -> Option<&str> {
|
||||||
self.icon.as_ref().map(|v| v.as_str())
|
self.icon.as_ref().map(|v| v.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the key referencing the named behavior resource for the default verb.
|
||||||
|
/// Return `None` if user doesn't specify this.
|
||||||
pub(super) fn get_behavior(&self) -> Option<&str> {
|
pub(super) fn get_behavior(&self) -> Option<&str> {
|
||||||
self.behavior.as_ref().map(|v| v.as_str())
|
self.behavior.as_ref().map(|v| v.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the string resources map.
|
||||||
pub(super) fn get_strs(&self) -> &HashMap<String, String> {
|
pub(super) fn get_strs(&self) -> &HashMap<String, String> {
|
||||||
&self.strs
|
&self.strs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the icon resources map.
|
||||||
pub(super) fn get_icons(&self) -> &HashMap<String, String> {
|
pub(super) fn get_icons(&self) -> &HashMap<String, String> {
|
||||||
&self.icons
|
&self.icons
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the behavior resources map.
|
||||||
pub(super) fn get_behaviors(&self) -> &HashMap<String, String> {
|
pub(super) fn get_behaviors(&self) -> &HashMap<String, String> {
|
||||||
&self.behaviors
|
&self.behaviors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the file extensions map.
|
||||||
pub(super) fn get_exts(&self) -> &HashMap<String, SchemaExt> {
|
pub(super) fn get_exts(&self) -> &HashMap<String, SchemaExt> {
|
||||||
&self.exts
|
&self.exts
|
||||||
}
|
}
|
||||||
@@ -189,6 +229,7 @@ pub(crate) struct SchemaExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SchemaExt {
|
impl SchemaExt {
|
||||||
|
/// Create a new `SchemaExt` with the given name, icon key and behavior key.
|
||||||
fn new(name: &str, icon: &str, behavior: &str) -> Self {
|
fn new(name: &str, icon: &str, behavior: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
@@ -199,14 +240,17 @@ impl SchemaExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SchemaExt {
|
impl SchemaExt {
|
||||||
|
/// Get the key referencing the named string resource for display name.
|
||||||
pub(super) fn get_name(&self) -> &str {
|
pub(super) fn get_name(&self) -> &str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the key referencing the named icon resource for file icon.
|
||||||
pub(super) fn get_icon(&self) -> &str {
|
pub(super) fn get_icon(&self) -> &str {
|
||||||
&self.icon
|
&self.icon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the key referencing the named behavior resource.
|
||||||
pub(super) fn get_behavior(&self) -> &str {
|
pub(super) fn get_behavior(&self) -> &str {
|
||||||
&self.behavior
|
&self.behavior
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ impl Clsid {
|
|||||||
|
|
||||||
/// The error occurs when parsing CLSID.
|
/// The error occurs when parsing CLSID.
|
||||||
#[derive(Debug, TeError)]
|
#[derive(Debug, TeError)]
|
||||||
#[error("given string \"{inner}\" is invalid for uuid")]
|
#[error("given string \"{inner}\" is invalid for CLSID")]
|
||||||
pub struct ParseClsidError {
|
pub struct ParseClsidError {
|
||||||
/// The clone of string which is not a valid CLSID.
|
/// The clone of string which is not a valid CLSID.
|
||||||
inner: String,
|
inner: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user