Created
June 29, 2022 21:13
-
-
Save hube12/7be195cbc713826200232eb555f95185 to your computer and use it in GitHub Desktop.
Unification technics in Rust
This file contains hidden or 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
#![allow(dead_code)] | |
use std::any::Any; | |
#[derive(Default, Debug)] | |
pub struct TestA { | |
pub field_a: usize, | |
pub field_b: u8, | |
} | |
#[derive(Default, Debug)] | |
pub struct TestB { | |
pub field_a: std::ffi::CString, | |
pub field_b: String, | |
} | |
trait Test { | |
fn as_any(&self) -> &dyn Any; | |
fn into_any(self: Box<Self>) -> Box<dyn Any>; | |
} | |
impl Test for TestA { | |
fn as_any(&self) -> &dyn Any { | |
self | |
} | |
fn into_any(self: Box<Self>) -> Box<dyn Any> { | |
self | |
} | |
} | |
impl Test for TestB { | |
fn as_any(&self) -> &dyn Any { | |
self | |
} | |
fn into_any(self: Box<Self>) -> Box<dyn Any> { | |
self | |
} | |
} | |
fn joined_1(input: bool) -> Box<dyn Test> { | |
if input { | |
Box::new(TestA::default()) | |
} else { | |
Box::new(TestB::default()) | |
} | |
} | |
fn split_1(input: Box<dyn Test>) { | |
if input.as_any().is::<TestA>() { | |
let _test_a: &TestA = input.as_any().downcast_ref::<TestA>().expect("This is correct"); | |
let _test_a_2: &TestA = unsafe { &*(&input as *const dyn Any as *const TestA) }; | |
let box_back: Box<TestA> = input.into_any().downcast::<TestA>().expect("works like a charm"); | |
let _inner: TestA = *box_back; | |
dbg!(_inner); | |
} else { | |
let _test_b: &TestB = input.as_any().downcast_ref::<TestB>().expect("This is correct"); | |
let _test_b_2: &TestB = unsafe { &*(&input as *const dyn Any as *const TestB) }; | |
let box_back: Box<TestB> = input.into_any().downcast::<TestB>().expect("works like a charm"); | |
let _inner: TestB = *box_back; | |
dbg!(_inner); | |
} | |
} | |
pub enum JoinedTest { | |
TestA(TestA), | |
TestB(TestB), | |
} | |
impl From<TestA> for JoinedTest { | |
fn from(test_a: TestA) -> Self { | |
JoinedTest::TestA(test_a) | |
} | |
} | |
fn joined_2(input: bool) -> JoinedTest { | |
if input { | |
JoinedTest::from(TestA::default()) | |
} else { | |
JoinedTest::TestB(TestB::default()) | |
} | |
} | |
fn split_2(input: JoinedTest) { | |
match input { | |
JoinedTest::TestA(test_a) => { | |
dbg!(test_a); | |
} | |
JoinedTest::TestB(test_b) => { | |
dbg!(test_b); | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn test_trait_unification() { | |
let test_a = joined_1(true); | |
split_1(test_a); | |
let test_b = joined_1(false); | |
split_1(test_b); | |
} | |
#[test] | |
fn test_enum_unification() { | |
let test_a = joined_2(true); | |
split_2(test_a); | |
let test_b = joined_2(false); | |
split_2(test_b); | |
} | |
} | |
fn main() {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment