Skip to main content

appletheia_application/command/
command_name_owned.rs

1use std::{fmt, fmt::Display, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4
5use super::{CommandName, CommandNameOwnedError};
6
7#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
8#[serde(transparent)]
9pub struct CommandNameOwned(String);
10
11impl CommandNameOwned {
12    pub fn new(value: String) -> Result<Self, CommandNameOwnedError> {
13        Self::validate(&value)?;
14        Ok(Self(value))
15    }
16
17    pub fn value(&self) -> &str {
18        &self.0
19    }
20
21    fn validate(value: &str) -> Result<(), CommandNameOwnedError> {
22        if value.is_empty() {
23            return Err(CommandNameOwnedError::Empty);
24        }
25        if value.len() > CommandName::MAX_LENGTH {
26            return Err(CommandNameOwnedError::TooLong);
27        }
28        if !value.as_bytes().iter().all(|&b| {
29            let is_lower = b.is_ascii_lowercase();
30            let is_digit = b.is_ascii_digit();
31            let is_underscore = b == b'_';
32            is_lower || is_digit || is_underscore
33        }) {
34            return Err(CommandNameOwnedError::InvalidFormat);
35        }
36        Ok(())
37    }
38}
39
40impl Display for CommandNameOwned {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        write!(f, "{}", self.value())
43    }
44}
45
46impl FromStr for CommandNameOwned {
47    type Err = CommandNameOwnedError;
48
49    fn from_str(s: &str) -> Result<Self, Self::Err> {
50        Self::new(s.to_string())
51    }
52}
53
54impl TryFrom<&str> for CommandNameOwned {
55    type Error = CommandNameOwnedError;
56
57    fn try_from(value: &str) -> Result<Self, Self::Error> {
58        Self::from_str(value)
59    }
60}
61
62impl From<CommandName> for CommandNameOwned {
63    fn from(value: CommandName) -> Self {
64        Self(value.value().to_string())
65    }
66}