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::BigUint(_) => "BigUint",
181 Value::Time(_) => "Time",
182 Value::Hex(_) => "Hex",
183 Value::Float(_) => "Float",
184 Value::IpNet(_) => "IpNet",
185 Value::IpAddr(_) => "IpAddr",
186 Value::Ignore(_) => "Ignore",
187 Value::Obj(_) => "Map",
188 Value::Array(_) => "Array",
189 Value::Domain(_) => "Domain",
190 Value::Url(_) => "Url",
191 Value::Email(_) => "Email",
192 Value::IdCard(_) => "IdCard",
193 Value::MobilePhone(_) => "MobilePhone",
194 }
195 }
196
197 pub fn is_empty(&self) -> bool {
198 match self {
199 Value::Time(_)
200 | Value::IpNet(_)
201 | Value::IpAddr(_)
202 | Value::Float(_)
203 | Value::Digit(_)
204 | Value::BigUint(_)
205 | Value::Bool(_)
206 | Value::Hex(_) => false,
207 Value::Domain(v) => v.0.is_empty(),
208 Value::Url(v) => v.0.is_empty(),
209 Value::Email(v) => v.0.is_empty(),
210 Value::IdCard(v) => v.0.is_empty(),
211 Value::MobilePhone(v) => v.0.is_empty(),
212 Value::Chars(v) => v.is_empty(),
213 Value::Obj(v) => v.is_empty(),
214 Value::Array(v) => v.is_empty(),
215 Value::Symbol(v) => v.is_empty(),
216 Value::Ignore(_) => true,
217 Value::Null => true,
218 }
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225 use crate::model::{DataField, FValueStr};
226 use chrono::NaiveDateTime;
227 use smol_str::SmolStr;
228 use std::net::{IpAddr, Ipv4Addr};
229
230 #[test]
233 fn test_field_from_bool() {
234 let field: DataField = Field::from_bool("is_active", true);
235 assert_eq!(field.get_name(), "is_active");
236 assert_eq!(field.meta, DataType::Bool);
237 assert_eq!(field.value, Value::Bool(true));
238 }
239
240 #[test]
241 fn test_field_from_chars() {
242 let field: DataField = Field::from_chars("message", "hello");
243 assert_eq!(field.get_name(), "message");
244 assert_eq!(field.meta, DataType::Chars);
245 assert_eq!(field.value, Value::Chars(FValueStr::from("hello")));
246 }
247
248 #[test]
249 fn test_field_from_symbol() {
250 let field: DataField = Field::from_symbol("status", "OK");
251 assert_eq!(field.get_name(), "status");
252 assert_eq!(field.meta, DataType::Symbol);
253 assert_eq!(field.value, Value::Symbol(SmolStr::from("OK")));
254 }
255
256 #[test]
257 fn test_field_from_digit() {
258 let field: DataField = Field::from_digit("count", 42);
259 assert_eq!(field.get_name(), "count");
260 assert_eq!(field.meta, DataType::Digit);
261 assert_eq!(field.value, Value::Digit(42));
262 }
263
264 #[test]
265 fn test_field_from_float() {
266 let field: DataField = Field::from_float("ratio", 2.14);
267 assert_eq!(field.get_name(), "ratio");
268 assert_eq!(field.meta, DataType::Float);
269 assert_eq!(field.value, Value::Float(2.14));
270 }
271
272 #[test]
273 fn test_field_from_hex() {
274 let field: DataField = Field::from_hex("color", HexT(0xFF00FF));
275 assert_eq!(field.get_name(), "color");
276 assert_eq!(field.meta, DataType::Hex);
277 assert_eq!(field.value, Value::Hex(HexT(0xFF00FF)));
278 }
279
280 #[test]
281 fn test_field_from_ip() {
282 let ip = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
283 let field: DataField = Field::from_ip("src_ip", ip);
284 assert_eq!(field.get_name(), "src_ip");
285 assert_eq!(field.meta, DataType::IP);
286 assert_eq!(field.value, Value::IpAddr(ip));
287 }
288
289 #[test]
290 fn test_field_from_domain() {
291 let field: DataField = Field::from_domain("host", "example.com");
292 assert_eq!(field.get_name(), "host");
293 assert_eq!(field.meta, DataType::Domain);
294 assert_eq!(field.value, Value::Domain(DomainT("example.com".into())));
295 }
296
297 #[test]
298 fn test_field_from_url() {
299 let field: DataField = Field::from_url("link", "https://example.com");
300 assert_eq!(field.get_name(), "link");
301 assert_eq!(field.meta, DataType::Url);
302 assert_eq!(
303 field.value,
304 Value::Url(UrlValue("https://example.com".into()))
305 );
306 }
307
308 #[test]
309 fn test_field_from_email() {
310 let field: DataField = Field::from_email("contact", "test@example.com");
311 assert_eq!(field.get_name(), "contact");
312 assert_eq!(field.meta, DataType::Email);
313 assert_eq!(field.value, Value::Email(EmailT("test@example.com".into())));
314 }
315
316 #[test]
317 fn test_field_from_id_card() {
318 let field: DataField = Field::from_id_card("id", "123456789");
319 assert_eq!(field.get_name(), "id");
320 assert_eq!(field.meta, DataType::IdCard);
321 assert_eq!(field.value, Value::IdCard(IdCardT("123456789".into())));
322 }
323
324 #[test]
325 fn test_field_from_mobile_phone() {
326 let field: DataField = Field::from_mobile_phone("phone", "13800138000");
327 assert_eq!(field.get_name(), "phone");
328 assert_eq!(field.meta, DataType::MobilePhone);
329 assert_eq!(
330 field.value,
331 Value::MobilePhone(MobilePhoneT("13800138000".into()))
332 );
333 }
334
335 #[test]
336 fn test_field_from_ignore() {
337 let field: DataField = Field::from_ignore("unused");
338 assert_eq!(field.get_name(), "unused");
339 assert_eq!(field.meta, DataType::Ignore);
340 assert_eq!(field.value, Value::Ignore(IgnoreT::default()));
341 }
342
343 #[test]
344 fn test_field_from_time() {
345 let dt = NaiveDateTime::parse_from_str("2024-01-15 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
346 let field: DataField = Field::from_time("timestamp", dt);
347 assert_eq!(field.get_name(), "timestamp");
348 assert_eq!(field.meta, DataType::Time);
349 assert_eq!(field.value, Value::Time(dt));
350 }
351
352 #[test]
353 fn test_field_from_arr_with_elements() {
354 let arr = vec![Field::from_digit("item", 1), Field::from_digit("item", 2)];
355 let field: DataField = Field::from_arr("numbers", arr);
356 assert_eq!(field.get_name(), "numbers");
357 assert_eq!(field.meta, DataType::Array("digit".into()));
358 }
359
360 #[test]
361 fn test_field_from_arr_empty() {
362 let arr: Vec<DataField> = vec![];
363 let field: DataField = Field::from_arr("empty", arr);
364 assert_eq!(field.get_name(), "empty");
365 assert_eq!(field.meta, DataType::Array("auto".into()));
366 }
367
368 #[test]
369 fn test_field_from_obj() {
370 let obj = ObjectValue::new();
371 let field: DataField = Field::from_obj("data", obj.clone());
372 assert_eq!(field.get_name(), "data");
373 assert_eq!(field.meta, DataType::Obj);
374 assert_eq!(field.value, Value::Obj(obj));
375 }
376
377 #[test]
380 fn test_value_tag() {
381 assert_eq!(Value::Null.tag(), "Null");
382 assert_eq!(Value::Bool(true).tag(), "Bool");
383 assert_eq!(Value::Chars(FValueStr::from("x")).tag(), "Chars");
384 assert_eq!(Value::Symbol(SmolStr::from("x")).tag(), "Symbol");
385 assert_eq!(Value::Digit(1).tag(), "Digit");
386 assert_eq!(Value::Float(1.0).tag(), "Float");
387 assert_eq!(Value::Hex(HexT(0)).tag(), "Hex");
388 assert_eq!(Value::Ignore(IgnoreT::default()).tag(), "Ignore");
389 assert_eq!(Value::Obj(ObjectValue::new()).tag(), "Map");
390 assert_eq!(Value::Array(vec![]).tag(), "Array");
391 assert_eq!(Value::Domain(DomainT("x".into())).tag(), "Domain");
392 assert_eq!(Value::Url(UrlValue("x".into())).tag(), "Url");
393 assert_eq!(Value::Email(EmailT("x".into())).tag(), "Email");
394 assert_eq!(Value::IdCard(IdCardT("x".into())).tag(), "IdCard");
395 assert_eq!(
396 Value::MobilePhone(MobilePhoneT("x".into())).tag(),
397 "MobilePhone"
398 );
399 }
400
401 #[test]
402 fn test_value_tag_ip() {
403 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
404 assert_eq!(Value::IpAddr(ip).tag(), "IpAddr");
405 }
406
407 #[test]
410 fn test_is_empty_always_false() {
411 assert!(!Value::Bool(false).is_empty());
413 assert!(!Value::Digit(0).is_empty());
414 assert!(!Value::Float(0.0).is_empty());
415 assert!(!Value::Hex(HexT(0)).is_empty());
416 }
417
418 #[test]
419 fn test_is_empty_always_true() {
420 assert!(Value::Null.is_empty());
421 assert!(Value::Ignore(IgnoreT::default()).is_empty());
422 }
423
424 #[test]
425 fn test_is_empty_string_types() {
426 assert!(Value::Chars(FValueStr::from("")).is_empty());
428 assert!(Value::Symbol(SmolStr::from("")).is_empty());
429 assert!(Value::Domain(DomainT("".into())).is_empty());
430 assert!(Value::Url(UrlValue("".into())).is_empty());
431 assert!(Value::Email(EmailT("".into())).is_empty());
432 assert!(Value::IdCard(IdCardT("".into())).is_empty());
433 assert!(Value::MobilePhone(MobilePhoneT("".into())).is_empty());
434
435 assert!(!Value::Chars(FValueStr::from("x")).is_empty());
437 assert!(!Value::Symbol(SmolStr::from("x")).is_empty());
438 assert!(!Value::Domain(DomainT("x".into())).is_empty());
439 assert!(!Value::Url(UrlValue("x".into())).is_empty());
440 assert!(!Value::Email(EmailT("x".into())).is_empty());
441 assert!(!Value::IdCard(IdCardT("x".into())).is_empty());
442 assert!(!Value::MobilePhone(MobilePhoneT("x".into())).is_empty());
443 }
444
445 #[test]
446 fn test_is_empty_collections() {
447 assert!(Value::Array(vec![]).is_empty());
449 assert!(Value::Obj(ObjectValue::new()).is_empty());
450
451 let arr = vec![Field::from_digit("x", 1)];
453 assert!(!Value::Array(arr.into_iter().collect()).is_empty());
454 }
455}