Skip to content

Commit

Permalink
Merge pull request #288 from DmitryPodpryatov/byte-reader-writer
Browse files Browse the repository at this point in the history
Add reader and writer for Byte
  • Loading branch information
dos65 authored May 17, 2024
2 parents 56baa08 + a264c4b commit 065af1a
Show file tree
Hide file tree
Showing 18 changed files with 106 additions and 1 deletion.
6 changes: 6 additions & 0 deletions modules/core/src/main/scala/tethys/commons/TokenNode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ object TokenNode {
override val token: Token = NumberValueToken
}

case class ByteValueNode(value: Byte) extends TokenNode {
override def token: Token = NumberValueToken
}
case class ShortValueNode(value: Short) extends TokenNode {
override val token: Token = NumberValueToken
}
Expand Down Expand Up @@ -71,6 +74,7 @@ object TokenNode {

def value(v: String): List[TokenNode] = StringValueNode(v) :: Nil
def value(v: Boolean): List[TokenNode] = BooleanValueNode(v) :: Nil
def value(v: Byte): List[TokenNode] = ByteValueNode(v) :: Nil
def value(v: Short): List[TokenNode] = ShortValueNode(v) :: Nil
def value(v: Int): List[TokenNode] = IntValueNode(v) :: Nil
def value(v: Long): List[TokenNode] = LongValueNode(v) :: Nil
Expand All @@ -85,6 +89,7 @@ object TokenNode {
case v: TokenNode => v :: Nil
case nodes: List[_] => nodes.flatMap(anyToTokens)
case v: String => value(v)
case v: Byte => value(v)
case v: Short => value(v)
case v: Int => value(v)
case v: Long => value(v)
Expand Down Expand Up @@ -115,6 +120,7 @@ object TokenNode {
else if (token.isFieldName) FieldNameNode(iterator.fieldName())
else if (token.isStringValue) StringValueNode(iterator.string())
else if (token.isNumberValue) iterator.number() match {
case v: java.lang.Byte => ByteValueNode(v)
case v: java.lang.Short => ShortValueNode(v)
case v: java.lang.Integer => IntValueNode(v)
case v: java.lang.Long => LongValueNode(v)
Expand Down
2 changes: 1 addition & 1 deletion modules/core/src/main/scala/tethys/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import scala.Specializable.Group

package object tethys {

final val specializations = new Group((Short, Int, Long, Float, Double, Boolean))
final val specializations = new Group((Byte, Short, Int, Long, Float, Double, Boolean))

// given

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ trait AllJsonReaders extends OptionReaders {
}
}

implicit lazy val byteReader: JsonReader[Byte] = new JsonReader[Byte] {
override def read(it: TokenIterator)(implicit fieldName: FieldName): Byte = {
if(it.currentToken().isNumberValue) {
val res = it.byte()
it.next()
res
} else {
ReaderError.wrongJson(s"Expected byte value but found: ${it.currentToken()}")
}
}
}

implicit lazy val shortReader: JsonReader[Short] = new JsonReader[Short] {
override def read(it: TokenIterator)(implicit fieldName: FieldName): Short = {
if(it.currentToken().isNumberValue) {
Expand Down Expand Up @@ -112,6 +124,7 @@ trait AllJsonReaders extends OptionReaders {
case bi: BigInt => BigDecimal(bi)
case jbd: java.math.BigDecimal => BigDecimal(jbd)
case jint: java.lang.Integer => BigDecimal(jint)
case jbyte: java.lang.Byte => BigDecimal(jbyte.longValue())
case jshort: java.lang.Short => BigDecimal(jshort.longValue())
case jlong: java.lang.Long => BigDecimal(jlong)
case jbi: java.math.BigInteger => BigDecimal(jbi)
Expand All @@ -126,13 +139,15 @@ trait AllJsonReaders extends OptionReaders {
case bd: BigDecimal => bd.toBigInt
case jbd: java.math.BigDecimal => jbd.toBigInteger
case jint: java.lang.Integer => BigInt(jint)
case jbyte: java.lang.Byte => BigInt(jbyte.longValue())
case jshort: java.lang.Short => BigInt(jshort.longValue())
case jlong: java.lang.Long => BigInt(jlong)
case num => BigInt(num.longValue())
}


implicit lazy val javaBooleanReader: JsonReader[java.lang.Boolean] = booleanReader.map(a => a)
implicit lazy val javaByteReader: JsonReader[java.lang.Byte] = byteReader.map(a => a)
implicit lazy val javaShortReader: JsonReader[java.lang.Short] = shortReader.map(a => a)
implicit lazy val javaIntReader: JsonReader[java.lang.Integer] = intReader.map(a => a)
implicit lazy val javaLongReader: JsonReader[java.lang.Long] = longReader.map(a => a)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import scala.language.higherKinds

private[tethys] trait IterableReaders extends LowPriorityIterableReaders {

implicit def byteIterableReader[C[X] <: Iterable[X]](implicit
cb: CollectionBuilder[Byte, C[Byte]]): JsonReader[C[Byte]] = new TraversableReader[Byte, C] {
override protected def appendBuilder(it: TokenIterator, builder: mutable.Builder[Byte, C[Byte]])(implicit fieldName: FieldName): Unit = {
builder += PrimitiveReaders.ByteJsonReader.read(it)
}
}

implicit def shortIterableReader[C[X] <: Iterable[X]](implicit
cb: CollectionBuilder[Short, C[Short]]): JsonReader[C[Short]] = new TraversableReader[Short, C] {
override protected def appendBuilder(it: TokenIterator, builder: mutable.Builder[Short, C[Short]])(implicit fieldName: FieldName): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import scala.collection.mutable
import scala.language.higherKinds

private[tethys] trait MapReaders extends LowPriorityMapReaders {
implicit def byteMapReader[K, M[X, Y] <: scala.collection.Map[X, Y]](implicit
keyReader: KeyReader[K],
cb: CollectionBuilder[(K, Byte), M[K, Byte]]
): JsonReader[M[K, Byte]] = {
new MapReader[K, Byte, M] {
override protected def appendBuilder(it: TokenIterator, builder: mutable.Builder[(K, Byte), M[K, Byte]], key: K)(implicit fieldName: FieldName): Unit = {
builder += key -> PrimitiveReaders.ByteJsonReader.read(it)
}
}
}

implicit def shortMapReader[K, M[X, Y] <: scala.collection.Map[X, Y]](implicit
keyReader: KeyReader[K],
cb: CollectionBuilder[(K, Short), M[K, Short]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import tethys.readers.FieldName
import tethys.readers.tokens.TokenIterator

private[tethys] trait OptionReaders extends LowPriorityOptionReaders {
implicit lazy val byteOptionReader: JsonReader[Option[Byte]] = new OptionJsonReader[Byte] {
override protected def readSomeValue(it: TokenIterator)(implicit fieldName: FieldName): Option[Byte] = {
Some(PrimitiveReaders.ByteJsonReader.read(it))
}
}

implicit lazy val shortOptionReader: JsonReader[Option[Short]] = new OptionJsonReader[Short] {
override protected def readSomeValue(it: TokenIterator)(implicit fieldName: FieldName): Option[Short] = {
Some(PrimitiveReaders.ShortJsonReader.read(it))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import tethys.readers.tokens.TokenIterator
import tethys.readers.{FieldName, ReaderError}

object PrimitiveReaders {
object ByteJsonReader {
def read(it: TokenIterator)(implicit fieldName: FieldName): Byte = {
if(it.currentToken().isNumberValue) {
val res = it.byte()
it.nextToken()
res
} else {
ReaderError.wrongJson(s"Expected byte value but found: ${it.currentToken()}")
}
}
}

object ShortJsonReader {
def read(it: TokenIterator)(implicit fieldName: FieldName): Short = {
if(it.currentToken().isNumberValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ trait BaseTokenIterator extends TokenIterator {
else if(token.isFieldName) FieldNameNode(fieldName()) -> 0
else if(token.isStringValue) StringValueNode(string()) -> 0
else if(token.isNumberValue) number() match {
case v: java.lang.Byte => ByteValueNode(v) -> 0
case v: java.lang.Short => ShortValueNode(v) -> 0
case v: java.lang.Integer => IntValueNode(v) -> 0
case v: java.lang.Long => LongValueNode(v) -> 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT

override def number(): Number = nodes.front match {
case NumberValueNode(value) => value
case ByteValueNode(value) => value
case ShortValueNode(value) => value
case IntValueNode(value) => value
case LongValueNode(value) => value
Expand All @@ -46,9 +47,21 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT
case node => fail[NumberValueNode](node)
}

override def byte(): Byte = nodes.front match {
case ByteValueNode(value) => value
case NumberValueNode(value) => value.byteValue()
case ShortValueNode(value) => value.toByte
case IntValueNode(value) => value.toByte
case LongValueNode(value) => value.toByte
case FloatValueNode(value) => value.toByte
case DoubleValueNode(value) => value.toByte
case node => fail[ByteValueNode](node)
}

override def short(): Short = nodes.front match {
case ShortValueNode(value) => value
case NumberValueNode(value) => value.shortValue()
case ByteValueNode(value) => value.toShort
case IntValueNode(value) => value.toShort
case LongValueNode(value) => value.toShort
case FloatValueNode(value) => value.toShort
Expand All @@ -59,6 +72,7 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT
override def int(): Int = nodes.front match {
case IntValueNode(value) => value
case NumberValueNode(value) => value.intValue()
case ByteValueNode(value) => value.toInt
case ShortValueNode(value) => value.toInt
case LongValueNode(value) => value.toInt
case FloatValueNode(value) => value.toInt
Expand All @@ -69,6 +83,7 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT
override def long(): Long = nodes.front match {
case LongValueNode(value) => value
case NumberValueNode(value) => value.longValue()
case ByteValueNode(value) => value.toLong
case ShortValueNode(value) => value.toLong
case IntValueNode(value) => value.toLong
case FloatValueNode(value) => value.toLong
Expand All @@ -79,6 +94,7 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT
override def float(): Float = nodes.front match {
case FloatValueNode(value) => value
case NumberValueNode(value) => value.floatValue()
case ByteValueNode(value) => value.toFloat
case ShortValueNode(value) => value.toFloat
case IntValueNode(value) => value.toFloat
case LongValueNode(value) => value.toFloat
Expand All @@ -89,6 +105,7 @@ class QueueIterator(private var nodes: immutable.Queue[TokenNode]) extends BaseT
override def double(): Double = nodes.front match {
case DoubleValueNode(value) => value
case NumberValueNode(value) => value.doubleValue()
case ByteValueNode(value) => value.toDouble
case ShortValueNode(value) => value.toDouble
case IntValueNode(value) => value.toDouble
case LongValueNode(value) => value.toDouble
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ trait TokenIterator {

def number(): Number

def byte(): Byte

def short(): Short

def int(): Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ trait AllJsonWriters extends OptionWriters with EitherWriters {
override def write(value: Long, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}

implicit lazy val byteWriter: JsonWriter[Byte] = new JsonWriter[Byte] {
override def write(value: Byte, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}

implicit lazy val shortWriter: JsonWriter[Short] = new JsonWriter[Short] {
override def write(value: Short, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}
Expand Down Expand Up @@ -52,6 +56,10 @@ trait AllJsonWriters extends OptionWriters with EitherWriters {
override def write(value: java.lang.Long, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}

implicit lazy val javaByteWriter: JsonWriter[java.lang.Byte] = new JsonWriter[java.lang.Byte] {
override def write(value: java.lang.Byte, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}

implicit lazy val javaShortWriter: JsonWriter[java.lang.Short] = new JsonWriter[java.lang.Short] {
override def write(value: java.lang.Short, tokenWriter: TokenWriter): Unit = tokenWriter.writeNumber(value)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class SimpleTokenWriter extends TokenWriter {

override def writeString(v: String): SimpleTokenWriter.this.type = append(StringValueNode(v))

override def writeNumber(v: Byte): SimpleTokenWriter.this.type = append(ByteValueNode(v))

override def writeNumber(v: Short): SimpleTokenWriter.this.type = append(ShortValueNode(v))

override def writeNumber(v: Int): SimpleTokenWriter.this.type = append(IntValueNode(v))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ trait TokenWriter {

def writeString(v: String): this.type

def writeNumber(v: Byte): this.type

def writeNumber(v: Short): this.type

def writeNumber(v: Int): this.type
Expand All @@ -30,6 +32,7 @@ trait TokenWriter {
def writeRawNumber(n: Number): this.type = n match {
case jbd: java.math.BigDecimal => writeNumber(BigDecimal(jbd))
case jint: java.lang.Integer => writeNumber(jint.intValue())
case jbyte: java.lang.Byte => writeNumber(jbyte.longValue())
case jshort: java.lang.Short => writeNumber(jshort.longValue())
case jlong: java.lang.Long => writeNumber(jlong.longValue())
case jbi: java.math.BigInteger => writeNumber(BigInt(jbi))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class DefaultReadersTest extends AnyFlatSpec {
test("1") -> value("1"),
test('1') -> value("1"),
test(1) -> value(1),
test(1: Byte) -> value(1: Byte),
test(1: Short) -> value(1: Short),
test(1L) -> value(1L),
test(1f) -> value(1f),
Expand All @@ -42,6 +43,7 @@ class DefaultReadersTest extends AnyFlatSpec {
test(Option(1), "Option.nonEmpty") -> value(1),
test(Option.empty[Int], "Option.empty") -> List(NullValueNode) ,
test(1: java.lang.Integer) -> value(1),
test(java.lang.Byte.valueOf(1: Byte)) -> value(1: Byte),
test(java.lang.Short.valueOf(1: Short)) -> value(1: Short),
test(1L: java.lang.Long) -> value(1L),
test(1f: java.lang.Float) -> value(1f),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class DefaultWritersTest extends AnyFlatSpec {
test("1") -> value("1"),
test('1') -> value("1"),
test(1) -> value(1),
test(1: Byte) -> value(1: Byte),
test(1: Short) -> value(1: Short),
test(1L) -> value(1L),
test(1f) -> value(1f),
Expand All @@ -44,6 +45,7 @@ class DefaultWritersTest extends AnyFlatSpec {
test(Right(1): Either[String, Int], "Either.right") -> value(1),
test(Left("Not an Int"): Either[String, Int], "Either.left") -> value("Not an Int"),
test(1: java.lang.Integer) -> value(1),
test(java.lang.Byte.valueOf(1: Byte)) -> value(1: Byte),
test(java.lang.Short.valueOf(1: Short)) -> value(1: Short),
test(1L: java.lang.Long) -> value(1L),
test(1f: java.lang.Float) -> value(1f),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ final class JacksonTokenIterator(jsonParser: JsonParser) extends BaseTokenIterat

override def number(): Number = jsonParser.getNumberValue

override def byte(): Byte = jsonParser.getByteValue

override def short(): Short = jsonParser.getShortValue

override def int(): Int = jsonParser.getIntValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class JacksonTokenWriter(jsonGenerator: JsonGenerator) extends TokenWriter {
this
}

override def writeNumber(v: Byte): JacksonTokenWriter.this.type = {
jsonGenerator.writeNumber(v)
this
}

override def writeNumber(v: Short): JacksonTokenWriter.this.type = {
jsonGenerator.writeNumber(v)
this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class JacksonTokenWriterTest extends AnyFlatSpec with Matchers {
iterate(_.writeString("string")) shouldBe """"string""""
}

it should "write Byte value" in {
iterate(_.writeNumber(1: Byte)) shouldBe """1"""
}

it should "write Short value" in {
iterate(_.writeNumber(1: Short)) shouldBe """1"""
}
Expand Down

0 comments on commit 065af1a

Please sign in to comment.