@@ -11,29 +11,64 @@ trait Output[T] {
1111// and then demand Output[Nothing] in the abstract PickleFormat
1212// in JSON we can demand Output[String], since Output[Nothing] <: Output[String]
1313
14+ import scala .reflect .ClassTag
15+ // Array output with a few more methods for performance
16+ abstract class ArrayOutput [T : ClassTag ] extends Output [Array [T ]] {
17+ // Put a single T
18+ def += (obj : T ): Unit
19+ // Allocate a new array.
20+ def target (len : Int ): (Array [T ], Int ) =
21+ (Array .ofDim[T ](len), 0 )
22+ // Flush the allocated array by target().
23+ def flush (arr : Array [T ]): Unit =
24+ this .put(arr)
25+ }
26+
27+ import scala .collection .mutable .ArrayBuffer
28+
29+ class ByteArrayBufferOutput extends ArrayOutput [Byte ] {
1430
15- // encoded primitives: Byte, Short, Char, Int, Long, Boolean, String
16- // encoded primitive arrays: Array[Byte], Array[Int]
17-
18- trait EncodingOutput [T ] extends Output [T ] {
19- def encodeByteTo (pos : Int , value : Byte ): Unit
20- def encodeShortTo (pos : Int , value : Short ): Unit
21- def encodeCharTo (pos : Int , value : Char ): Unit
22- def encodeIntTo (pos : Int , value : Int ): Unit
23- def encodeLongTo (pos : Int , value : Long ): Unit
24- def encodeBooleanTo (pos : Int , value : Boolean ): Unit
25- def encodeStringTo (pos : Int , value : String ): Int
26- def encodeByteArrayTo (pos : Int , ia : Array [Byte ]): Int
27- def encodeShortArrayTo (pos : Int , ia : Array [Short ]): Int
28- def encodeCharArrayTo (pos : Int , ia : Array [Char ]): Int
29- def encodeIntArrayTo (pos : Int , ia : Array [Int ]): Int
30- def encodeLongArrayTo (pos : Int , ia : Array [Long ]): Int
31- def encodeBooleanArrayTo (pos : Int , ia : Array [Boolean ]): Int
32- def encodeFloatArrayTo (pos : Int , ia : Array [Float ]): Int
33- def encodeDoubleArrayTo (pos : Int , ia : Array [Double ]): Int
34- def copyTo (pos : Int , bytes : Array [Byte ]): Unit
31+ private val buf =
32+ ArrayBuffer [Byte ]()
33+
34+ def result (): Array [Byte ] =
35+ buf.toArray
36+
37+ def += (obj : Byte ) =
38+ buf += obj
39+
40+ def put (obj : Array [Byte ]): this .type = {
41+ buf ++= obj
42+ this
43+ }
3544}
3645
46+ class ByteArrayOutput (len : Int ) extends ArrayOutput [Byte ] {
47+
48+ private var pos = 0
49+ private val arr = Array .ofDim[Byte ](len)
50+
51+ def result (): Array [Byte ] =
52+ arr
53+
54+ def += (obj : Byte ) = {
55+ arr(pos) = obj
56+ pos = pos + 1
57+ }
58+
59+ def put (obj : Array [Byte ]): this .type = {
60+ // target() should be used to avoid double copy
61+ throw new java.lang.IllegalStateException
62+ }
63+
64+ override def target (len : Int ) = {
65+ val oldpos = pos
66+ pos = pos + len
67+ (arr, oldpos)
68+ }
69+
70+ override def flush (arr : Array [Byte ]) = { /* noop*/ }
71+ }
3772
3873class StringOutput extends Output [String ] {
3974
0 commit comments