fluvio_sc_schema/
shared.rs

1use thiserror::Error;
2
3pub type Result = std::result::Result<(), ValidateResourceNameError>;
4
5pub const MAX_RESOURCE_NAME_LEN: usize = 63;
6
7#[derive(Copy, Clone, Debug, Error)]
8pub enum ValidateResourceNameError {
9    #[error("Name exceeds max characters allowed {MAX_RESOURCE_NAME_LEN}")]
10    NameLengthExceeded,
11    #[error("Contain only lowercase alphanumeric characters or '-'")]
12    InvalidCharacterEncountered,
13}
14
15/// Checks if the Resource Name is valid for internal resources.
16///
17/// ```test
18/// let name = "prices-list-scrapper";
19/// assert!(validate_resource_name(name).is_ok());
20///
21/// let name = "prices list scrapper";
22/// assert!(validate_resource_name(name).is_err());
23///
24/// let name = "price$-l1st-scr@pper";
25/// assert!(validate_resource_name(name).is_err());
26/// ```
27pub fn validate_resource_name(name: &str) -> Result {
28    if name.len() > MAX_RESOURCE_NAME_LEN {
29        return Err(ValidateResourceNameError::NameLengthExceeded);
30    }
31
32    if name
33        .chars()
34        .all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '-')
35        && !name.ends_with('-')
36        && !name.starts_with('-')
37    {
38        return Ok(());
39    }
40
41    Err(ValidateResourceNameError::InvalidCharacterEncountered)
42}
43
44#[cfg(test)]
45mod test {
46    use super::validate_resource_name;
47
48    #[test]
49    fn validates_name_length() {
50        let name = "this-is-a-very-long-long-long-long-long-long-name-and-its-not-valid";
51
52        assert!(validate_resource_name(name).is_err());
53    }
54
55    #[test]
56    fn validates_no_spaces_allowed() {
57        let name = "Hello World";
58
59        assert!(validate_resource_name(name).is_err());
60    }
61
62    #[test]
63    fn validates_no_special_chars_allowed() {
64        let name = "!@#$%^&*()👻";
65
66        assert!(validate_resource_name(name).is_err());
67    }
68
69    #[test]
70    fn allows_valid_names() {
71        let names = vec![
72            "prices-list-scrapper",
73            "final-countdown-actual-countdown-timer",
74            "luke-i-am-your-father",
75            "im-not-looking-for-funny-names-in-the-internet",
76            "use-fluvio-exclamation-sign",
77            "testing-1234",
78        ];
79
80        for name in names {
81            assert!(validate_resource_name(name).is_ok());
82        }
83    }
84
85    #[test]
86    fn reject_topics_with_spaces() {
87        assert!(validate_resource_name("hello world").is_err());
88    }
89
90    #[test]
91    fn reject_topics_with_uppercase() {
92        assert!(validate_resource_name("helloWorld").is_err());
93    }
94
95    #[test]
96    fn reject_topics_with_underscore() {
97        assert!(validate_resource_name("hello_world").is_err());
98    }
99
100    #[test]
101    fn valid_topic() {
102        assert!(validate_resource_name("hello-world").is_ok());
103    }
104    #[test]
105    fn reject_topics_that_start_with_hyphen() {
106        assert!(validate_resource_name("-helloworld").is_err());
107    }
108}