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
use serde::Serialize;
use serde_json::value::{to_value, Value as Json};
#[derive(Debug)]
pub enum ScopedJson<'reg: 'rc, 'rc> {
Constant(&'reg Json),
Derived(Json),
Context(&'rc Json),
}
impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc> {
pub fn as_json(&self) -> &Json {
match self {
ScopedJson::Constant(j) => j,
ScopedJson::Derived(ref j) => j,
ScopedJson::Context(j) => j,
}
}
pub fn render(&self) -> String {
self.as_json().render()
}
}
impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
fn from(v: Json) -> ScopedJson<'reg, 'rc> {
ScopedJson::Derived(v)
}
}
#[derive(Debug)]
pub struct PathAndJson<'reg: 'rc, 'rc> {
path: Option<String>,
value: ScopedJson<'reg, 'rc>,
}
impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
pub fn new(path: Option<String>, value: ScopedJson<'reg, 'rc>) -> PathAndJson<'reg, 'rc> {
PathAndJson { path, value }
}
pub fn path(&self) -> Option<&String> {
self.path.as_ref()
}
pub fn path_root(&self) -> Option<&str> {
self.path
.as_ref()
.and_then(|p| p.split(|c| c == '.' || c == '/').nth(0))
}
pub fn value(&self) -> &Json {
self.value.as_json()
}
}
pub trait JsonRender {
fn render(&self) -> String;
}
pub trait JsonTruthy {
fn is_truthy(&self) -> bool;
}
impl JsonRender for Json {
fn render(&self) -> String {
match *self {
Json::String(ref s) => s.to_string(),
Json::Bool(i) => i.to_string(),
Json::Number(ref n) => n.to_string(),
Json::Null => "".to_owned(),
Json::Array(ref a) => {
let mut buf = String::new();
buf.push('[');
for i in a.iter() {
buf.push_str(i.render().as_ref());
buf.push_str(", ");
}
buf.push(']');
buf
}
Json::Object(_) => "[object]".to_owned(),
}
}
}
pub fn to_json<T>(src: &T) -> Json
where
T: Serialize,
{
to_value(src).unwrap_or_default()
}
pub fn as_string(src: &Json) -> Option<&str> {
src.as_str()
}
impl JsonTruthy for Json {
fn is_truthy(&self) -> bool {
match *self {
Json::Bool(ref i) => *i,
Json::Number(ref n) => n.as_f64().map(|f| f.is_normal()).unwrap_or(false),
Json::Null => false,
Json::String(ref i) => i.len() > 0,
Json::Array(ref i) => i.len() > 0,
Json::Object(ref i) => i.len() > 0,
}
}
}
#[test]
fn test_json_render() {
let raw = "<p>Hello world</p>\n<p thing=\"hello\"</p>";
let thing = Json::String(raw.to_string());
assert_eq!(raw, thing.render());
}