Skip to content

Instantly share code, notes, and snippets.

@BruJu
Last active January 19, 2021 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BruJu/a896cd3e885790e661e738101ecd8d35 to your computer and use it in GitHub Desktop.
Save BruJu/a896cd3e885790e661e738101ecd8d35 to your computer and use it in GitHub Desktop.
manual_enum_dispatch.rs
/*
The problematic:
I want enum dispatch for a trait.
I could used
https://docs.rs/enum_dispatch/0.3.5/enum_dispatch/
but while it tackles the same problem, it doesn't apply the solution I want.
It also does not support binary functions (in the sens of two parameters of type Self).
The solution I will use / I'm using to generate this kind of files is a python script,
which is a less clean solution, but actually do what I want.
*/
// Structs
#[derive(Debug)] struct A { a: u32 }
#[derive(Debug)] struct B { b: u32 }
#[derive(Debug)] struct C { c: u32 }
// Enum struct
#[derive(Debug)]
enum ABC {
A(A),
B(B),
C(C)
}
// Unary trait
trait Unary { fn add_one(&mut self); }
impl Unary for A {
fn add_one(&mut self) {
self.a += 1;
}
}
impl Unary for B {
fn add_one(&mut self) {
self.b += 1;
}
}
impl Unary for C {
fn add_one(&mut self) {
self.c += 1;
}
}
impl Unary for ABC {
fn add_one(&mut self) {
match self {
ABC::A(a) => a.add_one(),
ABC::B(b) => b.add_one(),
ABC::C(c) => c.add_one(),
}
}
}
// Binary trait
trait Binary {
fn plus(&self, other: &Self) -> Self;
//fn equal(&self, other: &Self) -> bool;
}
trait BinaryOpt {
// Self: converted to Option<Self> where Self: Size
fn plus(&self, other: &Self) -> Option<Self> where Self: Sized;
// Another type: converted to Option<itself>
//fn equal(&self, other: &Self) -> Option<bool>;
}
impl Binary for A {
fn plus(&self, other: &Self) -> Self {
A { a: self.a + other.a }
}
}
impl Binary for B {
fn plus(&self, other: &Self) -> Self {
B { b: self.b + other.b }
}
}
impl Binary for C {
fn plus(&self, other: &Self) -> Self {
C { c: self.c + other.c }
}
}
impl BinaryOpt for ABC {
fn plus(&self, other: &Self) -> Option<Self> {
match (self, other) {
(ABC::A(a1), ABC::A(a2)) => Some(ABC::A ( a1.plus(&a2) )),
(ABC::B(b1), ABC::B(b2)) => Some(ABC::B ( b1.plus(&b2) )),
(ABC::C(c1), ABC::C(c2)) => Some(ABC::C ( c1.plus(&c2) )),
(_, _) => None
}
}
}
fn main() {
let mut a = ABC::A(A { a: 77 });
a.add_one();
print!("{:?}\n", a);
let a3 = A { a: 3 };
let a2 = A { a: 2 };
let a5 = a3.plus(&a2);
print!("{:?} + {:?} = {:?}\n", a3, a2, a5);
let a10 = ABC::A(A { a: 10 });
let b12 = ABC::B(B { b: 12 });
let b8 = ABC::B(B { b: 8 });
print!("{:?} + {:?} = {:?}\n", a10, b12, a10.plus(&b12));
print!("{:?} + {:?} = {:?}\n", b12, b8, b12.plus(&b8));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment