cubic_chat/
identifier.rs

1use std::fmt::{Display, Formatter};
2use serde::{Serialize, Deserialize};
3use crate::identifier::IdentifierError::{NoAnyDoubleDots, TooManyDoubleDots};
4
5#[derive(Serialize, Deserialize, Clone, Debug)]
6#[serde(try_from = "String", into = "String")]
7pub struct Identifier {
8    domain: String,
9    key: String,
10    full: String,
11}
12
13#[derive(Debug, PartialEq)]
14pub enum IdentifierError {
15    TooManyDoubleDots,
16    NoAnyDoubleDots,
17}
18
19impl Identifier {
20    pub fn from_parts(domain: String, key: String) -> Result<Identifier, IdentifierError> {
21        match domain.contains(':') || key.contains(':') {
22            true => Err(TooManyDoubleDots),
23            false => {
24                let full = format!("{}:{}", domain, key);
25                Ok(Identifier { domain, key, full })
26            }
27        }
28    }
29
30    pub fn from_full(full: String) -> Result<Identifier, IdentifierError> {
31        match full.find(':') {
32            Some(index) => match full.rfind(':') {
33                Some(rindex) => match index == rindex {
34                    true => Ok(Identifier {
35                        domain: full[0..index].to_owned(),
36                        key: full[index+1..].to_owned(),
37                        full,
38                    }),
39                    false => Err(TooManyDoubleDots),
40                },
41                None => unreachable!(),
42            },
43            None => Err(NoAnyDoubleDots)
44        }
45    }
46
47    pub fn get_domain(&self) -> &String {
48        &self.domain
49    }
50
51    pub fn get_key(&self) -> &String {
52        &self.key
53    }
54
55    pub fn get_full(&self) -> &String {
56        &self.domain
57    }
58}
59
60impl Display for Identifier {
61    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
62        write!(f, "{}", self.full)
63    }
64}
65
66impl From<Identifier> for String {
67    fn from(identifier: Identifier) -> Self {
68        identifier.to_string()
69    }
70}
71
72impl TryFrom<String> for Identifier {
73    type Error = IdentifierError;
74
75    fn try_from(value: String) -> Result<Self, Self::Error> {
76        Identifier::from_full(value)
77    }
78}
79
80impl std::error::Error for IdentifierError {}
81
82impl Display for IdentifierError {
83    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84        match self {
85            IdentifierError::TooManyDoubleDots => write!(f, "Too many double dots"),
86            IdentifierError::NoAnyDoubleDots => write!(f, "No any double dots"),
87        }
88    }
89}
90
91impl PartialEq for Identifier {
92    fn eq(&self, other: &Self) -> bool {
93        self.domain == other.domain && self.key == other.key
94    }
95
96    fn ne(&self, other: &Self) -> bool {
97        !self.eq(other)
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    pub fn success_from_parts_test() {
107        let identifier = Identifier::from_parts("minecraft".into(), "grass_block".into()).unwrap();
108        assert_eq!(identifier.get_domain(), "minecraft");
109        assert_eq!(identifier.get_key(), "grass_block");
110    }
111
112    #[test]
113    pub fn too_many_double_dots_from_parts_test() {
114        assert_eq!(
115            Identifier::from_parts("minecraft:".into(), "some".into()).unwrap_err(),
116            IdentifierError::TooManyDoubleDots
117        );
118        assert_eq!(
119            Identifier::from_parts("minecraft".into(), "some:".into()).unwrap_err(),
120            IdentifierError::TooManyDoubleDots
121        );
122    }
123
124    #[test]
125    pub fn success_from_full_test() {
126        let identifier = Identifier::from_full("minecraft:grass_block".into()).unwrap();
127        assert_eq!(identifier.get_domain(), "minecraft");
128        assert_eq!(identifier.get_key(), "grass_block");
129    }
130
131    #[test]
132    pub fn too_many_double_dots_from_full_test() {
133        assert_eq!(
134            Identifier::from_full("minecraft::grass_block".into()).unwrap_err(),
135            IdentifierError::TooManyDoubleDots
136        );
137    }
138
139    #[test]
140    pub fn no_any_double_dots_from_full_test() {
141        assert_eq!(
142            Identifier::from_full("minecraft_grass_block".into()).unwrap_err(),
143            IdentifierError::NoAnyDoubleDots
144        )
145    }
146
147}