structform/
numeric_input.rs1#[macro_export]
14macro_rules! impl_numeric_input_with_stringops {
15 ($numeric_input: ident, $type_name: literal, $type: ty, $underlying_numeric_type: ty) => {
16 impl_numeric_input_with_stringops!(
17 $numeric_input,
18 $type_name,
19 $type,
20 $underlying_numeric_type,
21 <$type>::MIN,
22 <$type>::MAX
23 );
24 };
25 ($numeric_input: ident, $type_name: literal, $type: ty, $underlying_numeric_type: ty, $min: expr, $max: expr) => {
26 impl structform::ParseAndFormat<$type> for $numeric_input<$type> {
27 fn parse(value: &str) -> Result<$type, ParseError> {
28 use std::convert::TryFrom;
29 let trimmed = value.trim();
30 if trimmed.is_empty() {
31 Err(ParseError::Required)
32 } else {
33 trimmed
34 .parse::<$underlying_numeric_type>()
35 .map_err(|_e| ParseError::NumberOutOfRange {
36 required_type: $type_name.to_string(),
37 min: $min.to_string(),
38 max: $max.to_string(),
39 })
40 .and_then(|via| {
41 <$type>::try_from(via)
42 .map_err(|e| ParseError::FromStrError(e.to_string()))
43 })
44 }
45 }
46
47 fn format(value: &$type) -> String {
48 value.to_string()
49 }
50 }
51
52 impl structform::ParseAndFormat<Option<$type>> for $numeric_input<Option<$type>> {
53 fn parse(value: &str) -> Result<Option<$type>, structform::ParseError> {
54 use std::convert::TryFrom;
55
56 let trimmed = value.trim();
57 if trimmed.is_empty() {
58 Ok(None)
59 } else {
60 trimmed
61 .parse::<$underlying_numeric_type>()
62 .map_err(|_e| structform::ParseError::NumberOutOfRange {
63 required_type: $type_name.to_string(),
64 min: $min.to_string(),
65 max: $max.to_string(),
66 })
67 .and_then(|via| {
68 <$type>::try_from(via)
69 .map_err(|e| structform::ParseError::FromStrError(e.to_string()))
70 })
71 .map(Option::Some)
72 }
73 }
74
75 fn format(value: &Option<$type>) -> String {
76 match value {
77 None => "".to_string(),
78 Some(inner) => inner.to_string(),
79 }
80 }
81 }
82 };
83}
84
85#[macro_export]
90macro_rules! impl_numeric_input_with_default_with_stringops {
91 ($numeric_input: ident, $type_name: literal, $type: ty, $underlying_numeric_type: ty) => {
92 impl_numeric_input_with_default_with_stringops!(
93 $numeric_input,
94 $type_name,
95 $type,
96 $underlying_numeric_type,
97 <$type>::MIN,
98 <$type>::MAX
99 );
100 };
101 ($numeric_input: ident, $type_name: literal, $type: ty, $underlying_numeric_type: ty, $min: expr, $max: expr) => {
102 impl structform::ParseAndFormat<$type> for $numeric_input<$type> {
103 fn parse(value: &str) -> Result<$type, ParseError> {
104 use std::convert::TryFrom;
105 let trimmed = value.trim();
106 if trimmed.is_empty() {
107 Ok(<$type>::default())
108 } else {
109 trimmed
110 .parse::<$underlying_numeric_type>()
111 .map_err(|_e| ParseError::NumberOutOfRange {
112 required_type: $type_name.to_string(),
113 min: $min.to_string(),
114 max: $max.to_string(),
115 })
116 .and_then(|via| {
117 <$type>::try_from(via)
118 .map_err(|e| ParseError::FromStrError(e.to_string()))
119 })
120 }
121 }
122
123 fn format(value: &$type) -> String {
124 value.to_string()
125 }
126 }
127 };
128}