use crate::{make_concrete::MakeConcrete, ordmap::OrdDynMap};
pub type DynKey<T> = crate::key::DynKey<usize, T>;
#[derive(Debug, Clone, Default, PartialEq, PartialOrd, Hash)]
pub struct DynSet<DynT>
where
DynT: ?Sized,
{
inner: OrdDynMap<usize, DynT>,
cur_id: usize,
}
impl<DynT> DynSet<DynT>
where
DynT: ?Sized,
{
pub const fn new() -> Self {
Self {
inner: OrdDynMap::new(),
cur_id: 0,
}
}
pub fn push<T>(&mut self, value: T) -> DynKey<T>
where
DynT: MakeConcrete<T>,
{
let id = self.cur_id;
self.cur_id += 1;
unsafe { self.inner.insert_overwrite(id, value) }
}
pub fn get<T>(&self, key: &DynKey<T>) -> Option<&T>
where
DynT: MakeConcrete<T>,
{
self.inner.get(key)
}
pub fn get_mut<T>(&mut self, key: &DynKey<T>) -> Option<&mut T>
where
DynT: MakeConcrete<T>,
{
self.inner.get_mut(key)
}
pub fn get_dyn(&self, id: usize) -> Option<&DynT> {
self.inner.get_dyn(&id)
}
pub fn get_dyn_mut(&mut self, id: usize) -> Option<&mut DynT> {
self.inner.get_dyn_mut(&id)
}
pub fn iter(&self) -> impl Iterator<Item = &Box<DynT>> {
self.inner.iter().map(|(_, v)| v)
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Box<DynT>> {
self.inner.iter_mut().map(|(_, v)| v)
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn remove<T>(&mut self, key: &DynKey<T>) -> Option<Box<T>>
where
DynT: MakeConcrete<T>,
{
self.inner.remove(key)
}
pub fn remove_dyn(&mut self, id: usize) -> Option<Box<DynT>> {
self.inner.remove_dyn(&id)
}
pub fn clear(&mut self) {
self.inner.clear();
}
}
impl<DynT: ?Sized> IntoIterator for DynSet<DynT> {
type IntoIter = DynSetIter<DynT>;
type Item = Box<DynT>;
fn into_iter(self) -> Self::IntoIter {
DynSetIter {
btree_iter: self.inner.into_iter(),
}
}
}
pub struct DynSetIter<DynT: ?Sized> {
btree_iter: std::collections::btree_map::IntoIter<usize, Box<DynT>>,
}
impl<DynT: ?Sized> Iterator for DynSetIter<DynT> {
type Item = Box<DynT>;
fn next(&mut self) -> Option<Self::Item> {
self.btree_iter.next().map(|(_, v)| v)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.btree_iter.size_hint()
}
}
#[cfg(test)]
mod test {
use crate::{dynamify, set::DynSet};
trait Test {
fn message(&self) -> &'static str;
}
#[derive(Debug)]
struct Hello;
impl Hello {
fn hello_own_fn(&self) -> &'static str {
"Hello, I'm concrete `Hello` instance"
}
}
impl Test for Hello {
fn message(&self) -> &'static str {
"Hello"
}
}
#[derive(Debug)]
struct World;
impl World {
fn world_own_fn(&self) -> &'static str {
"World, I'm concrete `World` instance"
}
}
impl Test for World {
fn message(&self) -> &'static str {
"World"
}
}
dynamify!(Test);
#[test]
fn test_push_and_get() {
let mut dynset: DynSet<dyn Test> = DynSet::new();
let hello_key = dynset.push(Hello);
let world_key = dynset.push(World);
assert_eq!(
dynset.get(&hello_key).unwrap().hello_own_fn(),
"Hello, I'm concrete `Hello` instance"
);
assert_eq!(
dynset.get(&world_key).unwrap().world_own_fn(),
"World, I'm concrete `World` instance"
);
}
#[test]
fn test_iter() {
let mut dynset: DynSet<dyn Test> = DynSet::new();
let _hello_key = dynset.push(Hello);
let _world_key = dynset.push(World);
let messages: Vec<_> = dynset.iter().map(|i| i.message()).collect();
assert_eq!(messages, vec!["Hello", "World"]);
}
}