1// Copyright (c) 2023 Huawei Device Co., Ltd. 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14use crate::{consts::*, Array, Error, JsonValue, Number, Object}; 15#[cfg(feature = "c_adapter")] 16use std::ffi::CString; 17use std::io::Write; 18 19// todo: Considers extracting Encoder traits. 20 21/// JSON encoder with additional formats, used to output JsonValue instances in JSON format to the specified location. 22/// 23/// This encoder will add additional formatting control whitespace characters during encoding. 24pub(crate) struct FormattedEncoder<'a, W: Write> { 25 output: &'a mut W, 26 /// The current number of nested layers 27 tab: usize, 28} 29 30impl<'a, W: Write> FormattedEncoder<'a, W> { 31 /// Creates 32 pub(crate) fn new(output: &'a mut W) -> Self { 33 Self { output, tab: 0 } 34 } 35 36 /// Encodes 37 pub(crate) fn encode(&mut self, value: &JsonValue) -> Result<(), Error> { 38 self.encode_value(value)?; 39 self.output.write_all(LINE_FEED_STR)?; 40 Ok(()) 41 } 42 43 /// Encodes JsonValue 44 fn encode_value(&mut self, value: &JsonValue) -> Result<(), Error> { 45 match value { 46 JsonValue::Null => self.encode_null(), 47 JsonValue::Boolean(boolean) => self.encode_boolean(boolean), 48 JsonValue::Number(number) => self.encode_number(number), 49 JsonValue::String(string) => self.encode_string(string), 50 JsonValue::Array(array) => self.encode_array(array), 51 JsonValue::Object(object) => self.encode_object(object), 52 } 53 } 54 55 /// Add tabs to improve readability. 56 fn add_tab(&mut self) -> Result<(), Error> { 57 for _ in 0..self.tab { 58 self.output.write_all(FOUR_SPACES_STR)?; 59 } 60 Ok(()) 61 } 62 63 /// Encodes Null 64 fn encode_null(&mut self) -> Result<(), Error> { 65 encode_null(self.output) 66 } 67 68 /// Encodes Boolean 69 fn encode_boolean(&mut self, boolean: &bool) -> Result<(), Error> { 70 encode_boolean(self.output, *boolean) 71 } 72 73 /// Encodes Number 74 fn encode_number(&mut self, number: &Number) -> Result<(), Error> { 75 encode_number(self.output, number) 76 } 77 78 /// Encodes Key 79 fn encode_key(&mut self, key: &str) -> Result<(), Error> { 80 encode_string(self.output, key) 81 } 82 83 /// Encodes String 84 #[cfg(feature = "c_adapter")] 85 fn encode_string(&mut self, string: &CString) -> Result<(), Error> { 86 encode_string(self.output, unsafe { 87 core::str::from_utf8_unchecked(string.as_bytes()) 88 }) 89 } 90 91 /// Encodes String 92 #[cfg(not(feature = "c_adapter"))] 93 fn encode_string(&mut self, string: &str) -> Result<(), Error> { 94 encode_string(self.output, string) 95 } 96 97 /// Encodes Array 98 fn encode_array(&mut self, array: &Array) -> Result<(), Error> { 99 // Check whether multiple lines are required. If array or object 100 // exists in the array value, multiple lines are required. 101 let mut multiple_line = false; 102 for v in array.iter() { 103 if v.is_array() | v.is_object() { 104 multiple_line = true; 105 break; 106 } 107 } 108 109 self.output.write_all(LEFT_SQUARE_BRACKET_STR)?; 110 if multiple_line { 111 self.output.write_all(LINE_FEED_STR)?; 112 self.tab += 1; 113 self.add_tab()?; 114 for (n, v) in array.iter().enumerate() { 115 if n != 0 { 116 self.output.write_all(COMMA_STR)?; 117 self.output.write_all(LINE_FEED_STR)?; 118 self.add_tab()?; 119 } 120 self.encode_value(v)?; 121 } 122 self.output.write_all(LINE_FEED_STR)?; 123 self.tab -= 1; 124 self.add_tab()?; 125 } else { 126 for (n, v) in array.iter().enumerate() { 127 if n != 0 { 128 self.output.write_all(COMMA_STR)?; 129 self.output.write_all(SPACE_STR)?; 130 } 131 self.encode_value(v)?; 132 } 133 } 134 self.output.write_all(RIGHT_SQUARE_BRACKET_STR)?; 135 Ok(()) 136 } 137 138 /// Encodes Object 139 fn encode_object(&mut self, object: &Object) -> Result<(), Error> { 140 self.output.write_all(LEFT_CURLY_BRACKET_STR)?; 141 self.tab += 1; 142 for (u, (k, v)) in object.iter().enumerate() { 143 if u != 0 { 144 self.output.write_all(COMMA_STR)?; 145 } 146 self.output.write_all(LINE_FEED_STR)?; 147 self.add_tab()?; 148 self.encode_key(k)?; 149 self.output.write_all(COLON_STR)?; 150 self.output.write_all(SPACE_STR)?; 151 self.encode_value(v)?; 152 } 153 self.tab -= 1; 154 // Non-empty objects require additional newlines and tabs. 155 if !object.is_empty() { 156 self.output.write_all(LINE_FEED_STR)?; 157 self.add_tab()?; 158 } 159 self.output.write_all(RIGHT_CURLY_BRACKET_STR)?; 160 Ok(()) 161 } 162} 163 164/// JSON encoder that outputs no extra whitespace characters , 165/// used to output a JsonValue instance in JSON format to a specified location. 166pub(crate) struct CompactEncoder<'a, W: Write> { 167 output: &'a mut W, 168} 169 170impl<'a, W: Write> CompactEncoder<'a, W> { 171 /// Creates 172 pub(crate) fn new(output: &'a mut W) -> Self { 173 Self { output } 174 } 175 176 /// Encodes 177 pub(crate) fn encode(&mut self, value: &JsonValue) -> Result<(), Error> { 178 self.encode_value(value) 179 } 180 181 /// Encodes JsonValue 182 fn encode_value(&mut self, value: &JsonValue) -> Result<(), Error> { 183 match value { 184 JsonValue::Null => self.encode_null(), 185 JsonValue::Boolean(boolean) => self.encode_boolean(boolean), 186 JsonValue::Number(number) => self.encode_number(number), 187 JsonValue::String(string) => self.encode_string(string), 188 JsonValue::Array(array) => self.encode_array(array), 189 JsonValue::Object(object) => self.encode_object(object), 190 } 191 } 192 193 /// Encodes Null 194 fn encode_null(&mut self) -> Result<(), Error> { 195 encode_null(self.output) 196 } 197 198 /// Encodes Boolean 199 fn encode_boolean(&mut self, boolean: &bool) -> Result<(), Error> { 200 encode_boolean(self.output, *boolean) 201 } 202 203 /// Encodes Number 204 fn encode_number(&mut self, number: &Number) -> Result<(), Error> { 205 encode_number(self.output, number) 206 } 207 208 /// Encodes Key 209 fn encode_key(&mut self, key: &str) -> Result<(), Error> { 210 encode_string(self.output, key) 211 } 212 213 /// Encodes String 214 #[cfg(feature = "c_adapter")] 215 fn encode_string(&mut self, string: &CString) -> Result<(), Error> { 216 encode_string(self.output, unsafe { 217 std::str::from_utf8_unchecked(string.as_bytes()) 218 }) 219 } 220 221 /// Encodes String 222 #[cfg(not(feature = "c_adapter"))] 223 fn encode_string(&mut self, string: &str) -> Result<(), Error> { 224 encode_string(self.output, string) 225 } 226 227 /// Encodes Array 228 fn encode_array(&mut self, array: &Array) -> Result<(), Error> { 229 self.output.write_all(LEFT_SQUARE_BRACKET_STR)?; 230 for (n, v) in array.iter().enumerate() { 231 if n != 0 { 232 self.output.write_all(COMMA_STR)?; 233 } 234 self.encode_value(v)?; 235 } 236 self.output.write_all(RIGHT_SQUARE_BRACKET_STR)?; 237 Ok(()) 238 } 239 240 /// Encodes Object 241 fn encode_object(&mut self, object: &Object) -> Result<(), Error> { 242 self.output.write_all(LEFT_CURLY_BRACKET_STR)?; 243 for (u, (k, v)) in object.iter().enumerate() { 244 if u != 0 { 245 self.output.write_all(COMMA_STR)?; 246 } 247 self.encode_key(k)?; 248 self.output.write_all(COLON_STR)?; 249 self.encode_value(v)?; 250 } 251 self.output.write_all(RIGHT_CURLY_BRACKET_STR)?; 252 Ok(()) 253 } 254} 255 256#[inline] 257fn encode_null(writer: &mut dyn Write) -> Result<(), Error> { 258 writer.write_all(NULL_STR)?; 259 Ok(()) 260} 261 262#[inline] 263fn encode_boolean(writer: &mut dyn Write, boolean: bool) -> Result<(), Error> { 264 if boolean { 265 writer.write_all(TRUE_STR)?; 266 } else { 267 writer.write_all(FALSE_STR)?; 268 } 269 Ok(()) 270} 271 272#[inline] 273pub(crate) fn encode_number(writer: &mut dyn Write, number: &Number) -> Result<(), Error> { 274 write!(writer, "{number}")?; 275 Ok(()) 276} 277 278#[inline] 279fn encode_string(writer: &mut dyn Write, string: &str) -> Result<(), Error> { 280 writer.write_all(QUOTATION_MARK_STR)?; 281 encode_string_inner(writer, string)?; 282 writer.write_all(QUOTATION_MARK_STR)?; 283 Ok(()) 284} 285 286#[cfg(feature = "ascii_only")] 287pub(crate) fn encode_string_inner(writer: &mut dyn Write, string: &str) -> Result<(), Error> { 288 let bytes = string.as_bytes(); 289 let len = bytes.len(); 290 let mut start = 0usize; 291 292 for i in 0..len { 293 let ch = &bytes[i]; 294 if ESCAPE[(*ch) as usize] { 295 writer.write_all(&bytes[start..i])?; 296 start = i + 1; 297 298 match *ch { 299 REVERSE_SOLIDUS => writer.write_all(JSON_REVERSE_SOLIDUS)?, 300 QUOTATION_MARK => writer.write_all(JSON_QUOTATION_MARK)?, 301 BS_UNICODE_U8 => writer.write_all(JSON_BS)?, 302 FF_UNICODE_U8 => writer.write_all(JSON_FF)?, 303 LF_UNICODE_U8 => writer.write_all(JSON_LF)?, 304 CR_UNICODE_U8 => writer.write_all(JSON_CR)?, 305 HT_UNICODE_U8 => writer.write_all(JSON_HT)?, 306 x => write!(writer, "\\u{number:0>width$x}", number = x, width = 4)?, 307 } 308 } 309 } 310 if start != len { 311 writer.write_all(&bytes[start..len])?; 312 } 313 314 Ok(()) 315} 316 317#[cfg(not(feature = "ascii_only"))] 318pub(crate) fn encode_string_inner(writer: &mut dyn Write, string: &str) -> Result<(), Error> { 319 fn split_pattern( 320 writer: &mut dyn Write, 321 pattern: &mut &str, 322 split_pos: &mut usize, 323 ch: char, 324 ) -> Result<(), Error> { 325 let (l, r) = (*pattern).split_at(*split_pos); 326 writer.write_all(l.as_bytes())?; 327 *pattern = r; 328 329 let (_, r) = (*pattern).split_at(ch.len_utf8()); 330 *pattern = r; 331 *split_pos = 0; 332 Ok(()) 333 } 334 335 let mut pattern = string; 336 let mut split_pos = 0usize; 337 for ch in string.chars() { 338 if ch.is_ascii() { 339 match PRINT_MAP[ch as usize] { 340 PrintMapItem::Other => { 341 split_pos += 1; 342 continue; 343 } 344 PrintMapItem::Special(x) => { 345 split_pattern(writer, &mut pattern, &mut split_pos, ch)?; 346 writer.write_all(x)?; 347 } 348 PrintMapItem::Control => { 349 split_pattern(writer, &mut pattern, &mut split_pos, ch)?; 350 let bytes = ch as u32; 351 write!(writer, "\\u{number:0>width$x}", number = bytes, width = 4)?; 352 } 353 } 354 continue; 355 } 356 split_pattern(writer, &mut pattern, &mut split_pos, ch)?; 357 let bytes = ch as u32; 358 write!(writer, "\\u{number:0>width$x}", number = bytes, width = 4)?; 359 } 360 if split_pos != 0 { 361 writer.write_all(pattern.as_bytes())?; 362 } 363 Ok(()) 364} 365 366#[cfg(test)] 367mod ut_encoder { 368 use crate::{CompactEncoder, FormattedEncoder, JsonValue}; 369 use std::io::Write; 370 371 struct StringWriter { 372 string: String, 373 } 374 375 impl StringWriter { 376 fn new() -> Self { 377 Self { 378 string: String::new(), 379 } 380 } 381 } 382 383 impl Write for StringWriter { 384 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { 385 self.string 386 .push_str(unsafe { std::str::from_utf8_unchecked(buf) }); 387 self.flush()?; 388 Ok(buf.len()) 389 } 390 391 fn flush(&mut self) -> std::io::Result<()> { 392 Ok(()) 393 } 394 } 395 396 macro_rules! encoder_test_case { 397 ($encoder: ident, $input: expr, $output: expr $(,)?) => { 398 let value = JsonValue::from_text($input).unwrap(); 399 let mut writer = StringWriter::new(); 400 let mut encoder = $encoder::new(&mut writer); 401 assert!(encoder.encode(&value).is_ok()); 402 assert_eq!(writer.string, $output); 403 }; 404 } 405 406 /// UT test for `FormattedEncoder`. 407 /// 408 /// # Title 409 /// ut_formatted_encoder 410 /// 411 /// # Brief 412 /// 1. Creates a `JsonValue` called `json_value`. 413 /// 2. Creates a `FormattedEncoder` called `encoder`. 414 /// 3. Uses `encoder` to encode `json_value`. 415 /// 4. Checks if the results are correct. 416 #[test] 417 fn ut_formatted_encoder() { 418 encoder_test_case!( 419 FormattedEncoder, 420 "{\"null\":null}", 421 "{\n \"null\": null\n}\n", 422 ); 423 424 encoder_test_case!( 425 FormattedEncoder, 426 "{\"true\":true}", 427 "{\n \"true\": true\n}\n", 428 ); 429 430 encoder_test_case!( 431 FormattedEncoder, 432 "{\"false\":false}", 433 "{\n \"false\": false\n}\n", 434 ); 435 436 encoder_test_case!( 437 FormattedEncoder, 438 "{\"number\":3.14}", 439 "{\n \"number\": 3.14\n}\n", 440 ); 441 442 encoder_test_case!( 443 FormattedEncoder, 444 "{\"string\":\"HelloWorld\"}", 445 "{\n \"string\": \"HelloWorld\"\n}\n", 446 ); 447 448 encoder_test_case!( 449 FormattedEncoder, 450 "{\"array\":[1, 2, 3]}", 451 "{\n \"array\": [1, 2, 3]\n}\n", 452 ); 453 454 encoder_test_case!( 455 FormattedEncoder, 456 "{\"object\":{\"key1\":1}}", 457 "{\n \"object\": {\n \"key1\": 1\n }\n}\n", 458 ); 459 } 460 461 /// UT test for `CompactEncoder`. 462 /// 463 /// # Title 464 /// ut_compact_encoder 465 /// 466 /// # Brief 467 /// 1. Creates a `JsonValue` called `json_value`. 468 /// 2. Creates a `Compact` called `encoder`. 469 /// 3. Uses `encoder` to encode `json_value`. 470 /// 4. Checks if the results are correct. 471 #[test] 472 fn ut_compact_encoder() { 473 encoder_test_case!(CompactEncoder, "{\"null\":null}", "{\"null\":null}",); 474 475 encoder_test_case!(CompactEncoder, "{\"true\":true}", "{\"true\":true}",); 476 477 encoder_test_case!(CompactEncoder, "{\"false\":false}", "{\"false\":false}",); 478 479 encoder_test_case!(CompactEncoder, "{\"number\":3.14}", "{\"number\":3.14}",); 480 481 encoder_test_case!( 482 CompactEncoder, 483 "{\"string\":\"HelloWorld\"}", 484 "{\"string\":\"HelloWorld\"}", 485 ); 486 487 #[cfg(not(feature = "ascii_only"))] 488 encoder_test_case!( 489 CompactEncoder, 490 "{\"string\":\"\\b\\t\\f\\n\\u0000\\u2764\"}", 491 "{\"string\":\"\\b\\t\\f\\n\\u0000\\u2764\"}", 492 ); 493 494 #[cfg(feature = "ascii_only")] 495 encoder_test_case!( 496 CompactEncoder, 497 "{\"string\":\"\\b\\t\\f\\n\\u0000\\u2764\"}", 498 "{\"string\":\"\\b\\t\\f\\n\\u0000\u{2764}\"}", 499 ); 500 501 encoder_test_case!(CompactEncoder, "{\"array\":[1,2,3]}", "{\"array\":[1,2,3]}",); 502 503 encoder_test_case!( 504 CompactEncoder, 505 "{\"object\":{\"key1\":1,\"key2\":2}}", 506 "{\"object\":{\"key1\":1,\"key2\":2}}", 507 ); 508 } 509} 510