Skip to content

Commit

Permalink
util-core: Enable ByteReader to Read Unsigned Longs
Browse files Browse the repository at this point in the history
Problem

readUnsignedLongBE and readUnsignedLongLE are missing in ByteReader
implementation.

Solution

Added readUnsignedLongBE and readUnsignedLongLE to ByteReader and
implemented in ByteReaderImpl.

Signed-off-by: Ryan O'Neill <ryano@twitter.com>

RB_ID=917289
  • Loading branch information
mehmetgunturkun authored and jenkins committed May 24, 2017
1 parent 225c44a commit 94ab01f
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -15,6 +15,9 @@ New Features:
* util-core: Added `writeBytes(Buf)` to the ByteWriter abstract class to allow
for efficient writing of the `c.t.io.Buf` type. ``RB_ID=917094``

* util-core: Added `ByteReader.readUnsignedLongBE` and `ByteReader.readUnsignedLongLE`.
``RB_ID=917289``

API Changes:

* util-collection: Removed deprecated `c.t.u.JMapWrapper`. Use
Expand Down
47 changes: 47 additions & 0 deletions util-core/src/main/scala/com/twitter/io/ByteReader.scala
Expand Up @@ -106,6 +106,16 @@ trait ByteReader extends AutoCloseable {
*/
def readLongLE(): Long

/**
* Extract 64 bits and interpret as a big endian unsigned integer, advancing the byte cursor by 8.
*/
def readUnsignedLongBE(): BigInt

/**
* Extract 64 bits and interpret as a little endian unsigned integer, advancing the byte cursor by 8.
*/
def readUnsignedLongLE(): BigInt

/**
* Extract 32 bits and interpret as a big endian floating point, advancing the byte cursor by 4.
*/
Expand Down Expand Up @@ -187,6 +197,10 @@ private[twitter] trait ProxyByteReader extends ByteReader {

def readLongLE(): Long = reader.readLongLE()

def readUnsignedLongBE(): BigInt = reader.readUnsignedLongBE()

def readUnsignedLongLE(): BigInt = reader.readUnsignedLongLE()

def readFloatBE(): Float = reader.readFloatBE()

def readFloatLE(): Float = reader.readFloatLE()
Expand Down Expand Up @@ -384,6 +398,39 @@ private class ByteReaderImpl(buf: Buf) extends ByteReader {
ret
}

def readUnsignedLongBE(): BigInt = {
checkRemaining(8)
val ret =
(buf.get(pos + 7) & 0xff).toLong |
(buf.get(pos + 6) & 0xff).toLong << 8 |
(buf.get(pos + 5) & 0xff).toLong << 16 |
(buf.get(pos + 4) & 0xff).toLong << 24 |
(buf.get(pos + 3) & 0xff).toLong << 32 |
(buf.get(pos + 2) & 0xff).toLong << 40 |
(buf.get(pos + 1) & 0xff).toLong << 48 |
BigInt((buf.get(pos) & 0xff).toLong) << 56
pos += 8

ret
}

def readUnsignedLongLE(): BigInt = {
checkRemaining(8)
val ret =
(buf.get(pos ) & 0xff).toLong |
(buf.get(pos + 1) & 0xff).toLong << 8 |
(buf.get(pos + 2) & 0xff).toLong << 16 |
(buf.get(pos + 3) & 0xff).toLong << 24 |
(buf.get(pos + 4) & 0xff).toLong << 32 |
(buf.get(pos + 5) & 0xff).toLong << 40 |
(buf.get(pos + 6) & 0xff).toLong << 48 |
BigInt(buf.get(pos + 7) & 0xff) << 56
pos += 8

ret
}


// - Floating Point -
def readFloatBE(): Float = JFloat.intBitsToFloat(readIntBE())

Expand Down
35 changes: 35 additions & 0 deletions util-core/src/test/scala/com/twitter/io/ByteReaderTest.scala
@@ -1,7 +1,9 @@
package com.twitter.io

import java.lang.{Double => JDouble, Float => JFloat}

import org.junit.runner.RunWith
import org.scalacheck.Gen
import org.scalatest.FunSuite
import org.scalatest.junit.JUnitRunner
import org.scalatest.prop.GeneratorDrivenPropertyChecks
Expand Down Expand Up @@ -154,6 +156,39 @@ class ByteReaderTest extends FunSuite with GeneratorDrivenPropertyChecks {
assert(br.readUnsignedIntLE() == (i & 0xffffffffl))
})


val uInt64s: Gen[BigInt] = Gen.chooseNum(Long.MinValue,Long.MaxValue)
.map(x => BigInt(x) + BigInt(2).pow(63))

test("readUnsignedLongBE") (forAll(uInt64s) { bi: BigInt =>
val br = readerWith(
((bi >> 56) & 0xff).toByte,
((bi >> 48) & 0xff).toByte,
((bi >> 40) & 0xff).toByte,
((bi >> 32) & 0xff).toByte,
((bi >> 24) & 0xff).toByte,
((bi >> 16) & 0xff).toByte,
((bi >> 8) & 0xff).toByte,
((bi ) & 0xff).toByte)
assert(br.readUnsignedLongBE() == bi)
val exc = intercept[UnderflowException] { br.readByte() }
})

test("readUnsignedLongLE") (forAll(uInt64s) { bi1: BigInt =>
val bi = bi1.abs
val br = readerWith(
((bi ) & 0xff).toByte,
((bi >> 8) & 0xff).toByte,
((bi >> 16) & 0xff).toByte,
((bi >> 24) & 0xff).toByte,
((bi >> 32) & 0xff).toByte,
((bi >> 40) & 0xff).toByte,
((bi >> 48) & 0xff).toByte,
((bi >> 56) & 0xff).toByte)
assert(br.readUnsignedLongLE() == bi)
val exc = intercept[UnderflowException] { br.readByte() }
})

// .equals is required to handle NaN
test("readFloatBE") (forAll { i: Int =>
val br = new ByteReaderImpl(Buf.Empty) { override def readIntBE() = i }
Expand Down

0 comments on commit 94ab01f

Please sign in to comment.