Last active
January 19, 2021 09:30
-
-
Save BruJu/a896cd3e885790e661e738101ecd8d35 to your computer and use it in GitHub Desktop.
manual_enum_dispatch.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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