Created
November 18, 2021 01:22
-
-
Save AngelicosPhosphoros/b73540a161527d8848ac899c065ba8a0 to your computer and use it in GitHub Desktop.
Tuple uniqueness test
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
#![feature(const_type_id)] | |
use std::any::TypeId; | |
use std::mem::{size_of, align_of}; | |
pub trait IsUniqueTuple{ | |
const IS_UNIQUE: bool; | |
type ElementTypesArray; | |
const ELEMENT_TYPES_SORTED: Self::ElementTypesArray; | |
} | |
const fn transmute_to_usize<const N: usize>(items: &[TypeId; N])->[usize;N]{ | |
use std::mem::transmute; | |
unsafe{ | |
// Ensure that alignment and sizes valid | |
static_assertions::assert_eq_align!(TypeId, usize); | |
static_assertions::assert_eq_size!(TypeId, usize); | |
let items: &[usize; N] = transmute(items); | |
*items | |
} | |
} | |
const fn transmute_to_type_ids<const N: usize>(items: &[usize; N])->[TypeId;N]{ | |
use std::mem::transmute; | |
unsafe{ | |
// Ensure that alignment and sizes valid | |
static_assertions::assert_eq_align!(TypeId, usize); | |
static_assertions::assert_eq_size!(TypeId, usize); | |
let items: &[TypeId; N] = transmute(items); | |
*items | |
} | |
} | |
/// Insertion sort which can run in compile time | |
const fn compile_time_sort<const N: usize>(items: &[TypeId; N])->[TypeId; N]{ | |
let mut items: [usize; N] = transmute_to_usize(items); | |
let mut outer_idx = 1; | |
while outer_idx < N { | |
let mut inner_idx = outer_idx; | |
while inner_idx > 0 && items[inner_idx - 1] > items[inner_idx]{ | |
let tmp = items[inner_idx - 1]; | |
items[inner_idx - 1] = items[inner_idx]; | |
items[inner_idx] = tmp; | |
inner_idx -= 1; | |
} | |
outer_idx += 1; | |
} | |
transmute_to_type_ids(&items) | |
} | |
const fn is_unique_all<const N: usize>(arr: &[TypeId; N])->bool{ | |
let arr = compile_time_sort(arr); | |
let arr: [usize; N] = transmute_to_usize(&arr); | |
let mut idx = 0; | |
while idx+1 < N{ | |
if arr[idx] >= arr[idx+1]{ | |
return false; | |
} | |
idx += 1; | |
} | |
true | |
} | |
impl<A, B, C> IsUniqueTuple for (A, B, C) | |
where Self: 'static | |
{ | |
type ElementTypesArray = [TypeId; 3]; | |
const ELEMENT_TYPES_SORTED: [TypeId; 3] = compile_time_sort(&[ | |
TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>(), | |
]); | |
const IS_UNIQUE: bool = is_unique_all(&Self::ELEMENT_TYPES_SORTED); | |
} | |
fn main(){ | |
println!("{:?}", <(i32, f64, usize)>::IS_UNIQUE); | |
println!("{:?}", <(i32, usize, f64)>::ELEMENT_TYPES_SORTED); | |
println!("{:?}", <(i32, usize, i32)>::IS_UNIQUE); | |
println!("{:?}", <(i32, usize, i32)>::ELEMENT_TYPES_SORTED); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment