1use std::cell::RefCell;
4use std::marker::PhantomData;
5
6use super::*;
7
8pub(crate) struct TokenStream {
9 handle: handle::Handle,
10}
11
12impl !Send for TokenStream {}
13impl !Sync for TokenStream {}
14
15impl Drop for TokenStream {
17 fn drop(&mut self) {
18 Methods::ts_drop(TokenStream { handle: self.handle });
19 }
20}
21
22impl<S> Encode<S> for TokenStream {
23 fn encode(self, w: &mut Buffer, s: &mut S) {
24 mem::ManuallyDrop::new(self).handle.encode(w, s);
25 }
26}
27
28impl<S> Encode<S> for &TokenStream {
29 fn encode(self, w: &mut Buffer, s: &mut S) {
30 self.handle.encode(w, s);
31 }
32}
33
34impl<S> Decode<'_, '_, S> for TokenStream {
35 fn decode(r: &mut &[u8], s: &mut S) -> Self {
36 TokenStream { handle: handle::Handle::decode(r, s) }
37 }
38}
39
40impl Encode<()> for crate::TokenStream {
41 fn encode(self, w: &mut Buffer, s: &mut ()) {
42 self.0.encode(w, s)
43 }
44}
45
46impl Decode<'_, '_, ()> for crate::TokenStream {
47 fn decode(r: &mut &[u8], s: &mut ()) -> Self {
48 crate::TokenStream(Some(Decode::decode(r, s)))
49 }
50}
51
52#[derive(#[automatically_derived]
impl ::core::marker::Copy for Span { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Span {
#[inline]
fn clone(&self) -> Span {
let _: ::core::clone::AssertParamIsClone<handle::Handle>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Span {
#[inline]
fn eq(&self, other: &Span) -> bool { self.handle == other.handle }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Span {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<handle::Handle>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Span {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.handle, state)
}
}Hash)]
53pub(crate) struct Span {
54 handle: handle::Handle,
55}
56
57impl !Send for Span {}
58impl !Sync for Span {}
59
60impl<S> Encode<S> for Span {
61 fn encode(self, w: &mut Buffer, s: &mut S) {
62 self.handle.encode(w, s);
63 }
64}
65
66impl<S> Decode<'_, '_, S> for Span {
67 fn decode(r: &mut &[u8], s: &mut S) -> Self {
68 Span { handle: handle::Handle::decode(r, s) }
69 }
70}
71
72impl Clone for TokenStream {
73 fn clone(&self) -> Self {
74 Methods::ts_clone(self)
75 }
76}
77
78impl Span {
79 pub(crate) fn def_site() -> Span {
80 Bridge::with(|bridge| bridge.globals.def_site)
81 }
82
83 pub(crate) fn call_site() -> Span {
84 Bridge::with(|bridge| bridge.globals.call_site)
85 }
86
87 pub(crate) fn mixed_site() -> Span {
88 Bridge::with(|bridge| bridge.globals.mixed_site)
89 }
90}
91
92impl fmt::Debug for Span {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 f.write_str(&Methods::span_debug(*self))
95 }
96}
97
98pub(crate) use super::Methods;
99pub(crate) use super::symbol::Symbol;
100
101macro_rules! define_client_side {
102 (
103 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
104 ) => {
105 impl Methods {
106 $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)? {
107 Bridge::with(|bridge| {
108 let mut buf = bridge.cached_buffer.take();
109
110 buf.clear();
111 ApiTags::$method.encode(&mut buf, &mut ());
112 $($arg.encode(&mut buf, &mut ());)*
113
114 buf = bridge.dispatch.call(buf);
115
116 let r = Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
117
118 bridge.cached_buffer = buf;
119
120 r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
121 })
122 })*
123 }
124 }
125}
126impl Methods {
pub(crate) fn injected_env_var(var: &str) -> Option<String> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::injected_env_var.encode(&mut buf, &mut ());
var.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn track_env_var(var: &str, value: Option<&str>) {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::track_env_var.encode(&mut buf, &mut ());
var.encode(&mut buf, &mut ());
value.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn track_path(path: &str) {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::track_path.encode(&mut buf, &mut ());
path.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn literal_from_str(s: &str)
-> Result<Literal<Span, Symbol>, String> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::literal_from_str.encode(&mut buf, &mut ());
s.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn emit_diagnostic(diagnostic: Diagnostic<Span>) {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::emit_diagnostic.encode(&mut buf, &mut ());
diagnostic.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_drop(stream: TokenStream) {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_drop.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_clone(stream: &TokenStream) -> TokenStream {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_clone.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_is_empty(stream: &TokenStream) -> bool {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_is_empty.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_expand_expr(stream: &TokenStream)
-> Result<TokenStream, ()> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_expand_expr.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_from_str(src: &str) -> Result<TokenStream, String> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_from_str.encode(&mut buf, &mut ());
src.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_to_string(stream: &TokenStream) -> String {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_to_string.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_from_token_tree(tree:
TokenTree<TokenStream, Span, Symbol>) -> TokenStream {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_from_token_tree.encode(&mut buf, &mut ());
tree.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_concat_trees(base: Option<TokenStream>,
trees: Vec<TokenTree<TokenStream, Span, Symbol>>) -> TokenStream {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_concat_trees.encode(&mut buf, &mut ());
base.encode(&mut buf, &mut ());
trees.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_concat_streams(base: Option<TokenStream>,
streams: Vec<TokenStream>) -> TokenStream {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_concat_streams.encode(&mut buf, &mut ());
base.encode(&mut buf, &mut ());
streams.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn ts_into_trees(stream: TokenStream)
-> Vec<TokenTree<TokenStream, Span, Symbol>> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::ts_into_trees.encode(&mut buf, &mut ());
stream.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_debug(span: Span) -> String {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_debug.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_parent(span: Span) -> Option<Span> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_parent.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_source(span: Span) -> Span {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_source.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_byte_range(span: Span) -> Range<usize> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_byte_range.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_start(span: Span) -> Span {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_start.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_end(span: Span) -> Span {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_end.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_line(span: Span) -> usize {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_line.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_column(span: Span) -> usize {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_column.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_file(span: Span) -> String {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_file.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_local_file(span: Span) -> Option<String> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_local_file.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_join(span: Span, other: Span) -> Option<Span> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_join.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
other.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_subspan(span: Span, start: Bound<usize>,
end: Bound<usize>) -> Option<Span> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_subspan.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
start.encode(&mut buf, &mut ());
end.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_resolved_at(span: Span, at: Span) -> Span {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_resolved_at.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
at.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_source_text(span: Span) -> Option<String> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_source_text.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_save_span(span: Span) -> usize {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_save_span.encode(&mut buf, &mut ());
span.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn span_recover_proc_macro_span(id: usize) -> Span {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::span_recover_proc_macro_span.encode(&mut buf,
&mut ());
id.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
pub(crate) fn symbol_normalize_and_validate_ident(string: &str)
-> Result<Symbol, ()> {
Bridge::with(|bridge|
{
let mut buf = bridge.cached_buffer.take();
buf.clear();
ApiTags::symbol_normalize_and_validate_ident.encode(&mut buf,
&mut ());
string.encode(&mut buf, &mut ());
buf = bridge.dispatch.call(buf);
let r =
Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
bridge.cached_buffer = buf;
r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
})
}
}with_api!(define_client_side, TokenStream, Span, Symbol);
127
128struct Bridge<'a> {
129 cached_buffer: Buffer,
132
133 dispatch: closure::Closure<'a>,
135
136 globals: ExpnGlobals<Span>,
138}
139
140impl<'a> !Send for Bridge<'a> {}
141impl<'a> !Sync for Bridge<'a> {}
142
143#[allow(unsafe_code)]
144mod state {
145 use std::cell::{Cell, RefCell};
146 use std::ptr;
147
148 use super::Bridge;
149
150 const BRIDGE_STATE: ::std::thread::LocalKey<Cell<*const ()>> =
{
const __RUST_STD_INTERNAL_INIT: Cell<*const ()> =
{ Cell::new(ptr::null()) };
unsafe {
::std::thread::LocalKey::new(const {
if ::std::mem::needs_drop::<Cell<*const ()>>() {
|_|
{
#[thread_local]
static __RUST_STD_INTERNAL_VAL:
::std::thread::local_impl::EagerStorage<Cell<*const ()>> =
::std::thread::local_impl::EagerStorage::new(__RUST_STD_INTERNAL_INIT);
__RUST_STD_INTERNAL_VAL.get()
}
} else {
|_|
{
#[thread_local]
static __RUST_STD_INTERNAL_VAL: Cell<*const ()> =
__RUST_STD_INTERNAL_INIT;
&__RUST_STD_INTERNAL_VAL
}
}
})
}
};thread_local! {
151 static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) };
152 }
153
154 pub(super) fn set<'bridge, R>(state: &RefCell<Bridge<'bridge>>, f: impl FnOnce() -> R) -> R {
155 struct RestoreOnDrop(*const ());
156 impl Drop for RestoreOnDrop {
157 fn drop(&mut self) {
158 BRIDGE_STATE.set(self.0);
159 }
160 }
161
162 let inner = ptr::from_ref(state).cast();
163 let outer = BRIDGE_STATE.replace(inner);
164 let _restore = RestoreOnDrop(outer);
165
166 f()
167 }
168
169 pub(super) fn with<R>(
170 f: impl for<'bridge> FnOnce(Option<&RefCell<Bridge<'bridge>>>) -> R,
171 ) -> R {
172 let state = BRIDGE_STATE.get();
173 let bridge = unsafe { state.cast::<RefCell<Bridge<'static>>>().as_ref() };
181 f(bridge)
182 }
183}
184
185impl Bridge<'_> {
186 fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
187 state::with(|state| {
188 let bridge = state.expect("procedural macro API is used outside of a procedural macro");
189 let mut bridge = bridge
190 .try_borrow_mut()
191 .expect("procedural macro API is used while it's already in use");
192 f(&mut bridge)
193 })
194 }
195}
196
197pub(crate) fn is_available() -> bool {
198 state::with(|s| s.is_some())
199}
200
201#[repr(C)]
213pub struct Client<I, O> {
214 pub(super) run: extern "C" fn(BridgeConfig<'_>) -> Buffer,
215
216 pub(super) _marker: PhantomData<fn(I) -> O>,
217}
218
219impl<I, O> Copy for Client<I, O> {}
220impl<I, O> Clone for Client<I, O> {
221 fn clone(&self) -> Self {
222 *self
223 }
224}
225
226fn maybe_install_panic_hook(force_show_panics: bool) {
227 static HIDE_PANICS_DURING_EXPANSION: Once = Once::new();
230 HIDE_PANICS_DURING_EXPANSION.call_once(|| {
231 let prev = panic::take_hook();
232 panic::set_hook(Box::new(move |info| {
233 if force_show_panics || !is_available() || !info.can_unwind() {
238 prev(info)
239 }
240 }));
241 });
242}
243
244fn run_client<A: for<'a, 's> Decode<'a, 's, ()>>(
247 config: BridgeConfig<'_>,
248 f: impl FnOnce(A) -> crate::TokenStream,
249) -> Buffer {
250 let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config;
251
252 let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
253 maybe_install_panic_hook(force_show_panics);
254
255 Symbol::invalidate_all();
257
258 let reader = &mut &buf[..];
259 let (globals, input) = <(ExpnGlobals<Span>, A)>::decode(reader, &mut ());
260
261 let state = RefCell::new(Bridge { cached_buffer: buf.take(), dispatch, globals });
263
264 let output = state::set(&state, || f(input));
265
266 buf = RefCell::into_inner(state).cached_buffer;
268
269 output
270 }));
271
272 buf.clear();
274 res.map_err(PanicMessage::from).encode(&mut buf, &mut ());
275
276 Symbol::invalidate_all();
279 buf
280}
281
282impl Client<crate::TokenStream, crate::TokenStream> {
283 pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self {
284 Client {
285 run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
286 run_client(bridge, |input| f(input))
287 }),
288 _marker: PhantomData,
289 }
290 }
291}
292
293impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> {
294 pub const fn expand2(
295 f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
296 ) -> Self {
297 Client {
298 run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
299 run_client(bridge, |(input, input2)| f(input, input2))
300 }),
301 _marker: PhantomData,
302 }
303 }
304}
305
306#[repr(C)]
307#[derive(#[automatically_derived]
impl ::core::marker::Copy for ProcMacro { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ProcMacro {
#[inline]
fn clone(&self) -> ProcMacro {
let _: ::core::clone::AssertParamIsClone<&'static str>;
let _: ::core::clone::AssertParamIsClone<&'static [&'static str]>;
let _:
::core::clone::AssertParamIsClone<Client<crate::TokenStream,
crate::TokenStream>>;
let _: ::core::clone::AssertParamIsClone<&'static str>;
let _:
::core::clone::AssertParamIsClone<Client<(crate::TokenStream,
crate::TokenStream), crate::TokenStream>>;
let _: ::core::clone::AssertParamIsClone<&'static str>;
let _:
::core::clone::AssertParamIsClone<Client<crate::TokenStream,
crate::TokenStream>>;
*self
}
}Clone)]
308pub enum ProcMacro {
309 CustomDerive {
310 trait_name: &'static str,
311 attributes: &'static [&'static str],
312 client: Client<crate::TokenStream, crate::TokenStream>,
313 },
314
315 Attr {
316 name: &'static str,
317 client: Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream>,
318 },
319
320 Bang {
321 name: &'static str,
322 client: Client<crate::TokenStream, crate::TokenStream>,
323 },
324}
325
326impl ProcMacro {
327 pub fn name(&self) -> &'static str {
328 match self {
329 ProcMacro::CustomDerive { trait_name, .. } => trait_name,
330 ProcMacro::Attr { name, .. } => name,
331 ProcMacro::Bang { name, .. } => name,
332 }
333 }
334
335 pub const fn custom_derive(
336 trait_name: &'static str,
337 attributes: &'static [&'static str],
338 expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
339 ) -> Self {
340 ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
341 }
342
343 pub const fn attr(
344 name: &'static str,
345 expand: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
346 ) -> Self {
347 ProcMacro::Attr { name, client: Client::expand2(expand) }
348 }
349
350 pub const fn bang(
351 name: &'static str,
352 expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
353 ) -> Self {
354 ProcMacro::Bang { name, client: Client::expand1(expand) }
355 }
356}