Skip to content

Commit

Permalink
Promote checking for padding and new lines/spaces to encoding-core
Browse files Browse the repository at this point in the history
  • Loading branch information
05nelsonm committed Jan 20, 2023
1 parent 1bad240 commit 52f426b
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import io.matthewnelson.encoding.core.internal.EncodingTable
import io.matthewnelson.encoding.core.internal.InternalEncodingApi
import io.matthewnelson.encoding.core.util.DecoderInput
import io.matthewnelson.encoding.core.util.char
import io.matthewnelson.encoding.core.util.isSpaceOrNewLine
import io.matthewnelson.encoding.core.util.lowercaseCharByte
import kotlin.jvm.JvmField
import kotlin.jvm.JvmSynthetic
Expand Down Expand Up @@ -151,14 +150,6 @@ public class Base16(config: Config): EncoderDecoder(config) {
input.char
}

if (char.isSpaceOrNewLine()) {
if (config.isLenient) {
return
} else {
throw DecoderInput.isLenientFalseEncodingException()
}
}

val bits: Int = when (char) {
in '0'..'9' -> {
// char ASCII value
Expand All @@ -173,9 +164,7 @@ public class Base16(config: Config): EncoderDecoder(config) {
char.code - 55
}
else -> {
throw EncodingException(
"Char[${input.char}] is not a valid Base16 character"
)
throw EncodingException("Char[${input.char}] is not a valid Base16 character")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,6 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
// everything that comes in.
val char = input.char.uppercaseChar()

if (char.isSpaceOrNewLine()) {
if (config.isLenient) {
return
} else {
throw DecoderInput.isLenientFalseEncodingException()
}
}

// Do after space/line/hyphen check in order to simply
// pass over them until the next relevant byte comes in
if (isCheckByteSet) {
val symbol = (config as Crockford.Config).checkSymbol
// If the set checkByte was not intended, it's only a valid
Expand Down Expand Up @@ -399,7 +389,6 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
return object : Decoder.Feed() {

private val buffer = Base32BitBuffer(out)
private var isPaddingSet = false

@Throws(EncodingException::class)
override fun updateProtected(input: Byte) {
Expand All @@ -409,14 +398,6 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
input.char
}

if (char.isSpaceOrNewLine()) {
if (config.isLenient) {
return
} else {
throw DecoderInput.isLenientFalseEncodingException()
}
}

val bits: Long = when (char) {
in '2'..'7' -> {
// char ASCII value
Expand All @@ -430,24 +411,11 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
// Z 90 25 (ASCII - 65)
char.code - 65L
}
config.paddingByte?.char -> {
// Skip over padding
isPaddingSet = true
return
}
else -> {
throw EncodingException("Char[${input.char}] is not a valid Base32 Default character")
}
}

if (isPaddingSet) {
// Trying to decode another non-padding character, after
// having already passed padding. e.g. ABC=DEF===
throw EncodingException(
"Padding[${config.paddingByte?.char}] was previously seen, but decoding is still being attempted."
)
}

buffer.update(bits)
}

Expand Down Expand Up @@ -569,7 +537,6 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
return object : Decoder.Feed() {

private val buffer = Base32BitBuffer(out)
private var isPaddingSet = false

@Throws(EncodingException::class)
override fun updateProtected(input: Byte) {
Expand All @@ -579,14 +546,6 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
input.char
}

if (char.isSpaceOrNewLine()) {
if (config.isLenient) {
return
} else {
throw DecoderInput.isLenientFalseEncodingException()
}
}

val bits: Long = when (char) {
in '0'..'9' -> {
// char ASCII value
Expand All @@ -600,24 +559,11 @@ public sealed class Base32(config: EncoderDecoder.Config): EncoderDecoder(config
// V 86 31 (ASCII - 55)
char.code - 55L
}
config.paddingByte?.char -> {
// Skip over padding
isPaddingSet = true
return
}
else -> {
throw EncodingException("Char[${input.char}] is not a valid Base32 Hex character")
}
}

if (isPaddingSet) {
// Trying to decode another non-padding character, after
// having already passed padding. e.g. ABC=DEF===
throw EncodingException(
"Padding[${config.paddingByte?.char}] was previously seen, but decoding is still being attempted."
)
}

buffer.update(bits)
}

Expand Down
5 changes: 1 addition & 4 deletions library/encoding-core/api/encoding-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public abstract class io/matthewnelson/encoding/core/EncoderDecoder$Config {
}

public abstract class io/matthewnelson/encoding/core/EncoderDecoder$Feed {
public synthetic fun <init> (Lio/matthewnelson/encoding/core/EncoderDecoder$Config;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun close ()V
public final fun doFinal ()V
protected abstract fun doFinalProtected ()V
Expand Down Expand Up @@ -130,7 +131,3 @@ public final class io/matthewnelson/encoding/core/util/_ConversionsKt {
public static final fun lowercaseCharByte (B)B
}

public final class io/matthewnelson/encoding/core/util/_HelpersKt {
public static final fun isSpaceOrNewLine (C)Z
}

Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public sealed class Decoder(public val config: EncoderDecoder.Config) {
* */
public abstract inner class Feed
@ExperimentalEncodingApi
constructor(): EncoderDecoder.Feed() {
constructor(): EncoderDecoder.Feed(config) {
final override fun toString(): String = "${this@Decoder}.Decoder.Feed@${hashCode()}"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public sealed class Encoder(config: EncoderDecoder.Config): Decoder(config) {
* */
public abstract inner class Feed
@ExperimentalEncodingApi
constructor(): EncoderDecoder.Feed() {
constructor(): EncoderDecoder.Feed(config) {
protected abstract override fun updateProtected(input: Byte)
protected abstract override fun doFinalProtected()
final override fun toString(): String = "${this@Encoder}.Encoder.Feed@${hashCode()}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

package io.matthewnelson.encoding.core

import io.matthewnelson.encoding.core.internal.isSpaceOrNewLine
import io.matthewnelson.encoding.core.util.DecoderInput
import io.matthewnelson.encoding.core.util.char
import io.matthewnelson.encoding.core.util.isSpaceOrNewLine
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName

Expand Down Expand Up @@ -205,11 +205,13 @@ constructor(config: Config): Encoder(config) {
* @see [Encoder.Feed]
* @see [Decoder.Feed]
* */
public sealed class Feed {
public sealed class Feed(private val config: Config) {
@get:JvmName("isClosed")
public var isClosed: Boolean = false
private set

private var isPaddingSet = false

// Only throws exception if decoding
@Throws(EncodingException::class)
protected abstract fun updateProtected(input: Byte)
Expand All @@ -230,6 +232,32 @@ constructor(config: Config): Encoder(config) {
if (isClosed) throw closedException()

try {
if (this is Decoder.Feed) {
if (input.char.isSpaceOrNewLine()) {
if (config.isLenient) {
return
} else {
throw DecoderInput.isLenientFalseEncodingException()
}
}

// if paddingByte is null, it will never equal
// input, thus never set isPaddingSet
if (config.paddingByte == input) {
isPaddingSet = true
return
}

if (isPaddingSet) {
// Trying to decode something else that is not
// a space, new line, or padding. Fail
throw EncodingException(
"Padding[${config.paddingByte?.char}] was previously passed, " +
"but decoding operations are still being attempted."
)
}
}

updateProtected(input)
} catch (t: Throwable) {
close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,17 @@ internal inline fun Encoder.encode(
}
}
}

/**
* Helper for checking if a character is a space or
* new line.
*
* @return true if the character matches '\n', '\r', ' ', or '\t'
* */
@Suppress("NOTHING_TO_INLINE")
internal inline fun Char.isSpaceOrNewLine(): Boolean {
return when(this) {
'\n', '\r', ' ', '\t' -> true
else -> false
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import io.matthewnelson.encoding.core.EncoderDecoder
import io.matthewnelson.encoding.core.EncodingException
import io.matthewnelson.encoding.core.EncodingSizeException
import io.matthewnelson.encoding.core.internal.InternalEncodingApi
import io.matthewnelson.encoding.core.internal.isSpaceOrNewLine
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
Expand Down Expand Up @@ -122,9 +123,7 @@ private constructor(

public companion object {

@JvmStatic
@InternalEncodingApi // might move this somewhere else... don't use.
public fun isLenientFalseEncodingException(): EncodingException {
internal fun isLenientFalseEncodingException(): EncodingException {
return EncodingException("Spaces and new lines are forbidden when isLenient[false]")
}

Expand Down

0 comments on commit 52f426b

Please sign in to comment.