valitron/rule/available/
contains.rs

1//! Require string to contain provided parameter, the parameter support `String`, `&str` or `char`,
2//! and verified data only support `String` or `&'static str` , other types always return false.
3//!
4//! # Examples
5//! ```
6//! # use serde::Serialize;
7//! # use valitron::{available::{Contains, MessageKind}, Validatable, Validator};
8//! #[derive(Serialize, Debug)]
9//! struct Input {
10//!     email: String,
11//! }
12//!
13//! let input = Input {
14//!     email: String::from("hi"),
15//! };
16//! let err = input
17//!     .validate(Validator::new().rule("email", Contains('@')))
18//!     .unwrap_err();
19//!
20//! assert!(matches!(
21//!     err.get("email").unwrap()[0].kind(),
22//!     MessageKind::Contains(_)
23//! ));
24//!
25//! let mut email_rule = Contains('@');
26//!
27//! let input = Input {
28//!     email: String::from("user@foo.com"),
29//! };
30//! input
31//!     .validate(Validator::new().rule("email", email_rule))
32//!     .unwrap();
33//!
34//! *email_rule = 'A';
35//!
36//! let input = Input {
37//!     email: String::from("user@foo.com"),
38//! };
39//! input
40//!     .validate(Validator::new().rule("email", email_rule))
41//!     .unwrap_err();
42//! ```
43
44use std::fmt::{Debug, Display};
45
46use crate::{rule::string::StringRule, Rule, Value};
47
48use super::Message;
49
50#[derive(Clone)]
51pub struct Contains<T>(pub T);
52
53impl<T: Debug> Debug for Contains<T> {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        f.debug_tuple("Contains").field(&self.0).finish()
56    }
57}
58
59crate::__impl_copy!(Contains);
60
61crate::__impl_deref!(Contains);
62
63const NAME: &str = "contains";
64
65impl<T> Contains<T> {
66    pub const fn as_ref(&self) -> Contains<&T> {
67        let Contains(ref t) = self;
68        Contains(t)
69    }
70
71    pub fn as_mut(&mut self) -> Contains<&mut T> {
72        let Contains(ref mut t) = self;
73        Contains(t)
74    }
75}
76
77impl<T> Contains<T>
78where
79    T: Display,
80{
81    fn message_in(&self) -> Message {
82        Message::new(super::MessageKind::Contains(self.0.to_string()))
83    }
84}
85
86impl Rule for Contains<&str> {
87    type Message = Message;
88
89    const NAME: &'static str = NAME;
90
91    fn message(&self) -> Self::Message {
92        self.message_in()
93    }
94
95    fn call(&mut self, value: &mut Value) -> bool {
96        match value {
97            Value::String(s) => s.contains(self.0),
98            _ => false,
99        }
100    }
101}
102
103impl Rule for Contains<String> {
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, value: &mut Value) -> bool {
113        match value {
114            Value::String(s) => s.contains(&self.0),
115            _ => false,
116        }
117    }
118}
119
120impl Rule for Contains<char> {
121    type Message = Message;
122
123    const NAME: &'static str = NAME;
124
125    fn message(&self) -> Self::Message {
126        self.message_in()
127    }
128
129    fn call(&mut self, value: &mut Value) -> bool {
130        match value {
131            Value::String(s) => s.contains(self.0),
132            _ => false,
133        }
134    }
135}
136
137impl StringRule for Contains<&'static str> {
138    type Message = Message;
139    const NAME: &'static str = NAME;
140
141    fn message(&self) -> Self::Message {
142        self.message_in()
143    }
144
145    fn call(&mut self, data: &mut String) -> bool {
146        data.contains(self.0)
147    }
148}
149
150impl StringRule for Contains<String> {
151    type Message = Message;
152    const NAME: &'static str = NAME;
153
154    fn message(&self) -> Self::Message {
155        self.message_in()
156    }
157
158    fn call(&mut self, data: &mut String) -> bool {
159        data.contains(&self.0)
160    }
161}
162
163impl StringRule for Contains<char> {
164    type Message = Message;
165    const NAME: &'static str = NAME;
166
167    fn message(&self) -> Self::Message {
168        self.message_in()
169    }
170
171    fn call(&mut self, data: &mut String) -> bool {
172        data.contains(self.0)
173    }
174}
175
176impl<T> Contains<&T> {
177    pub const fn copied(self) -> Contains<T>
178    where
179        T: Copy,
180    {
181        Contains(*self.0)
182    }
183
184    pub fn cloned(self) -> Contains<T>
185    where
186        T: Clone,
187    {
188        Contains(self.0.clone())
189    }
190}
191
192impl<T> Contains<&mut T> {
193    pub fn copied(self) -> Contains<T>
194    where
195        T: Copy,
196    {
197        Contains(*self.0)
198    }
199
200    pub fn cloned(self) -> Contains<T>
201    where
202        T: Clone,
203    {
204        Contains(self.0.clone())
205    }
206}
207
208impl<T: PartialEq> PartialEq for Contains<T> {
209    #[inline]
210    fn eq(&self, other: &Self) -> bool {
211        self.0 == other.0
212    }
213}