Skip to content

Commit

Permalink
ProgressiveStringDecoder
Browse files Browse the repository at this point in the history
Summary: Changelog: [Internal]

Differential Revision: D55981019
  • Loading branch information
Thomas Nardone authored and facebook-github-bot committed Apr 10, 2024
1 parent 021e0a4 commit 3c63378
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 88 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.modules.network

import com.facebook.common.logging.FLog
import com.facebook.react.common.ReactConstants
import java.nio.ByteBuffer
import java.nio.CharBuffer
import java.nio.charset.CharacterCodingException
import java.nio.charset.Charset
import java.nio.charset.CharsetDecoder

/**
* Class to decode encoded strings from byte array chunks. As in different encodings single
* character could take up to 4 characters byte array passed to decode could have parts of the
* characters which can't be correctly decoded.
*
* This class is designed in assumption that original byte stream is correctly formatted string in
* given encoding. Otherwise some parts of the data won't be decoded.
*/
internal class ProgressiveStringDecoder(charset: Charset) {

private val decoder: CharsetDecoder = charset.newDecoder()
private var remainder: ByteArray? = null

/**
* Parses data to String If there is a partial multi-byte symbol on the edge of the String it get
* saved to the reminder and added to the string on the decodeNext call.
*
* @param data
* @return
*/
fun decodeNext(data: ByteArray, length: Int): String {
var bufferLength = length
var decodeData: ByteArray = data
remainder?.let { remainder ->
decodeData = ByteArray(remainder.size + length)
System.arraycopy(remainder, 0, decodeData, 0, remainder.size)
System.arraycopy(data, 0, decodeData, remainder.size, length)
bufferLength += remainder.size
}
var decodeBuffer = ByteBuffer.wrap(decodeData, 0, bufferLength)
var result: CharBuffer? = null
var remainderLength = 0
while (result == null && (remainderLength < 4)) {
try {
result = decoder.decode(decodeBuffer)
} catch (e: CharacterCodingException) {
remainderLength++
decodeBuffer = ByteBuffer.wrap(decodeData, 0, bufferLength - remainderLength)
}
}
val hasRemainder = result != null && (remainderLength > 0)
if (hasRemainder) {
val newRemainder = ByteArray(remainderLength)
System.arraycopy(decodeData, bufferLength - remainderLength, newRemainder, 0, remainderLength)
remainder = newRemainder
} else {
remainder = null
}
if (result == null) {
FLog.w(ReactConstants.TAG, "failed to decode string from byte array")
return EMPTY_STRING
} else {
return String(result.array(), 0, result.length)
}
}
}

private const val EMPTY_STRING = ""

0 comments on commit 3c63378

Please sign in to comment.