ext/no_std/functions/
monoid.rs

1use core::marker::PhantomData;
2use alloc::{string::String, format};
3
4pub trait NotMonoid {
5    type Unit;
6    type P1;
7    type P2;
8    type Ret;
9
10    fn unit() -> Self::Unit;
11    fn merge(some: Self::P1, other: Self::P2) -> Self::Ret;
12}
13
14macro_rules! impl_str_not_monoid {
15    ($($id:ident, $ex:expr);* $(;)?) => {$(
16        pub struct $id<'a>(PhantomData<&'a ()>);
17
18        impl<'a> NotMonoid for $id<'a> {
19            // Unit = P1 = P2 = &'a str
20            // Ret = String
21            type Unit = &'a str;
22            type P1 = Self::Unit;
23            type P2 = Self::P1;
24            type Ret = String;
25
26            fn unit() -> Self::Unit { $ex }
27
28            fn merge(some: Self::P1, other: Self::P2) -> Self::Ret {
29                format!("{}{}{}", some, Self::unit(), other)
30            }
31        }
32    )*};
33}
34
35impl_str_not_monoid! {  StrEmpty, "";
36    StrDot, ".";        StrSlash, "/";
37    StrAdd, "+";        StrPercent, "%";
38    StrSub, "-";        StrBackslash, "\\";
39    StrMul, "*";        StrUnderscore, "_";
40}
41
42macro_rules! impl_num_not_monoid {
43    ($($ty:ty, $id:ident, $ex:expr);* $(;)?) => {$(
44        pub struct $id;
45
46        impl NotMonoid for $id {
47            type Unit = u8;
48            // P1 = P2 = Ret
49            type P1 = $ty;
50            type P2 = Self::P1;
51            type Ret = Self::P2;
52
53            fn unit() -> Self::Unit { $ex }
54
55            fn merge(some: Self::P1, other: Self::P2) -> Self::Ret {
56                match Self::unit() {
57                    0 => some + other,
58                    1 => some * other,
59                    _ => panic!("Unsupport Unit")
60                }
61            }
62        }
63    )*};
64}
65
66impl_num_not_monoid! {
67    u8, U8Add, 0;       i8, I8Add, 0;                               u8, U8Mul, 1;       i8, I8Mul, 1;
68    u16, U16Add, 0;     i16, I16Add, 0;                             u16, U16Mul, 1;     i16, I16Mul, 1;
69    u32, U32Add, 0;     i32, I32Add, 0;     f32, F32Add, 0;         u32, U32Mul, 1;     i32, I32Mul, 1;     f32, F32Mul, 1;
70    u64, U64Add, 0;     i64, I64Add, 0;     f64, F64Add, 0;         u64, U64Mul, 1;     i64, I64Mul, 1;     f64, F64Mul, 1;
71    usize, UsizeAdd, 0; isize, IsizeAdd, 0;                         usize, UsizeMul, 1; isize, IsizeMul, 1;
72    u128, U128Add, 0;   i128, I128Add, 0;                           u128, U128Mul, 1;   i128, I128Mul, 1;
73}
74
75#[cfg(test)]
76mod test {
77    use crate::assert_eqs;
78    use super::*;
79
80    #[test]
81    fn test_all() {
82        assert_eqs! {
83            "a.b", StrDot::merge("a", "b");
84            5, U8Add::merge(2, 3);
85            6, U8Mul::merge(2, 3);
86            4.6,  F64Add::merge(1.2, 3.4);
87            4.08, F64Mul::merge(1.2, 3.4);
88        }
89    }
90}