improved setTagUri

* renamed setTagUriForType to setTagUri
 * generated TagId is now const (can be used in case etc)
 * Uses compile-time counter independent from tag library
This commit is contained in:
Felix Krause 2016-04-21 18:58:53 +02:00
parent 62fa366ac7
commit 273093e390
4 changed files with 47 additions and 42 deletions

View File

@ -238,8 +238,8 @@ Defining a custom tag uri for a type
level, experience: int32 level, experience: int32
drops: seq[string] drops: seq[string]
setTagUriForType(Mob, "!Mob") setTagUri(Mob, "!Mob")
setTagUriForType(seq[string], "!Drops") setTagUri(seq[string], "!Drops")
var mob = Mob(level: 42, experience: 1800, drops: var mob = Mob(level: 42, experience: 1800, drops:
@["Sword of Mob Slaying"]) @["Sword of Mob Slaying"])
@ -352,8 +352,7 @@ Processing a Sequence of Heterogeneous Items
type Person = object type Person = object
name: string name: string
setTagUriForType(Person, "!nim:demo:Person", setTagUri(Person, "!nim:demo:Person", yTagPerson)
yTagPerson)
var var
s = newFileStream("in.yaml", fmRead) s = newFileStream("in.yaml", fmRead)
@ -367,7 +366,7 @@ Processing a Sequence of Heterogeneous Items
while nextEvent.kind != yamlEndSeq: while nextEvent.kind != yamlEndSeq:
var curTag = nextEvent.tag() var curTag = nextEvent.tag()
if curTag == yTagQuestionMark: if curTag == yTagQuestionMark:
# we only support implicitly tagged scalar events # we only support implicitly tagged scalars
assert nextEvent.kind == yamlScalar assert nextEvent.kind == yamlScalar
case guessType(nextEvent.scalarContent) case guessType(nextEvent.scalarContent)
of yTypeInteger: curTag = yTagInteger of yTypeInteger: curTag = yTagInteger
@ -390,14 +389,11 @@ Processing a Sequence of Heterogeneous Items
var b: bool var b: bool
events.constructChild(context, b) events.constructChild(context, b)
echo "got boolean: ", b echo "got boolean: ", b
else: of yTagPerson:
# non-standard tag ids are not available var p: Person
# at compile time events.constructChild(context, p)
if curTag == yTagPerson: echo "got Person with name: ", p.name
var p: Person else: assert false, "unsupported tag: " & $curTag
events.constructChild(context, p)
echo "got Person with name: ", p.name
else: assert false, "unsupported tag: " & $curTag
nextEvent = events.peek() nextEvent = events.peek()
assert events.next().kind == yamlEndSeq assert events.next().kind == yamlEndSeq
assert events.next().kind == yamlEndDoc assert events.next().kind == yamlEndDoc

View File

@ -142,13 +142,13 @@ These tags are generated on the fly based on the types you instantiate
``Table`` or ``seq`` with. ``Table`` or ``seq`` with.
You may customize the tags used for your types by using the template You may customize the tags used for your types by using the template
`setTagUriForType <yaml.html#setTagUriForType.t,typedesc,string>`_. It may not `setTagUri <yaml.html#setTagUri.t,typedesc,string>`_. It may not
be applied to scalar and collection types implemented by NimYAML, but you can be applied to scalar and collection types implemented by NimYAML, but you can
for example use it on a certain ``seq`` type: for example use it on a certain ``seq`` type:
.. code-block:: nim .. code-block:: nim
setTagUriForType(seq[string], "!nim:my:seq") setTagUri(seq[string], "!nim:my:seq")
Customize Serialization Customize Serialization
======================= =======================

View File

@ -30,9 +30,9 @@ type
proc `$`(v: BetterInt): string {.borrow.} proc `$`(v: BetterInt): string {.borrow.}
proc `==`(l, r: BetterInt): bool {.borrow.} proc `==`(l, r: BetterInt): bool {.borrow.}
setTagUriForType(TrafficLight, "!tl") setTagUri(TrafficLight, "!tl")
setTagUriForType(Node, "!example.net:Node") setTagUri(Node, "!example.net:Node")
setTagUriForType(BetterInt, "!test:BetterInt") setTagUri(BetterInt, "!test:BetterInt")
proc representObject*(value: BetterInt, ts: TagStyle = tsNone, proc representObject*(value: BetterInt, ts: TagStyle = tsNone,
c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} = c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} =

View File

@ -633,31 +633,40 @@ var
## Should not be modified manually. Will be extended by ## Should not be modified manually. Will be extended by
## `serializable <#serializable,stmt,stmt>`_. ## `serializable <#serializable,stmt,stmt>`_.
static: var
var nextStaticTagId {.compileTime.} = 100.TagId ## \
registeredUris {.compileTime.} = newSeq[string]() ## \ ## used for generating unique TagIds with ``setTagUri``.
## Since Table doesn't really work at compile time, we also store registeredUris {.compileTime.} = newSeq[string]() ## \
## registered URIs here to be able to generate a static compiler error ## Since Table doesn't really work at compile time, we also store
## when the user tries to register an URI more than once. ## registered URIs here to be able to generate a static compiler error
## when the user tries to register an URI more than once.
template setTagUriForType*(t: typedesc, uri: string): stmt = template setTagUri*(t: typedesc, uri: string): stmt =
## Associate the given uri with a certain type. This uri is used as YAML tag ## Associate the given uri with a certain type. This uri is used as YAML tag
## when loading and dumping values of this type. ## when loading and dumping values of this type.
when uri in registeredUris: when uri in registeredUris:
{. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .} {. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .}
static: registeredUris.add(uri) const id {.genSym.} = nextStaticTagId
let id {.gensym.} = serializationTagLibrary.registerUri(uri) static:
registeredUris.add(uri)
nextStaticTagId = TagId(int(nextStaticTagId) + 1)
when nextStaticTagId == yFirstCustomTagId:
{.fatal: "Too many tags!".}
serializationTagLibrary.tags[uri] = id
proc yamlTag*(T: typedesc[t]): TagId {.inline, raises: [].} = id proc yamlTag*(T: typedesc[t]): TagId {.inline, raises: [].} = id
## autogenerated ## autogenerated
template setTagUriForType*(t: typedesc, uri: string, idName: expr): stmt = template setTagUri*(t: typedesc, uri: string, idName: expr): stmt =
## Like `setTagUriForType <#setTagUriForType,typedesc,string>`_, but lets ## Like `setTagUri <#setTagUri.t,typedesc,string>`_, but lets
## you choose a symbol for the `TagId <#TagId>`_ of the uri. This is only ## you choose a symbol for the `TagId <#TagId>`_ of the uri. This is only
## necessary if you want to implement serialization / construction yourself. ## necessary if you want to implement serialization / construction yourself.
when uri in registeredUris: when uri in registeredUris:
{. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .} {. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .}
static: registeredUris.add(uri) const idName* = nextStaticTagId
let idName* = serializationTagLibrary.registerUri(uri) static:
registeredUris.add(uri)
nextStaticTagId = TagId(int(nextStaticTagId) + 1)
serializationTagLibrary.tags[uri] = idName
proc yamlTag*(T: typedesc[t]): TagId {.inline, raises: [].} = idName proc yamlTag*(T: typedesc[t]): TagId {.inline, raises: [].} = idName
## autogenerated ## autogenerated
@ -678,17 +687,17 @@ static:
registeredUris.add("!nim:nil:seq") registeredUris.add("!nim:nil:seq")
# tags for Nim's standard types # tags for Nim's standard types
setTagUriForType(char, "!nim:system:char", yTagNimChar) setTagUri(char, "!nim:system:char", yTagNimChar)
setTagUriForType(int8, "!nim:system:int8", yTagNimInt8) setTagUri(int8, "!nim:system:int8", yTagNimInt8)
setTagUriForType(int16, "!nim:system:int16", yTagNimInt16) setTagUri(int16, "!nim:system:int16", yTagNimInt16)
setTagUriForType(int32, "!nim:system:int32", yTagNimInt32) setTagUri(int32, "!nim:system:int32", yTagNimInt32)
setTagUriForType(int64, "!nim:system:int64", yTagNimInt64) setTagUri(int64, "!nim:system:int64", yTagNimInt64)
setTagUriForType(uint8, "!nim:system:uint8", yTagNimUInt8) setTagUri(uint8, "!nim:system:uint8", yTagNimUInt8)
setTagUriForType(uint16, "!nim:system:uint16", yTagNimUInt16) setTagUri(uint16, "!nim:system:uint16", yTagNimUInt16)
setTagUriForType(uint32, "!nim:system:uint32", yTagNimUInt32) setTagUri(uint32, "!nim:system:uint32", yTagNimUInt32)
setTagUriForType(uint64, "!nim:system:uint64", yTagNimUInt64) setTagUri(uint64, "!nim:system:uint64", yTagNimUInt64)
setTagUriForType(float32, "!nim:system:float32", yTagNimFloat32) setTagUri(float32, "!nim:system:float32", yTagNimFloat32)
setTagUriForType(float64, "!nim:system:float64", yTagNimFloat64) setTagUri(float64, "!nim:system:float64", yTagNimFloat64)
# implementation # implementation