Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin TLV Implementation: Removed Dependency on Protobuf #26641

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,9 @@ class WildcardFragment : Fragment() {
},
"ByteArray(Hex)" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
val byteStringValue = ByteString.fromHex(value)
writer.put(tag, byteStringValue)
writer.put(tag, value.chunked(2).map { it.toInt(16) and 0xFF }.map { it.toByte() }.toByteArray())
}
},
)
}
}
}
2 changes: 0 additions & 2 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ if (chip_link_tests) {
kotlin_library("tlv") {
output_name = "libCHIPTlv.jar"

deps = [ "${chip_root}/third_party/java_deps:protobuf-java" ]

sources = [
"src/chip/tlv/Element.kt",
"src/chip/tlv/TlvReader.kt",
Expand Down
5 changes: 2 additions & 3 deletions src/controller/java/src/chip/jsontlv/JsonToTlv.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.google.protobuf.ByteString
import java.util.Base64
import chip.tlv.*

Expand Down Expand Up @@ -150,8 +149,8 @@ private fun extractTagAndTypeFromJsonKey(key: String): Triple<Tag, String, Strin
return Triple(tag, type, subType)
}

private fun String.base64Encode(): ByteString {
return ByteString.copyFrom(Base64.getDecoder().decode(this))
private fun String.base64Encode(): ByteArray {
return Base64.getDecoder().decode(this)
}

/** Verifies JsonElement is Number. If yes, returns the value. */
Expand Down
5 changes: 2 additions & 3 deletions src/controller/java/src/chip/jsontlv/TlvToJson.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ private fun TlvReader.getStructJson(): JsonObject {
}
}
is Utf8StringValue -> json.addProperty(key, value.value)
is ByteStringValue ->
json.addProperty(key, Base64.getEncoder().encodeToString(value.value.toByteArray()))
is ByteStringValue -> json.addProperty(key, Base64.getEncoder().encodeToString(value.value))
is BooleanValue -> json.addProperty(key, value.value)
is FloatValue -> json.addProperty(key, validateFloat(value.value))
is DoubleValue -> json.addProperty(key, validateDouble(value.value))
Expand Down Expand Up @@ -144,7 +143,7 @@ private fun TlvReader.getArrayJsonWithElementsType(): Pair<JsonArray, String> {
}
}
is Utf8StringValue -> json.add(value.value)
is ByteStringValue -> json.add(Base64.getEncoder().encodeToString(value.value.toByteArray()))
is ByteStringValue -> json.add(Base64.getEncoder().encodeToString(value.value))
is BooleanValue -> json.add(value.value)
is FloatValue -> json.add(validateFloat(value.value))
is DoubleValue -> json.add(validateDouble(value.value))
Expand Down
5 changes: 2 additions & 3 deletions src/controller/java/src/chip/tlv/TlvReader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

package chip.tlv

import com.google.protobuf.ByteString
import java.lang.Double.longBitsToDouble
import java.lang.Float.intBitsToFloat

Expand Down Expand Up @@ -87,7 +86,7 @@ class TlvReader(bytes: ByteArray) : Iterable<Element> {
is SignedIntType -> IntValue(valueBytes.fromLittleEndianToLong(isSigned = true))
is UnsignedIntType -> UnsignedIntValue(valueBytes.fromLittleEndianToLong())
is Utf8StringType -> Utf8StringValue(String(valueBytes, Charsets.UTF_8))
is ByteStringType -> ByteStringValue(ByteString.copyFrom(valueBytes))
is ByteStringType -> ByteStringValue(valueBytes)
is BooleanType -> BooleanValue(elementType.value)
is FloatType -> FloatValue(intBitsToFloat(valueBytes.fromLittleEndianToLong().toInt()))
is DoubleType -> DoubleValue(longBitsToDouble(valueBytes.fromLittleEndianToLong()))
Expand Down Expand Up @@ -248,7 +247,7 @@ class TlvReader(bytes: ByteArray) : Iterable<Element> {
*
* @throws TlvParsingException if the element is not of the expected type or tag
*/
fun getByteString(tag: Tag): ByteString {
fun getByteString(tag: Tag): ByteArray {
val value = nextElement().verifyTagAndGetValue(tag)
require(value is ByteStringValue) {
"Unexpected value $value at index $index (expected ByteStringValue)"
Expand Down
7 changes: 3 additions & 4 deletions src/controller/java/src/chip/tlv/TlvWriter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package chip.tlv

import com.google.protobuf.ByteString
import java.io.ByteArrayOutputStream

/**
Expand Down Expand Up @@ -224,7 +223,7 @@ class TlvWriter(initialCapacity: Int = 32) {
*
* @throws TlvEncodingException if the data was invalid
*/
fun put(tag: Tag, value: ByteString): TlvWriter {
fun put(tag: Tag, value: ByteArray): TlvWriter {
return put(Element(tag, ByteStringValue(value)))
}

Expand Down Expand Up @@ -261,7 +260,7 @@ class TlvWriter(initialCapacity: Int = 32) {
*
* @throws TlvEncodingException if the data was invalid
*/
fun putByteStringArray(tag: Tag, array: List<ByteString>): TlvWriter {
fun putByteStringArray(tag: Tag, array: List<ByteArray>): TlvWriter {
startArray(tag)
array.forEach { put(AnonymousTag, it) }
return endArray()
Expand Down
2 changes: 1 addition & 1 deletion src/controller/java/src/chip/tlv/tags.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package chip.tlv

import kotlin.experimental.and
Expand Down
2 changes: 1 addition & 1 deletion src/controller/java/src/chip/tlv/types.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package chip.tlv

import kotlin.experimental.and
Expand Down
2 changes: 1 addition & 1 deletion src/controller/java/src/chip/tlv/utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package chip.tlv

/** Converts bytes in a Little Endian format into Long integer. */
Expand Down
12 changes: 5 additions & 7 deletions src/controller/java/src/chip/tlv/values.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package chip.tlv

import com.google.protobuf.ByteString
import java.lang.Double.doubleToLongBits
import java.lang.Float.floatToIntBits

Expand Down Expand Up @@ -65,11 +64,10 @@ data class Utf8StringValue(val value: String) : Value() {
value.toByteArray().size.toByteArrayLittleEndian(toType().lengthSize) + value.toByteArray()
}

/** Represents a byte string value of a TLV element. */
data class ByteStringValue(val value: ByteString) : Value() {
override fun toType() = ByteStringType(unsignedIntSize(value.size().toULong()))
override fun encode() =
value.toByteArray().size.toByteArrayLittleEndian(toType().lengthSize) + value.toByteArray()
/** Represents an octet string value of a TLV element. */
data class ByteStringValue(val value: ByteArray) : Value() {
override fun toType() = ByteStringType(unsignedIntSize(value.size.toULong()))
override fun encode() = value.size.toByteArrayLittleEndian(toType().lengthSize) + value
}

/** Represents a null value in a TLV element. */
Expand Down
37 changes: 17 additions & 20 deletions src/controller/java/tests/chip/jsontlv/JsonToTlvToJsonTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package chip.jsontlv

import com.google.common.truth.Truth.assertThat
import com.google.gson.JsonParser
import com.google.protobuf.ByteString
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -35,8 +34,6 @@ class JsonToTlvToJsonTest {
private fun String.octetsToByteArray(): ByteArray =
replace(" ", "").chunked(2).map { it.toInt(16) and 0xFF }.map { it.toByte() }.toByteArray()

private fun String.toByteString(): ByteString = ByteString.copyFrom(this.toByteArray())

private fun checkValidConversion(
jsonOriginal: String,
tlvEncoding: ByteArray,
Expand Down Expand Up @@ -283,7 +280,7 @@ class JsonToTlvToJsonTest {
@Test
fun convertOctetString() {
// Octet String, 1-octet length, octets 00 01 02 03 04
val value = ByteString.fromHex("0001020304")
val value = "0001020304".octetsToByteArray()
val encoding =
TlvWriter()
.startStructure(AnonymousTag)
Expand Down Expand Up @@ -1207,12 +1204,12 @@ class JsonToTlvToJsonTest {

@Test
fun convertByteStringArray() {
// Anonymous Array of ByteString, [{00 01 02 03 04}, {FF}, {4A EF 88}]
// Anonymous Array of ByteArray, [{00 01 02 03 04}, {FF}, {4A EF 88}]
val values =
listOf<ByteString>(
ByteString.fromHex("0001020304"),
ByteString.fromHex("FF"),
ByteString.fromHex("4AEF88")
listOf<ByteArray>(
"0001020304".octetsToByteArray(),
"FF".octetsToByteArray(),
"4AEF88".octetsToByteArray()
)
val encoding =
TlvWriter()
Expand Down Expand Up @@ -1245,7 +1242,7 @@ class JsonToTlvToJsonTest {
.put(ContextSpecificTag(0), 20.toLong())
.put(ContextSpecificTag(1), true)
.put(ContextSpecificTag(2), 0.toULong())
.put(ContextSpecificTag(3), "Test ByteString Value".toByteString())
.put(ContextSpecificTag(3), "Test ByteString Value".toByteArray())
.put(ContextSpecificTag(4), "hello")
.put(ContextSpecificTag(5), -500000)
.put(ContextSpecificTag(6), 17.9)
Expand Down Expand Up @@ -1284,7 +1281,7 @@ class JsonToTlvToJsonTest {
.put(ContextSpecificTag(0), 20)
.put(ContextSpecificTag(1), true)
.put(ContextSpecificTag(2), 0.toULong())
.put(ContextSpecificTag(3), "Test ByteString Value 1".toByteString())
.put(ContextSpecificTag(3), "Test ByteString Value 1".toByteArray())
.put(ContextSpecificTag(4), "hello1")
.put(ContextSpecificTag(5), -500000)
.put(ContextSpecificTag(6), 17.9)
Expand All @@ -1294,7 +1291,7 @@ class JsonToTlvToJsonTest {
.put(ContextSpecificTag(0), -10)
.put(ContextSpecificTag(1), false)
.put(ContextSpecificTag(2), 128.toULong())
.put(ContextSpecificTag(3), "Test ByteString Value 2".toByteString())
.put(ContextSpecificTag(3), "Test ByteString Value 2".toByteArray())
.put(ContextSpecificTag(4), "hello2")
.put(ContextSpecificTag(5), 40000000000)
.put(ContextSpecificTag(6), -1754.923)
Expand Down Expand Up @@ -1350,7 +1347,7 @@ class JsonToTlvToJsonTest {
.put(ContextSpecificTag(1), 17.4f)
.startStructure(ContextSpecificTag(2))
.put(ContextSpecificTag(0), "Test String Element #2")
.put(ContextSpecificTag(3), "Test ByteString Element #3".toByteString())
.put(ContextSpecificTag(3), "Test ByteString Element #3".toByteArray())
.endStructure()
.endStructure()
.endStructure()
Expand Down Expand Up @@ -1426,13 +1423,13 @@ class JsonToTlvToJsonTest {

@Test
fun convertArrayOfByteStrings() {
// Array of ByteString elements
// Array of ByteArray elements
val values =
listOf<ByteString>(
"Test array member 0".toByteString(),
"Test array member 1".toByteString(),
"Test array member 2".toByteString(),
"Test array member 3".toByteString(),
listOf<ByteArray>(
"Test array member 0".toByteArray(),
"Test array member 1".toByteArray(),
"Test array member 2".toByteArray(),
"Test array member 3".toByteArray(),
)
val encoding =
TlvWriter()
Expand Down Expand Up @@ -1463,7 +1460,7 @@ class JsonToTlvToJsonTest {
TlvWriter()
.startStructure(AnonymousTag)
.put(ContextSpecificTag(0), 42)
.put(ContextSpecificTag(1), "Test array member 0".toByteString())
.put(ContextSpecificTag(1), "Test array member 0".toByteArray())
.put(ContextSpecificTag(2), 156.398)
.put(ContextSpecificTag(3), 73709551615U)
.put(ContextSpecificTag(4), true)
Expand Down
11 changes: 5 additions & 6 deletions src/controller/java/tests/chip/tlv/TlvReadWriteTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package chip.tlv

import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ByteString
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -484,7 +483,7 @@ class TlvReadWriteTest {
@Test
fun encodeOctetString() {
// Octet String, 1-octet length, octets 00 01 02 03 04
val value = ByteString.fromHex("00 01 02 03 04".replace(" ", ""))
val value = "00 01 02 03 04".octetsToByteArray()
val encoding = "10 05 00 01 02 03 04".octetsToByteArray()

TlvWriter().apply {
Expand Down Expand Up @@ -1093,10 +1092,10 @@ class TlvReadWriteTest {
fun putByteStringArray() {
// Anonumous Array of Signed Integers, [{00 01 02 03 04}, {FF}, {4A EF 88}]
val values =
listOf<ByteString>(
ByteString.fromHex("0001020304"),
ByteString.fromHex("FF"),
ByteString.fromHex("4AEF88")
listOf<ByteArray>(
"0001020304".octetsToByteArray(),
"FF".octetsToByteArray(),
"4AEF88".octetsToByteArray()
)
val encoding = "16 10 05 00 01 02 03 04 10 01 FF 10 03 4A EF 88 18".octetsToByteArray()

Expand Down
18 changes: 10 additions & 8 deletions src/controller/java/tests/chip/tlv/TlvReaderTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package chip.tlv

import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ByteString
import java.math.BigInteger
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -45,6 +44,9 @@ private val fabricConfig =

@RunWith(JUnit4::class)
class TlvReaderTest {
private fun String.octetsToByteArray(): ByteArray =
replace(" ", "").chunked(2).map { it.toInt(16) and 0xFF }.map { it.toByte() }.toByteArray()

@Test
fun parsingFabricConfig_extractsFabricId() {
val reader = TlvReader(fabricConfig)
Expand Down Expand Up @@ -88,15 +90,15 @@ class TlvReaderTest {
assertThat((tag as ContextSpecificTag).tagNumber).isEqualTo(3)
assertThat(value).isInstanceOf(ByteStringValue::class.java)
assertThat((value as ByteStringValue).value)
.isEqualTo(ByteString.fromHex("149BF1430B26F5E4BBF380D3DB855BA1"))
.isEqualTo("149BF1430B26F5E4BBF380D3DB855BA1".octetsToByteArray())
}

reader.nextElement().apply {
assertThat(tag).isInstanceOf(ContextSpecificTag::class.java)
assertThat((tag as ContextSpecificTag).tagNumber).isEqualTo(4)
assertThat(value).isInstanceOf(ByteStringValue::class.java)
assertThat((value as ByteStringValue).value)
.isEqualTo(ByteString.fromHex("E0E8BAA1CAC6E8E7216D720BD13C61C5E0E7B901"))
.isEqualTo("E0E8BAA1CAC6E8E7216D720BD13C61C5E0E7B901".octetsToByteArray())
}

reader.nextElement().apply {
Expand Down Expand Up @@ -178,16 +180,16 @@ class TlvReaderTest {
// Common-profile 2-bytes Tag with ByteString 1-byte type
val control = 0b01010000.toByte()
val length = 0b10000.toByte()
val v = ByteString.copyFromUtf8("byte_string_utf8")
assertThat(v.toByteArray().size).isEqualTo(16)
val v = "byte_string_utf8".toByteArray()
assertThat(v.size).isEqualTo(16)

val reader = TlvReader(byteArrayOf(control, 0x0, 0x0, length, *v.toByteArray()))
val reader = TlvReader(byteArrayOf(control, 0x0, 0x0, length, *v))
reader.nextElement().apply {
assertThat(tag).isInstanceOf(CommonProfileTag::class.java)
assertThat((tag as CommonProfileTag).size).isEqualTo(2)
assertThat(value).isInstanceOf(ByteStringValue::class.java)
assertThat((value as ByteStringValue).value)
.isEqualTo(ByteString.copyFromUtf8("byte_string_utf8"))
.isEqualTo("byte_string_utf8".toByteArray())
}
}

Expand Down Expand Up @@ -268,4 +270,4 @@ class TlvReaderTest {
assertThat(tag).isInstanceOf(ContextSpecificTag::class.java)
assertThat((tag as ContextSpecificTag).tagNumber).isEqualTo(0xFE)
}
}
}
Loading