Skip to content
Open
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
12 changes: 12 additions & 0 deletions library/api/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ package me.saket.bytesize {
@kotlin.jvm.JvmInline public final value class BinaryByteSize implements me.saket.bytesize.ByteSize {
ctor public BinaryByteSize(Number bytes);
ctor public BinaryByteSize(@kotlin.PublishedApi long bytes);
method public inline operator int compareTo(long other);
method public inline int compareTo(me.saket.bytesize.ByteSize other);
method public inline long div(Number other);
method public inline operator double div(long other);
method public inline double div(me.saket.bytesize.ByteSize other);
method public inline long inWholeBytes();
method public inline long inWholeGibibytes();
method public inline long inWholeKibibytes();
method public inline long inWholeMebibytes();
method public inline operator long minus(long other);
method public inline operator me.saket.bytesize.ByteSize minus(me.saket.bytesize.ByteSize other);
method public inline operator long plus(long other);
method public inline operator long plus(me.saket.bytesize.ByteSize other);
method public inline long times(Number other);
method public inline String toString();
Expand Down Expand Up @@ -48,15 +52,19 @@ package me.saket.bytesize {
@kotlin.jvm.JvmInline public final value class DecimalBitSize implements me.saket.bytesize.ByteSize {
ctor public DecimalBitSize(Number bits);
ctor public DecimalBitSize(@kotlin.PublishedApi long bits);
method public inline operator int compareTo(long other);
method public inline int compareTo(me.saket.bytesize.ByteSize other);
method public inline long div(Number other);
method public inline operator double div(long other);
method public inline double div(me.saket.bytesize.ByteSize other);
method public inline long inWholeBits();
method public inline long inWholeBytes();
method public inline long inWholeGigabits();
method public inline long inWholeKilobits();
method public inline long inWholeMegabits();
method public inline operator long minus(long other);
method public inline long minus(me.saket.bytesize.ByteSize other);
method public inline operator long plus(long other);
method public inline long plus(me.saket.bytesize.ByteSize other);
method public inline long times(Number other);
method public inline String toString();
Expand All @@ -75,14 +83,18 @@ package me.saket.bytesize {
@kotlin.jvm.JvmInline public final value class DecimalByteSize implements me.saket.bytesize.ByteSize {
ctor public DecimalByteSize(Number bytes);
ctor public DecimalByteSize(@kotlin.PublishedApi long bytes);
method public inline operator int compareTo(long other);
method public inline int compareTo(me.saket.bytesize.ByteSize other);
method public inline long div(Number other);
method public inline operator double div(long other);
method public inline double div(me.saket.bytesize.ByteSize other);
method public inline long inWholeBytes();
method public inline long inWholeGigabytes();
method public inline long inWholeKilobytes();
method public inline long inWholeMegabytes();
method public inline operator long minus(long other);
method public inline operator long minus(me.saket.bytesize.ByteSize other);
method public inline operator long plus(long other);
method public inline operator long plus(me.saket.bytesize.ByteSize other);
method public inline long times(Number other);
method public inline String toString();
Expand Down
59 changes: 59 additions & 0 deletions library/src/commonMain/kotlin/me/saket/bytesize/BinaryByteSize.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

package me.saket.bytesize

import dev.erikchristensen.javamath2kmp.minusExact
import dev.erikchristensen.javamath2kmp.plusExact
import dev.erikchristensen.javamath2kmp.timesExact
import kotlin.jvm.JvmInline
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
Expand All @@ -24,6 +27,16 @@ import me.saket.bytesize.internal.toStringAsFixed
inline val Number.binaryBytes: BinaryByteSize
get() = BinaryByteSize(this)

/** Allocation-free overload of [binaryBytes] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.binaryBytes: BinaryByteSize
get() = BinaryByteSize(bytes = toLong())

/** Allocation-free overload of [binaryBytes] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.binaryBytes: BinaryByteSize
get() = BinaryByteSize(bytes = this)

/**
* Returns a [BinaryByteSize] equal to this number of kibibytes.
*
Expand All @@ -33,6 +46,16 @@ inline val Number.binaryBytes: BinaryByteSize
inline val Number.kibibytes: BinaryByteSize
get() = BinaryByteSize(BytesPerKiB) * this

/** Allocation-free overload of [kibibytes] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.kibibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerKiB.timesExact(toLong()))

/** Allocation-free overload of [kibibytes] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.kibibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerKiB.timesExact(this))

/**
* Returns a [BinaryByteSize] equal to this number of mebibytes.
*
Expand All @@ -42,6 +65,16 @@ inline val Number.kibibytes: BinaryByteSize
inline val Number.mebibytes: BinaryByteSize
get() = BinaryByteSize(BytesPerMiB) * this

/** Allocation-free overload of [mebibytes] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.mebibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerMiB.timesExact(toLong()))

/** Allocation-free overload of [mebibytes] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.mebibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerMiB.timesExact(this))

/**
* Returns a [BinaryByteSize] equal to this number of gibibytes.
*
Expand All @@ -51,6 +84,16 @@ inline val Number.mebibytes: BinaryByteSize
inline val Number.gibibytes: BinaryByteSize
get() = BinaryByteSize(BytesPerGiB) * this

/** Allocation-free overload of [gibibytes] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.gibibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerGiB.timesExact(toLong()))

/** Allocation-free overload of [gibibytes] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.gibibytes: BinaryByteSize
get() = BinaryByteSize(bytes = BytesPerGiB.timesExact(this))

/** Returns this size without its sign. */
@get:JvmSynthetic
inline val BinaryByteSize.absoluteValue: BinaryByteSize
Expand Down Expand Up @@ -91,15 +134,27 @@ value class BinaryByteSize(
override inline operator fun plus(other: ByteSize): BinaryByteSize =
BinaryByteSize(commonPlus(other))

/** Allocation-free overload of [plus] for same-precision operands. */
inline operator fun plus(other: BinaryByteSize): BinaryByteSize =
BinaryByteSize(bytes.plusExact(other.bytes))

override inline operator fun minus(other: ByteSize): ByteSize =
BinaryByteSize(commonMinus(other))

/** Allocation-free overload of [minus] for same-precision operands. */
inline operator fun minus(other: BinaryByteSize): BinaryByteSize =
BinaryByteSize(bytes.minusExact(other.bytes))

override inline fun times(other: Number): BinaryByteSize =
BinaryByteSize(commonTimes(other))

override inline fun div(other: ByteSize): Double =
commonDiv(other)

/** Allocation-free overload of [div] for same-precision operands. */
inline operator fun div(other: BinaryByteSize): Double =
bytes.toDouble() / other.bytes

override inline fun div(other: Number): BinaryByteSize =
BinaryByteSize(commonDiv(other))

Expand All @@ -109,6 +164,10 @@ value class BinaryByteSize(
override inline fun compareTo(other: ByteSize): Int =
commonCompareTo(other)

/** Allocation-free overload of [compareTo] for same-precision operands. */
inline operator fun compareTo(other: BinaryByteSize): Int =
bytes.compareTo(other.bytes)

override inline fun toString(): String {
val sign = if (inWholeBytes < 0) "-" else ""
val bytes = abs(inWholeBytes)
Expand Down
6 changes: 6 additions & 0 deletions library/src/commonMain/kotlin/me/saket/bytesize/ByteSize.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import me.saket.bytesize.internal.BitsPerByte
* Represents a size that can be expressed in bytes.
*
* A [ByteSize] is one of [BinaryByteSize], [DecimalByteSize], or [DecimalBitSize].
*
* The operators declared here accept this interface so that sizes of different precisions can be
* mixed. That comes at a cost: a `value class` is only kept unboxed while its static type _is_ the
* value class, so passing one as a [ByteSize] boxes it. Each subtype therefore also declares
* same-precision overloads of these operators, which the compiler prefers when both operands have
* the same concrete type. Those overloads read the backing `Long` directly and allocate nothing.
*/
sealed interface ByteSize : Comparable<ByteSize> {
@get:JvmName("inWholeBytes")
Expand Down
63 changes: 63 additions & 0 deletions library/src/commonMain/kotlin/me/saket/bytesize/DecimalBitSize.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

package me.saket.bytesize

import dev.erikchristensen.javamath2kmp.minusExact
import dev.erikchristensen.javamath2kmp.plusExact
import dev.erikchristensen.javamath2kmp.timesExact
import kotlin.jvm.JvmInline
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
Expand All @@ -25,6 +28,16 @@ import me.saket.bytesize.internal.toStringAsFixed
inline val Number.decimalBits: DecimalBitSize
get() = DecimalBitSize(this)

/** Allocation-free overload of [decimalBits] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.decimalBits: DecimalBitSize
get() = DecimalBitSize(bits = toLong())

/** Allocation-free overload of [decimalBits] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.decimalBits: DecimalBitSize
get() = DecimalBitSize(bits = this)

/**
* Returns a [DecimalBitSize] equal to this number of kilobits.
*
Expand All @@ -34,6 +47,16 @@ inline val Number.decimalBits: DecimalBitSize
inline val Number.kilobits: DecimalBitSize
get() = DecimalBitSize(BitsPerKb) * this

/** Allocation-free overload of [kilobits] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.kilobits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerKb.timesExact(toLong()))

/** Allocation-free overload of [kilobits] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.kilobits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerKb.timesExact(this))

/**
* Returns a [DecimalBitSize] equal to this number of megabits.
*
Expand All @@ -43,6 +66,16 @@ inline val Number.kilobits: DecimalBitSize
inline val Number.megabits: DecimalBitSize
get() = DecimalBitSize(BitsPerMb) * this

/** Allocation-free overload of [megabits] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.megabits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerMb.timesExact(toLong()))

/** Allocation-free overload of [megabits] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.megabits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerMb.timesExact(this))

/**
* Returns a [DecimalBitSize] equal to this number of gigabits.
*
Expand All @@ -52,6 +85,16 @@ inline val Number.megabits: DecimalBitSize
inline val Number.gigabits: DecimalBitSize
get() = DecimalBitSize(BitsPerGb) * this

/** Allocation-free overload of [gigabits] for [Int] receivers. */
@get:JvmSynthetic
inline val Int.gigabits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerGb.timesExact(toLong()))

/** Allocation-free overload of [gigabits] for [Long] receivers. */
@get:JvmSynthetic
inline val Long.gigabits: DecimalBitSize
get() = DecimalBitSize(bits = BitsPerGb.timesExact(this))

/** Returns this size without its sign. */
@get:JvmSynthetic
inline val DecimalBitSize.absoluteValue: DecimalBitSize
Expand Down Expand Up @@ -98,10 +141,20 @@ value class DecimalBitSize(
return DecimalBitSize(bits = commonPlus(other))
}

/** Allocation-free overload of [plus] for same-precision operands. */
inline operator fun plus(other: DecimalBitSize): DecimalBitSize {
return DecimalBitSize(bits = bits.plusExact(other.bits))
}

override inline fun minus(other: ByteSize): DecimalBitSize {
return DecimalBitSize(bits = commonMinus(other))
}

/** Allocation-free overload of [minus] for same-precision operands. */
inline operator fun minus(other: DecimalBitSize): DecimalBitSize {
return DecimalBitSize(bits = bits.minusExact(other.bits))
}

override inline fun times(other: Number): DecimalBitSize {
return DecimalBitSize(bits = commonTimes(other))
}
Expand All @@ -110,6 +163,11 @@ value class DecimalBitSize(
return commonDiv(other)
}

/** Allocation-free overload of [div] for same-precision operands. */
inline operator fun div(other: DecimalBitSize): Double {
return bits.toDouble() / other.bits
}

override inline fun div(other: Number): DecimalBitSize {
return DecimalBitSize(bits = commonDiv(other))
}
Expand All @@ -121,6 +179,11 @@ value class DecimalBitSize(
return commonCompareTo(other)
}

/** Allocation-free overload of [compareTo] for same-precision operands. */
inline operator fun compareTo(other: DecimalBitSize): Int {
return bits.compareTo(other.bits)
}

override inline fun toString(): String {
val sign = if (inWholeBits < 0) "-" else ""
val bits = abs(inWholeBits)
Expand Down
Loading