Skip to main content

fn0_deploy/
name.rs

1pub const MAX_PROJECT_NAME_LEN: usize = 100;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum NameError {
5    Empty,
6    TooLong { len: usize },
7    InvalidChar { ch: char },
8}
9
10impl std::fmt::Display for NameError {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        match self {
13            NameError::Empty => write!(f, "name cannot be empty"),
14            NameError::TooLong { len } => write!(
15                f,
16                "name too long: {len} chars (max {MAX_PROJECT_NAME_LEN})"
17            ),
18            NameError::InvalidChar { ch } => write!(
19                f,
20                "name contains invalid character {ch:?}; allowed: letters, digits, '.', '_', '-'"
21            ),
22        }
23    }
24}
25
26impl std::error::Error for NameError {}
27
28pub fn validate_project_name(s: &str) -> std::result::Result<(), NameError> {
29    let len = s.chars().count();
30    if len == 0 {
31        return Err(NameError::Empty);
32    }
33    if len > MAX_PROJECT_NAME_LEN {
34        return Err(NameError::TooLong { len });
35    }
36    if let Some(ch) = s
37        .chars()
38        .find(|c| !c.is_ascii_alphanumeric() && *c != '.' && *c != '_' && *c != '-')
39    {
40        return Err(NameError::InvalidChar { ch });
41    }
42    Ok(())
43}
44
45pub fn is_valid_project_name(s: &str) -> bool {
46    validate_project_name(s).is_ok()
47}