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
pub trait Succ {
    fn succ(self) -> Self;
}

macro_rules! auto_succ {
    ( $t:ty ) => {
        impl Succ for $t {
            fn succ(self) -> Self { self + 1 }
        }
    }
}

auto_succ!(i8);
auto_succ!(i16);
auto_succ!(i32);
auto_succ!(i64);
auto_succ!(u8);
auto_succ!(u16);
auto_succ!(u32);
auto_succ!(u64);

impl Succ for bool {
    fn succ(self) -> Self { true }
}

impl Succ for char {
    fn succ(self) -> Self { std::char::from_u32(self as u32 + 1).unwrap_or('\0') }
}

pub fn succ<T: Succ>(x: T) -> T {
    x.succ()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn succ_int() {
        assert!(succ(4i8) == 5);
        assert!(succ(4i16) == 5);
        assert!(succ(4i32) == 5);
        assert!(succ(4u64) == 5);
        assert!(succ(4u8) == 5);
        assert!(succ(4u16) == 5);
        assert!(succ(4u32) == 5);
        assert!(succ(4u64) == 5);
    }

    #[test]
    fn succ_char() {
        assert!(succ('a') == 'b');
        assert!(succ('0') == '1');
    }
}