logform/formats/
format.rs1pub trait Format {
2 type Input;
3
4 fn transform(&self, input: Self::Input) -> Option<Self::Input>;
5
6 fn chain<F>(self, next: F) -> ChainedFormat<Self, F>
7 where
8 Self: Sized,
9 F: Format<Input = Self::Input>,
10 {
11 ChainedFormat { first: self, next }
12 }
13}
14
15pub struct ChainedFormat<F1, F2> {
16 first: F1,
17 next: F2,
18}
19
20impl<T, F1, F2> Format for ChainedFormat<F1, F2>
21where
22 F1: Format<Input = T>,
23 F2: Format<Input = T>,
24{
25 type Input = T;
26
27 fn transform(&self, input: T) -> Option<T> {
28 self.first
29 .transform(input)
30 .and_then(|res| self.next.transform(res))
31 }
32}
33
34struct UpperCase;
36impl Format for UpperCase {
37 type Input = String;
38
39 fn transform(&self, input: String) -> Option<Self::Input> {
40 Some(input.to_uppercase())
41 }
42}
43
44struct NonEmpty;
45
46impl Format for NonEmpty {
47 type Input = String;
48
49 fn transform(&self, input: String) -> Option<Self::Input> {
50 if input.is_empty() {
51 None
52 } else {
53 Some(input)
54 }
55 }
56}
57
58struct ReverseFormat;
59impl Format for ReverseFormat {
60 type Input = String;
61
62 fn transform(&self, input: String) -> Option<Self::Input> {
63 Some(input.chars().rev().collect())
64 }
65}
66
67#[derive(Clone)]
68struct AddSuffix(String);
69impl Format for AddSuffix {
70 type Input = String;
71
72 fn transform(&self, input: String) -> Option<Self::Input> {
73 Some(format!("{}{}", input, self.0))
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_proposed_format() {
83 let upper = UpperCase;
84 let reverse = ReverseFormat;
85 let suffix = AddSuffix("-end".to_string());
86
87 let format = upper.chain(reverse).chain(suffix);
88
89 let result = format.transform("hello".to_string());
90
91 assert_eq!(result, Some("OLLEH-end".to_string()));
92 }
93}