feat: add convenient constructors for dict and list types, add int and string extension bencode functions

This commit is contained in:
0x330a
2022-10-28 15:17:18 +11:00
parent 3078d18ebd
commit 35902e5047
2 changed files with 43 additions and 34 deletions

View File

@@ -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<Char>().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>): 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>): BencodeElement() {
}.toCharArray()
}
data class BencodeDict(val values: Map<String, BencodeElement>): BencodeElement() {
constructor(vararg values: Pair<String, BencodeElement>) : this(values.toMap())
override fun encode(): CharArray = buildString {
append('d')
for ((key, value) in values) {

View File

@@ -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)
}
}