1use std::str::FromStr;
2
3use crate::EntityRoot;
4use crate::errors::ErnError;
5use crate::model::{Account, Category, Domain, Ern, Part, Parts};
6
7pub struct ErnParser {
12 ern: String,
14}
15
16impl ErnParser {
17 pub fn new(ern: String) -> Self {
30 Self {
31 ern,
32 }
33 }
34
35 pub fn parse(&self) -> Result<Ern, ErnError> {
61 let parts: Vec<String> = self.ern.splitn(5, ':').map(|s| s.to_string()).collect();
62
63 if parts.len() != 5 || parts[0] != "ern" {
64 return Err(ErnError::InvalidFormat);
65 }
66
67 let domain = Domain::from_str(&parts[1])?;
68 let category = Category::from_str(&parts[2])?;
69 let account = Account::from_str(&parts[3])?;
70
71 let root_path: Vec<String> = parts[4].splitn(2, '/').map(|s| s.to_string()).collect();
73 let root_str = root_path[0].clone();
74 let root: EntityRoot = EntityRoot::from_str(root_str.as_str())?;
75
76 let mut ern_parts = Vec::new();
78 if root_path.len() > 1 {
79 let path_parts: Vec<String> = root_path[1].split('/').map(|s| s.to_string()).collect();
80 for part in path_parts.iter() {
81 ern_parts.push(Part::from_str(part)?);
82 }
83 }
84
85 let parts = Parts::new(ern_parts);
86 Ok(Ern::new(domain, category, account, root, parts))
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_valid_ern_parsing() {
96 let ern_str = "ern:custom:service:account123:root/resource/subresource".to_string();
97 let parser: ErnParser = ErnParser::new(ern_str);
98 let result = parser.parse();
99
100 assert!(result.is_ok());
101 let ern = result.unwrap();
102 assert_eq!(ern.domain.as_str(), "custom");
103 }
104
105 #[test]
106 fn test_invalid_ern_format() {
107 let ern_str = "invalid:ern:format";
108 let parser: ErnParser = ErnParser::new(ern_str.to_string());
109 let result = parser.parse();
110 assert!(result.is_err());
111 assert_eq!(result.err().unwrap(), ErnError::InvalidFormat);
112 }
114
115 #[test]
116 fn test_ern_with_invalid_part() -> anyhow::Result<()> {
117 let ern_str = "ern:domain:category:account:root/invalid:part";
118 let parser: ErnParser = ErnParser::new(ern_str.to_string());
119 let result = parser.parse();
120 assert!(result.is_err());
121 Ok(())
123 }
124
125 #[test]
126 fn test_ern_parsing_with_owned_string() {
127 let ern_str = String::from("ern:custom:service:account123:root/resource");
128 let parser: ErnParser = ErnParser::new(ern_str);
129 let result = parser.parse();
130 assert!(result.is_ok());
131 }
132}