1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use std::fmt::{Display, Formatter, Result as DisplayResult};
pub trait Validation where Self: Sized {
fn validate(&self) -> Result<(), ValidationError>;
fn validated(self) -> Result<Self, ValidationError> {
self.validate().and_then(|_| Ok(self))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ValidationError {
pub description: String
}
impl ValidationError {
pub fn new(description: &str) -> ValidationError {
ValidationError {
description: description.to_owned()
}
}
}
impl Display for ValidationError {
fn fmt(&self, f: &mut Formatter) -> DisplayResult {
write!(f, "{}", self.description)
}
}
#[cfg(test)]
mod tests {
use super::super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
struct Test {
pub value: String
}
impl Validation for Test {
fn validate(&self) -> Result<(), ValidationError> {
if self.value == "invalid" {
return Err(ValidationError::new("invalid value"));
}
Ok(())
}
}
#[test]
fn test_validation() {
let valid_test = Test { value: "valid".to_owned() };
assert_eq!(valid_test.clone().validate(), Ok(()));
let valid_test = Test { value: "valid".to_owned() };
assert_eq!(valid_test.clone().validated(), Ok(valid_test));
let invalid_test = Test { value: "invalid".to_owned() };
assert_eq!(invalid_test.clone().validate(), Err(ValidationError::new("invalid value")));
assert_eq!(format!("{}", ValidationError::new("invalid value")), "invalid value".to_owned());
}
}