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