From fdecff3e91f0f902b8dfe6ea50640d89e3321981 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 22 Jul 2021 20:58:13 +0100 Subject: [PATCH] Fix #196 remove all unused boopickle codecs from interned boopickle --- .../internal/boopickle/CodecSize.scala | 404 +----------------- .../internal/boopickle/Codecs.scala | 184 +------- .../boopickle/CompositePicklers.scala | 66 +-- .../internal/boopickle/Constants.scala | 17 +- .../internal/boopickle/Default.scala | 57 +-- .../internal/boopickle/Pickler.scala | 275 +----------- 6 files changed, 31 insertions(+), 972 deletions(-) diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CodecSize.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CodecSize.scala index a792b6b2..817c9c95 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CodecSize.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CodecSize.scala @@ -18,14 +18,12 @@ package izumi.reflect.thirdparty.internal.boopickle -import java.nio.charset.CharacterCodingException -import java.nio.{ByteBuffer, ByteOrder} +import java.nio.ByteBuffer private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder { val stringCodec: StringCodecBase = StringCodec - /** - * Decodes a single byte + /** Decodes a single byte * * @return */ @@ -33,35 +31,7 @@ private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder { buf.get } - /** - * Decodes a UTF-8 encoded character (1-3 bytes) and produces a single UTF-16 character - * - * @return - */ - def readChar: Char = { - val b0 = buf.get & 0xFF - if (b0 < 0x80) - b0.toChar - else if ((b0 & 0xE0) == 0xC0) { - val b1 = buf.get & 0x3F - ((b0 & 0x1F) << 6 | b1).toChar - } else if ((b0 & 0xF0) == 0xE0) { - val s0 = buf.get & 0x3F - val s1 = buf.get & 0x3F - ((b0 & 0x0F) << 12 | s0 << 6 | s1).toChar - } else - throw new CharacterCodingException - } - - /** - * Decodes a 16-bit integer - */ - def readShort: Short = { - buf.getShort - } - - /** - * Decodes a 32-bit integer (1-5 bytes) + /** Decodes a 32-bit integer (1-5 bytes) *
     * 0XXX XXXX                            = 0 to 127
     * 1000 XXXX  b0                        = 128 to 4095
@@ -81,7 +51,7 @@ private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder {
     if ((b & 0x80) != 0) {
       // special coding, expand sign bit
       val sign = if ((b & 0x10) == 0) 1 else -1
-      val b0   = b & 0xF
+      val b0 = b & 0xF
       b >> 4 match {
         case 0x8 | 0x9 =>
           val b1 = buf.get & 0xFF
@@ -109,108 +79,7 @@ private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder {
     buf.getInt
   }
 
-  /**
-    * Decodes a 64-bit integer (1-9 bytes)
-    * 
-    * 0XXX XXXX                            = 0 to 127
-    * 1000 XXXX  b0                        = 128 to 4095
-    * 1001 XXXX  b0                        = -1 to -4095
-    * 1010 XXXX  b0 b1                     = 4096 to 1048575
-    * 1011 XXXX  b0 b1                     = -4096 to -1048575
-    * 1100 XXXX  b0 b1 b2                  = 1048576 to 268435455
-    * 1101 XXXX  b0 b1 b2                  = -1048576 to -268435455
-    * 1110 0000  b0 b1 b2 b3               = MinInt to MaxInt
-    * 1110 0001  b0 b1 b2 b3 b4 b5 b6 b7   = anything larger
-    * 1111 ????                            = reserved for special codings
-    * 
- * - * @return - */ - def readLong: Long = { - val b = buf.get & 0xFF - if (b != 0xE1) { - (buf: java.nio.Buffer).position(buf.position() - 1) - readInt.toLong - } else { - readRawLong - } - } - - def readRawLong: Long = { - buf.getLong - } - - /** - * Decodes a 32-bit integer, or returns the first byte if it doesn't contain a valid encoding marker - * - * @return - */ - def readIntCode: Either[Byte, Int] = { - val b = buf.get & 0xFF - if ((b & 0x80) != 0) { - // special coding, expand sign bit - val sign = if ((b & 0x10) == 0) 1 else -1 - val b0 = b & 0xF - b >> 4 match { - case 0x8 | 0x9 => - val b1 = buf.get & 0xFF - Right(sign * (b0 << 8 | b1)) - case 0xA | 0xB => - val b1 = buf.get & 0xFF - val b2 = buf.get & 0xFF - Right(sign * (b0 << 16 | b1 << 8 | b2)) - case 0xC | 0xD => - val b1 = buf.get & 0xFF - val b2 = buf.get & 0xFF - val b3 = buf.get & 0xFF - Right(sign * (b0 << 24 | b1 << 16 | b2 << 8 | b3)) - case 0xE if b == 0xE0 => - Right(sign * readRawInt) - case _ => - Left((b & 0xF).toByte) - } - } else { - Right(b) - } - } - - /** - * Decodes a 64-bit long, or returns the first byte if it doesn't contain a valid encoding marker - * - * @return - */ - def readLongCode: Either[Byte, Long] = { - val b = buf.get & 0xFF - if (b != 0xE1) { - (buf: java.nio.Buffer).position(buf.position() - 1) - readIntCode match { - case Left(x) => Left((x & 0xF).toByte) - case Right(x) => Right(x.toLong) - } - } else - Right(readRawLong) - } - - /** - * Decodes a 32-bit float (4 bytes) - * - * @return - */ - def readFloat: Float = { - buf.getFloat - } - - /** - * Decodes a 64-bit double (8 bytes) - * - * @return - */ - def readDouble: Double = { - buf.getDouble - } - - /** - * Decodes a UTF-8 encoded string + /** Decodes a UTF-8 encoded string * * @return */ @@ -220,8 +89,7 @@ private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder { stringCodec.decodeFast(len, buf) } - /** - * Decodes a UTF-8 encoded string whose length is already known + /** Decodes a UTF-8 encoded string whose length is already known * * @param len Length of the string (in bytes) * @return @@ -230,69 +98,6 @@ private[reflect] class DecoderSize(val buf: ByteBuffer) extends Decoder { stringCodec.decodeFast(len, buf) } - def readByteBuffer: ByteBuffer = { - // length and byte order are encoded into same integer - val sizeBO = readInt - if (sizeBO < 0) - throw new IllegalArgumentException(s"Invalid size $sizeBO for ByteBuffer") - val size = sizeBO >> 1 - val byteOrder = if ((sizeBO & 1) == 1) ByteOrder.BIG_ENDIAN else ByteOrder.LITTLE_ENDIAN - // create a copy (sharing content), set correct byte order - val b = buf.slice().order(byteOrder) - (buf: java.nio.Buffer).position(buf.position() + size) - (b: java.nio.Buffer).limit(b.position() + size) - b - } - - /** - * Decodes an array of Bytes - */ - def readByteArray(): Array[Byte] = readByteArray(readRawInt) - def readByteArray(len: Int): Array[Byte] = { - val array = new Array[Byte](len) - buf.get(array) - array - } - - /** - * Decodes an array of Integers - */ - def readIntArray(): Array[Int] = readIntArray(readRawInt) - def readIntArray(len: Int): Array[Int] = { - val array = new Array[Int](len) - var i = 0 - while (i < len) { - array(i) = readInt - i += 1 - } - array - } - - /** - * Decodes an array of Floats - */ - def readFloatArray(): Array[Float] = readFloatArray(readRawInt) - def readFloatArray(len: Int): Array[Float] = { - val array = new Array[Float](len) - buf.asFloatBuffer().get(array) - (buf: java.nio.Buffer).position(buf.position() + len * 4) - array - } - - /** - * Decodes an array of Doubles - */ - def readDoubleArray(): Array[Double] = { - val len = readRawInt - readRawInt // remove padding - readDoubleArray(len) - } - def readDoubleArray(len: Int): Array[Double] = { - val array = new Array[Double](len) - buf.asDoubleBuffer().get(array) - (buf: java.nio.Buffer).position(buf.position() + len * 8) - array - } } private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteBufferProvider.provider) extends Encoder { @@ -300,8 +105,7 @@ private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteB @inline private def alloc(size: Int): ByteBuffer = bufferProvider.alloc(size) - /** - * Encodes a single byte + /** Encodes a single byte * * @param b Byte to encode * @return @@ -311,33 +115,7 @@ private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteB this } - /** - * Encodes a single character using UTF-8 encoding - * - * @param c Character to encode - * @return - */ - def writeChar(c: Char): Encoder = { - if (c < 0x80) { - alloc(1).put(c.toByte) - } else if (c < 0x800) { - alloc(2).put((0xC0 | (c >>> 6 & 0x3F)).toByte).put((0x80 | (c & 0x3F)).toByte) - } else { - alloc(3).put((0xE0 | (c >>> 12)).toByte).put((0x80 | (c >>> 6 & 0x3F)).toByte).put((0x80 | (c & 0x3F)).toByte) - } - this - } - - /** - * Encodes a short integer - */ - def writeShort(s: Short): Encoder = { - alloc(2).putShort(s) - this - } - - /** - * Encodes an integer efficiently in 1 to 5 bytes + /** Encodes an integer efficiently in 1 to 5 bytes *
     * 0XXX XXXX                            = 0 to 127
     * 1000 XXXX  b0                        = 128 to 4095
@@ -359,7 +137,7 @@ private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteB
     } else {
       if (i > -268435456 && i < 268435456) {
         val mask = i >>> 31 << 4
-        val a    = Math.abs(i)
+        val a = Math.abs(i)
         if (a < 4096) {
           alloc(2).put((mask | 0x80 | (a >> 8)).toByte).put((a & 0xFF).toByte)
         } else if (a < 1048576) {
@@ -378,86 +156,7 @@ private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteB
     this
   }
 
-  /**
-    * Encodes an integer in 32-bits
-    *
-    * @param i Integer to encode
-    * @return
-    */
-  def writeRawInt(i: Int): Encoder = {
-    alloc(4).putInt(i)
-    this
-  }
-
-  /**
-    * Encodes a long efficiently in 1 to 9 bytes
-    * 
-    * 0XXX XXXX                            = 0 to 127
-    * 1000 XXXX  b0                        = 128 to 4095
-    * 1001 XXXX  b0                        = -1 to -4096
-    * 1010 XXXX  b0 b1                     = 4096 to 1048575
-    * 1011 XXXX  b0 b1                     = -4096 to -1048575
-    * 1100 XXXX  b0 b1 b2                  = 1048576 to 268435455
-    * 1101 XXXX  b0 b1 b2                  = -1048576 to -268435455
-    * 1110 0000  b0 b1 b2 b3               = MinInt to MaxInt
-    * 1110 0001  b0 b1 b2 b3 b4 b5 b6 b7   = anything larger
-    * 1111 ????                            = reserved for special codings
-    * 
- * - * @param l Long to encode - */ - def writeLong(l: Long): Encoder = { - if (l <= Int.MaxValue && l >= Int.MinValue) - writeInt(l.toInt) - else { - alloc(9).put(0xE1.toByte).putLong(l) - } - this - } - - /** - * Encodes a long in 64-bits - * - * @param l Long to encode - * @return - */ - def writeRawLong(l: Long): Encoder = { - alloc(8).putLong(l) - this - } - - /** - * Writes either a code byte (0-15) or an Int - * - * @param intCode Integer or a code byte - */ - def writeIntCode(intCode: Either[Byte, Int]): Encoder = { - intCode match { - case Left(code) => - alloc(1).put((code | 0xF0).toByte) - case Right(i) => - writeInt(i) - } - this - } - - /** - * Writes either a code byte (0-15) or a Long - * - * @param longCode Long or a code byte - */ - def writeLongCode(longCode: Either[Byte, Long]): Encoder = { - longCode match { - case Left(code) => - alloc(1).put((code | 0xF0).toByte) - case Right(l) => - writeLong(l) - } - this - } - - /** - * Encodes a string using UTF8 + /** Encodes a string using UTF8 * * @param s String to encode * @return @@ -469,88 +168,7 @@ private[reflect] class EncoderSize(bufferProvider: BufferProvider = DefaultByteB this } - /** - * Encodes a float as 4 bytes - * - * @param f Float to encode - * @return - */ - def writeFloat(f: Float): Encoder = { - alloc(4).putFloat(f) - this - } - - /** - * Encodes a double as 8 bytes - * - * @param d Double to encode - * @return - */ - def writeDouble(d: Double): Encoder = { - alloc(8).putDouble(d) - this - } - - /** - * Encodes a ByteBuffer by writing its length and content - * - * @param bb ByteBuffer to encode - * @return - */ - def writeByteBuffer(bb: ByteBuffer): Encoder = { - bb.mark() - val byteOrder = if (bb.order() == ByteOrder.BIG_ENDIAN) 1 else 0 - // encode byte order as bit 0 in the length - writeInt(bb.remaining * 2 | byteOrder) - alloc(bb.remaining).put(bb) - (bb: java.nio.Buffer).reset() - this - } - - /** - * Encodes an array of Bytes - */ - def writeByteArray(ba: Array[Byte]): Encoder = { - writeRawInt(ba.length) - alloc(ba.length).put(ba) - this - } - - /** - * Encodes an array of Integers - */ - def writeIntArray(ia: Array[Int]): Encoder = { - writeRawInt(ia.length) - ia.foreach(writeInt) - this - } - - /** - * Encodes an array of Floats - */ - def writeFloatArray(fa: Array[Float]): Encoder = { - writeRawInt(fa.length) - val bb = alloc(fa.length * 4) - bb.asFloatBuffer().put(fa) - (bb: java.nio.Buffer).position(bb.position() + fa.length * 4) - this - } - - /** - * Encodes an array of Doubles - */ - def writeDoubleArray(da: Array[Double]): Encoder = { - writeRawInt(da.length) - // padding - writeRawInt(0) - val bb = alloc(da.length * 8) - bb.asDoubleBuffer().put(da) - (bb: java.nio.Buffer).position(bb.position() + da.length * 8) - this - } - - /** - * Completes the encoding and returns the ByteBuffer + /** Completes the encoding and returns the ByteBuffer * * @return */ diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Codecs.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Codecs.scala index 0d002fb9..5f9959cc 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Codecs.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Codecs.scala @@ -22,212 +22,44 @@ import java.nio.ByteBuffer private[reflect] trait Decoder { - /** - * Decodes a single byte - * + /** Decodes a single byte */ def readByte: Byte - /** - * Decodes a UTF-8 encoded character (1-3 bytes) and produces a single UTF-16 character - * - */ - def readChar: Char - - /** - * Decodes a 16-bit integer - */ - def readShort: Short - - /** - * Decodes a 32-bit integer + /** Decodes a 32-bit integer */ def readInt: Int - def readRawInt: Int - - /** - * Decodes a 64-bit integer - */ - def readLong: Long - - def readRawLong: Long - - /** - * Decodes a 32-bit integer, or returns the first byte if it doesn't contain a valid encoding marker - */ - def readIntCode: Either[Byte, Int] - - /** - * Decodes a 64-bit long, or returns the first byte if it doesn't contain a valid encoding marker - */ - def readLongCode: Either[Byte, Long] - - /** - * Decodes a 32-bit float (4 bytes) - */ - def readFloat: Float - - /** - * Decodes a 64-bit double (8 bytes) - * - */ - def readDouble: Double - - /** - * Decodes a string - * + /** Decodes a string */ def readString: String - /** - * Decodes a string whose length is already known + /** Decodes a string whose length is already known * * @param len Length of the string (in bytes) */ def readString(len: Int): String - - /** - * Decodes a ByteBuffer - */ - def readByteBuffer: ByteBuffer - - /** - * Decodes an array of Bytes - */ - def readByteArray(): Array[Byte] - def readByteArray(len: Int): Array[Byte] - - /** - * Decodes an array of Integers - */ - def readIntArray(): Array[Int] - def readIntArray(len: Int): Array[Int] - - /** - * Decodes an array of Floats - */ - def readFloatArray(): Array[Float] - def readFloatArray(len: Int): Array[Float] - - /** - * Decodes an array of Doubles - */ - def readDoubleArray(): Array[Double] - def readDoubleArray(len: Int): Array[Double] } private[reflect] trait Encoder { - /** - * Encodes a single byte + /** Encodes a single byte * * @param b Byte to encode */ def writeByte(b: Byte): Encoder - /** - * Encodes a single character using UTF-8 encoding - * - * @param c Character to encode - */ - def writeChar(c: Char): Encoder - - /** - * Encodes a short integer - */ - def writeShort(s: Short): Encoder - - /** - * Encodes an integer + /** Encodes an integer */ def writeInt(i: Int): Encoder - /** - * Encodes an integer in 32-bits - * - * @param i Integer to encode - */ - def writeRawInt(i: Int): Encoder - - /** - * Encodes a long - * - * @param l Long to encode - */ - def writeLong(l: Long): Encoder - - /** - * Encodes a long in 64-bits - * - * @param l Long to encode - */ - def writeRawLong(l: Long): Encoder - - /** - * Writes either a code byte (0-15) or an Int - * - * @param intCode Integer or a code byte - */ - def writeIntCode(intCode: Either[Byte, Int]): Encoder - - /** - * Writes either a code byte (0-15) or a Long - * - * @param longCode Long or a code byte - */ - def writeLongCode(longCode: Either[Byte, Long]): Encoder - - /** - * Encodes a string + /** Encodes a string * * @param s String to encode */ def writeString(s: String): Encoder - /** - * Encodes a float as 4 bytes - * - * @param f Float to encode - */ - def writeFloat(f: Float): Encoder - - /** - * Encodes a double as 8 bytes - * - * @param d Double to encode - */ - def writeDouble(d: Double): Encoder - - /** - * Encodes a ByteBuffer by writing its length and content - * - * @param bb ByteBuffer to encode - */ - def writeByteBuffer(bb: ByteBuffer): Encoder - - /** - * Encodes an array of Bytes - */ - def writeByteArray(ba: Array[Byte]): Encoder - - /** - * Encodes an array of Integers - */ - def writeIntArray(ia: Array[Int]): Encoder - - /** - * Encodes an array of Floats - */ - def writeFloatArray(fa: Array[Float]): Encoder - - /** - * Encodes an array of Doubles - */ - def writeDoubleArray(da: Array[Double]): Encoder - - /** - * Completes the encoding and returns the ByteBuffer + /** Completes the encoding and returns the ByteBuffer */ def asByteBuffer: ByteBuffer } diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CompositePicklers.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CompositePicklers.scala index dbc965ee..129e2dff 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CompositePicklers.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/CompositePicklers.scala @@ -21,8 +21,7 @@ package izumi.reflect.thirdparty.internal.boopickle import scala.collection.mutable import scala.reflect.ClassTag -/** - * Encodes a class belonging to a type hierarchy. Type is identified by the index in the `picklers` sequence, so care +/** Encodes a class belonging to a type hierarchy. Type is identified by the index in the `picklers` sequence, so care * must be taken to ensure picklers are added in the same order. */ private[reflect] class CompositePickler[A] extends Pickler[A] { @@ -30,7 +29,7 @@ private[reflect] class CompositePickler[A] extends Pickler[A] { import Constants._ private var picklerClasses = IdentMap.empty - private val picklers = mutable.ArrayBuffer.empty[(Class[_], Pickler[_])] + private val picklers = mutable.ArrayBuffer.empty[(Class[_], Pickler[_])] override def pickle(obj: A)(implicit state: PickleState): Unit = { if (obj == null) { @@ -72,65 +71,4 @@ private[reflect] class CompositePickler[A] extends Pickler[A] { this } - @noinline def addTransform[B <: A, C](transformTo: (B) => C, transformFrom: (C) => B)( - implicit p: Pickler[C], - tag: ClassTag[B]): CompositePickler[A] = { - val pickler = p.xmap(transformFrom)(transformTo) - addPickler(pickler, tag) - this - } - - @noinline def addException[B <: A with Throwable](ctor: (String) => B)(implicit tag: ClassTag[B]): CompositePickler[A] = { - import NoMacro.stringPickler - val pickler = new Pickler[B] { - override def pickle(ex: B)(implicit state: PickleState): Unit = { - state.pickle(ex.getMessage) - } - - override def unpickle(implicit state: UnpickleState): B = { - ctor(state.unpickle[String]) - } - } - addPickler(pickler, tag) - this - } - - def join[B <: A](implicit cp: CompositePickler[B]): CompositePickler[A] = { - picklers.appendAll(cp.picklers) - picklerClasses = IdentMap.empty - picklers.foreach(cp => picklerClasses = picklerClasses.updated(cp._1)) - this - } -} - -private[reflect] object CompositePickler { - def apply[A] = new CompositePickler[A] -} - -private[reflect] object ExceptionPickler { - def empty = CompositePickler[Throwable] - // generate base exception picklers - private lazy val basePicklers = CompositePickler[Throwable] - .addException[Exception](m => new Exception(m)) - .addException[RuntimeException](m => new RuntimeException(m)) - .addException[MatchError](m => new MatchError(m)) - .addException[UninitializedFieldError](m => new UninitializedFieldError(m)) - .addException[NullPointerException](m => new NullPointerException(m)) - .addException[ClassCastException](m => new ClassCastException(m)) - .addException[IndexOutOfBoundsException](m => new IndexOutOfBoundsException(m)) - .addException[ArrayIndexOutOfBoundsException](m => new ArrayIndexOutOfBoundsException(m)) - .addException[StringIndexOutOfBoundsException](m => new StringIndexOutOfBoundsException(m)) - .addException[UnsupportedOperationException](m => new UnsupportedOperationException(m)) - .addException[IllegalArgumentException](m => new IllegalArgumentException(m)) - .addException[IllegalStateException](m => new IllegalStateException(m)) - .addException[NoSuchElementException](m => new NoSuchElementException(m)) - .addException[NumberFormatException](m => new NumberFormatException(m)) - .addException[ArithmeticException](m => new ArithmeticException(m)) - .addException[InterruptedException](m => new InterruptedException(m)) - - /** - * Provides simple (message only) pickling of most common Java/Scala exception types. This can be used - * as a base for adding custom exception types. - */ - def base = CompositePickler[Throwable].join(basePicklers) } diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Constants.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Constants.scala index bf7bbc8c..9125e267 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Constants.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Constants.scala @@ -19,24 +19,9 @@ package izumi.reflect.thirdparty.internal.boopickle private[boopickle] object Constants { - final val NullRef = -1 + final val NullRef = -1 final val NullObject = 0 - // codes for special strings - final val StringInt: Byte = 1 - final val StringLong: Byte = 2 - final val StringUUID: Byte = 3 - final val StringUUIDUpper: Byte = 4 - - // codes for special Durations - final val DurationInf: Byte = 1 - final val DurationMinusInf: Byte = 2 - final val DurationUndefined: Byte = 3 - - // codes for Either - final val EitherLeft: Byte = 1 - final val EitherRight: Byte = 2 - // codes for Option final val OptionNone: Byte = 1 final val OptionSome: Byte = 2 diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Default.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Default.scala index 0b12333c..aee160ec 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Default.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Default.scala @@ -18,41 +18,15 @@ package izumi.reflect.thirdparty.internal.boopickle +import java.nio.ByteBuffer import java.nio.charset.StandardCharsets -import java.nio.{ByteBuffer, ByteOrder} -import java.util.UUID -import scala.concurrent.duration.{Duration, FiniteDuration} -//import scala.language.experimental.macros -import scala.reflect.ClassTag -import scala.util.Try private[reflect] trait BasicImplicitPicklers extends PicklerHelper with XCompatImplicitPicklers { - implicit def unitPickler: ConstPickler[Unit] = BasicPicklers.UnitPickler implicit def booleanPickler: P[Boolean] = BasicPicklers.BooleanPickler - implicit def bytePickler: P[Byte] = BasicPicklers.BytePickler - implicit def shortPickler: P[Short] = BasicPicklers.ShortPickler - implicit def charPickler: P[Char] = BasicPicklers.CharPickler implicit def intPickler: P[Int] = BasicPicklers.IntPickler - implicit def longPickler: P[Long] = BasicPicklers.LongPickler - implicit def floatPickler: P[Float] = BasicPicklers.FloatPickler - implicit def doublePickler: P[Double] = BasicPicklers.DoublePickler - implicit def byteBufferPickler: P[ByteBuffer] = BasicPicklers.ByteBufferPickler implicit def stringPickler: P[String] = BasicPicklers.StringPickler - // less frequently used picklers are initializes lazily to enable DCE - implicit lazy val bigIntPickler: P[BigInt] = BasicPicklers.BigIntPickler - implicit lazy val bigDecimalPickler: P[BigDecimal] = BasicPicklers.BigDecimalPickler - implicit lazy val UUIDPickler: P[UUID] = BasicPicklers.UUIDPickler - implicit lazy val durationPickler: P[Duration] = BasicPicklers.DurationPickler - implicit lazy val finiteDurationPickler: P[FiniteDuration] = BasicPicklers.FiniteDurationPickler - implicit lazy val infiniteDurationPickler: P[Duration.Infinite] = BasicPicklers.InfiniteDurationPickler - implicit def optionPickler[T: P]: P[Option[T]] = BasicPicklers.OptionPickler[T] - implicit def somePickler[T: P]: P[Some[T]] = BasicPicklers.SomePickler[T] - implicit def eitherPickler[T: P, S: P]: P[Either[T, S]] = BasicPicklers.EitherPickler[T, S] - implicit def leftPickler[T: P, S: P]: P[Left[T, S]] = BasicPicklers.LeftPickler[T, S] - implicit def rightPickler[T: P, S: P]: P[Right[T, S]] = BasicPicklers.RightPickler[T, S] - implicit def arrayPickler[T: P: ClassTag]: P[Array[T]] = BasicPicklers.ArrayPickler[T] } private[reflect] object PickleImpl { @@ -72,38 +46,9 @@ private[reflect] object PickleImpl { } } -private[reflect] object UnpickleImpl { - def apply[A](implicit u: Pickler[A]) = UnpickledCurry(u) - - private[reflect] case class UnpickledCurry[A](u: Pickler[A]) { - def apply(implicit state: UnpickleState): A = u.unpickle(state) - - def fromBytes(bytes: ByteBuffer)(implicit buildState: ByteBuffer => UnpickleState): A = { - // keep original byte order - val origByteOrder = bytes.order() - // but decode as little-endian - val result = u.unpickle(buildState(bytes.order(ByteOrder.LITTLE_ENDIAN))) - bytes.order(origByteOrder) - result - } - - def tryFromBytes(bytes: ByteBuffer)(implicit buildState: ByteBuffer => UnpickleState): Try[A] = Try(fromBytes(bytes)) - - def fromState(state: UnpickleState): A = u.unpickle(state) - } - -} - private[reflect] trait Base { type Pickler[A] = _root_.izumi.reflect.thirdparty.internal.boopickle.Pickler[A] - def Pickle: PickleImpl.type = _root_.izumi.reflect.thirdparty.internal.boopickle.PickleImpl type PickleState = _root_.izumi.reflect.thirdparty.internal.boopickle.PickleState - def Unpickle: UnpickleImpl.type = _root_.izumi.reflect.thirdparty.internal.boopickle.UnpickleImpl - type UnpickleState = _root_.izumi.reflect.thirdparty.internal.boopickle.UnpickleState - - def compositePickler[A <: AnyRef]: CompositePickler[A] = CompositePickler[A] - - def exceptionPickler: CompositePickler[Throwable] = ExceptionPickler.base } private[reflect] object NoMacro extends Base with BasicImplicitPicklers with TuplePicklers diff --git a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Pickler.scala b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Pickler.scala index f671870b..aeb3c5e8 100644 --- a/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Pickler.scala +++ b/izumi-reflect/izumi-reflect-thirdparty-boopickle-shaded/src/main/scala/izumi/reflect/thirdparty/internal/boopickle/Pickler.scala @@ -19,11 +19,7 @@ package izumi.reflect.thirdparty.internal.boopickle import java.nio.ByteBuffer -import java.util.UUID - import scala.collection.mutable -import scala.concurrent.duration.{Duration, FiniteDuration} -import scala.reflect.ClassTag private[reflect] trait Pickler[A] { def pickle(obj: A)(implicit state: PickleState): Unit @@ -42,26 +38,14 @@ private[reflect] trait Pickler[A] { } } -/** - * A Pickler that always returns a constant value. - * - * Stores nothing in the pickled output. - */ -private[reflect] final case class ConstPickler[A](a: A) extends Pickler[A] { - @inline override def pickle(x: A)(implicit s: PickleState) = () - @inline override def unpickle(implicit s: UnpickleState) = a -} - private[reflect] trait PicklerHelper { protected type P[A] = Pickler[A] - /** - * Helper function to write pickled types + /** Helper function to write pickled types */ protected def write[A](value: A)(implicit state: PickleState, p: P[A]): Unit = p.pickle(value)(state) - /** - * Helper function to unpickle a type + /** Helper function to unpickle a type */ protected def read[A](implicit state: UnpickleState, u: P[A]): A = u.unpickle } @@ -70,8 +54,6 @@ private[reflect] object BasicPicklers extends PicklerHelper with XCompatPicklers import Constants._ - val UnitPickler = ConstPickler(()) - object BooleanPickler extends P[Boolean] { @inline override def pickle(value: Boolean)(implicit state: PickleState): Unit = state.enc.writeByte(if (value) 1 else 0) @inline override def unpickle(implicit state: UnpickleState): Boolean = { @@ -83,71 +65,11 @@ private[reflect] object BasicPicklers extends PicklerHelper with XCompatPicklers } } - object BytePickler extends P[Byte] { - @inline override def pickle(value: Byte)(implicit state: PickleState): Unit = state.enc.writeByte(value) - @inline override def unpickle(implicit state: UnpickleState): Byte = state.dec.readByte - } - - object ShortPickler extends P[Short] { - @inline override def pickle(value: Short)(implicit state: PickleState): Unit = state.enc.writeShort(value) - @inline override def unpickle(implicit state: UnpickleState): Short = state.dec.readShort - } - - object CharPickler extends P[Char] { - @inline override def pickle(value: Char)(implicit state: PickleState): Unit = state.enc.writeChar(value) - @inline override def unpickle(implicit state: UnpickleState): Char = state.dec.readChar - } - object IntPickler extends P[Int] { @inline override def pickle(value: Int)(implicit state: PickleState): Unit = state.enc.writeInt(value) @inline override def unpickle(implicit state: UnpickleState): Int = state.dec.readInt } - object LongPickler extends P[Long] { - @inline override def pickle(value: Long)(implicit state: PickleState): Unit = state.enc.writeLong(value) - @inline override def unpickle(implicit state: UnpickleState): Long = state.dec.readLong - } - - object FloatPickler extends P[Float] { - @inline override def pickle(value: Float)(implicit state: PickleState): Unit = state.enc.writeFloat(value) - @inline override def unpickle(implicit state: UnpickleState): Float = state.dec.readFloat - } - - object DoublePickler extends P[Double] { - @inline override def pickle(value: Double)(implicit state: PickleState): Unit = state.enc.writeDouble(value) - @inline override def unpickle(implicit state: UnpickleState): Double = state.dec.readDouble - } - - object ByteBufferPickler extends P[ByteBuffer] { - @inline override def pickle(bb: ByteBuffer)(implicit state: PickleState): Unit = state.enc.writeByteBuffer(bb) - @inline override def unpickle(implicit state: UnpickleState): ByteBuffer = state.dec.readByteBuffer - } - - object BigIntPickler extends P[BigInt] { - implicit def bp: BytePickler.type = BytePickler - - @inline override def pickle(value: BigInt)(implicit state: PickleState): Unit = { - ArrayPickler.pickle(value.toByteArray) - } - @inline override def unpickle(implicit state: UnpickleState): BigInt = { - BigInt(ArrayPickler.unpickle) - } - } - - object BigDecimalPickler extends P[BigDecimal] { - implicit def bp: BytePickler.type = BytePickler - - @inline override def pickle(value: BigDecimal)(implicit state: PickleState): Unit = { - state.enc.writeInt(value.scale) - ArrayPickler.pickle(value.underlying().unscaledValue.toByteArray) - } - @inline override def unpickle(implicit state: UnpickleState): BigDecimal = { - val scale = state.dec.readInt - val arr = ArrayPickler.unpickle - BigDecimal(BigInt(arr), scale) - } - } - object StringPickler extends P[String] { override def pickle(s: String)(implicit state: PickleState): Unit = { state.immutableRefFor(s) match { @@ -177,74 +99,6 @@ private[reflect] object BasicPicklers extends PicklerHelper with XCompatPicklers } } - object UUIDPickler extends P[UUID] { - override def pickle(s: UUID)(implicit state: PickleState): Unit = { - if (s == null) { - state.enc.writeRawLong(0) - state.enc.writeRawLong(0) - state.enc.writeByte(0) - } else { - val msb = s.getMostSignificantBits - val lsb = s.getLeastSignificantBits - state.enc.writeRawLong(msb) - state.enc.writeRawLong(lsb) - // special encoding for UUID zero, to differentiate from null - if (msb == 0 && lsb == 0) - state.enc.writeByte(1) - } - } - - @inline override def unpickle(implicit state: UnpickleState): UUID = { - val msb = state.dec.readRawLong - val lsb = state.dec.readRawLong - - if (msb == 0 && lsb == 0) { - val actualUuidByte = state.dec.readByte - if (actualUuidByte == 0) null else new UUID(0, 0) - } else - new UUID(msb, lsb) - } - } - - object DurationPickler extends P[Duration] { - override def pickle(value: Duration)(implicit state: PickleState): Unit = { - // take care of special Durations - value match { - case null => - state.enc.writeLongCode(Left(NullObject.toByte)) - case Duration.Inf => - state.enc.writeLongCode(Left(DurationInf)) - case Duration.MinusInf => - state.enc.writeLongCode(Left(DurationMinusInf)) - case x if x eq Duration.Undefined => - state.enc.writeLongCode(Left(DurationUndefined)) - case x => - state.enc.writeLongCode(Right(x.toNanos)) - } - } - - @inline override def unpickle(implicit state: UnpickleState): Duration = { - state.dec.readLongCode match { - case Left(NullObject) => - null - case Left(DurationInf) => - Duration.Inf - case Left(DurationMinusInf) => - Duration.MinusInf - case Left(DurationUndefined) => - Duration.Undefined - case Right(value) => - Duration.fromNanos(value) - case Left(_) => - null - } - } - } - - def FiniteDurationPickler: P[FiniteDuration] = DurationPickler.asInstanceOf[P[FiniteDuration]] - - def InfiniteDurationPickler: P[Duration.Infinite] = DurationPickler.asInstanceOf[P[Duration.Infinite]] - def OptionPickler[T: P]: P[Option[T]] = new P[Option[T]] { override def pickle(obj: Option[T])(implicit state: PickleState): Unit = { obj match { @@ -274,108 +128,9 @@ private[reflect] object BasicPicklers extends PicklerHelper with XCompatPicklers } } - def SomePickler[T: P]: P[Some[T]] = OptionPickler[T].asInstanceOf[P[Some[T]]] - - def EitherPickler[T: P, S: P]: P[Either[T, S]] = new P[Either[T, S]] { - override def pickle(obj: Either[T, S])(implicit state: PickleState): Unit = { - obj match { - case null => - state.enc.writeInt(NullObject) - case Left(l) => - state.enc.writeInt(EitherLeft.toInt) - write[T](l) - case Right(r) => - state.enc.writeInt(EitherRight.toInt) - write[S](r) - } - } - - override def unpickle(implicit state: UnpickleState): Either[T, S] = { - state.dec.readInt match { - case NullObject => - null - case EitherLeft => - Left(read[T]) - case EitherRight => - Right(read[S]) - case _ => - throw new IllegalArgumentException("Invalid coding for Either type") - } - } - } - - def LeftPickler[T: P, S: P]: P[Left[T, S]] = EitherPickler[T, S].asInstanceOf[P[Left[T, S]]] - - def RightPickler[T: P, S: P]: P[Right[T, S]] = EitherPickler[T, S].asInstanceOf[P[Right[T, S]]] - - /** - * Specific pickler for Arrays - * - * @tparam T Type of values - * @return - */ - def ArrayPickler[T: P: ClassTag]: P[Array[T]] = new P[Array[T]] { - override def pickle(array: Array[T])(implicit state: PickleState): Unit = { - if (array == null) - state.enc.writeRawInt(NullRef) - else { - // check if this iterable has been pickled already - implicitly[ClassTag[T]] match { - // handle specialization - case ClassTag.Byte => - state.enc.writeByteArray(array.asInstanceOf[Array[Byte]]) - case ClassTag.Int => - state.enc.writeIntArray(array.asInstanceOf[Array[Int]]) - case ClassTag.Float => - state.enc.writeFloatArray(array.asInstanceOf[Array[Float]]) - case ClassTag.Double => - state.enc.writeDoubleArray(array.asInstanceOf[Array[Double]]) - case _ => - // encode length - state.enc.writeRawInt(array.length) - // encode contents - array.foreach(a => write[T](a)) - } - } - } - - override def unpickle(implicit state: UnpickleState): Array[T] = { - state.dec.readRawInt match { - case NullRef => - null - case 0 => - // empty Array - Array.empty[T] - case len => - val r = implicitly[ClassTag[T]] match { - // handle specialization - case ClassTag.Byte => - state.dec.readByteArray(len).asInstanceOf[Array[T]] - case ClassTag.Int => - state.dec.readIntArray(len).asInstanceOf[Array[T]] - case ClassTag.Float => - state.dec.readFloatArray(len).asInstanceOf[Array[T]] - case ClassTag.Double => - // remove padding - state.dec.readRawInt - state.dec.readDoubleArray(len).asInstanceOf[Array[T]] - case _ => - val a = new Array[T](len) - var i = 0 - while (i < len) { - a(i) = read[T] - i += 1 - } - a - } - r - } - } - } } -/** - * Manage state for a pickling "session". +/** Manage state for a pickling "session". * * @param enc Encoder instance to use * @param dedupImmutable Set to `false` if you want to disable deduplication of immutable values (like Strings) @@ -386,8 +141,7 @@ private[reflect] final class PickleState(val enc: Encoder, dedupImmutable: Boole @inline def addIdentityRef(obj: AnyRef): Unit = () - /** - * Object reference for immutable pickled objects + /** Object reference for immutable pickled objects */ private[this] var immutableRefs: mutable.AnyRefMap[AnyRef, Int] = null private[this] var immutableIdx = 2 @@ -422,16 +176,14 @@ private[reflect] final class PickleState(val enc: Encoder, dedupImmutable: Boole private[reflect] object PickleState { - /** - * Provides a default PickleState if none is available implicitly + /** Provides a default PickleState if none is available implicitly * * @return */ implicit def pickleStateSpeed: PickleState = new PickleState(new EncoderSize, dedupImmutable = true) } -/** - * Manage state for an unpickling "session" +/** Manage state for an unpickling "session" * * @param dec Decoder instance to use * @param deduplicate Set to `false` if you want to disable deduplication @@ -439,8 +191,7 @@ private[reflect] object PickleState { */ private[reflect] final class UnpickleState(val dec: Decoder, deduplicate: Boolean = true, dedupImmutable: Boolean = true) { - /** - * Object reference for pickled objects (use identity for equality comparison) + /** Object reference for pickled objects (use identity for equality comparison) * * Index 0 is not used * Index 1 = null @@ -465,8 +216,7 @@ private[reflect] final class UnpickleState(val dec: Decoder, deduplicate: Boolea if (deduplicate) identityRefs = identityRefs.updated(obj) - /** - * Object reference for immutable pickled objects + /** Object reference for immutable pickled objects */ private[this] var immutableRefs: IdentList = EmptyIdentList @@ -488,15 +238,6 @@ private[reflect] final class UnpickleState(val dec: Decoder, deduplicate: Boolea } private[reflect] object UnpickleState { - - /** - * Provides a default UnpickleState if none is available implicitly - * - * @return - */ - implicit def unpickleStateSpeed: ByteBuffer => UnpickleState = - bytes => new UnpickleState(new DecoderSize(bytes), true, true) - def apply(bytes: ByteBuffer) = new UnpickleState(new DecoderSize(bytes)) def apply(decoder: Decoder, deduplicate: Boolean = false, dedupImmutable: Boolean = false) =