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

Use Long to back the UInt64 type #1109

Merged
merged 10 commits into from
Sep 4, 2019
36 changes: 19 additions & 17 deletions eclair-core/src/main/scala/fr/acinq/eclair/UInt64.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,42 @@

package fr.acinq.eclair

import java.math.BigInteger

import com.google.common.primitives.UnsignedLongs
import scodec.bits.ByteVector
import scodec.bits._
araspitzu marked this conversation as resolved.
Show resolved Hide resolved

case class UInt64(private val underlying: BigInt) extends Ordered[UInt64] {
case class UInt64(private val underlying: Long) extends Ordered[UInt64] {

require(underlying >= 0, s"uint64 must be positive (actual=$underlying)")
require(underlying <= UInt64.MaxValueBigInt, s"uint64 must be < 2^64 -1 (actual=$underlying)")
override def compare(o: UInt64): Int = UnsignedLongs.compare(underlying, o.underlying)
t-bast marked this conversation as resolved.
Show resolved Hide resolved

override def compare(o: UInt64): Int = underlying.compare(o.underlying)
def toByteVector: ByteVector = this match {
case x if x <= UInt64(255) => ByteVector.fromLong(underlying, size = 1)
araspitzu marked this conversation as resolved.
Show resolved Hide resolved
case x if x <= UInt64(65535) => ByteVector.fromLong(underlying, size = 2)
case x if x <= UInt64(16777215) => ByteVector.fromLong(underlying, size = 3)
case x if x <= UInt64(4294967295L) => ByteVector.fromLong(underlying, size = 4)
case x if x <= UInt64(1099511627775L) => ByteVector.fromLong(underlying, size = 5)
case x if x <= UInt64(281474976710655L) => ByteVector.fromLong(underlying, size = 6)
case x if x <= UInt64(72057594037927935L) => ByteVector.fromLong(underlying, size = 7)
case _ => ByteVector.fromLong(underlying, size = 8)
}

def toByteVector: ByteVector = ByteVector.view(underlying.toByteArray.takeRight(8))
def toBigInt: BigInt = BigInt(toString)
araspitzu marked this conversation as resolved.
Show resolved Hide resolved

def toBigInt: BigInt = underlying
def toLong: Long = underlying
araspitzu marked this conversation as resolved.
Show resolved Hide resolved

override def toString: String = underlying.toString
override def toString: String = UnsignedLongs.toString(underlying, 10)
t-bast marked this conversation as resolved.
Show resolved Hide resolved
}


object UInt64 {

private val MaxValueBigInt = BigInt(new BigInteger("ffffffffffffffff", 16))
val MaxValue = UInt64(hex"0xffffffffffffffff")

val MaxValue = UInt64(MaxValueBigInt)

def apply(bin: ByteVector) = new UInt64(new BigInteger(1, bin.toArray))

def apply(value: Long) = new UInt64(BigInt(value))
def apply(bin: ByteVector): UInt64 = UInt64(bin.toLong(signed = false))

object Conversions {
t-bast marked this conversation as resolved.
Show resolved Hide resolved

implicit def intToUint64(l: Int) = UInt64(l)

implicit def longToUint64(l: Long) = UInt64(l)
}

}
3 changes: 3 additions & 0 deletions eclair-core/src/test/scala/fr/acinq/eclair/UInt64Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class UInt64Spec extends FunSuite {
assert(b < a)
assert(z < a && z < b && z < c)
assert(a == a)
assert(a == UInt64.MaxValue)
t-bast marked this conversation as resolved.
Show resolved Hide resolved
assert(a.toByteVector === hex"0xffffffffffffffff")
assert(a.toString === "18446744073709551615")
assert(b.toByteVector === hex"0xfffffffffffffffe")
Expand All @@ -39,6 +40,8 @@ class UInt64Spec extends FunSuite {
assert(c.toString === "42")
assert(z.toByteVector === hex"0x00")
assert(z.toString === "0")
assert(UInt64(hex"0xff").toByteVector == hex"0xff")
assert(UInt64(hex"0x800").toByteVector == hex"0x800")
}

}