1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Implementations for storing normal rust structs inside any object as internal state.

use std::{
    any::Any,
    fmt::{self, Debug},
    ops::{Deref, DerefMut},
    rc::Rc,
};

use gc::{unsafe_empty_trace, Finalize, Trace};

/// Wrapper around `Rc` to implement `Trace` and `Finalize`.
#[derive(Clone)]
pub struct InternalStateCell {
    /// The internal state.
    state: Rc<dyn Any>,
}

impl Finalize for InternalStateCell {}

unsafe impl Trace for InternalStateCell {
    unsafe_empty_trace!();
}

impl Deref for InternalStateCell {
    type Target = dyn Any;
    fn deref(&self) -> &Self::Target {
        Deref::deref(&self.state)
    }
}

impl DerefMut for InternalStateCell {
    fn deref_mut(&mut self) -> &mut Self::Target {
        Rc::get_mut(&mut self.state).expect("failed to get mutable")
    }
}

/// The derived version would print 'InternalStateCell { state: ... }', this custom implementation
/// only prints the actual internal state.
impl Debug for InternalStateCell {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Debug::fmt(&self.state, f)
    }
}

impl InternalStateCell {
    /// Create new `InternalStateCell` from a value.
    pub fn new<T: Any + InternalState>(value: T) -> Self {
        Self {
            state: Rc::new(value),
        }
    }
    /// Get a reference to the stored value and cast it to `T`.
    pub fn downcast_ref<T: Any + InternalState>(&self) -> Option<&T> {
        self.deref().downcast_ref::<T>()
    }
    /// Get a mutable reference to the stored value and cast it to `T`.
    pub fn downcast_mut<T: Any + InternalState>(&mut self) -> Option<&mut T> {
        self.deref_mut().downcast_mut::<T>()
    }
}

/// This trait must be implemented by all structs used for internal state.
pub trait InternalState: Debug {}