remote_context.rs 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. use std::any::Any;
  2. use std::cell::RefCell;
  3. use crate::term_marker::TermMarker;
  4. #[derive(Clone)]
  5. pub(crate) struct RemoteContext<Command> {
  6. term_marker: TermMarker<Command>,
  7. }
  8. impl<Command: 'static> RemoteContext<Command> {
  9. pub fn create(term_marker: TermMarker<Command>) -> Self {
  10. Self { term_marker }
  11. }
  12. pub fn term_marker() -> &'static TermMarker<Command> {
  13. &Self::fetch_context().term_marker
  14. }
  15. thread_local! {
  16. // Using Any to mask the fact that we are storing a generic struct.
  17. static REMOTE_CONTEXT: RefCell<Option<&'static dyn Any>> = RefCell::new(None);
  18. }
  19. pub fn attach(self) {
  20. Self::set_context(Box::new(self))
  21. }
  22. pub fn detach() -> Box<Self> {
  23. let static_context = Self::fetch_context();
  24. unsafe { Box::from_raw((static_context as *const Self) as *mut Self) }
  25. }
  26. fn set_context(context: Box<Self>) {
  27. let context_ref = Box::leak(context);
  28. let any_ref: &'static mut dyn Any = context_ref;
  29. Self::REMOTE_CONTEXT
  30. .with(|context| *context.borrow_mut() = Some(any_ref));
  31. }
  32. fn fetch_context() -> &'static Self {
  33. let any_ref = Self::REMOTE_CONTEXT.with(|context| *context.borrow());
  34. if let Some(any_ref) = any_ref {
  35. any_ref
  36. .downcast_ref::<Self>()
  37. .expect("Context is set to the wrong type.")
  38. } else {
  39. panic!("Context is not set");
  40. }
  41. }
  42. }