appletheia_application/command/
command_name_owned.rs1use 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}