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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
extern crate futures;
extern crate tokio_timer;
use std::any::Any;
use std::rc::Rc;
use std::cell::RefCell;
use std::error::Error;
use std::fmt;
use std::time::Instant;
use futures::{Future, Poll};
mod with_value;
mod with_cancel;
mod with_deadline;
pub use with_value::{WithValue, with_value};
pub use with_cancel::{WithCancel, with_cancel};
pub use with_deadline::{WithDeadline, with_deadline, with_timeout};
pub struct Context(pub Rc<RefCell<Box<InnerContext<Item = (), Error = ContextError>>>>);
impl Context {
pub fn new<C: 'static + InnerContext>(ctx: C) -> Self {
Context(Rc::new(RefCell::new(Box::new(ctx))))
}
pub fn deadline(&self) -> Option<Instant> {
self.0.borrow().deadline()
}
pub fn value<T>(&self) -> Option<T>
where T: Any + Clone
{
let ctx = self.0.borrow();
ctx.value()
.and_then(|val_any| val_any.downcast_ref::<T>())
.map(|v| (*v).clone())
.or_else(|| ctx.parent().and_then(|parent| parent.value()))
}
}
impl Future for Context {
type Item = ();
type Error = ContextError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut inner = self.0.borrow_mut();
inner.poll()
}
}
impl Clone for Context {
fn clone(&self) -> Self {
Context(self.0.clone())
}
}
pub trait InnerContext: Future<Item = (), Error = ContextError> {
fn deadline(&self) -> Option<Instant> {
None
}
fn value(&self) -> Option<&Any> {
None
}
fn parent(&self) -> Option<Context> {
None
}
}
#[derive(Debug, PartialEq)]
pub enum ContextError {
Canceled,
DeadlineExceeded,
DeadlineTooLong,
}
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ContextError: {}", self.description())
}
}
impl Error for ContextError {
fn description(&self) -> &str {
match *self {
ContextError::Canceled => "context has been canceled",
ContextError::DeadlineExceeded => "deadline has been exceeded",
ContextError::DeadlineTooLong => "requested deadline too long",
}
}
}
mod background {
use {InnerContext, ContextError};
use futures::{Future, Poll, Async};
#[derive(Clone)]
pub struct Background {}
impl InnerContext for Background {}
impl Future for Background {
type Item = ();
type Error = ContextError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::NotReady)
}
}
}
pub fn background() -> Context {
Context::new(background::Background {})
}