1use std::cell::RefCell;
4use std::marker::PhantomData;
5use std::sync::atomic::AtomicU32;
6
7use super::*;
8
9#[repr(C)]
10pub(super) struct HandleCounters {
11 pub(super) token_stream: AtomicU32,
12 pub(super) span: AtomicU32,
13}
14
15static COUNTERS: HandleCounters =
16 HandleCounters { token_stream: AtomicU32::new(1), span: AtomicU32::new(1) };
17
18pub(crate) struct TokenStream {
19 handle: handle::Handle,
20}
21
22impl !Send for TokenStream {}
23impl !Sync for TokenStream {}
24
25impl Drop for TokenStream {
27 fn drop(&mut self) {
28 Methods::ts_drop(TokenStream { handle: self.handle });
29 }
30}
31
32impl<S> Encode<S> for TokenStream {
33 fn encode(self, w: &mut Buffer, s: &mut S) {
34 mem::ManuallyDrop::new(self).handle.encode(w, s);
35 }
36}
37
38impl<S> Encode<S> for &TokenStream {
39 fn encode(self, w: &mut Buffer, s: &mut S) {
40 self.handle.encode(w, s);
41 }
42}
43
44impl<S> Decode<'_, '_, S> for TokenStream {
45 fn decode(r: &mut &[u8], s: &mut S) -> Self {
46 TokenStream { handle: handle::Handle::decode(r, s) }
47 }
48}
49
50#[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_receiver_is_total_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)]
51pub(crate) struct Span {
52 handle: handle::Handle,
53}
54
55impl !Send for Span {}
56impl !Sync for Span {}
57
58impl<S> Encode<S> for Span {
59 fn encode(self, w: &mut Buffer, s: &mut S) {
60 self.handle.encode(w, s);
61 }
62}
63
64impl<S> Decode<'_, '_, S> for Span {
65 fn decode(r: &mut &[u8], s: &mut S) -> Self {
66 Span { handle: handle::Handle::decode(r, s) }
67 }
68}
69
70impl Clone for TokenStream {
71 fn clone(&self) -> Self {
72 Methods::ts_clone(self)
73 }
74}
75
76impl Span {
77 pub(crate) fn def_site() -> Span {
78 Bridge::with(|bridge| bridge.globals.def_site)
79 }
80
81 pub(crate) fn call_site() -> Span {
82 Bridge::with(|bridge| bridge.globals.call_site)
83 }
84
85 pub(crate) fn mixed_site() -> Span {
86 Bridge::with(|bridge| bridge.globals.mixed_site)
87 }
88}
89
90impl fmt::Debug for Span {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 f.write_str(&Methods::span_debug(*self))
93 }
94}
95
96pub(crate) use super::Methods;
97pub(crate) use super::symbol::Symbol;
98
99macro_rules! define_client_side {
100 (
101 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
102 ) => {
103 impl Methods {
104 $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)? {
105 Bridge::with(|bridge| {
106 let mut buf = bridge.cached_buffer.take();
107
108 buf.clear();
109 ApiTags::$method.encode(&mut buf, &mut ());
110 $($arg.encode(&mut buf, &mut ());)*
111
112 buf = bridge.dispatch.call(buf);
113
114 let r = Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ());
115
116 bridge.cached_buffer = buf;
117
118 r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
119 })
120 })*
121 }
122 }
123}
124impl 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<self::Span, self::Symbol>, ()> {
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<self::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: self::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: &self::TokenStream) -> self::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: &self::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: &self::TokenStream)
-> Result<self::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) -> self::TokenStream {
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: &self::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<self::TokenStream, self::Span, self::Symbol>)
-> self::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<self::TokenStream>,
trees: Vec<TokenTree<self::TokenStream, self::Span, self::Symbol>>)
-> self::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<self::TokenStream>,
streams: Vec<self::TokenStream>) -> self::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: self::TokenStream)
-> Vec<TokenTree<self::TokenStream, self::Span, self::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: self::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: self::Span) -> Option<self::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: self::Span) -> self::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: self::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: self::Span) -> self::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: self::Span) -> self::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: self::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: self::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: self::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: self::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: self::Span, other: self::Span)
-> Option<self::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: self::Span, start: Bound<usize>,
end: Bound<usize>) -> Option<self::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: self::Span, at: self::Span)
-> self::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: self::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: self::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) -> self::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<self::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!(self, define_client_side);
125
126struct Bridge<'a> {
127 cached_buffer: Buffer,
130
131 dispatch: closure::Closure<'a, Buffer, Buffer>,
133
134 globals: ExpnGlobals<Span>,
136}
137
138impl<'a> !Send for Bridge<'a> {}
139impl<'a> !Sync for Bridge<'a> {}
140
141#[allow(unsafe_code)]
142mod state {
143 use std::cell::{Cell, RefCell};
144 use std::ptr;
145
146 use super::Bridge;
147
148 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! {
149 static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) };
150 }
151
152 pub(super) fn set<'bridge, R>(state: &RefCell<Bridge<'bridge>>, f: impl FnOnce() -> R) -> R {
153 struct RestoreOnDrop(*const ());
154 impl Drop for RestoreOnDrop {
155 fn drop(&mut self) {
156 BRIDGE_STATE.set(self.0);
157 }
158 }
159
160 let inner = ptr::from_ref(state).cast();
161 let outer = BRIDGE_STATE.replace(inner);
162 let _restore = RestoreOnDrop(outer);
163
164 f()
165 }
166
167 pub(super) fn with<R>(
168 f: impl for<'bridge> FnOnce(Option<&RefCell<Bridge<'bridge>>>) -> R,
169 ) -> R {
170 let state = BRIDGE_STATE.get();
171 let bridge = unsafe { state.cast::<RefCell<Bridge<'static>>>().as_ref() };
179 f(bridge)
180 }
181}
182
183impl Bridge<'_> {
184 fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
185 state::with(|state| {
186 let bridge = state.expect("procedural macro API is used outside of a procedural macro");
187 let mut bridge = bridge
188 .try_borrow_mut()
189 .expect("procedural macro API is used while it's already in use");
190 f(&mut bridge)
191 })
192 }
193}
194
195pub(crate) fn is_available() -> bool {
196 state::with(|s| s.is_some())
197}
198
199#[repr(C)]
211pub struct Client<I, O> {
212 pub(super) handle_counters: &'static HandleCounters,
213
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, ()>, R: Encode<()>>(
248 config: BridgeConfig<'_>,
249 f: impl FnOnce(A) -> R,
250) -> Buffer {
251 let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config;
252
253 panic::catch_unwind(panic::AssertUnwindSafe(|| {
254 maybe_install_panic_hook(force_show_panics);
255
256 Symbol::invalidate_all();
258
259 let reader = &mut &buf[..];
260 let (globals, input) = <(ExpnGlobals<Span>, A)>::decode(reader, &mut ());
261
262 let state = RefCell::new(Bridge { cached_buffer: buf.take(), dispatch, globals });
264
265 let output = state::set(&state, || f(input));
266
267 buf = RefCell::into_inner(state).cached_buffer;
269
270 buf.clear();
280 Ok::<_, ()>(output).encode(&mut buf, &mut ());
281 }))
282 .map_err(PanicMessage::from)
283 .unwrap_or_else(|e| {
284 buf.clear();
285 Err::<(), _>(e).encode(&mut buf, &mut ());
286 });
287
288 Symbol::invalidate_all();
291 buf
292}
293
294impl Client<crate::TokenStream, crate::TokenStream> {
295 pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self {
296 Client {
297 handle_counters: &COUNTERS,
298 run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
299 run_client(bridge, |input| f(crate::TokenStream(Some(input))).0)
300 }),
301 _marker: PhantomData,
302 }
303 }
304}
305
306impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> {
307 pub const fn expand2(
308 f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
309 ) -> Self {
310 Client {
311 handle_counters: &COUNTERS,
312 run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
313 run_client(bridge, |(input, input2)| {
314 f(crate::TokenStream(Some(input)), crate::TokenStream(Some(input2))).0
315 })
316 }),
317 _marker: PhantomData,
318 }
319 }
320}
321
322#[repr(C)]
323#[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)]
324pub enum ProcMacro {
325 CustomDerive {
326 trait_name: &'static str,
327 attributes: &'static [&'static str],
328 client: Client<crate::TokenStream, crate::TokenStream>,
329 },
330
331 Attr {
332 name: &'static str,
333 client: Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream>,
334 },
335
336 Bang {
337 name: &'static str,
338 client: Client<crate::TokenStream, crate::TokenStream>,
339 },
340}
341
342impl ProcMacro {
343 pub fn name(&self) -> &'static str {
344 match self {
345 ProcMacro::CustomDerive { trait_name, .. } => trait_name,
346 ProcMacro::Attr { name, .. } => name,
347 ProcMacro::Bang { name, .. } => name,
348 }
349 }
350
351 pub const fn custom_derive(
352 trait_name: &'static str,
353 attributes: &'static [&'static str],
354 expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
355 ) -> Self {
356 ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
357 }
358
359 pub const fn attr(
360 name: &'static str,
361 expand: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy,
362 ) -> Self {
363 ProcMacro::Attr { name, client: Client::expand2(expand) }
364 }
365
366 pub const fn bang(
367 name: &'static str,
368 expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
369 ) -> Self {
370 ProcMacro::Bang { name, client: Client::expand1(expand) }
371 }
372}