@@ -225,22 +225,66 @@ proc readRecordValue*[T](r: var JsonReader, value: var T)
225225 else :
226226 r.raiseUnexpectedField (key, cstring typeName)
227227
228- template autoSerializeCheck (F: distinct type , T: distinct type ) =
228+ template autoSerializeCheck (F: distinct type , T: distinct type , body ) =
229229 when declared (macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey
230230 mixin typeAutoSerialize
231231 when not F.typeAutoSerialize (T):
232- const typeName = typetraits.name (T)
233- {.error : " automatic serialization is not enabled or readValue not implemented for `" &
232+ const
233+ typeName = typetraits.name (T)
234+ flavorName = typetraits.name (F)
235+ {.error : flavorName &
236+ " : automatic serialization is not enabled or readValue not implemented for `" &
234237 typeName & " `" .}
238+ else :
239+ body
240+ else :
241+ body
235242
236- template autoSerializeCheck (F: distinct type , TC: distinct type , M: distinct type ) =
243+ template autoSerializeCheck (F: distinct type , TC: distinct type , M: distinct type , body ) =
237244 when declared (macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey
238245 mixin typeClassOrMemberAutoSerialize
239246 when not F.typeClassOrMemberAutoSerialize (TC , M):
240- const typeName = typetraits.name (M)
241- const typeClassName = typetraits.name (TC )
242- {.error : " automatic serialization is not enabled or readValue not implemented for `" &
247+ const
248+ typeName = typetraits.name (M)
249+ typeClassName = typetraits.name (TC )
250+ flavorName = typetraits.name (F)
251+ {.error : flavorName &
252+ " : automatic serialization is not enabled or readValue not implemented for `" &
243253 typeName & " ` of typeclass `" & typeClassName & " `" .}
254+ else :
255+ body
256+ else :
257+ body
258+
259+ template readValueRefOrPtr (r, value) =
260+ mixin readValue
261+ when compiles (isNotNilCheck (value)):
262+ allocPtr value
263+ value[] = readValue (r, type (value[]))
264+ else :
265+ if r.tokKind == JsonValueKind .Null :
266+ value = nil
267+ r.parseNull ()
268+ else :
269+ allocPtr value
270+ value[] = readValue (r, type (value[]))
271+
272+ template readValueObjectOrTuple (Flavor, r, value) =
273+ mixin flavorUsesAutomaticObjectSerialization
274+
275+ const isAutomatic =
276+ flavorUsesAutomaticObjectSerialization (Flavor )
277+
278+ when not isAutomatic:
279+ const
280+ flavor =
281+ " JsonReader[" & typetraits.name (typeof (r).Flavor ) & " ], " &
282+ typetraits.name (T)
283+ {.error :
284+ " Missing Json serialization import or implementation for readValue(" &
285+ flavor & " )" .}
286+
287+ readRecordValue (r, value)
244288
245289proc readValue * [T](r: var JsonReader , value: var T)
246290 {.raises : [SerializationError , IOError ].} =
@@ -261,129 +305,110 @@ proc readValue*[T](r: var JsonReader, value: var T)
261305 type Flavor = JsonReader .Flavor
262306
263307 when value is JsonString :
264- autoSerializeCheck (Flavor , JsonString )
265- value = r.parseAsString ()
308+ autoSerializeCheck (Flavor , JsonString ):
309+ value = r.parseAsString ()
266310
267311 elif value is JsonNode :
268- autoSerializeCheck (Flavor , JsonNode )
269- value = r.parseJsonNode ()
312+ autoSerializeCheck (Flavor , JsonNode ):
313+ value = r.parseJsonNode ()
270314
271315 elif value is JsonNumber :
272- autoSerializeCheck (Flavor , JsonNumber )
273- r.parseNumber (value)
316+ autoSerializeCheck (Flavor , JsonNumber ):
317+ r.parseNumber (value)
274318
275319 elif value is JsonVoid :
276- autoSerializeCheck (Flavor , JsonVoid )
277- r.skipSingleJsValue ()
320+ autoSerializeCheck (Flavor , JsonVoid ):
321+ r.skipSingleJsValue ()
278322
279323 elif value is JsonValueRef :
280- autoSerializeCheck (Flavor , JsonValueRef )
281- r.parseValue (value)
324+ autoSerializeCheck (Flavor , JsonValueRef ):
325+ r.parseValue (value)
282326
283327 elif value is string :
284- autoSerializeCheck (Flavor , string )
285- value = r.parseString ()
328+ autoSerializeCheck (Flavor , string ):
329+ value = r.parseString ()
286330
287331 elif value is seq [char ]:
288- autoSerializeCheck (Flavor , seq [char ])
289- let val = r.parseString ()
290- value.setLen (val.len)
291- for i in 0 ..< val.len:
292- value[i] = val[i]
332+ autoSerializeCheck (Flavor , seq [char ]):
333+ let val = r.parseString ()
334+ value.setLen (val.len)
335+ for i in 0 ..< val.len:
336+ value[i] = val[i]
293337
294338 elif isCharArray (value):
295- autoSerializeCheck (Flavor , array , typeof (value))
296- let val = r.parseString ()
297- if val.len != value.len:
298- # Raise tkString because we expected a `"` earlier
299- r.raiseUnexpectedToken (etString)
300- for i in 0 ..< value.len:
301- value[i] = val[i]
339+ autoSerializeCheck (Flavor , array , typeof (value)):
340+ let val = r.parseString ()
341+ if val.len != value.len:
342+ # Raise tkString because we expected a `"` earlier
343+ r.raiseUnexpectedToken (etString)
344+ for i in 0 ..< value.len:
345+ value[i] = val[i]
302346
303347 elif value is bool :
304- autoSerializeCheck (Flavor , bool )
305- value = r.parseBool ()
348+ autoSerializeCheck (Flavor , bool ):
349+ value = r.parseBool ()
306350
307- elif value is ref | ptr :
308- when value is ref :
309- autoSerializeCheck ( Flavor , ref , typeof ( value) )
351+ elif value is ref :
352+ autoSerializeCheck ( Flavor , ref , typeof (value)) :
353+ readValueRefOrPtr (r, value)
310354
311- when value is ptr :
312- autoSerializeCheck (Flavor , ptr , typeof (value))
313-
314- when compiles (isNotNilCheck (value)):
315- allocPtr value
316- value[] = readValue (r, type (value[]))
317- else :
318- if r.tokKind == JsonValueKind .Null :
319- value = nil
320- r.parseNull ()
321- else :
322- allocPtr value
323- value[] = readValue (r, type (value[]))
355+ elif value is ptr :
356+ autoSerializeCheck (Flavor , ptr , typeof (value)):
357+ readValueRefOrPtr (r, value)
324358
325359 elif value is enum :
326- autoSerializeCheck (Flavor , enum , typeof (value))
327- r.parseEnum (value)
360+ autoSerializeCheck (Flavor , enum , typeof (value)):
361+ r.parseEnum (value)
328362
329363 elif value is SomeInteger :
330- autoSerializeCheck (Flavor , SomeInteger , typeof (value))
331- value = r.parseInt (typeof value,
332- JsonReaderFlag .portableInt in r.lex.flags)
364+ autoSerializeCheck (Flavor , SomeInteger , typeof (value)):
365+ value = r.parseInt (typeof value,
366+ JsonReaderFlag .portableInt in r.lex.flags)
333367
334368 elif value is SomeFloat :
335- autoSerializeCheck (Flavor , SomeFloat , typeof (value))
336- let val = r.parseNumber (uint64 )
337- if val.isFloat:
338- value = r.toFloat (val, typeof value)
339- else :
340- value = T (val.integer)
369+ autoSerializeCheck (Flavor , SomeFloat , typeof (value)):
370+ let val = r.parseNumber (uint64 )
371+ if val.isFloat:
372+ value = r.toFloat (val, typeof value)
373+ else :
374+ value = T (val.integer)
341375
342376 elif value is seq :
343- autoSerializeCheck (Flavor , seq , typeof (value))
344- r.parseArray:
345- let lastPos = value.len
346- value.setLen (lastPos + 1 )
347- readValue (r, value[lastPos])
377+ autoSerializeCheck (Flavor , seq , typeof (value)):
378+ r.parseArray:
379+ let lastPos = value.len
380+ value.setLen (lastPos + 1 )
381+ readValue (r, value[lastPos])
348382
349383 elif value is array :
350- autoSerializeCheck (Flavor , array , typeof (value))
351- type IDX = typeof low (value)
352- r.parseArray (idx):
353- if idx < value.len:
354- let i = IDX (idx + low (value).int )
355- readValue (r, value[i])
356- else :
357- r.raiseUnexpectedValue (" Too many items for " & $ (typeof (value)))
358-
359- elif value is (object or tuple ):
360- when declared (macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey
361- when value is object :
362- autoSerializeCheck (Flavor , object , typeof (value))
363-
364- when value is tuple :
365- autoSerializeCheck (Flavor , tuple , typeof (value))
366-
367- # Keep existing object/tuple auto serialization
368- # But make it deprecated.
369- mixin flavorUsesAutomaticObjectSerialization
384+ autoSerializeCheck (Flavor , array , typeof (value)):
385+ type IDX = typeof low (value)
386+ r.parseArray (idx):
387+ if idx < value.len:
388+ let i = IDX (idx + low (value).int )
389+ readValue (r, value[i])
390+ else :
391+ r.raiseUnexpectedValue (" Too many items for " & $ (typeof (value)))
392+
393+ elif value is object :
394+ when declared (macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey and cannot accept `object` param
395+ autoSerializeCheck (Flavor , object , typeof (value)):
396+ readValueObjectOrTuple (Flavor , r, value)
397+ else :
398+ readValueObjectOrTuple (Flavor , r, value)
370399
371- const isAutomatic =
372- flavorUsesAutomaticObjectSerialization (Flavor )
400+ elif value is tuple :
401+ when declared (macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey and cannot accept `tuple` param
402+ autoSerializeCheck (Flavor , tuple , typeof (value)):
403+ readValueObjectOrTuple (Flavor , r, value)
404+ else :
405+ readValueObjectOrTuple (Flavor , r, value)
373406
374- when not isAutomatic:
375- const
376- flavor =
377- " JsonReader[" & typetraits.name (typeof (r).Flavor ) & " ], " &
378- typetraits.name (T)
379- {.error :
380- " Missing Json serialization import or implementation for readValue(" &
381- flavor & " )" .}
382-
383- readRecordValue (r, value)
384407 else :
385- const typeName = typetraits.name (T)
386- {.error : " Failed to convert to JSON an unsupported type: " &
408+ const
409+ typeName = typetraits.name (T)
410+ flavorName = typetraits.name (Flavor )
411+ {.error : flavorName & " : Failed to convert from JSON an unsupported type: " &
387412 typeName.}
388413
389414iterator readObjectFields * (r: var JsonReader ): string {.
0 commit comments