valitron/rule/available/
range.rs1use std::{fmt::Debug, marker::PhantomData, ops::RangeBounds};
30
31use super::Message;
32use crate::{Rule, Value};
33
34#[derive(Clone)]
35pub struct Range<T, Num> {
36 value: T,
37 _marker: PhantomData<Num>,
38}
39
40impl<T: Debug, Num> Debug for Range<T, Num> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 f.debug_struct("Range")
43 .field("value", &self.value)
44 .field("_marker", &format_args!("-"))
45 .finish()
46 }
47}
48
49impl<T: Copy, Num: Clone> Copy for Range<T, Num> {}
50
51const NAME: &str = "range";
52
53impl<T, Num> Range<T, Num> {
54 pub fn new(value: T) -> Self {
55 Self {
56 value,
57 _marker: PhantomData,
58 }
59 }
60
61 fn message_in(&self) -> Message {
62 Message::new(super::MessageKind::Range)
63 }
64}
65
66macro_rules! impl_range {
67 ($val:ident($ty:ty)) => {
68 impl<T> Rule for Range<T, $ty>
69 where
70 T: RangeBounds<$ty> + Clone,
71 {
72 type Message = Message;
73
74 const NAME: &'static str = NAME;
75
76 fn message(&self) -> Self::Message {
77 self.message_in()
78 }
79
80 fn call(&mut self, data: &mut Value) -> bool {
81 match data {
82 Value::$val(n) => self.value.contains(n),
83 _ => false,
84 }
85 }
86 }
87 };
88}
89
90impl_range!(Uint8(u8));
91impl_range!(Int8(i8));
92impl_range!(Uint16(u16));
93impl_range!(Int16(i16));
94impl_range!(Uint32(u32));
95impl_range!(Int32(i32));
96impl_range!(Uint64(u64));
97impl_range!(Int64(i64));
98impl_range!(Char(char));
99
100impl<T> Rule for Range<T, f32>
101where
102 T: RangeBounds<f32> + Clone + 'static,
103{
104 type Message = Message;
105
106 const NAME: &'static str = NAME;
107
108 fn message(&self) -> Self::Message {
109 self.message_in()
110 }
111
112 fn call(&mut self, data: &mut Value) -> bool {
113 match data {
114 Value::Float32(f) => self.value.contains(f.as_ref()),
115 _ => false,
116 }
117 }
118}
119
120impl<T> Rule for Range<T, f64>
121where
122 T: RangeBounds<f64> + Clone + 'static,
123{
124 type Message = Message;
125
126 const NAME: &'static str = NAME;
127
128 fn message(&self) -> Self::Message {
129 self.message_in()
130 }
131
132 fn call(&mut self, data: &mut Value) -> bool {
133 match data {
134 Value::Float64(f) => self.value.contains(f.as_ref()),
135 _ => false,
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use crate::{rule::IntoRuleList, RuleExt, ValueMap};
143
144 use super::{super::Required, Range};
145
146 fn register<R: IntoRuleList<ValueMap, M>, M>(_: R) {}
147
148 #[test]
149 fn test_register() {
150 register(Required.and(Range::new(1..10)));
151 }
152}