1#[allow(deprecated)]
2use crate::formatter::DataFormat;
3use crate::formatter::{RecordFormatter, ValueFormatter};
4use wp_model_core::model::types::value::ObjectValue;
5use wp_model_core::model::{DataRecord, DataType, FieldStorage, Value};
6
7#[derive(Debug, Default)]
8pub struct Raw;
9
10impl Raw {
11 pub fn new() -> Self {
12 Self
13 }
14}
15
16#[allow(deprecated)]
17impl DataFormat for Raw {
18 type Output = String;
19 fn format_null(&self) -> String {
20 String::new()
21 }
22 fn format_bool(&self, v: &bool) -> String {
23 v.to_string()
24 }
25 fn format_string(&self, v: &str) -> String {
26 v.to_string()
27 }
28 fn format_i64(&self, v: &i64) -> String {
29 v.to_string()
30 }
31 fn format_f64(&self, v: &f64) -> String {
32 v.to_string()
33 }
34 fn format_ip(&self, v: &std::net::IpAddr) -> String {
35 v.to_string()
36 }
37 fn format_datetime(&self, v: &chrono::NaiveDateTime) -> String {
38 v.to_string()
39 }
40 fn format_object(&self, value: &ObjectValue) -> String {
41 if value.is_empty() {
42 return "{}".to_string();
43 }
44 let segments: Vec<String> = value
45 .iter()
46 .map(|(k, v)| format!("{}={}", k, self.fmt_value(v.get_value())))
47 .collect();
48 format!("{{{}}}", segments.join(", "))
49 }
50 fn format_array(&self, value: &[FieldStorage]) -> String {
51 if value.is_empty() {
52 return "[]".to_string();
53 }
54 let content: Vec<String> = value
55 .iter()
56 .map(|field| self.fmt_value(field.get_value()))
57 .collect();
58 format!("[{}]", content.join(", "))
59 }
60 fn format_field(&self, field: &FieldStorage) -> String {
61 match field.get_value() {
62 Value::Chars(s) => s.to_string(),
63 _ => self.fmt_value(field.get_value()),
64 }
65 }
66 fn format_record(&self, record: &DataRecord) -> String {
67 record
68 .items
69 .iter()
70 .filter(|f| *f.get_meta() != DataType::Ignore)
71 .map(|f| self.format_field(f))
72 .collect::<Vec<_>>()
73 .join(" ")
74 }
75}
76
77#[cfg(test)]
78#[allow(deprecated)]
79mod tests {
80 use super::*;
81 use std::net::IpAddr;
82 use std::str::FromStr;
83 use wp_model_core::model::DataField;
84
85 #[test]
86 fn test_raw_new() {
87 let raw = Raw::new();
88 assert_eq!(raw.format_null(), "");
89 }
90
91 #[test]
92 fn test_raw_default() {
93 let raw = Raw;
94 assert_eq!(raw.format_null(), "");
95 }
96
97 #[test]
98 fn test_format_null() {
99 let raw = Raw;
100 assert_eq!(raw.format_null(), "");
101 }
102
103 #[test]
104 fn test_format_bool() {
105 let raw = Raw;
106 assert_eq!(raw.format_bool(&true), "true");
107 assert_eq!(raw.format_bool(&false), "false");
108 }
109
110 #[test]
111 fn test_format_string() {
112 let raw = Raw;
113 assert_eq!(raw.format_string("hello"), "hello");
114 assert_eq!(raw.format_string("world"), "world");
115 assert_eq!(raw.format_string(""), "");
116 }
117
118 #[test]
119 fn test_format_i64() {
120 let raw = Raw;
121 assert_eq!(raw.format_i64(&0), "0");
122 assert_eq!(raw.format_i64(&42), "42");
123 assert_eq!(raw.format_i64(&-100), "-100");
124 assert_eq!(raw.format_i64(&i64::MAX), i64::MAX.to_string());
125 }
126
127 #[test]
128 fn test_format_f64() {
129 let raw = Raw;
130 assert_eq!(raw.format_f64(&3.24), "3.24");
131 assert_eq!(raw.format_f64(&0.0), "0");
132 assert_eq!(raw.format_f64(&-2.5), "-2.5");
133 }
134
135 #[test]
136 fn test_format_ip() {
137 let raw = Raw;
138 let ipv4 = IpAddr::from_str("192.168.1.1").unwrap();
139 assert_eq!(raw.format_ip(&ipv4), "192.168.1.1");
140
141 let ipv6 = IpAddr::from_str("::1").unwrap();
142 assert_eq!(raw.format_ip(&ipv6), "::1");
143 }
144
145 #[test]
146 fn test_format_datetime() {
147 let raw = Raw;
148 let dt = chrono::NaiveDateTime::parse_from_str("2024-01-15 10:30:45", "%Y-%m-%d %H:%M:%S")
149 .unwrap();
150 let result = raw.format_datetime(&dt);
151 assert!(result.contains("2024"));
152 assert!(result.contains("01"));
153 assert!(result.contains("15"));
154 }
155
156 #[test]
157 fn test_format_field_chars() {
158 let raw = Raw;
159 let field = FieldStorage::from_owned(DataField::from_chars("name", "Alice"));
160 let result = raw.format_field(&field);
161 assert_eq!(result, "Alice");
162 }
163
164 #[test]
165 fn test_format_field_digit() {
166 let raw = Raw;
167 let field = FieldStorage::from_owned(DataField::from_digit("age", 30));
168 let result = raw.format_field(&field);
169 assert_eq!(result, "30");
170 }
171
172 #[test]
173 fn test_format_record() {
174 let raw = Raw;
175 let record = DataRecord {
176 id: Default::default(),
177 items: vec![
178 FieldStorage::from_owned(DataField::from_chars("name", "Alice")),
179 FieldStorage::from_owned(DataField::from_digit("age", 30)),
180 ],
181 };
182 let result = raw.format_record(&record);
183 assert_eq!(result, "Alice 30");
184 }
185
186 #[test]
187 fn test_format_array_empty() {
188 let raw = Raw;
189 let arr: Vec<FieldStorage> = vec![];
190 assert_eq!(raw.format_array(&arr), "[]");
191 }
192
193 #[test]
194 fn test_format_array_with_values() {
195 let raw = Raw;
196 let arr = vec![
197 FieldStorage::from_owned(DataField::from_digit("", 1)),
198 FieldStorage::from_owned(DataField::from_digit("", 2)),
199 FieldStorage::from_owned(DataField::from_digit("", 3)),
200 ];
201 let result = raw.format_array(&arr);
202 assert_eq!(result, "[1, 2, 3]");
203 }
204
205 #[test]
206 fn test_format_object_empty() {
207 let raw = Raw;
208 let obj = ObjectValue::new();
209 assert_eq!(raw.format_object(&obj), "{}");
210 }
211
212 fn make_record_with_obj() -> DataRecord {
213 let mut obj = ObjectValue::new();
214 obj.insert(
215 "ssl_cipher".to_string(),
216 FieldStorage::from_owned(DataField::from_chars("ssl_cipher", "ECDHE")),
217 );
218 DataRecord {
219 id: Default::default(),
220 items: vec![
221 FieldStorage::from_owned(DataField::from_digit("status", 200)),
222 FieldStorage::from_owned(DataField::from_obj("extends", obj)),
223 FieldStorage::from_owned(DataField::from_digit("length", 50)),
224 ],
225 }
226 }
227
228 #[test]
229 fn test_format_record_with_obj_no_newlines() {
230 let raw = Raw;
231 let record = make_record_with_obj();
232 let result = raw.format_record(&record);
233 assert!(
234 !result.contains('\n'),
235 "record output should not contain newlines: {}",
236 result
237 );
238 assert!(result.contains("ECDHE"));
239 }
240
241 #[test]
242 fn test_fmt_record_with_obj_no_newlines() {
243 let raw = Raw;
244 let record = make_record_with_obj();
245 let result = raw.fmt_record(&record);
246 assert!(
247 !result.contains('\n'),
248 "record output should not contain newlines: {}",
249 result
250 );
251 }
252
253 #[test]
254 fn test_old_new_api_consistency_nested() {
255 let raw = Raw;
256 let record = make_record_with_obj();
257 assert_eq!(raw.format_record(&record), raw.fmt_record(&record));
258 }
259}
260
261#[allow(clippy::items_after_test_module)]
266impl ValueFormatter for Raw {
267 type Output = String;
268
269 fn format_value(&self, value: &Value) -> String {
270 match value {
271 Value::Null => String::new(),
272 Value::Bool(v) => v.to_string(),
273 Value::Chars(v) => v.to_string(),
274 Value::Digit(v) => v.to_string(),
275 Value::Float(v) => v.to_string(),
276 Value::IpAddr(v) => v.to_string(),
277 Value::Time(v) => v.to_string(),
278 Value::Obj(obj) => {
279 if obj.is_empty() {
280 "{}".to_string()
281 } else {
282 let segments: Vec<String> = obj
283 .iter()
284 .map(|(k, field)| format!("{}={}", k, self.format_value(field.get_value())))
285 .collect();
286 format!("{{{}}}", segments.join(", "))
287 }
288 }
289 Value::Array(arr) => {
290 if arr.is_empty() {
291 "[]".to_string()
292 } else {
293 let content: Vec<String> = arr
294 .iter()
295 .map(|field| self.format_value(field.get_value()))
296 .collect();
297 format!("[{}]", content.join(", "))
298 }
299 }
300 _ => value.to_string(),
301 }
302 }
303}
304
305impl RecordFormatter for Raw {
306 fn fmt_field(&self, field: &FieldStorage) -> String {
307 match field.get_value() {
308 Value::Chars(s) => s.to_string(),
309 _ => self.format_value(field.get_value()),
310 }
311 }
312
313 fn fmt_record(&self, record: &DataRecord) -> String {
314 record
315 .items
316 .iter()
317 .filter(|f| *f.get_meta() != DataType::Ignore)
318 .map(|f| self.fmt_field(f))
319 .collect::<Vec<_>>()
320 .join(" ")
321 }
322}