Skip to content

Commit 1d5c442

Browse files
authored
Merge pull request #18 from b41sh/fix-string-display
Fix: Fix some special characters display errors
2 parents 5b0e20e + 1838d34 commit 1d5c442

File tree

4 files changed

+47
-17
lines changed

4 files changed

+47
-17
lines changed

src/functions.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -871,10 +871,7 @@ fn container_to_string(value: &[u8], offset: &mut usize, json: &mut String) {
871871
let jentry_encoded = read_u32(value, jentry_offset).unwrap();
872872
let jentry = JEntry::decode_jentry(jentry_encoded);
873873
let key_length = jentry.length as usize;
874-
let key = unsafe {
875-
std::str::from_utf8_unchecked(&value[key_offset..key_offset + key_length])
876-
};
877-
keys.push_back(key);
874+
keys.push_back((key_offset, key_offset + key_length));
878875
jentry_offset += 4;
879876
key_offset += key_length;
880877
}
@@ -883,8 +880,8 @@ fn container_to_string(value: &[u8], offset: &mut usize, json: &mut String) {
883880
if i > 0 {
884881
json.push(',');
885882
}
886-
let key = keys.pop_front().unwrap();
887-
json.extend(format!("{:?}", key).chars());
883+
let (key_start, key_end) = keys.pop_front().unwrap();
884+
escape_scalar_string(value, key_start, key_end, json);
888885
json.push(':');
889886
scalar_to_string(value, &mut jentry_offset, &mut value_offset, json);
890887
}
@@ -912,10 +909,7 @@ fn scalar_to_string(
912909
json.push_str(&format!("{num}"));
913910
}
914911
STRING_TAG => {
915-
let val = unsafe {
916-
std::str::from_utf8_unchecked(&value[*value_offset..*value_offset + length])
917-
};
918-
json.extend(format!("{:?}", val).chars());
912+
escape_scalar_string(value, *value_offset, *value_offset + length, json);
919913
}
920914
CONTAINER_TAG => {
921915
container_to_string(value, value_offset, json);
@@ -926,6 +920,38 @@ fn scalar_to_string(
926920
*value_offset += length;
927921
}
928922

923+
fn escape_scalar_string(value: &[u8], start: usize, end: usize, json: &mut String) {
924+
json.push('\"');
925+
let mut last_start = start;
926+
for i in start..end {
927+
// add backslash for escaped characters.
928+
let c = match value[i] {
929+
0x5C => "\\\\",
930+
0x22 => "\\\"",
931+
0x2F => "\\/",
932+
0x08 => "\\b",
933+
0x0C => "\\f",
934+
0x0A => "\\n",
935+
0x0D => "\\r",
936+
0x09 => "\\t",
937+
_ => {
938+
continue;
939+
}
940+
};
941+
if i > last_start {
942+
let val = unsafe { std::str::from_utf8_unchecked(&value[last_start..i]) };
943+
json.push_str(val);
944+
}
945+
json.push_str(c);
946+
last_start = i + 1;
947+
}
948+
if last_start < end {
949+
let val = unsafe { std::str::from_utf8_unchecked(&value[last_start..end]) };
950+
json.push_str(val);
951+
}
952+
json.push('\"');
953+
}
954+
929955
// Check whether the value is `JSONB` format,
930956
// for compatibility with previous `JSON` string.
931957
fn is_jsonb(value: &[u8]) -> bool {

src/util.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ pub fn parse_escaped_string<'a>(
6565
data = &data[1..];
6666
data.read_exact(numbers.as_mut_slice())?;
6767
if data[0] != b'}' {
68-
return Err(Error::Syntax(ParseErrorCode::UnexpectedEndOfHexEscape, *idx));
68+
return Err(Error::Syntax(
69+
ParseErrorCode::UnexpectedEndOfHexEscape,
70+
*idx,
71+
));
6972
}
7073
data = &data[1..];
7174
*idx += 6;
@@ -102,7 +105,10 @@ pub fn parse_escaped_string<'a>(
102105
data = &data[1..];
103106
data.read_exact(lower_numbers.as_mut_slice())?;
104107
if data[0] != b'}' {
105-
return Err(Error::Syntax(ParseErrorCode::UnexpectedEndOfHexEscape, *idx));
108+
return Err(Error::Syntax(
109+
ParseErrorCode::UnexpectedEndOfHexEscape,
110+
*idx,
111+
));
106112
}
107113
data = &data[1..];
108114
*idx += 6;

tests/it/functions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ fn test_to_string() {
662662
(r#"123.4567"#, r#"123.4567"#),
663663
(r#""abcdef""#, r#""abcdef""#),
664664
(r#""ab\n\"\uD83D\uDC8E测试""#, r#""ab\n\"💎测试""#),
665+
(r#""မြန်မာဘာသာ""#, r#""မြန်မာဘာသာ""#),
666+
(r#""⚠️✅❌""#, r#""⚠️✅❌""#),
665667
(r#"[1,2,3,4]"#, r#"[1,2,3,4]"#),
666668
(
667669
r#"["a","b",true,false,[1,2,3],{"a":"b"}]"#,
@@ -675,7 +677,6 @@ fn test_to_string() {
675677
let mut buf: Vec<u8> = Vec::new();
676678
for (s, expect) in sources {
677679
let value = parse_value(s.as_bytes()).unwrap();
678-
assert_eq!(format!("{}", value), expect);
679680
value.write_to_vec(&mut buf);
680681
let res = to_string(&buf);
681682
assert_eq!(res, expect);

tests/it/parser.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,7 @@ fn test_parse_string() {
310310
r#""\"ab\"\uD803\uDC0B测试""#,
311311
Value::String(Cow::from("\"ab\"𐰋测试")),
312312
),
313-
(
314-
r#""⚠\u{fe0f}""#,
315-
Value::String(Cow::from("⚠\u{fe0f}")),
316-
),
313+
(r#""⚠\u{fe0f}""#, Value::String(Cow::from("⚠\u{fe0f}"))),
317314
]);
318315
}
319316

0 commit comments

Comments
 (0)