Skip to main content

quincy_gui/
validation.rs

1use quincy::error::ConfigError;
2use quincy::{QuincyError, Result};
3use regex::Regex;
4use std::sync::OnceLock;
5
6/// Compiled regex for valid configuration/instance names.
7///
8/// Pattern allows ASCII letters, digits, '-' and '_'.
9/// Names must be non-empty.
10static NAME_RE: OnceLock<Regex> = OnceLock::new();
11
12fn name_re() -> &'static Regex {
13    NAME_RE.get_or_init(|| Regex::new(r"^[A-Za-z0-9_-]+$").expect("valid name regex"))
14}
15
16/// Returns true if the provided name matches the allowed pattern.
17///
18/// Allowed: ASCII letters, digits, spaces, '-' and '_'.
19pub fn is_valid_config_name(name: &str) -> bool {
20    !name.is_empty() && name_re().is_match(name)
21}
22
23/// Validates a configuration file/display name.
24///
25/// Returns a `ConfigError::InvalidValue` on failure with a descriptive reason.
26pub fn validate_config_name(name: &str) -> Result<()> {
27    is_valid_config_name(name).then_some(()).ok_or_else(|| {
28        QuincyError::Config(ConfigError::InvalidValue {
29            field: "config_name".to_string(),
30            reason: "contains unsupported characters (allowed: letters, digits, '-', '_')"
31                .to_string(),
32        })
33    })
34}
35
36/// Validates an instance name (used for IPC identification).
37///
38/// Uses the same rules as configuration names but distinguishes the field for clearer errors.
39pub fn validate_instance_name(name: &str) -> Result<()> {
40    is_valid_config_name(name).then_some(()).ok_or_else(|| {
41        QuincyError::Config(ConfigError::InvalidValue {
42            field: "instance_name".to_string(),
43            reason: "contains unsupported characters (allowed: letters, digits, '-', '_')"
44                .to_string(),
45        })
46    })
47}