Skip to content

Instantly share code, notes, and snippets.

@AngelicosPhosphoros
Created November 18, 2021 01:22
Show Gist options
  • Save AngelicosPhosphoros/b73540a161527d8848ac899c065ba8a0 to your computer and use it in GitHub Desktop.
Save AngelicosPhosphoros/b73540a161527d8848ac899c065ba8a0 to your computer and use it in GitHub Desktop.
Tuple uniqueness test
#![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