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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::any::Any;
use std::boxed::Box;
use std::marker::Send;

use super::super::SpanReference;


/// TODO
pub trait ImplContext : Send {
    /// TODO
    fn impl_context(&self) -> &Any;

    /// TODO
    fn clone(&self) -> Box<ImplContext>;

    /// TODO
    fn reference_span(&mut self, _reference: &SpanReference);
}


/// TODO
pub struct ImplWrapper<T: Any + Clone + Send> {
    inner: T
}

impl<T: Any + Clone + Send> ImplWrapper<T> {
    /// TODO
    pub fn new(inner: T) -> ImplWrapper<T> {
        ImplWrapper { inner }
    }
}

impl<T: Any + Clone + Send + SpanReferenceAware> ImplContext for ImplWrapper<T> {
    fn impl_context(&self) -> &Any {
        &self.inner
    }

    fn clone(&self) -> Box<ImplContext> {
        Box::new(ImplWrapper {
            inner: self.inner.clone()
        })
    }

    fn reference_span(&mut self, reference: &SpanReference) {
        self.inner.reference_span(reference);
    }
}


/// TODO
pub trait SpanReferenceAware {
    /// TODO
    fn reference_span(&mut self, _reference: &SpanReference);
}


#[cfg(test)]
mod tests {
    use super::super::super::SpanReference;
    use super::ImplContext;
    use super::ImplWrapper;
    use super::SpanReferenceAware;

    #[derive(Debug, Clone)]
    struct TestContext {
        pub id: String
    }
    impl SpanReferenceAware for TestContext {
        fn reference_span(&mut self, _: &SpanReference) {}
    }

    #[test]
    fn clone_context() {
        let clone = {
            let context = ImplWrapper::new(TestContext {
                id: "ABC".to_owned()
            });
            context.clone()
        };
        let inner = clone.impl_context();
        if let Some(inner) = inner.downcast_ref::<TestContext>() {
            assert_eq!(inner.id, "ABC");
        } else {
            panic!("Failed to downcast inner context");
        }
    }

    #[test]
    fn unwrap_context() {
        let context = ImplWrapper::new(TestContext { id: "ABC".to_owned() });
        let inner = context.impl_context();
        if let Some(inner) = inner.downcast_ref::<TestContext>() {
            assert_eq!(inner.id, "ABC");
        } else {
            panic!("Failed to downcast inner context");
        }
    }
}