1use std::collections::HashMap;
4
5pub trait Resolver {
7 fn resolve_tag(&self, value: &str, implicit: bool) -> Option<String>;
9
10 fn add_implicit_resolver(&mut self, tag: String, pattern: String);
12
13 fn reset(&mut self);
15}
16
17#[derive(Debug)]
19pub struct BasicResolver {
20 implicit_resolvers: HashMap<String, String>,
21}
22
23impl BasicResolver {
24 pub fn new() -> Self {
26 let mut resolver = Self {
27 implicit_resolvers: HashMap::new(),
28 };
29
30 resolver.add_standard_resolvers();
32 resolver
33 }
34
35 fn add_standard_resolvers(&mut self) {
36 self.implicit_resolvers
38 .insert("true".to_string(), "tag:yaml.org,2002:bool".to_string());
39 self.implicit_resolvers
40 .insert("True".to_string(), "tag:yaml.org,2002:bool".to_string());
41 self.implicit_resolvers
42 .insert("TRUE".to_string(), "tag:yaml.org,2002:bool".to_string());
43 self.implicit_resolvers
44 .insert("false".to_string(), "tag:yaml.org,2002:bool".to_string());
45 self.implicit_resolvers
46 .insert("False".to_string(), "tag:yaml.org,2002:bool".to_string());
47 self.implicit_resolvers
48 .insert("FALSE".to_string(), "tag:yaml.org,2002:bool".to_string());
49
50 self.implicit_resolvers
52 .insert("null".to_string(), "tag:yaml.org,2002:null".to_string());
53 self.implicit_resolvers
54 .insert("Null".to_string(), "tag:yaml.org,2002:null".to_string());
55 self.implicit_resolvers
56 .insert("NULL".to_string(), "tag:yaml.org,2002:null".to_string());
57 self.implicit_resolvers
58 .insert("~".to_string(), "tag:yaml.org,2002:null".to_string());
59 }
60
61 pub fn is_int(&self, value: &str) -> bool {
63 value.parse::<i64>().is_ok()
64 }
65
66 pub fn is_float(&self, value: &str) -> bool {
68 value.parse::<f64>().is_ok()
69 }
70}
71
72impl Default for BasicResolver {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78impl Resolver for BasicResolver {
79 fn resolve_tag(&self, value: &str, implicit: bool) -> Option<String> {
80 if !implicit {
81 return None;
82 }
83
84 if let Some(tag) = self.implicit_resolvers.get(value) {
86 return Some(tag.clone());
87 }
88
89 if self.is_int(value) {
91 return Some("tag:yaml.org,2002:int".to_string());
92 }
93
94 if self.is_float(value) {
95 return Some("tag:yaml.org,2002:float".to_string());
96 }
97
98 Some("tag:yaml.org,2002:str".to_string())
100 }
101
102 fn add_implicit_resolver(&mut self, tag: String, pattern: String) {
103 self.implicit_resolvers.insert(pattern, tag);
104 }
105
106 fn reset(&mut self) {
107 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_resolver_creation() {
117 let resolver = BasicResolver::new();
118 assert!(!resolver.implicit_resolvers.is_empty());
119 }
120
121 #[test]
122 fn test_boolean_resolution() {
123 let resolver = BasicResolver::new();
124
125 assert_eq!(
126 resolver.resolve_tag("true", true),
127 Some("tag:yaml.org,2002:bool".to_string())
128 );
129 assert_eq!(
130 resolver.resolve_tag("false", true),
131 Some("tag:yaml.org,2002:bool".to_string())
132 );
133 }
134
135 #[test]
136 fn test_null_resolution() {
137 let resolver = BasicResolver::new();
138
139 assert_eq!(
140 resolver.resolve_tag("null", true),
141 Some("tag:yaml.org,2002:null".to_string())
142 );
143 assert_eq!(
144 resolver.resolve_tag("~", true),
145 Some("tag:yaml.org,2002:null".to_string())
146 );
147 }
148
149 #[test]
150 fn test_numeric_resolution() {
151 let resolver = BasicResolver::new();
152
153 assert_eq!(
154 resolver.resolve_tag("42", true),
155 Some("tag:yaml.org,2002:int".to_string())
156 );
157 assert_eq!(
158 resolver.resolve_tag("3.14", true),
159 Some("tag:yaml.org,2002:float".to_string())
160 );
161 }
162
163 #[test]
164 fn test_string_resolution() {
165 let resolver = BasicResolver::new();
166
167 assert_eq!(
168 resolver.resolve_tag("hello", true),
169 Some("tag:yaml.org,2002:str".to_string())
170 );
171 }
172
173 #[test]
174 fn test_explicit_tag_resolution() {
175 let resolver = BasicResolver::new();
176
177 assert_eq!(resolver.resolve_tag("true", false), None);
179 }
180
181 #[test]
182 fn test_custom_resolver() {
183 let mut resolver = BasicResolver::new();
184
185 resolver.add_implicit_resolver(
186 "tag:example.com,2002:custom".to_string(),
187 "CUSTOM".to_string(),
188 );
189
190 assert_eq!(
191 resolver.resolve_tag("CUSTOM", true),
192 Some("tag:example.com,2002:custom".to_string())
193 );
194 }
195}