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

Refactor Counter #83

Merged
merged 2 commits into from
Jan 2, 2025
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
23 changes: 12 additions & 11 deletions library/core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,42 @@ public abstract interface class org/kotlincrypto/core/Copyable {
public abstract fun copy ()Ljava/lang/Object;
}

public abstract class org/kotlincrypto/core/Counter {
public abstract class org/kotlincrypto/core/Counter : org/kotlincrypto/core/Copyable, org/kotlincrypto/core/Resettable {
public final fun equals (Ljava/lang/Object;)Z
public final fun hashCode ()I
protected abstract fun increment ()V
protected abstract fun reset ()V
public abstract fun increment ()V
public final fun toString ()Ljava/lang/String;
}

public abstract class org/kotlincrypto/core/Counter$Bit32 : org/kotlincrypto/core/Counter {
public final class org/kotlincrypto/core/Counter$Bit32 : org/kotlincrypto/core/Counter {
public static final field Companion Lorg/kotlincrypto/core/Counter$Bit32$Companion;
public static final field MAX_INCREMENT I
public final field incrementBy I
public fun <init> (I)V
public fun <init> (III)V
public fun <init> (Lorg/kotlincrypto/core/Counter$Bit32;)V
public synthetic fun copy ()Ljava/lang/Object;
public fun copy ()Lorg/kotlincrypto/core/Counter$Bit32;
public final fun hi ()I
protected fun increment ()V
public fun increment ()V
public final fun lo ()I
protected fun reset ()V
public fun reset ()V
}

public final class org/kotlincrypto/core/Counter$Bit32$Companion {
}

public abstract class org/kotlincrypto/core/Counter$Bit64 : org/kotlincrypto/core/Counter {
public final class org/kotlincrypto/core/Counter$Bit64 : org/kotlincrypto/core/Counter {
public static final field Companion Lorg/kotlincrypto/core/Counter$Bit64$Companion;
public static final field MAX_INCREMENT J
public final field incrementBy J
public fun <init> (J)V
public fun <init> (JJJ)V
public fun <init> (Lorg/kotlincrypto/core/Counter$Bit64;)V
public synthetic fun copy ()Ljava/lang/Object;
public fun copy ()Lorg/kotlincrypto/core/Counter$Bit64;
public final fun hi ()J
protected fun increment ()V
public fun increment ()V
public final fun lo ()J
protected fun reset ()V
public fun reset ()V
}

public final class org/kotlincrypto/core/Counter$Bit64$Companion {
Expand Down
19 changes: 9 additions & 10 deletions library/core/api/core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ abstract interface org.kotlincrypto.core/Updatable { // org.kotlincrypto.core/Up
abstract fun update(kotlin/ByteArray, kotlin/Int, kotlin/Int) // org.kotlincrypto.core/Updatable.update|update(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0]
}

sealed class org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter|null[0]
sealed class org.kotlincrypto.core/Counter : org.kotlincrypto.core/Copyable<org.kotlincrypto.core/Counter>, org.kotlincrypto.core/Resettable { // org.kotlincrypto.core/Counter|null[0]
abstract fun increment() // org.kotlincrypto.core/Counter.increment|increment(){}[0]
abstract fun reset() // org.kotlincrypto.core/Counter.reset|reset(){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // org.kotlincrypto.core/Counter.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // org.kotlincrypto.core/Counter.hashCode|hashCode(){}[0]
final fun toString(): kotlin/String // org.kotlincrypto.core/Counter.toString|toString(){}[0]

abstract class Bit32 : org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter.Bit32|null[0]
final class Bit32 : org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter.Bit32|null[0]
constructor <init>(kotlin/Int) // org.kotlincrypto.core/Counter.Bit32.<init>|<init>(kotlin.Int){}[0]
constructor <init>(kotlin/Int, kotlin/Int, kotlin/Int) // org.kotlincrypto.core/Counter.Bit32.<init>|<init>(kotlin.Int;kotlin.Int;kotlin.Int){}[0]
constructor <init>(org.kotlincrypto.core/Counter.Bit32) // org.kotlincrypto.core/Counter.Bit32.<init>|<init>(org.kotlincrypto.core.Counter.Bit32){}[0]

final val incrementBy // org.kotlincrypto.core/Counter.Bit32.incrementBy|{}incrementBy[0]
final fun <get-incrementBy>(): kotlin/Int // org.kotlincrypto.core/Counter.Bit32.incrementBy.<get-incrementBy>|<get-incrementBy>(){}[0]
Expand All @@ -52,19 +50,19 @@ sealed class org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter|nu
final var lo // org.kotlincrypto.core/Counter.Bit32.lo|{}lo[0]
final fun <get-lo>(): kotlin/Int // org.kotlincrypto.core/Counter.Bit32.lo.<get-lo>|<get-lo>(){}[0]

open fun increment() // org.kotlincrypto.core/Counter.Bit32.increment|increment(){}[0]
open fun reset() // org.kotlincrypto.core/Counter.Bit32.reset|reset(){}[0]
final fun copy(): org.kotlincrypto.core/Counter.Bit32 // org.kotlincrypto.core/Counter.Bit32.copy|copy(){}[0]
final fun increment() // org.kotlincrypto.core/Counter.Bit32.increment|increment(){}[0]
final fun reset() // org.kotlincrypto.core/Counter.Bit32.reset|reset(){}[0]

final object Companion { // org.kotlincrypto.core/Counter.Bit32.Companion|null[0]
final const val MAX_INCREMENT // org.kotlincrypto.core/Counter.Bit32.Companion.MAX_INCREMENT|{}MAX_INCREMENT[0]
final fun <get-MAX_INCREMENT>(): kotlin/Int // org.kotlincrypto.core/Counter.Bit32.Companion.MAX_INCREMENT.<get-MAX_INCREMENT>|<get-MAX_INCREMENT>(){}[0]
}
}

abstract class Bit64 : org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter.Bit64|null[0]
final class Bit64 : org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter.Bit64|null[0]
constructor <init>(kotlin/Long) // org.kotlincrypto.core/Counter.Bit64.<init>|<init>(kotlin.Long){}[0]
constructor <init>(kotlin/Long, kotlin/Long, kotlin/Long) // org.kotlincrypto.core/Counter.Bit64.<init>|<init>(kotlin.Long;kotlin.Long;kotlin.Long){}[0]
constructor <init>(org.kotlincrypto.core/Counter.Bit64) // org.kotlincrypto.core/Counter.Bit64.<init>|<init>(org.kotlincrypto.core.Counter.Bit64){}[0]

final val incrementBy // org.kotlincrypto.core/Counter.Bit64.incrementBy|{}incrementBy[0]
final fun <get-incrementBy>(): kotlin/Long // org.kotlincrypto.core/Counter.Bit64.incrementBy.<get-incrementBy>|<get-incrementBy>(){}[0]
Expand All @@ -74,8 +72,9 @@ sealed class org.kotlincrypto.core/Counter { // org.kotlincrypto.core/Counter|nu
final var lo // org.kotlincrypto.core/Counter.Bit64.lo|{}lo[0]
final fun <get-lo>(): kotlin/Long // org.kotlincrypto.core/Counter.Bit64.lo.<get-lo>|<get-lo>(){}[0]

open fun increment() // org.kotlincrypto.core/Counter.Bit64.increment|increment(){}[0]
open fun reset() // org.kotlincrypto.core/Counter.Bit64.reset|reset(){}[0]
final fun copy(): org.kotlincrypto.core/Counter.Bit64 // org.kotlincrypto.core/Counter.Bit64.copy|copy(){}[0]
final fun increment() // org.kotlincrypto.core/Counter.Bit64.increment|increment(){}[0]
final fun reset() // org.kotlincrypto.core/Counter.Bit64.reset|reset(){}[0]

final object Companion { // org.kotlincrypto.core/Counter.Bit64.Companion|null[0]
final const val MAX_INCREMENT // org.kotlincrypto.core/Counter.Bit64.Companion.MAX_INCREMENT|{}MAX_INCREMENT[0]
Expand Down
64 changes: 34 additions & 30 deletions library/core/src/commonMain/kotlin/org/kotlincrypto/core/Counter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,28 @@ import kotlin.jvm.JvmName
/**
* Utility for counting things.
* */
public sealed class Counter private constructor() {
public sealed class Counter private constructor(): Resettable, Copyable<Counter> {

/**
* Increments the counter
* */
public abstract fun increment()

/**
* A counter that utilizes 32-bit numbers providing a maximum count of 2^64.
*
* @see [Bit64]
* */
public abstract class Bit32: Counter {
public class Bit32: Counter {

public companion object {

/**
* The maximum value for which [Bit32.incrementBy] can be set to.
*
* 1024 * 1024 >> 1048576
* 1024^2 >> 1048576
* */
public const val MAX_INCREMENT: Int = 1024 * 1024 // Never decrease, only increase.
public const val MAX_INCREMENT: Int = 1048576 // Never decrease, only increase.
}

/**
Expand Down Expand Up @@ -90,39 +97,40 @@ public sealed class Counter private constructor() {
* */
public constructor(incrementBy: Int): this(0, 0, incrementBy)

/**
* Creates a clone of [other]
* */
public constructor(other: Bit32): super() {
this.incrementBy = other.incrementBy
this.lo = other.lo
this.hi = other.hi
}
public override fun copy(): Bit32 = Bit32(this)

protected override fun increment() {
public override fun increment() {
lo += incrementBy
if (lo == 0) hi++
}

protected override fun reset() {
public override fun reset() {
lo = 0
hi = 0
}

private constructor(other: Bit32): super() {
this.incrementBy = other.incrementBy
this.lo = other.lo
this.hi = other.hi
}
}

/**
* A counter that utilizes 64-bit numbers providing a maximum count of 2^128.
*
* @see [Bit32]
* */
public abstract class Bit64: Counter {
public class Bit64: Counter {

public companion object {

/**
* The maximum value for which [Bit64.incrementBy] can be set to.
*
* @see [Bit32.MAX_INCREMENT]
* 1024^4 >> 1099511627776
* */
public const val MAX_INCREMENT: Long = Bit32.MAX_INCREMENT.toLong()
public const val MAX_INCREMENT: Long = 1099511627776L // Never decrease, only increase.
}

/**
Expand Down Expand Up @@ -175,28 +183,24 @@ public sealed class Counter private constructor() {
* */
public constructor(incrementBy: Long): this(0, 0, incrementBy)

/**
* Creates a clone of [other]
* */
public constructor(other: Bit64): super() {
this.incrementBy = other.incrementBy
this.lo = other.lo
this.hi = other.hi
}
public override fun copy(): Bit64 = Bit64(this)

protected override fun increment() {
public override fun increment() {
lo += incrementBy
if (lo == 0L) hi++
}

protected override fun reset() {
public override fun reset() {
lo = 0L
hi = 0L
}
}

protected abstract fun increment()
protected abstract fun reset()
private constructor(other: Bit64): super() {
this.incrementBy = other.incrementBy
this.lo = other.lo
this.hi = other.hi
}
}

private val code = Any()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,56 +18,57 @@ package org.kotlincrypto.core
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNotEquals

class CounterUnitTest {

@Test
fun givenIncrementBy_when0_thenThrowsException() {
assertFailsWith<IllegalArgumentException> {
TestBit32Counter(0)
Counter.Bit32(0)
}
assertFailsWith<IllegalArgumentException> {
TestBit64Counter(0)
Counter.Bit64(0)
}
}

@Test
fun givenIncrementBy_whenExceedsMaximum_thenThrowsException() {
assertFailsWith<IllegalArgumentException> {
TestBit32Counter(Counter.Bit32.MAX_INCREMENT + 8)
Counter.Bit32(Counter.Bit32.MAX_INCREMENT + 8)
}
assertFailsWith<IllegalArgumentException> {
TestBit64Counter(Counter.Bit64.MAX_INCREMENT + 8)
Counter.Bit64(Counter.Bit64.MAX_INCREMENT + 8)
}
}

@Test
fun givenIncrementBy_whenNotFactory8_thenThrowsException() {
assertFailsWith<IllegalArgumentException> {
TestBit32Counter(9)
Counter.Bit32(9)
}
assertFailsWith<IllegalArgumentException> {
TestBit64Counter(9)
Counter.Bit64(9)
}
}

@Test
fun givenLo_whenNotFactoryIncrementBy_thenThrowsException() {
// Would throw if 24 was not a factor of 8...
TestBit32Counter(24)
TestBit64Counter(24)
Counter.Bit32(24)
Counter.Bit64(24)

assertFailsWith<IllegalArgumentException> {
TestBit32Counter(8, 0, 24)
Counter.Bit32(8, 0, 24)
}
assertFailsWith<IllegalArgumentException> {
TestBit64Counter(16, 0, 24)
Counter.Bit64(16, 0, 24)
}
}

@Test
fun givenBit32_whenReset_thenIsZero() {
val c = TestBit32Counter(8, 8, 8)
val c = Counter.Bit32(8, 8, 8)
assertEquals(8, c.lo)
assertEquals(8, c.hi)
assertEquals(8, c.incrementBy)
Expand All @@ -78,7 +79,7 @@ class CounterUnitTest {

@Test
fun givenBit64_whenReset_thenIsZero() {
val c = TestBit64Counter(8, 8, 8)
val c = Counter.Bit64(8, 8, 8)
assertEquals(8, c.lo)
assertEquals(8, c.hi)
assertEquals(8, c.incrementBy)
Expand All @@ -89,42 +90,57 @@ class CounterUnitTest {

@Test
fun givenBit32_whenIncrement_thenIncrements() {
var c = TestBit32Counter(-16, 0, 8)
var c = Counter.Bit32(-16, 0, 8)
c.increment()
assertEquals(-8, c.lo)
assertEquals(0, c.hi)
c.increment()
assertEquals(0, c.lo)
assertEquals(1, c.hi)

c = TestBit32Counter(Int.MAX_VALUE - 7, 0, 8)
c = Counter.Bit32(Int.MAX_VALUE - 7, 0, 8)
c.increment()
assertEquals(Int.MIN_VALUE, c.lo)
assertEquals(0, c.hi)
}

@Test
fun givenBit64_whenIncrement_thenIncrements() {
var c = TestBit64Counter(-16, 0, 8)
var c = Counter.Bit64(-16, 0, 8)
c.increment()
assertEquals(-8, c.lo)
assertEquals(0, c.hi)
c.increment()
assertEquals(0, c.lo)
assertEquals(1, c.hi)

c = TestBit64Counter(Long.MAX_VALUE - 7, 0, 8)
c = Counter.Bit64(Long.MAX_VALUE - 7, 0, 8)
c.increment()
assertEquals(Long.MIN_VALUE, c.lo)
assertEquals(0, c.hi)
}

@Test
fun givenBit32_whenClone_thenCopiesValues() {
val expected = TestBit32Counter(8, 8, 8)
val actual = TestBit32Counter(expected)
assertEquals(expected.incrementBy, actual.incrementBy)
assertEquals(expected.lo, actual.lo)
assertEquals(expected.hi, actual.hi)
fun givenBit32_whenCopy_thenCopiesValues() {
val expected = Counter.Bit32(8, 8, 8)
val copy = expected.copy()
assertNotEquals(expected, copy)
assertEquals(expected.incrementBy, copy.incrementBy)
assertEquals(expected.lo, copy.lo)
assertEquals(expected.hi, copy.hi)
copy.increment()
assertNotEquals(expected.lo, copy.lo)
}

@Test
fun givenBit64_whenCopy_thenCopiesValues() {
val expected = Counter.Bit64(8, 8, 8)
val copy = expected.copy()
assertNotEquals(expected, copy)
assertEquals(expected.incrementBy, copy.incrementBy)
assertEquals(expected.lo, copy.lo)
assertEquals(expected.hi, copy.hi)
copy.increment()
assertNotEquals(expected.lo, copy.lo)
}
}
Loading
Loading