]> git.proxmox.com Git - rustc.git/blob - vendor/handlebars/src/json/value.rs
New upstream version 1.47.0~beta.2+dfsg1
[rustc.git] / vendor / handlebars / src / json / value.rs
1 use serde::Serialize;
2 use serde_json::value::{to_value, Value as Json};
3
4 pub(crate) static DEFAULT_VALUE: Json = Json::Null;
5
6 /// A JSON wrapper designed for handlebars internal use case
7 ///
8 /// * Constant: the JSON value hardcoded into template
9 /// * Context: the JSON value referenced in your provided data context
10 /// * Derived: the owned JSON value computed during rendering process
11 ///
12 #[derive(Debug)]
13 pub enum ScopedJson<'reg: 'rc, 'rc> {
14 Constant(&'reg Json),
15 Derived(Json),
16 // represents a json reference to context value, its full path
17 Context(&'rc Json, Vec<String>),
18 Missing,
19 }
20
21 impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc> {
22 /// get the JSON reference
23 pub fn as_json(&self) -> &Json {
24 match self {
25 ScopedJson::Constant(j) => j,
26 ScopedJson::Derived(ref j) => j,
27 ScopedJson::Context(j, _) => j,
28 _ => &DEFAULT_VALUE,
29 }
30 }
31
32 pub fn render(&self) -> String {
33 self.as_json().render()
34 }
35
36 pub fn is_missing(&self) -> bool {
37 match self {
38 ScopedJson::Missing => true,
39 _ => false,
40 }
41 }
42
43 pub fn into_derived(self) -> ScopedJson<'reg, 'rc> {
44 let v = self.as_json();
45 ScopedJson::Derived(v.clone())
46 }
47
48 pub fn context_path(&self) -> Option<&Vec<String>> {
49 match self {
50 ScopedJson::Context(_, ref p) => Some(p),
51 _ => None,
52 }
53 }
54 }
55
56 impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
57 fn from(v: Json) -> ScopedJson<'reg, 'rc> {
58 ScopedJson::Derived(v)
59 }
60 }
61
62 /// Json wrapper that holds the Json value and reference path information
63 ///
64 #[derive(Debug)]
65 pub struct PathAndJson<'reg, 'rc> {
66 relative_path: Option<String>,
67 value: ScopedJson<'reg, 'rc>,
68 }
69
70 impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
71 pub fn new(
72 relative_path: Option<String>,
73 value: ScopedJson<'reg, 'rc>,
74 ) -> PathAndJson<'reg, 'rc> {
75 PathAndJson {
76 relative_path,
77 value,
78 }
79 }
80
81 /// Returns relative path when the value is referenced
82 /// If the value is from a literal, the path is `None`
83 pub fn relative_path(&self) -> Option<&String> {
84 self.relative_path.as_ref()
85 }
86
87 /// Returns full path to this value if any
88 pub fn context_path(&self) -> Option<&Vec<String>> {
89 self.value.context_path()
90 }
91
92 /// Returns the value
93 pub fn value(&self) -> &Json {
94 self.value.as_json()
95 }
96
97 /// Test if value is missing
98 pub fn is_value_missing(&self) -> bool {
99 self.value.is_missing()
100 }
101
102 pub fn render(&self) -> String {
103 self.value.render()
104 }
105 }
106
107 /// Render Json data with default format
108 pub trait JsonRender {
109 fn render(&self) -> String;
110 }
111
112 pub trait JsonTruthy {
113 fn is_truthy(&self, include_zero: bool) -> bool;
114 }
115
116 impl JsonRender for Json {
117 fn render(&self) -> String {
118 match *self {
119 Json::String(ref s) => s.to_string(),
120 Json::Bool(i) => i.to_string(),
121 Json::Number(ref n) => n.to_string(),
122 Json::Null => "".to_owned(),
123 Json::Array(ref a) => {
124 let mut buf = String::new();
125 buf.push('[');
126 for i in a.iter() {
127 buf.push_str(i.render().as_ref());
128 buf.push_str(", ");
129 }
130 buf.push(']');
131 buf
132 }
133 Json::Object(_) => "[object]".to_owned(),
134 }
135 }
136 }
137
138 /// Convert any serializable data into Serde Json type
139 pub fn to_json<T>(src: T) -> Json
140 where
141 T: Serialize,
142 {
143 to_value(src).unwrap_or_default()
144 }
145
146 pub fn as_string(src: &Json) -> Option<&str> {
147 src.as_str()
148 }
149
150 impl JsonTruthy for Json {
151 fn is_truthy(&self, include_zero: bool) -> bool {
152 match *self {
153 Json::Bool(ref i) => *i,
154 Json::Number(ref n) => {
155 if include_zero {
156 n.as_f64().map(|f| !f.is_nan()).unwrap_or(false)
157 } else {
158 // there is no inifity in json/serde_json
159 n.as_f64().map(|f| f.is_normal()).unwrap_or(false)
160 }
161 }
162 Json::Null => false,
163 Json::String(ref i) => !i.is_empty(),
164 Json::Array(ref i) => !i.is_empty(),
165 Json::Object(ref i) => !i.is_empty(),
166 }
167 }
168 }
169
170 #[test]
171 fn test_json_render() {
172 let raw = "<p>Hello world</p>\n<p thing=\"hello\"</p>";
173 let thing = Json::String(raw.to_string());
174
175 assert_eq!(raw, thing.render());
176 }
177
178 #[test]
179 fn test_json_number_truthy() {
180 use std::f64;
181 assert!(json!(16i16).is_truthy(false));
182 assert!(json!(16i16).is_truthy(true));
183
184 assert!(json!(0i16).is_truthy(true));
185 assert!(!json!(0i16).is_truthy(false));
186
187 assert!(json!(1.0f64).is_truthy(false));
188 assert!(json!(1.0f64).is_truthy(true));
189
190 assert!(json!(Some(16i16)).is_truthy(false));
191 assert!(json!(Some(16i16)).is_truthy(true));
192
193 assert!(!json!(None as Option<i16>).is_truthy(false));
194 assert!(!json!(None as Option<i16>).is_truthy(true));
195
196 assert!(!json!(f64::NAN).is_truthy(false));
197 assert!(!json!(f64::NAN).is_truthy(true));
198
199 // there is no infinity in json/serde_json
200 // assert!(json!(f64::INFINITY).is_truthy(false));
201 // assert!(json!(f64::INFINITY).is_truthy(true));
202
203 // assert!(json!(f64::NEG_INFINITY).is_truthy(false));
204 // assert!(json!(f64::NEG_INFINITY).is_truthy(true));
205 }