1use crate::model::{
2 DataType, DateTimeValue, DomainT, EmailT, FNameStr, FValueStr, HexT, IdCardT, IgnoreT, Maker,
3 MobilePhoneT, UrlValue, Value,
4 types::value::{ObjectValue, SymbolValue},
5};
6use smol_str::SmolStr;
7use std::net::IpAddr;
8
9use super::Field;
10
11impl<T> Field<T>
12where
13 T: Maker<bool>,
14{
15 pub fn from_bool<S: Into<FNameStr>>(name: S, val: bool) -> Self {
16 Self::new(DataType::Bool, name.into(), T::make(val))
17 }
18}
19
20impl<T> Field<T>
21where
22 T: Maker<FValueStr>,
23{
24 pub fn from_chars<N: Into<FNameStr>, V: Into<FValueStr>>(name: N, val: V) -> Self {
25 Self::new(DataType::Chars, name.into(), T::make(val.into()))
26 }
27}
28impl<T> Field<T>
29where
30 T: Maker<Value>,
31{
32 pub fn from_symbol<N: Into<FNameStr>, V: Into<SmolStr>>(name: N, val: V) -> Self {
33 let value = SymbolValue::from(val.into());
34 Self::new(DataType::Symbol, name.into(), T::make(value.into()))
35 }
36}
37
38impl<T> Field<T>
39where
40 T: Maker<i64>,
41{
42 pub fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
43 Self::new(DataType::Digit, name.into(), T::make(val))
44 }
45}
46impl<T> Field<T>
47where
48 T: Maker<HexT>,
49{
50 pub fn from_hex<S: Into<FNameStr>>(name: S, val: HexT) -> Self {
51 Self::new(DataType::Hex, name.into(), T::make(val))
52 }
53}
54impl<T> Field<T>
55where
56 T: Maker<f64>,
57{
58 pub fn from_float<S: Into<FNameStr>>(name: S, val: f64) -> Self {
59 Self::new(DataType::Float, name.into(), T::make(val))
60 }
61}
62impl<T> Field<T>
63where
64 T: Maker<IpAddr>,
65{
66 pub fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
67 Self::new(DataType::IP, name.into(), T::make(ip))
68 }
69}
70
71impl<T> Field<T>
72where
73 T: Maker<DomainT>,
74{
75 pub fn from_domain<S: Into<FNameStr>, V: Into<SmolStr>>(name: S, domain: V) -> Self {
76 Self::new(
77 DataType::Domain,
78 name.into(),
79 T::make(DomainT(domain.into())),
80 )
81 }
82}
83
84impl<T> Field<T>
85where
86 T: Maker<UrlValue>,
87{
88 pub fn from_url<S: Into<FNameStr>, V: Into<SmolStr>>(name: S, url: V) -> Self {
89 Self::new(DataType::Url, name.into(), T::make(UrlValue(url.into())))
90 }
91}
92
93impl<T> Field<T>
94where
95 T: Maker<EmailT>,
96{
97 pub fn from_email<S: Into<FNameStr>, V: Into<SmolStr>>(name: S, email: V) -> Self {
98 Self::new(DataType::Email, name.into(), T::make(EmailT(email.into())))
99 }
100}
101
102impl<T> Field<T>
103where
104 T: Maker<IdCardT>,
105{
106 pub fn from_id_card<S: Into<FNameStr>, V: Into<SmolStr>>(name: S, id_card: V) -> Self {
107 Self::new(
108 DataType::IdCard,
109 name.into(),
110 T::make(IdCardT(id_card.into())),
111 )
112 }
113}
114
115impl<T> Field<T>
116where
117 T: Maker<MobilePhoneT>,
118{
119 pub fn from_mobile_phone<S: Into<FNameStr>, V: Into<SmolStr>>(
120 name: S,
121 mobile_phone: V,
122 ) -> Self {
123 Self::new(
124 DataType::MobilePhone,
125 name.into(),
126 T::make(MobilePhoneT(mobile_phone.into())),
127 )
128 }
129}
130
131impl<T> Field<T>
132where
133 T: Maker<IgnoreT>,
134{
135 pub fn from_ignore<S: Into<FNameStr>>(name: S) -> Self {
136 Self::new(DataType::Ignore, name.into(), T::make(IgnoreT::default()))
137 }
138}
139
140impl<T> Field<T>
141where
142 T: Maker<DateTimeValue>,
143{
144 pub fn from_time<S: Into<FNameStr>>(name: S, val: DateTimeValue) -> Self {
145 Self::new(DataType::Time, name.into(), T::make(val))
146 }
147}
148impl<T> Field<T>
149where
150 T: Maker<Vec<Field<Value>>>,
151{
152 pub fn from_arr<S: Into<FNameStr>>(name: S, val: Vec<Field<Value>>) -> Self {
153 if let Some(f) = val.first() {
154 let meta = f.get_meta().to_string();
155 Self::new(DataType::Array(meta), name.into(), T::make(val))
156 } else {
157 Self::new(DataType::Array("auto".into()), name.into(), T::make(val))
158 }
160 }
161}
162
163impl<T> Field<T>
164where
165 T: Maker<ObjectValue>,
166{
167 pub fn from_obj<S: Into<FNameStr>>(name: S, val: ObjectValue) -> Self {
168 Self::new(DataType::Obj, name.into(), T::make(val))
169 }
170}
171
172impl Value {
173 pub fn tag(&self) -> &str {
174 match self {
175 Value::Null => "Null",
176 Value::Bool(_) => "Bool",
177 Value::Chars(_) => "Chars",
178 Value::Symbol(_) => "Symbol",
179 Value::Digit(_) => "Digit",
180 Value::Time(_) => "Time",
181 Value::Hex(_) => "Hex",
182 Value::Float(_) => "Float",
183 Value::IpNet(_) => "IpNet",
184 Value::IpAddr(_) => "IpAddr",
185 Value::Ignore(_) => "Ignore",
186 Value::Obj(_) => "Map",
187 Value::Array(_) => "Array",
188 Value::Domain(_) => "Domain",
189 Value::Url(_) => "Url",
190 Value::Email(_) => "Email",
191 Value::IdCard(_) => "IdCard",
192 Value::MobilePhone(_) => "MobilePhone",
193 }
194 }
195
196 pub fn is_empty(&self) -> bool {
197 match self {
198 Value::Time(_)
199 | Value::IpNet(_)
200 | Value::IpAddr(_)
201 | Value::Float(_)
202 | Value::Digit(_)
203 | Value::Bool(_)
204 | Value::Hex(_) => false,
205 Value::Domain(v) => v.0.is_empty(),
206 Value::Url(v) => v.0.is_empty(),
207 Value::Email(v) => v.0.is_empty(),
208 Value::IdCard(v) => v.0.is_empty(),
209 Value::MobilePhone(v) => v.0.is_empty(),
210 Value::Chars(v) => v.is_empty(),
211 Value::Obj(v) => v.is_empty(),
212 Value::Array(v) => v.is_empty(),
213 Value::Symbol(v) => v.is_empty(),
214 Value::Ignore(_) => true,
215 Value::Null => true,
216 }
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223 use crate::model::{DataField, FValueStr};
224 use chrono::NaiveDateTime;
225 use smol_str::SmolStr;
226 use std::net::{IpAddr, Ipv4Addr};
227
228 #[test]
231 fn test_field_from_bool() {
232 let field: DataField = Field::from_bool("is_active", true);
233 assert_eq!(field.get_name(), "is_active");
234 assert_eq!(field.meta, DataType::Bool);
235 assert_eq!(field.value, Value::Bool(true));
236 }
237
238 #[test]
239 fn test_field_from_chars() {
240 let field: DataField = Field::from_chars("message", "hello");
241 assert_eq!(field.get_name(), "message");
242 assert_eq!(field.meta, DataType::Chars);
243 assert_eq!(field.value, Value::Chars(FValueStr::from("hello")));
244 }
245
246 #[test]
247 fn test_field_from_symbol() {
248 let field: DataField = Field::from_symbol("status", "OK");
249 assert_eq!(field.get_name(), "status");
250 assert_eq!(field.meta, DataType::Symbol);
251 assert_eq!(field.value, Value::Symbol(SmolStr::from("OK")));
252 }
253
254 #[test]
255 fn test_field_from_digit() {
256 let field: DataField = Field::from_digit("count", 42);
257 assert_eq!(field.get_name(), "count");
258 assert_eq!(field.meta, DataType::Digit);
259 assert_eq!(field.value, Value::Digit(42));
260 }
261
262 #[test]
263 fn test_field_from_float() {
264 let field: DataField = Field::from_float("ratio", 2.14);
265 assert_eq!(field.get_name(), "ratio");
266 assert_eq!(field.meta, DataType::Float);
267 assert_eq!(field.value, Value::Float(2.14));
268 }
269
270 #[test]
271 fn test_field_from_hex() {
272 let field: DataField = Field::from_hex("color", HexT(0xFF00FF));
273 assert_eq!(field.get_name(), "color");
274 assert_eq!(field.meta, DataType::Hex);
275 assert_eq!(field.value, Value::Hex(HexT(0xFF00FF)));
276 }
277
278 #[test]
279 fn test_field_from_ip() {
280 let ip = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
281 let field: DataField = Field::from_ip("src_ip", ip);
282 assert_eq!(field.get_name(), "src_ip");
283 assert_eq!(field.meta, DataType::IP);
284 assert_eq!(field.value, Value::IpAddr(ip));
285 }
286
287 #[test]
288 fn test_field_from_domain() {
289 let field: DataField = Field::from_domain("host", "example.com");
290 assert_eq!(field.get_name(), "host");
291 assert_eq!(field.meta, DataType::Domain);
292 assert_eq!(field.value, Value::Domain(DomainT("example.com".into())));
293 }
294
295 #[test]
296 fn test_field_from_url() {
297 let field: DataField = Field::from_url("link", "https://example.com");
298 assert_eq!(field.get_name(), "link");
299 assert_eq!(field.meta, DataType::Url);
300 assert_eq!(
301 field.value,
302 Value::Url(UrlValue("https://example.com".into()))
303 );
304 }
305
306 #[test]
307 fn test_field_from_email() {
308 let field: DataField = Field::from_email("contact", "test@example.com");
309 assert_eq!(field.get_name(), "contact");
310 assert_eq!(field.meta, DataType::Email);
311 assert_eq!(field.value, Value::Email(EmailT("test@example.com".into())));
312 }
313
314 #[test]
315 fn test_field_from_id_card() {
316 let field: DataField = Field::from_id_card("id", "123456789");
317 assert_eq!(field.get_name(), "id");
318 assert_eq!(field.meta, DataType::IdCard);
319 assert_eq!(field.value, Value::IdCard(IdCardT("123456789".into())));
320 }
321
322 #[test]
323 fn test_field_from_mobile_phone() {
324 let field: DataField = Field::from_mobile_phone("phone", "13800138000");
325 assert_eq!(field.get_name(), "phone");
326 assert_eq!(field.meta, DataType::MobilePhone);
327 assert_eq!(
328 field.value,
329 Value::MobilePhone(MobilePhoneT("13800138000".into()))
330 );
331 }
332
333 #[test]
334 fn test_field_from_ignore() {
335 let field: DataField = Field::from_ignore("unused");
336 assert_eq!(field.get_name(), "unused");
337 assert_eq!(field.meta, DataType::Ignore);
338 assert_eq!(field.value, Value::Ignore(IgnoreT::default()));
339 }
340
341 #[test]
342 fn test_field_from_time() {
343 let dt = NaiveDateTime::parse_from_str("2024-01-15 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
344 let field: DataField = Field::from_time("timestamp", dt);
345 assert_eq!(field.get_name(), "timestamp");
346 assert_eq!(field.meta, DataType::Time);
347 assert_eq!(field.value, Value::Time(dt));
348 }
349
350 #[test]
351 fn test_field_from_arr_with_elements() {
352 let arr = vec![Field::from_digit("item", 1), Field::from_digit("item", 2)];
353 let field: DataField = Field::from_arr("numbers", arr);
354 assert_eq!(field.get_name(), "numbers");
355 assert_eq!(field.meta, DataType::Array("digit".into()));
356 }
357
358 #[test]
359 fn test_field_from_arr_empty() {
360 let arr: Vec<DataField> = vec![];
361 let field: DataField = Field::from_arr("empty", arr);
362 assert_eq!(field.get_name(), "empty");
363 assert_eq!(field.meta, DataType::Array("auto".into()));
364 }
365
366 #[test]
367 fn test_field_from_obj() {
368 let obj = ObjectValue::new();
369 let field: DataField = Field::from_obj("data", obj.clone());
370 assert_eq!(field.get_name(), "data");
371 assert_eq!(field.meta, DataType::Obj);
372 assert_eq!(field.value, Value::Obj(obj));
373 }
374
375 #[test]
378 fn test_value_tag() {
379 assert_eq!(Value::Null.tag(), "Null");
380 assert_eq!(Value::Bool(true).tag(), "Bool");
381 assert_eq!(Value::Chars(FValueStr::from("x")).tag(), "Chars");
382 assert_eq!(Value::Symbol(SmolStr::from("x")).tag(), "Symbol");
383 assert_eq!(Value::Digit(1).tag(), "Digit");
384 assert_eq!(Value::Float(1.0).tag(), "Float");
385 assert_eq!(Value::Hex(HexT(0)).tag(), "Hex");
386 assert_eq!(Value::Ignore(IgnoreT::default()).tag(), "Ignore");
387 assert_eq!(Value::Obj(ObjectValue::new()).tag(), "Map");
388 assert_eq!(Value::Array(vec![]).tag(), "Array");
389 assert_eq!(Value::Domain(DomainT("x".into())).tag(), "Domain");
390 assert_eq!(Value::Url(UrlValue("x".into())).tag(), "Url");
391 assert_eq!(Value::Email(EmailT("x".into())).tag(), "Email");
392 assert_eq!(Value::IdCard(IdCardT("x".into())).tag(), "IdCard");
393 assert_eq!(
394 Value::MobilePhone(MobilePhoneT("x".into())).tag(),
395 "MobilePhone"
396 );
397 }
398
399 #[test]
400 fn test_value_tag_ip() {
401 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
402 assert_eq!(Value::IpAddr(ip).tag(), "IpAddr");
403 }
404
405 #[test]
408 fn test_is_empty_always_false() {
409 assert!(!Value::Bool(false).is_empty());
411 assert!(!Value::Digit(0).is_empty());
412 assert!(!Value::Float(0.0).is_empty());
413 assert!(!Value::Hex(HexT(0)).is_empty());
414 }
415
416 #[test]
417 fn test_is_empty_always_true() {
418 assert!(Value::Null.is_empty());
419 assert!(Value::Ignore(IgnoreT::default()).is_empty());
420 }
421
422 #[test]
423 fn test_is_empty_string_types() {
424 assert!(Value::Chars(FValueStr::from("")).is_empty());
426 assert!(Value::Symbol(SmolStr::from("")).is_empty());
427 assert!(Value::Domain(DomainT("".into())).is_empty());
428 assert!(Value::Url(UrlValue("".into())).is_empty());
429 assert!(Value::Email(EmailT("".into())).is_empty());
430 assert!(Value::IdCard(IdCardT("".into())).is_empty());
431 assert!(Value::MobilePhone(MobilePhoneT("".into())).is_empty());
432
433 assert!(!Value::Chars(FValueStr::from("x")).is_empty());
435 assert!(!Value::Symbol(SmolStr::from("x")).is_empty());
436 assert!(!Value::Domain(DomainT("x".into())).is_empty());
437 assert!(!Value::Url(UrlValue("x".into())).is_empty());
438 assert!(!Value::Email(EmailT("x".into())).is_empty());
439 assert!(!Value::IdCard(IdCardT("x".into())).is_empty());
440 assert!(!Value::MobilePhone(MobilePhoneT("x".into())).is_empty());
441 }
442
443 #[test]
444 fn test_is_empty_collections() {
445 assert!(Value::Array(vec![]).is_empty());
447 assert!(Value::Obj(ObjectValue::new()).is_empty());
448
449 let arr = vec![Field::from_digit("x", 1)];
451 assert!(!Value::Array(arr).is_empty());
452 }
453}