use alloc::boxed::Box;
use alloc::vec::Vec;
use core::any::{Any, TypeId, type_name};
use core::fmt::{self, Debug};
#[derive(Copy, Clone)]
pub(crate) struct TypeKey(pub(crate) TypeId, &'static str);
impl TypeKey {
pub(crate) fn of<T: 'static>() -> TypeKey {
TypeKey(TypeId::of::<T>(), type_name::<T>())
}
}
impl PartialEq for TypeKey {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for TypeKey {}
impl Debug for TypeKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.1)
}
}
pub(crate) trait DebugAny: Any + Debug + Send + Sync {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T: Any + Debug + Send + Sync + 'static> DebugAny for T {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
}
trait EventAny: DebugAny + Sync {}
impl<T: DebugAny + Sync> EventAny for T {}
impl dyn DebugAny {
#[inline(always)]
pub(crate) unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
debug_assert!(self.as_any().is::<T>());
unsafe { &*(self as *const dyn DebugAny).cast::<T>() }
}
#[inline(always)]
pub(crate) unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
debug_assert!(self.as_any_mut().is::<T>());
unsafe { &mut *(self as *mut dyn DebugAny).cast::<T>() }
}
}
impl dyn EventAny {
#[inline(always)]
unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
debug_assert!(self.as_any().is::<T>());
unsafe { &*(self as *const dyn EventAny).cast::<T>() }
}
#[inline(always)]
unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
debug_assert!(self.as_any_mut().is::<T>());
unsafe { &mut *(self as *mut dyn EventAny).cast::<T>() }
}
}
#[derive(Copy, Clone)]
struct CloneFns {
clone: fn(&dyn DebugAny) -> Box<dyn DebugAny>,
clone_into: fn(&mut dyn DebugAny, &dyn DebugAny),
}
impl CloneFns {
fn of<T: Clone + Debug + Send + Sync + 'static>() -> CloneFns {
CloneFns {
clone: |value| Box::new(value.as_any().downcast_ref::<T>().unwrap().clone()),
clone_into: |target, value| {
target
.as_any_mut()
.downcast_mut::<T>()
.unwrap()
.clone_from(value.as_any().downcast_ref::<T>().unwrap())
},
}
}
}
#[derive(Copy, Clone)]
struct EventFns {
clone: fn(&dyn EventAny) -> Box<dyn EventAny>,
clone_into: fn(&mut dyn EventAny, &dyn EventAny),
}
impl EventFns {
fn of<T: Clone + Debug + Send + Sync + 'static>() -> EventFns {
EventFns {
clone: |value| Box::new(value.as_any().downcast_ref::<T>().unwrap().clone()),
clone_into: |target, value| {
target
.as_any_mut()
.downcast_mut::<T>()
.unwrap()
.clone_from(value.as_any().downcast_ref::<T>().unwrap())
},
}
}
}
struct EventEntry {
key: TypeKey,
active: bool,
value: Box<dyn EventAny>,
fns: EventFns,
}
#[derive(Default)]
pub(crate) struct Extensions {
entries: Vec<(TypeKey, Box<dyn DebugAny>)>,
replayable: Vec<(TypeKey, CloneFns)>,
events: Vec<EventEntry>,
has_event_data: bool,
}
impl Debug for Extensions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map()
.entries(self.entries.iter().map(|(key, value)| (key, value)))
.entries(
self.events
.iter()
.filter(|entry| entry.active)
.map(|entry| (entry.key, &entry.value)),
)
.finish()
}
}
impl Extensions {
#[inline]
fn position(&self, key: TypeId) -> Option<usize> {
self.entries.iter().position(|(k, _)| k.0 == key)
}
#[inline]
pub(crate) fn get<T: Debug + Send + Sync + 'static>(&self) -> Option<&T> {
let index = self.position(TypeId::of::<T>())?;
Some(unsafe { self.entries[index].1.downcast_ref_unchecked::<T>() })
}
#[inline]
pub(crate) fn get_mut<T: Default + Debug + Send + Sync + 'static>(&mut self) -> &mut T {
let index = match self.position(TypeId::of::<T>()) {
Some(index) => index,
None => self.insert_default::<T>(),
};
unsafe { self.entries[index].1.downcast_mut_unchecked::<T>() }
}
#[cold]
fn insert_default<T: Default + Debug + Send + Sync + 'static>(&mut self) -> usize {
self.entries
.push((TypeKey::of::<T>(), Box::new(T::default())));
self.entries.len() - 1
}
pub(crate) fn set_replayable<T: Clone + Debug + Send + Sync + 'static>(&mut self) {
let key = TypeKey::of::<T>();
if !self.replayable.iter().any(|(k, _)| *k == key) {
self.replayable.push((key, CloneFns::of::<T>()));
}
}
#[cfg(test)]
pub fn has_event_data(&self) -> bool {
self.has_event_data
}
#[inline]
fn event_position(&self, key: TypeId) -> Option<usize> {
self.events.iter().position(|entry| entry.key.0 == key)
}
#[inline(always)]
pub(crate) fn event<T: Debug + Send + Sync + 'static>(&self) -> Option<&T> {
if !self.has_event_data {
return None;
}
self.find_event()
}
#[inline]
fn find_event<T: Debug + Send + Sync + 'static>(&self) -> Option<&T> {
let entry = &self.events[self.event_position(TypeId::of::<T>())?];
if !entry.active {
return None;
}
Some(unsafe { entry.value.downcast_ref_unchecked::<T>() })
}
#[inline]
pub(crate) fn event_mut<T: Default + Clone + Debug + Send + Sync + 'static>(
&mut self,
) -> &mut T {
let index = match self.event_position(TypeId::of::<T>()) {
Some(index) => index,
None => self.insert_event::<T>(),
};
let entry = &mut self.events[index];
let value = unsafe { entry.value.downcast_mut_unchecked::<T>() };
if !entry.active {
value.clone_from(&T::default());
entry.active = true;
self.has_event_data = true;
}
value
}
pub(crate) fn take_event<T: Default + Debug + Send + Sync + 'static>(&mut self) -> Option<T> {
if !self.has_event_data {
return None;
}
let index = self.event_position(TypeId::of::<T>())?;
let entry = &mut self.events[index];
if !entry.active {
return None;
}
let value = core::mem::take((*entry.value).as_any_mut().downcast_mut::<T>()?);
entry.active = false;
self.has_event_data = self.events.iter().any(|entry| entry.active);
Some(value)
}
#[cold]
fn insert_event<T: Default + Clone + Debug + Send + Sync + 'static>(&mut self) -> usize {
self.events.push(EventEntry {
key: TypeKey::of::<T>(),
active: false,
value: Box::new(T::default()),
fns: EventFns::of::<T>(),
});
self.events.len() - 1
}
#[inline(always)]
pub(crate) fn clear_event_data(&mut self) {
if self.has_event_data {
self.deactivate_events();
}
}
#[inline(never)]
fn deactivate_events(&mut self) {
for entry in self.events.iter_mut() {
entry.active = false;
}
self.has_event_data = false;
}
#[inline]
pub(crate) fn snapshot_if_any(&self) -> Option<Snapshot> {
if self.replayable.is_empty() && !self.has_event_data {
return None;
}
Some(self.snapshot()).filter(|snapshot| !snapshot.is_empty())
}
pub(crate) fn snapshot(&self) -> Snapshot {
let mut snapshot = Snapshot::default();
if !self.replayable.is_empty() {
snapshot.replayable = self
.replayable
.iter()
.filter_map(|&(key, fns)| {
self.position(key.0)
.map(|index| (key, (fns.clone)(&*self.entries[index].1), fns))
})
.collect();
}
snapshot.events = self.capture_event_data();
snapshot
}
pub(crate) fn restore(&mut self, snapshot: &Snapshot) {
for (key, value, fns) in snapshot.replayable.iter() {
match self.position(key.0) {
Some(index) => (fns.clone_into)(&mut *self.entries[index].1, &**value),
None => self.entries.push((*key, (fns.clone)(&**value))),
}
}
self.restore_event_data(&snapshot.events);
}
pub(crate) fn capture_event_data(&self) -> EventData {
if !self.has_event_data {
return EventData::default();
}
EventData {
entries: self
.events
.iter()
.filter(|entry| entry.active)
.map(|entry| EventDataEntry {
key: entry.key,
value: (entry.fns.clone)(&*entry.value),
fns: entry.fns,
})
.collect(),
}
}
pub(crate) fn restore_event_data(&mut self, data: &EventData) {
self.clear_event_data();
self.attach_event_data(data);
}
pub(crate) fn attach_event_data(&mut self, data: &EventData) {
for entry in data.entries.iter() {
match self.event_position(entry.key.0) {
Some(index) => {
let target = &mut self.events[index];
(entry.fns.clone_into)(&mut *target.value, &*entry.value);
target.active = true;
}
None => self.events.push(EventEntry {
key: entry.key,
active: true,
value: (entry.fns.clone)(&*entry.value),
fns: entry.fns,
}),
}
self.has_event_data = true;
}
}
}
#[derive(Default)]
pub(crate) struct Snapshot {
replayable: Vec<(TypeKey, Box<dyn DebugAny>, CloneFns)>,
events: EventData,
}
impl Snapshot {
pub(crate) fn is_empty(&self) -> bool {
self.replayable.is_empty() && self.events.is_empty()
}
pub(crate) fn event_data(&self) -> &EventData {
&self.events
}
}
impl Clone for Snapshot {
fn clone(&self) -> Snapshot {
Snapshot {
replayable: self
.replayable
.iter()
.map(|(key, value, fns)| (*key, (fns.clone)(&**value), *fns))
.collect(),
events: self.events.clone(),
}
}
}
impl Debug for Snapshot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map()
.entries(self.replayable.iter().map(|(key, value, _)| (key, value)))
.entries(
self.events
.entries
.iter()
.map(|entry| (entry.key, &entry.value)),
)
.finish()
}
}
#[derive(Default)]
pub struct EventData {
entries: Vec<EventDataEntry>,
}
struct EventDataEntry {
key: TypeKey,
value: Box<dyn EventAny>,
fns: EventFns,
}
impl EventData {
pub const fn new() -> EventData {
EventData {
entries: Vec::new(),
}
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
fn position(&self, key: TypeId) -> Option<usize> {
self.entries.iter().position(|entry| entry.key.0 == key)
}
pub fn get<T: Debug + Send + 'static>(&self) -> Option<&T> {
let entry = &self.entries[self.position(TypeId::of::<T>())?];
Some(unsafe { entry.value.downcast_ref_unchecked::<T>() })
}
pub fn get_mut<T: Default + Clone + Debug + Send + Sync + 'static>(&mut self) -> &mut T {
let index = match self.position(TypeId::of::<T>()) {
Some(index) => index,
None => {
self.entries.push(EventDataEntry {
key: TypeKey::of::<T>(),
value: Box::new(T::default()),
fns: EventFns::of::<T>(),
});
self.entries.len() - 1
}
};
let entry = &mut self.entries[index];
unsafe { entry.value.downcast_mut_unchecked::<T>() }
}
pub fn insert<T: Clone + Debug + Send + Sync + 'static>(&mut self, value: T) {
let entry = EventDataEntry {
key: TypeKey::of::<T>(),
value: Box::new(value),
fns: EventFns::of::<T>(),
};
match self.position(TypeId::of::<T>()) {
Some(index) => self.entries[index] = entry,
None => self.entries.push(entry),
}
}
pub fn remove<T: Debug + Send + 'static>(&mut self) -> Option<T> {
let entry = self.entries.remove(self.position(TypeId::of::<T>())?);
entry
.value
.into_any()
.downcast::<T>()
.ok()
.map(|value| *value)
}
}
impl Clone for EventData {
fn clone(&self) -> EventData {
EventData {
entries: self
.entries
.iter()
.map(|entry| EventDataEntry {
key: entry.key,
value: (entry.fns.clone)(&*entry.value),
fns: entry.fns,
})
.collect(),
}
}
}
impl Debug for EventData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map()
.entries(self.entries.iter().map(|entry| (entry.key, &entry.value)))
.finish()
}
}
#[test]
fn test_extensions() {
#[derive(Debug, Default, Clone, PartialEq)]
struct A(u32);
#[derive(Debug, Default, Clone, PartialEq)]
struct B(String);
#[derive(Debug, Default, Clone, PartialEq)]
struct C(u8);
let mut ext = Extensions::default();
assert_eq!(ext.get::<A>(), None);
ext.get_mut::<A>().0 = 42;
ext.get_mut::<B>().0.push_str("hello");
ext.get_mut::<C>().0 = 1;
assert_eq!(ext.get::<A>(), Some(&A(42)));
assert_eq!(ext.get::<B>(), Some(&B("hello".into())));
assert_eq!(ext.get::<C>(), Some(&C(1)));
ext.set_replayable::<A>();
ext.set_replayable::<B>();
ext.set_replayable::<A>();
let snapshot = ext.snapshot();
ext.get_mut::<A>().0 = 1;
ext.get_mut::<B>().0.clear();
ext.get_mut::<C>().0 = 2;
ext.restore(&snapshot);
assert_eq!(ext.get::<A>(), Some(&A(42)));
assert_eq!(ext.get::<B>(), Some(&B("hello".into())));
assert_eq!(ext.get::<C>(), Some(&C(2)));
let mut other = Extensions::default();
other.restore(&snapshot.clone());
assert_eq!(other.get::<A>(), Some(&A(42)));
assert_eq!(other.get::<C>(), None);
assert_eq!(
format!("{:?}", other),
format!(
"{{{}: A(42), {}: B(\"hello\")}}",
core::any::type_name::<A>(),
core::any::type_name::<B>()
)
);
}
#[test]
fn test_event_data() {
#[derive(Debug, Default, PartialEq)]
struct Tags(Vec<u64>);
impl Clone for Tags {
fn clone(&self) -> Tags {
Tags(self.0.clone())
}
fn clone_from(&mut self, source: &Tags) {
self.0.clone_from(&source.0);
}
}
#[derive(Debug, Default, Clone, PartialEq)]
struct Span(usize, usize);
let mut ext = Extensions::default();
assert!(!ext.has_event_data());
assert_eq!(ext.event::<Tags>(), None);
ext.event_mut::<Tags>().0.extend([1, 2]);
assert!(ext.has_event_data());
assert_eq!(ext.event::<Tags>(), Some(&Tags(vec![1, 2])));
assert_eq!(ext.event::<Span>(), None);
ext.clear_event_data();
assert!(!ext.has_event_data());
assert_eq!(ext.event::<Tags>(), None);
let tags = ext.event_mut::<Tags>();
assert_eq!(tags, &Tags(vec![]));
assert!(tags.0.capacity() >= 2);
tags.0.push(3);
*ext.event_mut::<Span>() = Span(1, 2);
let snapshot = ext.snapshot();
ext.clear_event_data();
*ext.event_mut::<Span>() = Span(3, 4);
ext.restore(&snapshot);
assert_eq!(ext.event::<Tags>(), Some(&Tags(vec![3])));
assert_eq!(ext.event::<Span>(), Some(&Span(1, 2)));
ext.clear_event_data();
ext.event_mut::<Span>();
let empty = ext.snapshot();
*ext.event_mut::<Tags>() = Tags(vec![4]);
ext.restore(&empty);
assert_eq!(ext.event::<Tags>(), None);
assert_eq!(ext.event::<Span>(), Some(&Span(0, 0)));
*ext.event_mut::<Tags>() = Tags(vec![5]);
assert_eq!(ext.take_event::<Tags>(), Some(Tags(vec![5])));
assert_eq!(ext.take_event::<Tags>(), None);
assert_eq!(ext.event::<Tags>(), None);
assert_eq!(ext.event::<Span>(), Some(&Span(0, 0)));
assert!(ext.capture_event_data().entries.len() == 1);
assert_eq!(ext.take_event::<Span>(), Some(Span(0, 0)));
assert!(!ext.has_event_data());
assert!(ext.capture_event_data().is_empty());
}
#[test]
fn test_downcast_through_box() {
use alloc::sync::Arc;
let boxed: Box<dyn DebugAny> = Box::new(42u32);
assert_eq!(unsafe { *boxed.downcast_ref_unchecked::<u32>() }, 42);
let arc: Arc<dyn DebugAny> = Arc::new(42u32);
assert_eq!(unsafe { *arc.downcast_ref_unchecked::<u32>() }, 42);
let mut boxed: Box<dyn EventAny> = Box::new(1u32);
unsafe { *boxed.downcast_mut_unchecked::<u32>() += 1 };
assert_eq!(unsafe { *boxed.downcast_ref_unchecked::<u32>() }, 2);
}