tex_parser/ast/
input_context.rs1use super::Pos;
5use std::{cell::Cell, mem};
6
7#[derive(Clone, Copy)]
8#[repr(C)]
9pub struct InputContext<'a> {
10 pub file_name: &'a str,
11 pub input: &'a str,
12}
13
14thread_local! {
15 static INPUT_CONTEXT: Cell<Option<InputContext<'static>>> = Cell::new(None);
16}
17
18impl Pos {
19 pub fn get_input_context<R, F: for<'input> FnOnce(Option<InputContext<'input>>) -> R>(
20 f: F,
21 ) -> R {
22 let input: Option<InputContext> = INPUT_CONTEXT.with(|c| c.get());
23 f(input)
24 }
25 pub fn call_with_input_context<'input, R, F: FnOnce() -> R>(
26 input: InputContext<'input>,
27 f: F,
28 ) -> R {
29 struct RestoreOnDrop {
30 old_context: Option<InputContext<'static>>,
31 }
32
33 struct PanicOnDrop {}
34
35 impl Drop for PanicOnDrop {
36 fn drop(&mut self) {
37 panic!(
38 "restoring old context failed -- aborting via double-panic to prevent memory unsafety"
39 );
40 }
41 }
42
43 impl Drop for RestoreOnDrop {
44 fn drop(&mut self) {
45 let v = PanicOnDrop {};
46 INPUT_CONTEXT.with(|context| context.set(self.old_context));
47 mem::forget(v);
48 }
49 }
50
51 let restore_on_drop = unsafe {
52 INPUT_CONTEXT.with(|context| RestoreOnDrop {
53 old_context: context.replace(Some(mem::transmute::<
54 InputContext<'input>,
55 InputContext<'static>,
56 >(input))),
57 })
58 };
59 let retval = f();
60 drop(restore_on_drop);
61 retval
62 }
63}