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
use std::rc::Rc;
use std::mem::transmute;
use std::collections::HashMap;
use owning_ref::{ErasedRcRef, OwningRef, Erased};
use vars::{Variable, VarRef};
use render_error::DataError;
pub struct Context<'render> {
nothing: Rc<Erased+'render>,
vars: HashMap<&'render str, &'render (Variable<'render> + 'render)>,
}
pub enum Parent<'a, 'render: 'a> {
Root(&'a Context<'render>),
Sub(&'a SubContext<'a, 'render>),
}
pub struct SubContext<'a, 'render: 'a> {
parent: Parent<'a, 'render>,
local: HashMap<ErasedRcRef<str>, VarRef<'render>>,
}
impl<'render> Context<'render> {
pub fn new<'x>() -> Context<'x> {
Context {
nothing: Rc::new(()),
vars: HashMap::new(),
}
}
pub fn set<V>(&mut self, name: &'render str, var: &'render V)
where V: Variable<'render> + 'render
{
self.vars.insert(name, var);
}
}
impl<'a, 'render: 'a> SubContext<'a, 'render> {
pub fn from<'x>(parent: &'x Context<'render>) -> SubContext<'x, 'render> {
SubContext {
parent: Parent::Root(parent),
local: HashMap::new()
}
}
pub fn sub<'x>(&'x self) -> SubContext<'x, 'render> {
SubContext {
parent: Parent::Sub(self),
local: HashMap::new()
}
}
}
pub fn set<'x, 'render>(ctx: &mut SubContext<'x, 'render>,
name: ErasedRcRef<str>,
value: VarRef<'render>)
{
ctx.local.insert(name, value);
}
pub fn get<'x, 'render>(ctx: &SubContext<'x, 'render>, name: &str)
-> Result<VarRef<'render>, DataError>
{
if let Some(value) = ctx.local.get(name) {
return Ok(value.clone());
}
match ctx.parent {
Parent::Sub(ref parent) => get(parent, name),
Parent::Root(ref root) => {
if let Some(value) = root.vars.get(name) {
Ok(OwningRef::new(root.nothing.clone())
.map(|_| unsafe { transmute(*value) }))
} else {
Err(DataError::VariableNotFound(name.to_string()))
}
}
}
}