ospf_rust_base/
indexed_type.rs

1use std::any::TypeId;
2use std::cell::{Cell, SyncUnsafeCell};
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::sync::Mutex;
6
7pub trait Indexed: Sized {
8    fn index(&self) -> usize;
9
10    fn flush();
11}
12
13pub trait ManualIndexed: Indexed {
14    fn indexed(&self) -> bool;
15    fn set_indexed(&mut self)
16    where
17        Self: 'static,
18    {
19        self.set_indexed_with::<Self>()
20    }
21    fn set_indexed_with<T: 'static>(&mut self);
22}
23
24pub struct IndexGeneratorImpl {
25    next_index: usize,
26}
27
28impl IndexGeneratorImpl {
29    pub fn new() -> Self {
30        Self { next_index: 0 }
31    }
32
33    pub fn next(&mut self) -> usize {
34        let ret = self.next_index;
35        self.next_index += 1;
36        ret
37    }
38
39    pub fn flush(&mut self) {
40        self.next_index = 0
41    }
42}
43
44pub struct IndexGenerator {
45    inner: Option<HashMap<TypeId, Arc<Mutex<IndexGeneratorImpl>>>>,
46}
47
48static mut INDEX_GENERATOR: SyncUnsafeCell<IndexGenerator> = SyncUnsafeCell::new(IndexGenerator {
49    inner: None
50});
51
52impl IndexGenerator {
53    pub(self) fn self_instance() -> &'static mut IndexGenerator {
54        let mut instance = unsafe {
55            INDEX_GENERATOR.get().as_mut_unchecked()
56        };
57        if instance.inner.is_none() {
58            instance.inner = Some(HashMap::new());
59        }
60        instance
61    }
62
63    pub(crate) fn instance<T: 'static>() -> Arc<Mutex<IndexGeneratorImpl>> {
64        let instance = Self::self_instance();
65        instance.inner.as_mut().unwrap()
66            .entry(TypeId::of::<T>())
67            .insert_entry(Arc::new(Mutex::new(IndexGeneratorImpl::new())))
68            .get()
69            .clone()
70    }
71}
72
73#[macro_export]
74macro_rules! auto_indexed {
75    (#[derive($($derive:meta),*)] $pub:vis struct $name:ident { $($fpub:vis $field:ident : $type:ty,)* }) => {
76        #[derive($($derive),*)]
77        $pub struct $name {
78            index: usize,
79            $($fpub $field : $type,)*
80        }
81        impl $name {
82            $pub fn new<T: 'STATIC = Self>($($field:$type,)*) -> Self{
83                Self {
84                    index: (*IndexGenerator::instance::<T>().lock().unwrap()).next(),
85                    $($field,)*
86                }
87            }
88        }
89
90        impl Indexed for $name {
91            fn index(&self) -> usize {
92                self.index
93            }
94
95            fn flush<T: 'STATIC = Self>() {
96                (*IndexGenerator::instance::<T>().lock().unwrap()).flush();
97            }
98        }
99
100        impl Deref for &$name {
101            type Target = isize;
102
103            fn deref(&self) -> &Self::Target {
104                let ptr = &self.index as *const usize;
105                unsafe { &*(ptr as *const isize) }
106            }
107        }
108    }
109}
110
111#[macro_export]
112macro_rules! manual_indexed {
113    (#[derive($($derive:meta),*)] $pub:vis struct $name:ident { $($fpub:vis $field:ident : $type:ty,)* }) => {
114        #[derive($($derive),*)]
115        $pub struct $name {
116            index: Option<usize>,
117            $($fpub $field : $type,)*
118        }
119        impl $name {
120            $pub fn new($($field:$type,)*) -> Self{
121                Self {
122                    index: None,
123                    $($field,)*
124                }
125            }
126        }
127
128        impl Indexed for $name {
129            fn index(&self) -> usize {
130                self.index.unwrap()
131            }
132
133            fn flush<T: 'STATIC = Self>() {
134                (*IndexGenerator::instance::<T>().lock().unwrap()).flush();
135            }
136        }
137
138        impl ManualIndexed for $name {
139            fn indexed(&self) -> bool {
140                self.index.is_some()
141            }
142
143            fn set_indexed_with<T: 'static>(&mut self) {
144                self.index = Some((*IndexGenerator::instance::<T>().lock().unwrap()).next());
145            }
146        }
147
148        impl Deref for &$name {
149            type Target = isize;
150
151            fn deref(&self) -> &Self::Target {
152                let ptr = self.index.as_ref().unwrap() as *const usize;
153                unsafe { &*(ptr as *const isize) }
154            }
155        }
156    }
157}