mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-12 04:09:34 +00:00
69 lines
2.7 KiB
Nim
69 lines
2.7 KiB
Nim
# Helper module for tsighashstable.nim (not a test itself; no `discard`).
|
|
#
|
|
# Models nim-serialization's auto-serialization registry: a flavor records which
|
|
# types it auto-serializes in a `std/macrocache` keyed by `signatureHash(T)`,
|
|
# computed through a generic `{.compileTime.}` func. The registration happens
|
|
# here (at this module's compile time); the lookup happens in the importer.
|
|
#
|
|
# Under `nim ic` the two modules are compiled separately, so the generic
|
|
# `getSig[T]` is instantiated independently on each side. `signatureHash` must
|
|
# therefore hash the *type* `T` denotes, not the generic parameter symbol — the
|
|
# latter mixes in a per-module `disamb` counter and diverges across the NIF
|
|
# boundary, making the lookup miss.
|
|
|
|
import std/[macrocache, macros, typetraits]
|
|
|
|
type DefaultFlavor* = object
|
|
|
|
macro calcSig*(T: typed): untyped =
|
|
doAssert(T.typeKind == ntyTypeDesc)
|
|
result = newLit(signatureHash(T))
|
|
|
|
func getSig*(F: type DefaultFlavor, T: distinct type): string {.compileTime.} =
|
|
calcSig(T)
|
|
|
|
func getTable*(F: type DefaultFlavor): CacheTable {.compileTime.} =
|
|
CacheTable("nsrzStableTable" & typetraits.name(F))
|
|
|
|
func setAuto*(F: type DefaultFlavor, T: distinct type) {.compileTime.} =
|
|
let sig = F.getSig(T)
|
|
let table = F.getTable()
|
|
if not table.hasKey(sig):
|
|
table[sig] = newLit(1)
|
|
|
|
func getAuto*(F: type DefaultFlavor, T: distinct type): bool {.compileTime.} =
|
|
let sig = F.getSig(T)
|
|
let table = F.getTable()
|
|
table.hasKey(sig)
|
|
|
|
func tcOrMember*(F: type DefaultFlavor, TC: distinct type, TM: distinct type): bool {.compileTime.} =
|
|
## Is `TM` registered, or its parent type class `TC`? Models
|
|
## `typeClassOrMemberAutoSerialize` — used to auto-serialize any `object`/`tuple`.
|
|
if F.getAuto(TM): return true
|
|
if F.getAuto(TC): return true
|
|
false
|
|
|
|
template autoCheck*(F: distinct type, T: distinct type, body) =
|
|
when not F.getAuto(T):
|
|
{.error: "auto serialization not enabled for `" & typetraits.name(T) & "`".}
|
|
else:
|
|
body
|
|
|
|
template autoCheckTC*(F: distinct type, TC: distinct type, M: distinct type, body) =
|
|
when not F.tcOrMember(TC, M):
|
|
{.error: "auto serialization not enabled for `" & typetraits.name(M) &
|
|
"` of typeclass `" & typetraits.name(TC) & "`".}
|
|
else:
|
|
body
|
|
|
|
static:
|
|
setAuto(DefaultFlavor, string)
|
|
setAuto(DefaultFlavor, SomeInteger)
|
|
setAuto(DefaultFlavor, seq)
|
|
# Builtin *type classes*: `object`/`tuple` are `tyBuiltInTypeClass`, whose
|
|
# `signatureHash` must not mix in the placeholder son's process-local type id
|
|
# or the lookup misses across the NIF boundary (the real nim-serialization bug
|
|
# surfaced by Nimbus: `MultiAddress`/`RequestId` "of typeclass `object`").
|
|
setAuto(DefaultFlavor, object)
|
|
setAuto(DefaultFlavor, tuple)
|