#![cfg(not(feature = "no_object"))]
use crate::parser::ParseState;
use crate::tokenizer::Token;
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
impl Engine {
#[inline]
pub fn parse_json(&self, json: impl AsRef<str>, has_null: bool) -> RhaiResultOf<Map> {
let scripts = [json.as_ref()];
let (stream, tokenizer_control) = self.lex_raw(
&scripts,
if has_null {
Some(&|token, _, _| {
match token {
Token::Reserved(s) if &*s == "null" => Token::Unit,
Token::LeftBrace => Token::MapStart,
t @ (Token::Unit | Token::MapStart) => Token::LexError(
LexError::ImproperSymbol(t.literal_syntax().to_string(), String::new())
.into(),
),
Token::InterpolatedString(..) => Token::LexError(
LexError::ImproperSymbol(
"interpolated string".to_string(),
String::new(),
)
.into(),
),
_ => token,
}
})
} else {
Some(&|token, _, _| {
match token {
Token::Reserved(s) if &*s == "null" => Token::LexError(
LexError::ImproperSymbol("null".to_string(), String::new()).into(),
),
Token::LeftBrace => Token::MapStart,
t @ (Token::Unit | Token::MapStart) => Token::LexError(
LexError::ImproperSymbol(
t.literal_syntax().to_string(),
"Invalid JSON syntax".to_string(),
)
.into(),
),
Token::InterpolatedString(..) => Token::LexError(
LexError::ImproperSymbol(
"interpolated string".to_string(),
"Invalid JSON syntax".to_string(),
)
.into(),
),
_ => token,
}
})
},
);
let scope = Scope::new();
let mut state = ParseState::new(self, &scope, Default::default(), tokenizer_control);
let ast = self.parse_global_expr(
&mut stream.peekable(),
&mut state,
#[cfg(not(feature = "no_optimize"))]
OptimizationLevel::None,
#[cfg(feature = "no_optimize")]
OptimizationLevel::default(),
)?;
self.eval_ast(&ast)
}
}
#[inline]
#[must_use]
pub fn format_map_as_json(map: &Map) -> String {
let mut result = String::from('{');
for (key, value) in map {
use std::fmt::Write;
if result.len() > 1 {
result.push(',');
}
write!(result, "{:?}", key).unwrap();
result.push(':');
if let Some(val) = value.read_lock::<Map>() {
result.push_str(&format_map_as_json(&*val));
continue;
}
if value.is::<()>() {
result.push_str("null");
} else {
write!(result, "{:?}", value).unwrap();
}
}
result.push('}');
result
}