From 35902e5047628c24a06de70d10be9c1d4a1d1541 Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Fri, 28 Oct 2022 15:17:18 +1100 Subject: [PATCH] feat: add convenient constructors for dict and list types, add int and string extension bencode functions --- .../bencode/{Bencoder.kt => Bencode.kt} | 12 +++- .../libsession/utilities/BencoderTest.kt | 65 +++++++++---------- 2 files changed, 43 insertions(+), 34 deletions(-) rename libsession/src/main/java/org/session/libsession/utilities/bencode/{Bencoder.kt => Bencode.kt} (94%) diff --git a/libsession/src/main/java/org/session/libsession/utilities/bencode/Bencoder.kt b/libsession/src/main/java/org/session/libsession/utilities/bencode/Bencode.kt similarity index 94% rename from libsession/src/main/java/org/session/libsession/utilities/bencode/Bencoder.kt rename to libsession/src/main/java/org/session/libsession/utilities/bencode/Bencode.kt index 2674e5194c..53b535d1d8 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/bencode/Bencoder.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/bencode/Bencode.kt @@ -2,7 +2,7 @@ package org.session.libsession.utilities.bencode import java.util.LinkedList -object Bencoder { +object Bencode { class Decoder(source: CharArray) { private val iterator = LinkedList().apply { @@ -101,6 +101,10 @@ object Bencoder { sealed class BencodeElement { abstract fun encode(): CharArray } + +fun String.bencode() = BencodeString(this) +fun Int.bencode() = BencodeInteger(this) + data class BencodeString(val value: String): BencodeElement() { override fun encode(): CharArray = buildString { append(value.length.toString()) @@ -116,6 +120,9 @@ data class BencodeInteger(val value: Int): BencodeElement() { }.toCharArray() } data class BencodeList(val values: List): BencodeElement() { + + constructor(vararg values: BencodeElement) : this(values.toList()) + override fun encode(): CharArray = buildString { append('l') for (value in values) { @@ -125,6 +132,9 @@ data class BencodeList(val values: List): BencodeElement() { }.toCharArray() } data class BencodeDict(val values: Map): BencodeElement() { + + constructor(vararg values: Pair) : this(values.toMap()) + override fun encode(): CharArray = buildString { append('d') for ((key, value) in values) { diff --git a/libsession/src/test/java/org/session/libsession/utilities/BencoderTest.kt b/libsession/src/test/java/org/session/libsession/utilities/BencoderTest.kt index 127d708f8b..2286424a86 100644 --- a/libsession/src/test/java/org/session/libsession/utilities/BencoderTest.kt +++ b/libsession/src/test/java/org/session/libsession/utilities/BencoderTest.kt @@ -3,26 +3,26 @@ package org.session.libsession.utilities import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Test +import org.session.libsession.utilities.bencode.Bencode import org.session.libsession.utilities.bencode.BencodeDict import org.session.libsession.utilities.bencode.BencodeInteger import org.session.libsession.utilities.bencode.BencodeList -import org.session.libsession.utilities.bencode.BencodeString -import org.session.libsession.utilities.bencode.Bencoder +import org.session.libsession.utilities.bencode.bencode class BencoderTest { @Test fun `it should decode a basic string`() { val basicString = "5:howdy".toCharArray() - val bencoder = Bencoder.Decoder(basicString) + val bencoder = Bencode.Decoder(basicString) val result = bencoder.decode() - assertEquals(BencodeString("howdy"), result) + assertEquals("howdy".bencode(), result) } @Test fun `it should decode a basic integer`() { val basicInteger = "i3e".toCharArray() - val bencoder = Bencoder.Decoder(basicInteger) + val bencoder = Bencode.Decoder(basicInteger) val result = bencoder.decode() assertEquals(BencodeInteger(3), result) } @@ -30,14 +30,12 @@ class BencoderTest { @Test fun `it should decode a list of integers`() { val basicIntList = "li1ei2ee".toCharArray() - val bencoder = Bencoder.Decoder(basicIntList) + val bencoder = Bencode.Decoder(basicIntList) val result = bencoder.decode() assertEquals( BencodeList( - listOf( - BencodeInteger(1), - BencodeInteger(2) - ) + 1.bencode(), + 2.bencode() ), result ) @@ -46,17 +44,13 @@ class BencoderTest { @Test fun `it should decode a basic dict`() { val basicDict = "d4:spaml1:a1:bee".toCharArray() - val bencoder = Bencoder.Decoder(basicDict) + val bencoder = Bencode.Decoder(basicDict) val result = bencoder.decode() assertEquals( BencodeDict( - mapOf( - "spam" to BencodeList( - listOf( - BencodeString("a"), - BencodeString("b") - ) - ) + "spam" to BencodeList( + "a".bencode(), + "b".bencode() ) ), result @@ -66,26 +60,21 @@ class BencoderTest { @Test fun `it should encode a basic string`() { val basicString = "5:howdy".toCharArray() - val element = BencodeString("howdy") + val element = "howdy".bencode() assertArrayEquals(basicString, element.encode()) } @Test fun `it should encode a basic int`() { val basicInt = "i3e".toCharArray() - val element = BencodeInteger(3) + val element = 3.bencode() assertArrayEquals(basicInt, element.encode()) } @Test fun `it should encode a basic list`() { val basicList = "li1ei2ee".toCharArray() - val element = BencodeList( - listOf( - BencodeInteger(1), - BencodeInteger(2) - ) - ) + val element = BencodeList(1.bencode(),2.bencode()) assertArrayEquals(basicList, element.encode()) } @@ -93,16 +82,26 @@ class BencoderTest { fun `it should encode a basic dict`() { val basicDict = "d4:spaml1:a1:bee".toCharArray() val element = BencodeDict( - mapOf( - "spam" to BencodeList( - listOf( - BencodeString("a"), - BencodeString("b") - ) - ) + "spam" to BencodeList( + "a".bencode(), + "b".bencode() ) ) assertArrayEquals(basicDict, element.encode()) } + @Test + fun `it should encode a more complex real world case`() { + val source = "d15:lastReadMessaged66:031122334455667788990011223344556677889900112233445566778899001122i1234568790e66:051122334455667788990011223344556677889900112233445566778899001122i1234568790ee5:seqNoi1ee".toCharArray() + val result = Bencode.Decoder(source).decode() + val expected = BencodeDict( + "lastReadMessage" to BencodeDict( + "051122334455667788990011223344556677889900112233445566778899001122" to 1234568790.bencode(), + "031122334455667788990011223344556677889900112233445566778899001122" to 1234568790.bencode() + ), + "seqNo" to BencodeInteger(1) + ) + assertEquals(expected, result) + } + } \ No newline at end of file