1use crate::error::{Error, Result};
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum BpsvFieldType {
10 String(u32),
12 Hex(u32),
14 Decimal(u32),
16}
17
18impl BpsvFieldType {
19 pub fn parse(type_spec: &str) -> Result<Self> {
38 let parts: Vec<&str> = type_spec.split(':').collect();
39 if parts.len() != 2 {
40 return Err(Error::InvalidFieldType {
41 field_type: type_spec.to_string(),
42 });
43 }
44
45 let type_name = parts[0].to_uppercase();
46 let length_str = parts[1];
47
48 let length: u32 = length_str.parse().map_err(|_| Error::InvalidFieldType {
49 field_type: type_spec.to_string(),
50 })?;
51
52 match type_name.as_str() {
53 "STRING" => Ok(BpsvFieldType::String(length)),
54 "HEX" => Ok(BpsvFieldType::Hex(length)),
55 "DEC" | "DECIMAL" => Ok(BpsvFieldType::Decimal(length)),
56 _ => Err(Error::InvalidFieldType {
57 field_type: type_spec.to_string(),
58 }),
59 }
60 }
61
62 pub fn type_name(&self) -> &'static str {
64 match self {
65 BpsvFieldType::String(_) => "STRING",
66 BpsvFieldType::Hex(_) => "HEX",
67 BpsvFieldType::Decimal(_) => "DEC",
68 }
69 }
70
71 pub fn length(&self) -> u32 {
73 match self {
74 BpsvFieldType::String(len) => *len,
75 BpsvFieldType::Hex(len) => *len,
76 BpsvFieldType::Decimal(len) => *len,
77 }
78 }
79
80 pub fn is_valid_value(&self, value: &str) -> bool {
104 match self {
105 BpsvFieldType::String(max_len) => *max_len == 0 || value.len() <= *max_len as usize,
106 BpsvFieldType::Hex(byte_count) => {
107 if value.is_empty() {
108 return true; }
110 if *byte_count > 0 && value.len() != (*byte_count as usize * 2) {
112 return false;
113 }
114 value.chars().all(|c| c.is_ascii_hexdigit())
115 }
116 BpsvFieldType::Decimal(_) => value.is_empty() || value.parse::<i64>().is_ok(),
117 }
118 }
119
120 pub fn validate_value(&self, value: &str) -> Result<String> {
124 if !self.is_valid_value(value) {
125 return Err(Error::InvalidValue {
126 field: "unknown".to_string(),
127 field_type: self.to_string(),
128 value: value.to_string(),
129 });
130 }
131
132 match self {
133 BpsvFieldType::String(_) => Ok(value.to_string()),
134 BpsvFieldType::Hex(_) => {
135 if value.is_empty() {
136 return Ok(value.to_string()); }
138 Ok(value.to_lowercase()) }
140 BpsvFieldType::Decimal(_) => {
141 if value.is_empty() {
142 return Ok(value.to_string()); }
144 let num: i64 = value.parse().map_err(|_| Error::InvalidNumber {
146 value: value.to_string(),
147 })?;
148 Ok(num.to_string())
149 }
150 }
151 }
152}
153
154impl fmt::Display for BpsvFieldType {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "{}:{}", self.type_name(), self.length())
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_parse_field_types() {
166 assert_eq!(
167 BpsvFieldType::parse("STRING:0").unwrap(),
168 BpsvFieldType::String(0)
169 );
170 assert_eq!(
171 BpsvFieldType::parse("string:0").unwrap(),
172 BpsvFieldType::String(0)
173 );
174 assert_eq!(
175 BpsvFieldType::parse("String:0").unwrap(),
176 BpsvFieldType::String(0)
177 );
178 assert_eq!(
179 BpsvFieldType::parse("HEX:16").unwrap(),
180 BpsvFieldType::Hex(16)
181 );
182 assert_eq!(
183 BpsvFieldType::parse("hex:16").unwrap(),
184 BpsvFieldType::Hex(16)
185 );
186 assert_eq!(
187 BpsvFieldType::parse("DEC:4").unwrap(),
188 BpsvFieldType::Decimal(4)
189 );
190 assert_eq!(
191 BpsvFieldType::parse("dec:4").unwrap(),
192 BpsvFieldType::Decimal(4)
193 );
194 assert_eq!(
195 BpsvFieldType::parse("DECIMAL:4").unwrap(),
196 BpsvFieldType::Decimal(4)
197 );
198 }
199
200 #[test]
201 fn test_invalid_field_types() {
202 assert!(BpsvFieldType::parse("INVALID:0").is_err());
203 assert!(BpsvFieldType::parse("STRING").is_err());
204 assert!(BpsvFieldType::parse("STRING:abc").is_err());
205 assert!(BpsvFieldType::parse("").is_err());
206 }
207
208 #[test]
209 fn test_value_validation() {
210 let string_type = BpsvFieldType::String(5);
211 assert!(string_type.is_valid_value("hello"));
212 assert!(string_type.is_valid_value(""));
213 assert!(!string_type.is_valid_value("toolong"));
214
215 let string_unlimited = BpsvFieldType::String(0);
216 assert!(string_unlimited.is_valid_value("any length string here"));
217
218 let hex_type = BpsvFieldType::Hex(4); assert!(hex_type.is_valid_value("abcd1234"));
220 assert!(hex_type.is_valid_value("12345678"));
221 assert!(hex_type.is_valid_value("ABCD1234"));
222 assert!(!hex_type.is_valid_value("xyz12345")); assert!(!hex_type.is_valid_value("1234")); assert!(!hex_type.is_valid_value("123456789")); let hex_unlimited = BpsvFieldType::Hex(0);
227 assert!(hex_unlimited.is_valid_value("abc123"));
228 assert!(hex_unlimited.is_valid_value(""));
229 assert!(!hex_unlimited.is_valid_value("xyz"));
230
231 let dec_type = BpsvFieldType::Decimal(4);
232 assert!(dec_type.is_valid_value("1234"));
233 assert!(dec_type.is_valid_value("0"));
234 assert!(dec_type.is_valid_value("-123"));
235 assert!(!dec_type.is_valid_value("abc"));
236 assert!(!dec_type.is_valid_value("12.34"));
237 }
238
239 #[test]
240 fn test_normalize_values() {
241 let hex_type = BpsvFieldType::Hex(4); assert_eq!(hex_type.validate_value("ABCD1234").unwrap(), "abcd1234");
243
244 let dec_type = BpsvFieldType::Decimal(4);
245 assert_eq!(dec_type.validate_value("0123").unwrap(), "123");
246 assert_eq!(dec_type.validate_value("-0042").unwrap(), "-42");
247 }
248
249 #[test]
250 fn test_display() {
251 assert_eq!(BpsvFieldType::String(0).to_string(), "STRING:0");
252 assert_eq!(BpsvFieldType::Hex(16).to_string(), "HEX:16");
253 assert_eq!(BpsvFieldType::Decimal(4).to_string(), "DEC:4");
254 }
255}