Last active
March 13, 2025 17:23
-
-
Save bojidar-bg/05d569976d63d1c514e9d8c219d10cc0 to your computer and use it in GitHub Desktop.
Example of Rust specialization used for specializing structs ala C++
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(specialization)] | |
// feature(specialization) is still unstable as per https://github.com/rust-lang/rust/issues/31844>, but min_specialization is not enough for what we want to do, unless we use dyn. | |
struct VecOrBitset<T: MaybeSpecializedOn> { | |
inner: T::VecOrBitsetType | |
} | |
impl<T: MaybeSpecializedOn> VecOrBitset<T> { | |
fn new(x: impl IntoIterator<Item = T>) -> Self { | |
Self {inner: T::VecOrBitsetType::new(x.into_iter())} | |
} | |
fn get(&self, index: usize) -> Option<&T> { | |
self.inner.get(index) | |
} | |
} | |
trait MaybeSpecializedOn : Sized { | |
type VecOrBitsetType : VecOrBitsetImplementation<Item = Self>; | |
} | |
impl<T> MaybeSpecializedOn for T { | |
default type VecOrBitsetType = VecOrBitsetGeneric<T>; | |
} | |
impl MaybeSpecializedOn for bool { | |
type VecOrBitsetType = VecOrBitsetBool; | |
} | |
trait VecOrBitsetImplementation { | |
type Item; | |
fn new(x: impl Iterator<Item = Self::Item>) -> Self; | |
fn get(&self, index: usize) -> Option<&Self::Item>; | |
} | |
#[derive(Default)] | |
struct VecOrBitsetBool { | |
elements: Vec<i8>, | |
last_element_size: i8, | |
} | |
const TRUE: bool = true; | |
const FALSE: bool = false; | |
impl VecOrBitsetImplementation for VecOrBitsetBool { | |
type Item = bool; | |
fn new(x: impl Iterator<Item = bool>) -> Self { | |
let mut result = Self {elements: Vec::with_capacity(x.size_hint().0), last_element_size: 0}; | |
for bit in x { | |
if result.last_element_size == 0 { | |
result.elements.push(0); | |
} | |
let last = result.elements.last_mut().unwrap(); | |
*last |= (bit as i8) << result.last_element_size; | |
result.last_element_size = (result.last_element_size + 1) % 8; | |
} | |
result | |
} | |
fn get(&self, index: usize) -> Option<&bool> { | |
println!("Hello from bool specialization!"); | |
if index >= (self.elements.len() - 1) * 8 + (self.last_element_size as usize) { | |
None | |
} else { | |
self.elements.get(index / 8).map(|x| ((x >> (index % 8)) & 1) == 1).map(|x| if x { &TRUE } else { &FALSE }) | |
} | |
} | |
} | |
struct VecOrBitsetGeneric<T> { | |
elements: Vec<T>, | |
} | |
impl<T> VecOrBitsetImplementation for VecOrBitsetGeneric<T> { | |
type Item = T; | |
fn new(x: impl Iterator<Item = T>) -> Self { | |
Self {elements: x.collect()} | |
} | |
fn get(&self, index: usize) -> Option<&T> { | |
println!("Hello from generic specialization!"); | |
self.elements.get(index) | |
} | |
} | |
fn main() { | |
println!("Hello, world!"); | |
let a = VecOrBitset::new([true, false, false]); | |
let b = VecOrBitset::new([1, 2, 3]); | |
println!("{}", a.get(1).unwrap()); // Hello from bool specialization! | |
// false | |
println!("{}", b.get(2).unwrap()); // Hello from generic specialization! | |
// 3 | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment