1pub mod reexport {
2 pub use inventory::{collect, iter, submit};
3 pub use paste::paste;
4}
5
6#[macro_export]
7macro_rules! global {
8 (NEW $({$path:path})? $structname:ty; $instance:ident [$($arg:expr),*]) => {
9 $crate::globals::reexport::paste!{
10 pub static [<$instance:snake:upper>]: $($path::)?[<$structname Id>] = $($path::)?[<$structname Id>](&$($path::)?$structname::__new__(
11 stringify!($instance) $(,$arg)*
12 ));
13 $crate::globals::reexport::submit!([<$instance:snake:upper>]);
14 }
15 };
16 (SER?
17 $(#[$meta:meta])*
18 $structname:ident {
19 $mainname:ident
20 $(, $name:ident : $type:ty )*
21 }
22 ) => {
23 #[cfg(feature="serde")]
24 $crate::global!{SER
25 $(#[$meta])*
26 $structname { $mainname $(,$name : $type)*}
27 }
28 #[cfg(not(feature="serde"))]
29 $crate::global!{@BASE
30 $(#[$meta])*
31 $structname { $mainname $(,$name : $type)*}
32 }
33 };
34 (SER
35 $(#[$meta:meta])*
36 $structname:ident {
37 $mainname:ident
38 $(, $name:ident : $type:ty )*
39 }
40 ) => {
41 $crate::global!{@BASE
42 $(#[$meta])*
43 $structname { $mainname $(,$name : $type)*}
44 }
45
46 $crate::globals::reexport::paste!{
47 impl ::serde::Serialize for [<$structname Id>] {
48 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
49 where
50 S: ::serde::Serializer {
51 serializer.serialize_str(self.0.$mainname)
52 }
53 }
54
55 impl<'de> ::serde::Deserialize<'de> for [<$structname Id>] {
56 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57 where
58 D: ::serde::Deserializer<'de> {
59 let s = String::deserialize(deserializer)?;
60 $structname::get_from_str(&s)
61 .map_or_else(
62 || Err(::serde::de::Error::custom("Unknown source file type")),
63 Ok
64 )
65 }
66 }
67 }
68 };
69 (
70 $(#[$meta:meta])*
71 $structname:ident {
72 $mainname:ident
73 $(, $name:ident : $type:ty )*
74 }
75 ) => {
76 $crate::global!{@BASE
77 $(#[$meta])*
78 $structname { $mainname $(,$name : $type)*}
79 }
80 };
81 (@BASE
82 $(#[$meta:meta])*
83 $structname:ident {
84 $mainname:ident
85 $(, $name:ident : $type:ty )*
86 }
87 ) => {$crate::globals::reexport::paste!{
88
89 #[derive(Copy,Clone,Debug)]
90 pub struct [< $structname Id >](pub &'static $structname);
91 impl std::fmt::Display for [< $structname Id >] {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.write_str(self.0.$mainname)
94 }
95 }
96 impl Eq for [< $structname Id >] {}
97 impl PartialEq for [< $structname Id >] {
98 #[inline]
99 fn eq(&self, other: &Self) -> bool {
100 self.0.$mainname.as_ptr() == other.0.$mainname.as_ptr()
101 }
102 }
103 impl std::hash::Hash for [< $structname Id >] {
104 #[inline]
105 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
106 self.0.$mainname.as_ptr().hash(state);
107 }
108 }
109 impl std::convert::AsRef<$structname> for [< $structname Id >] {
110 #[inline]
111 fn as_ref(&self) -> &'static $structname { self.0 }
112 }
113 impl std::ops::Deref for [< $structname Id >] {
114 type Target = $structname;
115 #[inline]
116 fn deref(&self) -> &'static $structname { self.0 }
117 }
118
119
120 $(#[$meta])*
121 #[derive(Debug)]
122 pub struct $structname {
123 $mainname:&'static str
124 $( ,$name:$type )*
125 }
126 $crate::globals::reexport::collect!([< $structname Id >]);
127
128 impl $structname {
129 #[inline]#[must_use] pub const fn __new__($mainname:&'static str $(,$name:$type)*) -> Self {
130 Self { $mainname $(,$name)* }
131 }
132 #[inline] pub fn all() -> impl Iterator<Item=&'static Self> {
133 $crate::globals::reexport::iter::<[< $structname Id >]>.into_iter().map(|e| e.0)
134 }
135
136 #[inline]#[must_use] pub fn get_from_str(s:&str) -> Option<[< $structname Id >]> {
137 Self::all().find(|i| i.$mainname.eq_ignore_ascii_case(s)).map([< $structname Id >])
138 }
139
140 #[inline]#[must_use] pub const fn $mainname(&self) -> &'static str { self.$mainname }
141 $(
142 #[inline]#[must_use] pub const fn $name(&self) -> &$type { &self.$name }
143 )*
144 }
145
146 impl std::fmt::Display for $structname {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 f.write_str(self.$mainname)
149 }
150 }
151
152 impl std::hash::Hash for $structname {
153 #[inline]
154 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
155 self.$mainname.hash(state);
156 }
157 }
158 impl PartialEq for $structname {
159 #[inline]
160 fn eq(&self, other: &Self) -> bool {
161 self.$mainname.as_ptr() == other.$mainname.as_ptr()
162 }
163 }
164 }};
165}