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

Feature/ktxio #164

Open
wants to merge 6 commits into
base: development
Choose a base branch
from
Open

Feature/ktxio #164

wants to merge 6 commits into from

Conversation

JesusMcCloud
Copy link
Collaborator

use Kotlinx-io for decoding to avoid unneeded byte copying

Copy link
Collaborator

@iaik-jheher iaik-jheher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

partial review pending partial rewrite

Comment on lines 82 to 86
(children?.fold(Buffer()) { acc, extendedTlv -> acc.apply { write(extendedTlv.derEncoded) } }
?.let {
Buffer().apply { write(tlv.tag.encodedTag); encodeLength(it.size); it.transferTo(this) }
}?.readByteArray()
?: Buffer().apply { write(tlv.tag.encodedTag); write(encodedLength);write(tlv.content) }.readByteArray())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i suggest an if expression (or improved indentation)

children?.fold(byteArrayOf()) { acc, extendedTlv -> acc + extendedTlv.derEncoded }
?.let { byteArrayOf(*tlv.tag.encodedTag, *it.size.encodeLength(), *it) }
?: byteArrayOf(*tlv.tag.encodedTag, *encodedLength, *tlv.content)
(children?.fold(Buffer()) { acc, extendedTlv -> acc.apply { write(extendedTlv.derEncoded) } }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider Buffer.writeDerEncoded or similar to avoid copying to bytearray at every layer of the hierarchy

@@ -120,11 +122,9 @@ sealed class Asn1Element(
/**
* Convenience method to directly produce an HEX string of this element's ANS.1 representation
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Convenience method to directly produce an HEX string of this element's ANS.1 representation
* Convenience method to directly produce an HEX string of this element's ASN.1 representation

Comment on lines +125 to +127
fun toDerHexString(lineLen: Byte? = null) = @OptIn(ExperimentalStdlibApi::class)
derEncoded.toHexString(HexFormat.UpperCase)
.let { if (lineLen == null) it else it.chunked(lineLen.toInt()).joinToString("\n") }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken indentation

@@ -240,8 +240,12 @@ sealed class Asn1Element(
@Serializable(with = ByteArrayBase64Serializer::class) val encodedTag: ByteArray
) : Comparable<Tag> {
private constructor(values: Triple<ULong, Int, ByteArray>) : this(values.first, values.second, values.third)

//TODO this CTOR is internally called only using already validated inputs.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outstanding todo

@@ -312,7 +317,7 @@ sealed class Asn1Element(

override fun toString(): String =
"${tagClass.let { if (it == TagClass.UNIVERSAL) "" else it.name + " " }}${tagValue}${if (isConstructed) " CONSTRUCTED" else ""}" +
(" (=${encodedTag.encodeToString(Base16)})")
(" (=${@OptIn(ExperimentalStdlibApi::class) encodedTag.toHexString(HexFormat.UpperCase)})")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we just get a @file:OptIn for this marker

@@ -578,8 +583,7 @@ class Asn1CustomStructure private constructor(


override val content: ByteArray by lazy {
if (!tag.isConstructed)
children.fold(byteArrayOf()) { acc, asn1Element -> acc + asn1Element.derEncoded }
if (!tag.isConstructed) Buffer().apply { children.forEach { write(it.derEncoded) } }.readByteArray()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also avoid constant bytearray punning

@@ -16,11 +19,13 @@ internal data class TLV(val tag: Asn1Element.Tag, val content: ByteArray) {
val encodedTag get() = tag.encodedTag

override fun equals(other: Any?): Boolean {
if (other is TLV.Shallow || this is TLV.Shallow) throw IllegalStateException("Shallow TLVs may neve be compared")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (other is TLV.Shallow || this is TLV.Shallow) throw IllegalStateException("Shallow TLVs may neve be compared")
if (other is TLV.Shallow || this is TLV.Shallow) throw IllegalStateException("Shallow TLVs may never be compared")

* @see parse
*/
@Throws(Asn1Exception::class)
fun Asn1Element.Companion.parseFirst(source: ByteArray): Pair<Asn1Element, ByteArray> =
source.iterator().doParseSingle().let { Pair(it, source.copyOfRange(it.overallLength, source.size)) }
Buffer().apply { write(source) }.let { it.readAsn1Element() to it.snapshot().toByteArray() }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is Buffer().apply { write(source) } (used here) different from source.copyToSource() (used elsewhere)?

Comment on lines +85 to +97
if (tlv.isSequence()) Asn1Sequence(tlv.content.doParseAll())
else if (tlv.isSet()) Asn1Set.fromPresorted(tlv.content.doParseAll())
else if (tlv.isExplicitlyTagged())
Asn1ExplicitlyTagged(tlv.tag.tagValue, tlv.content.doParseAll())
else if (tlv.tag == Asn1Element.Tag.OCTET_STRING) catching {
val expected = tlv.content.size
Asn1EncapsulatingOctetString(tlv.content.peek().doParseAll()).also {
if (it.length != expected) throw Asn1StructuralException("The contents contain a valid structure and garbage.")
} as Asn1Element
}.getOrElse { Asn1PrimitiveOctetString(tlv.content.readByteArray()) as Asn1Element }
else if (tlv.tag.isConstructed) { //custom tags, we don't know if it is a SET OF, SET, SEQUENCE, … so we default to sequence semantics
Asn1CustomStructure(tlv.content.doParseAll(), tlv.tag.tagValue, tlv.tagClass)
} else Asn1Primitive(tlv.tag, tlv.content.readByteArray())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please indent:

if (a)
  A
else if (b)
  B

right now it's very hard to follow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants