Skip to content

Instantly share code, notes, and snippets.

@hube12
Created June 29, 2022 21:13
Show Gist options
  • Save hube12/7be195cbc713826200232eb555f95185 to your computer and use it in GitHub Desktop.
Save hube12/7be195cbc713826200232eb555f95185 to your computer and use it in GitHub Desktop.
Unification technics in Rust
#![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