@@ -46,8 +46,8 @@ object RLPImplicitDerivations {
46
46
rlp match {
47
47
case list : RLPList =>
48
48
decodeList(list.items.toList)._1
49
- case other =>
50
- throw RLPException (s " Expected to decode an RLPList " , other )
49
+ case _ =>
50
+ throw RLPException (s " Expected to decode an RLPList " , rlp )
51
51
}
52
52
}
53
53
object RLPListDecoder {
@@ -57,6 +57,21 @@ object RLPImplicitDerivations {
57
57
}
58
58
}
59
59
60
+ private def decodeError [T ](subject : String , error : String , maybeEncodeable : Option [RLPEncodeable ] = None ): T =
61
+ throw RLPException (s " error decoding $subject: $error" , maybeEncodeable)
62
+
63
+ private def tryDecode [T ](subject : => String , encodeable : RLPEncodeable )(f : RLPEncodeable => T ): T = {
64
+ try {
65
+ f(encodeable)
66
+ } catch {
67
+ case ex : RLPException =>
68
+ // Preserve the original encodeable if there is one.
69
+ decodeError(subject, ex.message, ex.encodeable orElse Some (encodeable))
70
+ case NonFatal (ex) =>
71
+ decodeError(subject, ex.getMessage, Some (encodeable))
72
+ }
73
+ }
74
+
60
75
/** Encoder for the empty list of fields. */
61
76
implicit val deriveHNilRLPListEncoder : RLPListEncoder [HNil ] =
62
77
RLPListEncoder (_ => RLPList () -> Nil )
@@ -148,6 +163,7 @@ object RLPImplicitDerivations {
148
163
policy : DerivationPolicy = DerivationPolicy .default
149
164
): RLPListDecoder [FieldType [K , H ] :: T ] = {
150
165
val fieldName : String = witness.value.name
166
+ val subject = s " optional field ' $fieldName' "
151
167
val hInfo = FieldInfo (isOptional = true )
152
168
153
169
RLPListDecoder {
@@ -158,16 +174,16 @@ object RLPImplicitDerivations {
158
174
(head :: tail) -> (hInfo :: tInfos)
159
175
160
176
case Nil =>
161
- throw RLPException ( s " Could not decode optional field ' $fieldName ': RLPList is empty." )
177
+ decodeError(subject, " RLPList is empty." )
162
178
163
179
case rlps =>
164
180
val (tail, tInfos) = tDecoder.value.decodeList(rlps.tail)
165
181
val value : H =
166
- try {
182
+ tryDecode(subject, rlps.head) { rlp =>
167
183
if (policy.omitTrailingOptionals && tInfos.forall(_.isOptional)) {
168
184
// Expect that it's a value. We have a decoder for optional fields, so we have to wrap it into a list.
169
185
try {
170
- hDecoder.value.decode(RLPList (rlps.head ))
186
+ hDecoder.value.decode(RLPList (rlp ))
171
187
} catch {
172
188
case NonFatal (_) =>
173
189
// The trailing fields can be followed in the RLP list by additional items
@@ -176,11 +192,8 @@ object RLPImplicitDerivations {
176
192
}
177
193
} else {
178
194
// Expect that it's a list of 0 or 1 items.
179
- hDecoder.value.decode(rlps.head )
195
+ hDecoder.value.decode(rlp )
180
196
}
181
- } catch {
182
- case NonFatal (ex) =>
183
- throw RLPException (s " Could not decode optional field ' $fieldName': ${ex.getMessage}" , rlps.head)
184
197
}
185
198
186
199
val head : FieldType [K , H ] = field[K ](value)
@@ -196,19 +209,17 @@ object RLPImplicitDerivations {
196
209
ev : H <:!< Option [_]
197
210
): RLPListDecoder [FieldType [K , H ] :: T ] = {
198
211
val fieldName : String = witness.value.name
212
+ val subject = s " field ' $fieldName' "
199
213
val hInfo = FieldInfo (isOptional = false )
200
214
201
215
RLPListDecoder {
202
216
case Nil =>
203
- throw RLPException ( s " Could not decode field ' $fieldName ': RLPList is empty." )
217
+ decodeError(subject, " RLPList is empty." )
204
218
205
219
case rlps =>
206
220
val value : H =
207
- try {
208
- hDecoder.value.decode(rlps.head)
209
- } catch {
210
- case NonFatal (ex) =>
211
- throw RLPException (s " Could not decode field ' $fieldName': ${ex.getMessage}" , rlps.head)
221
+ tryDecode(subject, rlps.head) {
222
+ hDecoder.value.decode(_)
212
223
}
213
224
val head : FieldType [K , H ] = field[K ](value)
214
225
val (tail, tInfos) = tDecoder.value.decodeList(rlps.tail)
@@ -224,11 +235,8 @@ object RLPImplicitDerivations {
224
235
recDecoder : Lazy [RLPDecoder [Rec ]],
225
236
ct : ClassTag [T ]
226
237
): RLPDecoder [T ] = RLPDecoder { rlp =>
227
- try {
238
+ tryDecode( s " type ${ct.runtimeClass.getSimpleName} " , rlp) { rlp =>
228
239
generic.from(recDecoder.value.decode(rlp))
229
- } catch {
230
- case NonFatal (ex) =>
231
- throw RLPException (s " Could not decode type ${ct.runtimeClass.getSimpleName}: ${ex.getMessage}" , rlp)
232
240
}
233
241
}
234
242
0 commit comments