Try to decode the given buffer and store the incomplete bytes. The logic was adapted from the [Node implementation]. [Node implementation]: https://github.com/nodejs/node/blob/ba06c5c509956dc413f91b755c1c93798bb700d4/src/string_decoder.cc#L66
(&mut self, ctx: &Ctx<'_>, mut data: &[u8])
| 27 | /// |
| 28 | /// [Node implementation]: https://github.com/nodejs/node/blob/ba06c5c509956dc413f91b755c1c93798bb700d4/src/string_decoder.cc#L66 |
| 29 | fn decode_data(&mut self, ctx: &Ctx<'_>, mut data: &[u8]) -> Result<String> { |
| 30 | let mut result = String::new(); |
| 31 | |
| 32 | if matches!( |
| 33 | self.encoder, |
| 34 | Encoder::Utf8 | Encoder::Utf16le | Encoder::Base64 |
| 35 | ) { |
| 36 | // See if we want bytes to finish a character from the previous |
| 37 | // chunk; if so, copy the new bytes to the missing bytes buffer |
| 38 | // and create a string from it that is to be prepended to the main body. |
| 39 | if self.missing_bytes > 0 { |
| 40 | if matches!(self.encoder, Encoder::Utf8) { |
| 41 | // For UTF-8, we need special alignment treatment: |
| 42 | // If an incomplete character is found at a chunk boundary, we use |
| 43 | // its remainder and try to decode it. |
| 44 | let mut i = 0; |
| 45 | while i < data.len() && i < self.missing_bytes { |
| 46 | if (data[i] & 0xC0) != 0x80 { |
| 47 | // This byte is not a continuation byte even though it should have |
| 48 | // been one. We stop decoding of the incomplete character at this |
| 49 | // point (but still use the rest of the incomplete bytes from this |
| 50 | // chunk) and assume that the new, unexpected byte starts a new one. |
| 51 | self.missing_bytes = 0; |
| 52 | self.buffer.extend_from_slice(&data[..i]); |
| 53 | self.buffered_bytes += i; |
| 54 | data = &data[i..]; |
| 55 | break; |
| 56 | } |
| 57 | i += 1; |
| 58 | } |
| 59 | } else if matches!(self.encoder, Encoder::Utf16le) { |
| 60 | // For UTF-16le, we need special alignment treatment: |
| 61 | // If we have a high surrogate we need to extend the missing bytes |
| 62 | // to 3 to get the low surrogate. |
| 63 | let mut i = 0; |
| 64 | while i < data.len() && i < self.missing_bytes { |
| 65 | if (data[i] & 0xFC) == 0xD8 { |
| 66 | self.missing_bytes = 3; |
| 67 | break; |
| 68 | } |
| 69 | i += 1; |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | let found_bytes = std::cmp::min(data.len(), self.missing_bytes); |
| 74 | self.buffer.extend_from_slice(&data[..found_bytes]); |
| 75 | |
| 76 | data = &data[found_bytes..]; |
| 77 | |
| 78 | self.missing_bytes -= found_bytes; |
| 79 | self.buffered_bytes += found_bytes; |
| 80 | if self.missing_bytes == 0 { |
| 81 | // We have enough bytes to decode the buffered character |
| 82 | result = self.make_string(ctx, &self.buffer)?; |
| 83 | self.buffer.clear(); |
| 84 | self.buffered_bytes = 0; |
| 85 | } |
| 86 | } |