rsdiff_core/ops/kinds/binary/
specs.rs

1/*
2    Appellation: specs <binary>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5
6pub type BoxedBinOp<A, B = A, C = A> = Box<dyn BinOp<A, B, Output = C>>;
7
8pub trait BinOp<A, B = A> {
9    type Output;
10
11    fn eval(&self, lhs: A, rhs: B) -> Self::Output;
12}
13
14pub trait BinaryAssignOp<A, B = A> {
15    fn eval(&self, lhs: &mut A, rhs: B);
16}
17
18impl<S, A, B, C> BinOp<A, B> for S
19where
20    S: Fn(A, B) -> C,
21{
22    type Output = C;
23
24    fn eval(&self, lhs: A, rhs: B) -> Self::Output {
25        self(lhs, rhs)
26    }
27}
28
29impl<A, B, C> BinOp<A, B> for Box<dyn BinOp<A, B, Output = C>> {
30    type Output = C;
31
32    fn eval(&self, lhs: A, rhs: B) -> Self::Output {
33        self.as_ref().eval(lhs, rhs)
34    }
35}
36
37impl<A, B> BinaryAssignOp<A, B> for Box<dyn BinaryAssignOp<A, B>> {
38    fn eval(&self, lhs: &mut A, rhs: B) {
39        self.as_ref().eval(lhs, rhs)
40    }
41}
42
43pub trait Log<T> {
44    type Output;
45
46    fn log(self, base: T) -> Self::Output;
47}
48
49macro_rules! impl_log {
50    ($($t:ty),*) => {
51        $(
52            impl_log!(@impl $t);
53        )*
54    };
55    ($($call:ident<$out:ty>($t:ty)),*) => {
56        $(
57            impl_log!(@impl $call<$out>($t));
58        )*
59    };
60    ($call:ident<$out:ty>: $($t:ty),*) => {
61        $(
62            impl_log!(@impl $call<$out>($t));
63        )*
64    };
65    (@impl $t:ty) => {
66        impl Log<$t> for $t {
67            type Output = $t;
68
69            fn log(self, base: $t) -> Self::Output {
70                self.log(base)
71            }
72        }
73    };
74    (@impl $call:ident<$out:ty>($t:ty)) => {
75        impl Log<$t> for $t {
76            type Output = $out;
77
78            fn log(self, base: $t) -> Self::Output {
79                self.$call(base)
80            }
81        }
82    };
83}
84
85impl_log!(f32, f64);
86
87impl_log!(ilog<u32>: i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);