ospf_rust_base/
indexed_type.rs1use 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}