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
|
//! ref: composer/src/Composer/Json/JsonFormatter.php
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_php_shim::{PhpMixed, function_exists, mb_convert_encoding, pack};
pub struct JsonFormatter;
impl JsonFormatter {
/**
* This code is based on the function found at:
* http://recursive-design.com/blog/2008/03/11/format-json-with-php/
*
* Originally licensed under MIT by Dave Perrett <mail@recursive-design.com>
*/
pub fn format(json: String, unescape_unicode: bool, unescape_slashes: bool) -> String {
let mut result = String::new();
let mut pos: usize = 0;
let indent_str = " ";
let new_line = "\n";
let mut out_of_quotes = true;
let mut buffer = String::new();
let mut noescape = true;
let chars: Vec<char> = json.chars().collect();
let str_len = chars.len();
for i in 0..str_len {
let char_ = chars[i];
if char_ == '"' && noescape {
out_of_quotes = !out_of_quotes;
}
if !out_of_quotes {
buffer.push(char_);
noescape = if char_ == '\\' { !noescape } else { true };
continue;
}
if !buffer.is_empty() {
if unescape_slashes {
buffer = buffer.replace("\\/", "/");
}
if unescape_unicode && function_exists("mb_convert_encoding") {
buffer = Preg::replace_callback(
r"/(\\+)u([0-9a-f]{4})/i",
|matches: &indexmap::IndexMap<CaptureKey, String>| -> String {
let m0 = matches
.get(&CaptureKey::ByIndex(0))
.cloned()
.unwrap_or_default();
let m1 = matches
.get(&CaptureKey::ByIndex(1))
.cloned()
.unwrap_or_default();
let m2 = matches
.get(&CaptureKey::ByIndex(2))
.cloned()
.unwrap_or_default();
let l = m1.len();
if l % 2 != 0 {
let code = i64::from_str_radix(&m2, 16).unwrap_or(0);
if code >= 0xD800 && code <= 0xDFFF {
return m0;
}
return "\\".repeat(l - 1)
+ &mb_convert_encoding(
pack("H*", &[PhpMixed::String(m2)]),
"UTF-8",
"UCS-2BE",
);
}
m0
},
&buffer,
)
.unwrap_or(buffer);
}
result.push_str(&buffer);
result.push(char_);
buffer = String::new();
continue;
}
let mut char_str = char_.to_string();
if char_ == ':' {
char_str.push(' ');
} else if char_ == '}' || char_ == ']' {
pos -= 1;
let prev_char = if i > 0 { chars[i - 1] } else { '\0' };
if prev_char != '{' && prev_char != '[' {
result.push_str(new_line);
result.push_str(&indent_str.repeat(pos));
} else {
result = result.trim_end().to_string();
}
}
result.push_str(&char_str);
if char_ == ',' || char_ == '{' || char_ == '[' {
result.push_str(new_line);
if char_ == '{' || char_ == '[' {
pos += 1;
}
result.push_str(&indent_str.repeat(pos));
}
}
result
}
}
|