# toml-serialization # Copyright (c) 2020 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT # * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) # at your option. This file may not be copied, modified, or distributed except according to those terms. import ../types, ./utils, stew/shims/macros, stew/objects, serialization/[object_serialization, errors] type ArrayReader*[RecordType, Reader] = tuple[ numRead: int, fieldName: string, reader: proc (rec: var RecordType, reader: var Reader, idx: int) {.gcsafe, nimcall, raises: [SerializationError, Defect].} ] ArrayReadersTable*[RecordType, Reader] = openArray[ArrayReader[RecordType, Reader]] const BadArrayReader* = -1 proc totalArrayFieldsImpl(T: type): int = mixin enumAllSerializedFields enumAllSerializedFields(T): when FieldType is (seq or array): inc result template totalArrayFields*(T: type): int = (static(totalArrayFieldsImpl(T))) proc makeArrayReadersTable(RecordType, Reader: distinct type, L: static[int]): array[L, ArrayReader[RecordType, Reader]] = var fieldPos = 0 enumAllSerializedFields(RecordType): when FieldType is (seq or array): proc readArray(obj: var RecordType, reader: var Reader, idx: int) {.gcsafe, nimcall, raises: [SerializationError, Defect].} = mixin readValue when RecordType is tuple: const i = fieldName.parseInt try: when RecordType is tuple: reader.readValue(obj[i], idx) else: reader.readValue(field(obj, realFieldName), idx) except SerializationError as err: raise err except CatchableError as err: reader.handleReadException( `RecordType`, fieldName, when RecordType is tuple: obj[i] else: field(obj, realFieldName), err) result[fieldPos] = (0, fieldName, readArray) inc fieldPos template arrayReadersTable*(RecordType, Reader: distinct type): auto = mixin readValue const len = totalArrayFieldsImpl(RecordType) makeArrayReadersTable(RecordType, Reader, len) proc findArrayReader*(fieldsTable: ArrayReadersTable, fieldName: string, tomlCase: TomlCase): int = for i in 0 ..< fieldsTable.len: if compare(fieldsTable[i].fieldName, fieldName, tomlCase): return i result = BadArrayReader template readArray*[T, Y](idx: int, fieldsTable: var ArrayReadersTable, rec: var T, r: var Y) = fieldsTable[idx].reader(rec, r, fieldsTable[idx].numRead) inc fieldsTable[idx].numRead