1
1
package scala .pickling
2
2
package pickler
3
3
4
+ import scala .pickling .PicklingErrors .TypeMismatch
5
+
4
6
/** Generate [[Pickler ]]s and [[Unpickler ]]s for [[Either ]]
5
7
* and its subclasses [[Right ]] and [[Left ]].
6
8
*/
7
- trait EitherPicklers {
8
- // TODO(jsuereth) - Register pickler generators
9
-
10
- implicit def pickleUnpickleLeft [L , R ](implicit lp : Pickler [L ], lu : Unpickler [L ],
11
- t : FastTypeTag [Left [L ,R ]]): AbstractPicklerUnpickler [Left [L , R ]] =
12
- new AbstractPicklerUnpickler [Left [L , R ]] with AutoRegister [Left [L , R ]] {
13
- override lazy val tag : FastTypeTag [Left [L , R ]] = t
14
- override def pickle (picklee : Left [L , R ], builder : PBuilder ): Unit = {
15
- builder.beginEntry(picklee, tag)
16
- if (lp.tag.isEffectivelyPrimitive) builder.hintElidedType(lp.tag)
17
- builder.putField(" a" , b => lp.pickle(picklee.a, b))
18
- builder.endEntry()
19
- }
20
- override def unpickle (tag : String , reader : PReader ): Any = {
21
- if (t.key == tag) {
22
- val rr = reader.readField(" a" )
23
- if (lp.tag.isEffectivelyPrimitive) rr.hintElidedType(lp.tag)
24
- Left (lu.unpickleEntry(rr).asInstanceOf [R ])
25
- } else throw new PicklingException (s " LeftUnpickler can't unpickle: $tag" )
26
- }
27
- override def toString = s " LeftPicklerUnpickler( $tag) "
28
- }
29
-
30
- implicit def pickleUnpickleRight [L ,R ](implicit rp : Pickler [R ], ru : Unpickler [R ],
31
- t : FastTypeTag [Right [L ,R ]]): AbstractPicklerUnpickler [Right [L ,R ]] =
9
+ trait EitherPicklers extends EitherPicklersRuntime with GeneratorRegistry {
10
+
11
+ implicit def pickleUnpickleLeft [L , R ]
12
+ (implicit lp : Pickler [L ], lu : Unpickler [L ],
13
+ t : FastTypeTag [Left [L ,R ]]): AbstractPicklerUnpickler [Left [L , R ]] = {
14
+ new AbstractPicklerUnpickler [Left [L , R ]] with AutoRegister [Left [L , R ]] {
15
+ override lazy val tag : FastTypeTag [Left [L , R ]] = t
16
+
17
+ override def pickle (picklee : Left [L , R ], builder : PBuilder ): Unit = {
18
+ builder.beginEntry(picklee, tag)
19
+ if (lp.tag.isEffectivelyPrimitive) builder.hintElidedType(lp.tag)
20
+ builder.putField(" a" , b => lp.pickle(picklee.a, b))
21
+ builder.endEntry()
22
+ }
23
+
24
+ override def unpickle (tag : String , reader : PReader ): Any = {
25
+ if (t.key == tag) {
26
+ val rr = reader.readField(" a" )
27
+ if (lp.tag.isEffectivelyPrimitive) rr.hintElidedType(lp.tag)
28
+ Left (lu.unpickleEntry(rr).asInstanceOf [R ])
29
+ } else throw TypeMismatch (List (t), List (FastTypeTag (tag)))
30
+ }
31
+
32
+ override def toString = s " LeftPicklerUnpickler( $tag) "
33
+ }
34
+ }
35
+
36
+ implicit def pickleUnpickleRight [L ,R ]
37
+ (implicit rp : Pickler [R ], ru : Unpickler [R ],
38
+ t : FastTypeTag [Right [L ,R ]]): AbstractPicklerUnpickler [Right [L ,R ]] = {
32
39
new AbstractPicklerUnpickler [Right [L , R ]] with AutoRegister [Right [L , R ]] {
33
40
override lazy val tag : FastTypeTag [Right [L , R ]] = t
41
+
34
42
override def pickle (picklee : Right [L , R ], builder : PBuilder ): Unit = {
35
43
builder.beginEntry(picklee, tag)
36
- if (rp.tag.isEffectivelyPrimitive) builder.hintElidedType(rp.tag)
44
+ if (rp.tag.isEffectivelyPrimitive) builder.hintElidedType(rp.tag)
37
45
builder.putField(" b" , b => rp.pickle(picklee.b, b))
38
46
builder.endEntry()
39
47
}
48
+
40
49
override def unpickle (tag : String , reader : PReader ): Any = {
41
50
if (t.key == tag) {
42
51
val rr = reader.readField(" b" )
43
- if (rp.tag.isEffectivelyPrimitive) rr.hintElidedType(rp.tag)
52
+ if (rp.tag.isEffectivelyPrimitive) rr.hintElidedType(rp.tag)
44
53
Right (ru.unpickleEntry(rr).asInstanceOf [R ])
45
- } else throw new PicklingException ( s " RightUnpickler can't unpickle: $ tag" )
54
+ } else throw TypeMismatch ( List (t), List ( FastTypeTag ( tag)) )
46
55
}
56
+
47
57
override def toString = s " RightPicklerUnpickler( $tag) "
48
58
}
59
+ }
49
60
50
- implicit def pickleUnpickleEither [L ,R ](implicit rp : Pickler [Right [L ,R ]], ru : Unpickler [Right [L , R ]],
51
- lp : Pickler [Left [L ,R ]], lu : Unpickler [Left [L , R ]],
52
- t : FastTypeTag [Either [L ,R ]]): AbstractPicklerUnpickler [Either [L ,R ]] =
61
+ implicit def pickleUnpickleEither [L ,R ]
62
+ (implicit rp : Pickler [Right [L ,R ]], ru : Unpickler [Right [L , R ]],
63
+ lp : Pickler [Left [L ,R ]], lu : Unpickler [Left [L , R ]],
64
+ t : FastTypeTag [Either [L ,R ]]): AbstractPicklerUnpickler [Either [L ,R ]] = {
53
65
new AbstractPicklerUnpickler [Either [L , R ]] with AutoRegister [Either [L , R ]] {
54
66
override def pickle (picklee : Either [L , R ], builder : PBuilder ): Unit = {
55
67
picklee match {
56
- case l : Left [L ,R ] => lp.pickle(l, builder)
57
- case r : Right [L ,R ] => rp.pickle(r, builder)
68
+ case l : Left [L , R ] => lp.pickle(l, builder)
69
+ case r : Right [L , R ] => rp.pickle(r, builder)
58
70
}
59
71
}
72
+
60
73
override def unpickle (tag : String , reader : PReader ): Any = {
61
- if (tag == rp.tag.key) ru.unpickle(tag,reader)
62
- else if (tag == lp.tag.key) lu.unpickle(tag, reader)
63
- else throw new PicklingException ( s " Unknown type tag for Either: $ tag" )
74
+ if (tag == rp.tag.key) ru.unpickle(tag, reader)
75
+ else if (tag == lp.tag.key) lu.unpickle(tag, reader)
76
+ else throw TypeMismatch ( List (rp.tag, lp. tag), List ( FastTypeTag ( tag)) )
64
77
}
78
+
65
79
override def tag : FastTypeTag [Either [L , R ]] = t
66
- override def toString = s " EitherPicklerUnpickler( $t) "
80
+
81
+ override def toString = s " EitherPicklerUnpickler( $tag) "
67
82
}
83
+ }
84
+
85
+ locally {
86
+
87
+ registerPicklerAsGen(RuntimeLeftPicklerUnpickler )
88
+ registerPicklerAsGen(RuntimeRightPicklerUnpickler )
89
+ registerPicklerAsGen(RuntimeEitherPicklerUnpickler )
90
+
91
+ }
92
+
93
+ }
94
+
95
+ trait EitherPicklersRuntime extends GeneratorHelper {
96
+
97
+ /** Pickle as [[Any ]] because the scala pickling
98
+ * use [[Any ]] as a placeholder for the type params.
99
+ */
100
+ private def pickleAsAny [S <: Either [_, _]]
101
+ (picklee : S , fullTpe : FastTypeTag [S ],
102
+ name : String , field : Any , builder : PBuilder ) = {
103
+
104
+ builder.beginEntry(picklee, fullTpe)
105
+ builder.putField(name, { b =>
106
+ AnyPicklerUnpickler .pickle(field, b)
107
+ })
108
+ builder.endEntry()
109
+
110
+ }
111
+
112
+ /** Unpickle with a given unpickler a concrete field. */
113
+ private def unpickleAsAny [T ](unpickler : Unpickler [T ],
114
+ reader : PReader , name : String ) = {
115
+ val field = reader.readField(name)
116
+ unpickler.unpickleEntry(field)
117
+ }
118
+
119
+
120
+ /** Custom runtime [[Pickler ]] and [[Unpickler ]] generator of [[Left ]]. */
121
+ object RuntimeLeftPicklerUnpickler
122
+ extends AbstractPicklerUnpickler [Left [Any , Any ]] {
123
+
124
+ val tag = FastTypeTag [Left [Any , Any ]](" scala.util.Left[scala.Any,scala.Any]" )
125
+
126
+ def pickle (picklee : Left [Any , Any ], builder : PBuilder ): Unit =
127
+ pickleAsAny(picklee, tag, " a" , picklee.a, builder)
128
+
129
+ def unpickle (tagTpe : String , reader : PReader ): Any = {
130
+
131
+ val tpe = FastTypeTag .apply(tagTpe)
132
+ val (leftTpe, _) = twoArgumentTagExtractor[Any , Any ](tpe)
133
+ Left (unpickleAsAny(getUnpickler(leftTpe, tag), reader, " a" ))
134
+
135
+ }
136
+
137
+ }
138
+
139
+ /** Custom runtime [[Pickler ]] and [[Unpickler ]] generator of [[Right ]]. */
140
+ object RuntimeRightPicklerUnpickler
141
+ extends AbstractPicklerUnpickler [Right [Any , Any ]] {
142
+
143
+ val tag = FastTypeTag [Right [Any , Any ]](" scala.util.Right[scala.Any,scala.Any]" )
144
+
145
+ def pickle (picklee : Right [Any , Any ], builder : PBuilder ): Unit =
146
+ pickleAsAny(picklee, tag, " b" , picklee.b, builder)
147
+
148
+ def unpickle (tagTpe : String , reader : PReader ): Any = {
149
+
150
+ val tpe = FastTypeTag .apply(tagTpe)
151
+ val (_, rightTpe) = twoArgumentTagExtractor[Any , Any ](tpe)
152
+ Right (unpickleAsAny(getUnpickler(rightTpe, tag), reader, " b" ))
153
+
154
+ }
155
+
156
+ }
157
+ /** Custom runtime [[Pickler ]] and [[Unpickler ]] generator of [[Either ]]. */
158
+ object RuntimeEitherPicklerUnpickler
159
+ extends AbstractPicklerUnpickler [Either [Any , Any ]] {
160
+
161
+ val tag = FastTypeTag [Either [Any , Any ]](" scala.util.Either[scala.Any,scala.Any]" )
162
+
163
+ def pickle (picklee : Either [Any , Any ], builder : PBuilder ): Unit = {
164
+ picklee match {
165
+ case r : Right [Any , Any ] =>
166
+ RuntimeRightPicklerUnpickler .pickle(r, builder)
167
+ case l : Left [Any , Any ] =>
168
+ RuntimeLeftPicklerUnpickler .pickle(l, builder)
169
+ }
170
+ }
171
+
172
+ def unpickle (tag : String , reader : PReader ): Any = {
173
+ // Tag is expected to be a concrete subclass of Either
174
+ AnyPicklerUnpickler .unpickle(tag, reader)
175
+ }
176
+
177
+ }
178
+
179
+ }
68
180
69
- }
0 commit comments