Use global tag handle for NimYAML

* NimYAML now uses the tag prefix tag:nimyaml.org,2016:
 * That tag handle is shortened to !n! when presenting
 * Also fixed some minor bugs dealing with tag handles
This commit is contained in:
Felix Krause 2016-10-10 20:16:54 +02:00
parent fa14a11957
commit 29352fa4fe
13 changed files with 181 additions and 129 deletions

View File

@ -1,5 +1,6 @@
%YAML 1.2
--- !nim:system:seq(nim:custom:Person)
%TAG !n! tag:nimyaml.org,2016:
--- !n!system:seq(tag:nimyaml.org;2016:custom:Person)
-
name: Karl Koch
age: 23

View File

@ -1,16 +1,17 @@
%YAML 1.1
%TAG !n! tag:nimyaml.org,2016:
---
!nim:system:seq(nim:custom:Person) [
!nim:custom:Person {
? !nim:field "name"
!n!system:seq(tag:nimyaml.org;2016:custom:Person) [
!n!custom:Person {
? !n!field "name"
: !!str "Karl Koch",
? !nim:field "age"
: !nim:system:int32 "23"
? !n!field "age"
: !n!system:int32 "23"
},
!nim:custom:Person {
? !nim:field "name"
!n!custom:Person {
? !n!field "name"
: !!str "Peter Pan",
? !nim:field "age"
: !nim:system:int32 "12"
? !n!field "age"
: !n!system:int32 "12"
}
]

View File

@ -1,5 +1,6 @@
%YAML 1.2
--- !nim:custom:NodeObj &a
%TAG !n! tag:nimyaml.org,2016:
--- !n!custom:NodeObj &a
name: Node 1
left:
name: Node 2

View File

@ -1,11 +1,12 @@
%YAML 1.2
--- !nim:custom:NodeObj &a
%TAG !n! tag:nimyaml.org,2016:
--- !n!custom:NodeObj &a
name: Node 1
left:
name: Node 2
left: ~
right: &b
right: &b
name: Node 3
left: *a
right: ~
right: *b
right: *b

View File

@ -1,5 +1,6 @@
%YAML 1.2
%TAG !n! tag:nimyaml.org,2016:
--- !Mob
!nim:field level: !nim:system:int32 42
!nim:field experience: !nim:system:int32 1800
!nim:field drops: !Drops [!!str Sword of Mob Slaying]
!n!field level: !n!system:int32 42
!n!field experience: !n!system:int32 1800
!n!field drops: !Drops [!!str Sword of Mob Slaying]

View File

@ -19,7 +19,7 @@ type
of ckNone:
discard
setTagUri(Person, "!nim:demo:Person")
setTagUri(Person, nimTag("demo:Person"))
# tell NimYAML to use Container as implicit type.
# only possible with variant object types where

View File

@ -1,8 +1,9 @@
%YAML 1.2
%TAG !n! tag:nimyaml.org,2016:
---
- this is a string
- 42
- false
- !!str 23
- !nim:demo:Person {name: Trillian}
- !n!demo:Person {name: Trillian}
- !!null

View File

@ -2,7 +2,7 @@ import yaml, streams
type Person = object
name: string
setTagUri(Person, "!nim:demo:Person", yTagPerson)
setTagUri(Person, nimTag("demo:Person"), yTagPerson)
var
s = newFileStream("in.yaml", fmRead)

View File

@ -1,7 +1,8 @@
%YAML 1.2
%TAG !n! tag:nimyaml.org,2016:
--- !!seq
- this is a string
- 42
- false
- !!str 23
- !nim:demo:Person {name: Trillian}
- !n!demo:Person {name: Trillian}

View File

@ -45,6 +45,8 @@ setTagUri(TrafficLight, "!tl")
setTagUri(Node, "!example.net:Node")
setTagUri(BetterInt, "!test:BetterInt")
const yamlDirs = "%YAML 1.2\n%TAG !n! tag:nimyaml.org,2016:\n--- "
proc representObject*(value: BetterInt, ts: TagStyle = tsNone,
c: SerializationContext, tag: TagId) {.raises: [].} =
var
@ -104,7 +106,7 @@ suite "Serialization":
test "Dump integer without fixed length":
var input = -4247
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n\"-4247\"", output
assertStringEqual yamlDirs & "\n\"-4247\"", output
when sizeof(int) == sizeof(int64):
input = int(int32.high) + 1
@ -162,7 +164,7 @@ suite "Serialization":
assert(result == 14)
test "Load nil string":
let input = newStringStream("!nim:nil:string \"\"")
let input = newStringStream("!<tag:nimyaml.org,2016:nil:string> \"\"")
var result: string
load(input, result)
assert isNil(result)
@ -170,7 +172,7 @@ suite "Serialization":
test "Dump nil string":
let input: string = nil
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n!nim:nil:string \"\"", output
assertStringEqual yamlDirs & "\n!n!nil:string \"\"", output
test "Load string sequence":
let input = newStringStream(" - a\n - b")
@ -183,10 +185,10 @@ suite "Serialization":
test "Dump string sequence":
var input = @["a", "b"]
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n- a\n- b", output
assertStringEqual yamlDirs & "\n- a\n- b", output
test "Load nil seq":
let input = newStringStream("!nim:nil:seq \"\"")
let input = newStringStream("!<tag:nimyaml.org,2016:nil:seq> \"\"")
var result: seq[int]
load(input, result)
assert isNil(result)
@ -194,7 +196,7 @@ suite "Serialization":
test "Dump nil seq":
let input: seq[int] = nil
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n!nim:nil:seq \"\"", output
assertStringEqual yamlDirs & "\n!n!nil:seq \"\"", output
test "Load char set":
let input = newStringStream("- a\n- b")
@ -207,7 +209,7 @@ suite "Serialization":
test "Dump char set":
var input = {'a', 'b'}
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n- a\n- b", output
assertStringEqual yamlDirs & "\n- a\n- b", output
test "Load array":
let input = newStringStream("- 23\n- 42\n- 47")
@ -220,7 +222,7 @@ suite "Serialization":
test "Dump array":
let input = [23'i32, 42'i32, 47'i32]
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n- 23\n- 42\n- 47", output
assertStringEqual yamlDirs & "\n- 23\n- 42\n- 47", output
test "Load Table[int, string]":
let input = newStringStream("23: dreiundzwanzig\n42: zweiundvierzig")
@ -235,7 +237,7 @@ suite "Serialization":
input[23] = "dreiundzwanzig"
input[42] = "zweiundvierzig"
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual("%YAML 1.2\n--- \n23: dreiundzwanzig\n42: zweiundvierzig",
assertStringEqual(yamlDirs & "\n23: dreiundzwanzig\n42: zweiundvierzig",
output)
test "Load OrderedTable[tuple[int32, int32], string]":
@ -259,8 +261,8 @@ suite "Serialization":
input.add((a: 23'i32, b: 42'i32), "dreiundzwanzigzweiundvierzig")
input.add((a: 13'i32, b: 47'i32), "dreizehnsiebenundvierzig")
var output = dump(input, tsRootOnly, asTidy, blockOnly)
assertStringEqual("""%YAML 1.2
--- !nim:tables:OrderedTable(nim:tuple(nim:system:int32,nim:system:int32),tag:yaml.org,2002:str)
assertStringEqual(yamlDirs &
"""!n!tables:OrderedTable(tag:nimyaml.org;2016:tuple(tag:nimyaml.org;2016:system:int32;tag:nimyaml.org;2016:system:int32);tag:yaml.org;2002:str)
-
?
a: 23
@ -284,11 +286,11 @@ suite "Serialization":
test "Dump Sequences in Sequence":
let input = @[@[1.int32, 2.int32, 3.int32], @[4.int32, 5.int32], @[6.int32]]
var output = dump(input, tsNone)
assertStringEqual "%YAML 1.2\n--- \n- [1, 2, 3]\n- [4, 5]\n- [6]", output
assertStringEqual yamlDirs & "\n- [1, 2, 3]\n- [4, 5]\n- [6]", output
test "Load Enum":
let input =
newStringStream("!nim:system:seq(tl)\n- !tl tlRed\n- tlGreen\n- tlYellow")
newStringStream("!<tag:nimyaml.org,2016:system:seq(tl)>\n- !tl tlRed\n- tlGreen\n- tlYellow")
var result: seq[TrafficLight]
load(input, result)
assert result.len == 3
@ -299,7 +301,7 @@ suite "Serialization":
test "Dump Enum":
let input = @[tlRed, tlGreen, tlYellow]
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n- tlRed\n- tlGreen\n- tlYellow", output
assertStringEqual yamlDirs & "\n- tlRed\n- tlGreen\n- tlYellow", output
test "Load Tuple":
let input = newStringStream("str: value\ni: 42\nb: true")
@ -312,7 +314,7 @@ suite "Serialization":
test "Dump Tuple":
let input = (str: "value", i: 42.int32, b: true)
var output = dump(input, tsNone)
assertStringEqual "%YAML 1.2\n--- \nstr: value\ni: 42\nb: y", output
assertStringEqual yamlDirs & "\nstr: value\ni: 42\nb: y", output
test "Load Tuple - unknown field":
let input = "str: value\nfoo: bar\ni: 42\nb: true"
@ -358,8 +360,8 @@ suite "Serialization":
test "Dump custom object":
let input = Person(firstnamechar: 'P', surname: "Pan", age: 12)
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual(
"%YAML 1.2\n--- \nfirstnamechar: P\nsurname: Pan\nage: 12", output)
assertStringEqual(yamlDirs &
"\nfirstnamechar: P\nsurname: Pan\nage: 12", output)
test "Load custom object - unknown field":
let input = " firstnamechar: P\n surname: Pan\n age: 12\n occupation: free"
@ -380,8 +382,8 @@ suite "Serialization":
load(input, result)
test "Load sequence with explicit tags":
let input = newStringStream("--- !nim:system:seq(" &
"tag:yaml.org,2002:str)\n- !!str one\n- !!str two")
let input = newStringStream(yamlDirs & "!n!system:seq(" &
"tag:yaml.org;2002:str)\n- !!str one\n- !!str two")
var result: seq[string]
load(input, result)
assert result[0] == "one"
@ -390,12 +392,12 @@ suite "Serialization":
test "Dump sequence with explicit tags":
let input = @["one", "two"]
var output = dump(input, tsAll, asTidy, blockOnly)
assertStringEqual("%YAML 1.2\n--- !nim:system:seq(" &
"tag:yaml.org,2002:str) \n- !!str one\n- !!str two", output)
assertStringEqual(yamlDirs & "!n!system:seq(" &
"tag:yaml.org;2002:str) \n- !!str one\n- !!str two", output)
test "Load custom object with explicit root tag":
let input = newStringStream(
"--- !nim:custom:Person\nfirstnamechar: P\nsurname: Pan\nage: 12")
"--- !<tag:nimyaml.org,2016:custom:Person>\nfirstnamechar: P\nsurname: Pan\nage: 12")
var result: Person
load(input, result)
assert result.firstnamechar == 'P'
@ -405,9 +407,8 @@ suite "Serialization":
test "Dump custom object with explicit root tag":
let input = Person(firstnamechar: 'P', surname: "Pan", age: 12)
var output = dump(input, tsRootOnly, asTidy, blockOnly)
assertStringEqual("%YAML 1.2\n" &
"--- !nim:custom:Person \nfirstnamechar: P\nsurname: Pan\nage: 12",
output)
assertStringEqual(yamlDirs &
"!n!custom:Person \nfirstnamechar: P\nsurname: Pan\nage: 12", output)
test "Load custom variant object":
let input = newStringStream(
@ -427,8 +428,8 @@ suite "Serialization":
let input = @[Animal(name: "Bastet", kind: akCat, purringIntensity: 7),
Animal(name: "Anubis", kind: akDog, barkometer: 13)]
var output = dump(input, tsNone, asTidy, blockOnly)
assertStringEqual """%YAML 1.2
---
assertStringEqual yamlDirs & """
-
-
name: Bastet
@ -459,8 +460,7 @@ suite "Serialization":
b.next = c
c.next = a
var output = dump(a, tsRootOnly, asTidy, blockOnly)
assertStringEqual """%YAML 1.2
--- !example.net:Node &a
assertStringEqual yamlDirs & """!example.net:Node &a
value: a
next:
value: b
@ -469,13 +469,12 @@ next:
next: *a""", output
test "Load cyclic data structure":
let input = newStringStream("""%YAML 1.2
--- !nim:system:seq(example.net:Node)
- &a
let input = newStringStream(yamlDirs & """!n!system:seq(example.net:Node)
- &a
value: a
next: &b
next: &b
value: b
next: &c
next: &c
value: c
next: *a
- *b
@ -517,8 +516,8 @@ next:
input.add(new string)
input[1][] = "~"
var output = dump(input, tsRootOnly, asTidy, blockOnly)
assertStringEqual(
"%YAML 1.2\n--- !nim:system:seq(tag:yaml.org,2002:str) \n- !!null ~\n- !!str ~",
assertStringEqual(yamlDirs &
"!n!system:seq(tag:yaml.org;2002:str) \n- !!null ~\n- !!str ~",
output)
test "Custom constructObject":
@ -532,8 +531,7 @@ next:
test "Custom representObject":
let input = @[1.BetterInt, 9998887.BetterInt, 98312.BetterInt]
var output = dump(input, tsAll, asTidy, blockOnly)
assertStringEqual """%YAML 1.2
--- !nim:system:seq(test:BetterInt)
assertStringEqual yamlDirs & """!n!system:seq(test:BetterInt)
- !test:BetterInt 1
- !test:BetterInt 9_998_887
- !test:BetterInt 98_312""", output

View File

@ -413,12 +413,10 @@ proc writeTagAndAnchor(target: PresenterTarget, tag: TagId,
try:
if tag notin [yTagQuestionMark, yTagExclamationMark]:
let tagUri = tagLib.uri(tag)
if tagUri.startsWith(tagLib.secondaryPrefix):
target.append("!!")
target.append(tagUri[18..tagUri.high])
target.append(' ')
elif tagUri.startsWith("!"):
target.append(tagUri)
let (handle, length) = tagLib.searchHandle(tagUri)
if length > 0:
target.append(handle)
target.append(tagUri[length..tagUri.high])
target.append(' ')
else:
target.append("!<")
@ -461,8 +459,15 @@ proc doPresent(s: var YamlStream, target: PresenterTarget,
of ov1_2: target.append("%YAML 1.2" & newline)
of ov1_1: target.append("%YAML 1.1" & newLine)
of ovNone: discard
if tagLib.secondaryPrefix != yamlTagRepositoryPrefix:
target.append("%TAG !! " & tagLib.secondaryPrefix & newline)
for prefix, handle in tagLib.handles():
if handle == "!":
if prefix != "!":
target.append("%TAG ! " & prefix & newline)
elif handle == "!!":
if prefix != yamlTagRepositoryPrefix:
target.append("%TAG !! " & prefix & newline)
else:
target.append("%TAG " & handle & ' ' & prefix & newline)
target.append("--- ")
except:
var e = newException(YamlPresenterOutputError, "")

View File

@ -104,9 +104,17 @@ proc lazyLoadTag(uri: string): TagId {.inline, raises: [].} =
proc safeTagUri(id: TagId): string {.raises: [].} =
try:
let uri = serializationTagLibrary.uri(id)
if uri.len > 0 and uri[0] == '!': return uri[1..uri.len - 1]
else: return uri
var
uri = serializationTagLibrary.uri(id)
i = 0
# '!' is not allowed inside a tag handle
if uri.len > 0 and uri[0] == '!': uri = uri[1..^1]
# ',' is not allowed after a tag handle in the suffix because it's a flow
# indicator
for c in uri.mitems():
if c == ',': c = ';'
inc(i)
return uri
except KeyError: internalError("Unexpected KeyError for TagId " & $id)
proc constructionError(s: YamlStream, msg: string): ref YamlConstructionError =
@ -314,11 +322,11 @@ proc representObject*(value: char, ts: TagStyle, c: SerializationContext,
c.put(scalarEvent("" & value, tag, yAnchorNone))
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline, raises: [].} =
let uri = "!nim:system:seq(" & safeTagUri(yamlTag(I)) & ')'
let uri = nimTag("system:seq(" & safeTagUri(yamlTag(I)) & ')')
result = lazyLoadTag(uri)
proc yamlTag*[I](T: typedesc[set[I]]): TagId {.inline, raises: [].} =
let uri = "!nim:system:set(" & safeTagUri(yamlTag(I)) & ')'
let uri = nimTag("system:set(" & safeTagUri(yamlTag(I)) & ')')
result = lazyLoadTag(uri)
proc constructObject*[T](s: var YamlStream, c: ConstructionContext,
@ -360,8 +368,8 @@ proc representObject*[T](value: seq[T]|set[T], ts: TagStyle,
proc yamlTag*[I, V](T: typedesc[array[I, V]]): TagId {.inline, raises: [].} =
const rangeName = name(I)
let uri = "!nim:system:array(" & rangeName[6..rangeName.high()] & "," &
safeTagUri(yamlTag(V)) & ')'
let uri = nimTag("system:array(" & rangeName[6..rangeName.high()] & ';' &
safeTagUri(yamlTag(V)) & ')')
result = lazyLoadTag(uri)
proc constructObject*[I, T](s: var YamlStream, c: ConstructionContext,
@ -391,8 +399,8 @@ proc representObject*[I, T](value: array[I, T], ts: TagStyle,
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
try:
let uri = "!nim:tables:Table(" & safeTagUri(yamlTag(K)) & "," &
safeTagUri(yamlTag(V)) & ")"
let uri = nimTag("tables:Table(" & safeTagUri(yamlTag(K)) & ';' &
safeTagUri(yamlTag(V)) & ")")
result = lazyLoadTag(uri)
except KeyError:
# cannot happen (theoretically, you know)
@ -430,8 +438,8 @@ proc representObject*[K, V](value: Table[K, V], ts: TagStyle,
proc yamlTag*[K, V](T: typedesc[OrderedTable[K, V]]): TagId
{.inline, raises: [].} =
try:
let uri = "!nim:tables:OrderedTable(" & safeTagUri(yamlTag(K)) & "," &
safeTagUri(yamlTag(V)) & ")"
let uri = nimTag("tables:OrderedTable(" & safeTagUri(yamlTag(K)) & ';' &
safeTagUri(yamlTag(V)) & ")")
result = lazyLoadTag(uri)
except KeyError:
# cannot happen (theoretically, you know)
@ -475,7 +483,7 @@ proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
proc yamlTag*(T: typedesc[object|enum]):
TagId {.inline, raises: [].} =
var uri = "!nim:custom:" & (typetraits.name(type(T)))
var uri = nimTag("custom:" & (typetraits.name(type(T))))
try: serializationTagLibrary.tags[uri]
except KeyError: serializationTagLibrary.registerUri(uri)
@ -483,7 +491,7 @@ proc yamlTag*(T: typedesc[tuple]):
TagId {.inline, raises: [].} =
var
i: T
uri = "!nim:tuple("
uri = nimTag("tuple(")
first = true
for name, value in fieldPairs(i):
if first: first = false
@ -741,6 +749,7 @@ macro constructImplicitVariantObject(s, c, r, possibleTagIds: untyped,
))
ifStmt.add(newNimNode(nnkElse).add(newNimNode(nnkTryStmt).add(
newStmtList(raiseStmt), newNimNode(nnkExceptBranch).add(
newIdentNode("KeyError"),
newNimNode(nnkDiscardStmt).add(newEmptyNode())
))))
result = newStmtList(newCall("reset", r), ifStmt)

View File

@ -12,7 +12,7 @@
## and create own tags. It also enables you to define tags for types used with
## the serialization API.
import tables, macros, hashes
import tables, macros, hashes, strutils
type
TagId* = distinct int ## \
@ -41,7 +41,7 @@ type
## `initExtendedTagLibrary <#initExtendedTagLibrary>`_.
tags*: Table[string, TagId]
nextCustomTagId*: TagId
secondaryPrefix*: string
tagHandles: Table[string, string]
const
# failsafe schema
@ -102,6 +102,7 @@ const
## exist in the ``YamlTagLibrary`` which is used for parsing.
yamlTagRepositoryPrefix* = "tag:yaml.org,2002:"
nimyamlTagRepositoryPrefix* = "tag:nimyaml.org,2016:"
proc `==`*(left, right: TagId): bool {.borrow.}
proc hash*(id: TagId): Hash {.borrow.}
@ -133,7 +134,7 @@ proc initTagLibrary*(): TagLibrary {.raises: [].} =
## ``yFirstCustomTagId``.
new(result)
result.tags = initTable[string, TagId]()
result.secondaryPrefix = yamlTagRepositoryPrefix
result.tagHandles = {"!": "!", yamlTagRepositoryPrefix : "!!"}.toTable()
result.nextCustomTagId = yFirstCustomTagId
proc registerUri*(tagLib: TagLibrary, uri: string): TagId {.raises: [].} =
@ -149,6 +150,9 @@ proc uri*(tagLib: TagLibrary, id: TagId): string {.raises: [KeyError].} =
if iId == id: return iUri
raise newException(KeyError, "Unknown tag id: " & $id)
template y(suffix: string): string = yamlTagRepositoryPrefix & suffix
template n(suffix: string): string = nimyamlTagRepositoryPrefix & suffix
proc initFailsafeTagLibrary*(): TagLibrary {.raises: [].} =
## Contains only:
## - ``!``
@ -159,9 +163,9 @@ proc initFailsafeTagLibrary*(): TagLibrary {.raises: [].} =
result = initTagLibrary()
result.tags["!"] = yTagExclamationMark
result.tags["?"] = yTagQuestionMark
result.tags["tag:yaml.org,2002:str"] = yTagString
result.tags["tag:yaml.org,2002:seq"] = yTagSequence
result.tags["tag:yaml.org,2002:map"] = yTagMapping
result.tags[y"str"] = yTagString
result.tags[y"seq"] = yTagSequence
result.tags[y"map"] = yTagMapping
proc initCoreTagLibrary*(): TagLibrary {.raises: [].} =
## Contains everything in ``initFailsafeTagLibrary`` plus:
@ -170,10 +174,10 @@ proc initCoreTagLibrary*(): TagLibrary {.raises: [].} =
## - ``!!int``
## - ``!!float``
result = initFailsafeTagLibrary()
result.tags["tag:yaml.org,2002:null"] = yTagNull
result.tags["tag:yaml.org,2002:bool"] = yTagBoolean
result.tags["tag:yaml.org,2002:int"] = yTagInteger
result.tags["tag:yaml.org,2002:float"] = yTagFloat
result.tags[y"null"] = yTagNull
result.tags[y"bool"] = yTagBoolean
result.tags[y"int"] = yTagInteger
result.tags[y"float"] = yTagFloat
proc initExtendedTagLibrary*(): TagLibrary {.raises: [].} =
## Contains everything from ``initCoreTagLibrary`` plus:
@ -186,29 +190,29 @@ proc initExtendedTagLibrary*(): TagLibrary {.raises: [].} =
## - ``!!value``
## - ``!!yaml``
result = initCoreTagLibrary()
result.tags["tag:yaml.org,2002:omap"] = yTagOrderedMap
result.tags["tag:yaml.org,2002:pairs"] = yTagPairs
result.tags["tag:yaml.org,2002:binary"] = yTagBinary
result.tags["tag:yaml.org,2002:merge"] = yTagMerge
result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp
result.tags["tag:yaml.org,2002:value"] = yTagValue
result.tags["tag:yaml.org,2002:yaml"] = yTagYaml
result.tags[y"omap"] = yTagOrderedMap
result.tags[y"pairs"] = yTagPairs
result.tags[y"binary"] = yTagBinary
result.tags[y"merge"] = yTagMerge
result.tags[y"timestamp"] = yTagTimestamp
result.tags[y"value"] = yTagValue
result.tags[y"yaml"] = yTagYaml
proc initSerializationTagLibrary*(): TagLibrary =
result = initTagLibrary()
result.tagHandles[nimyamlTagRepositoryPrefix] = "!n!"
result.tags["!"] = yTagExclamationMark
result.tags["?"] = yTagQuestionMark
result.tags["tag:yaml.org,2002:str"] = yTagString
result.tags["tag:yaml.org,2002:null"] = yTagNull
result.tags["tag:yaml.org,2002:bool"] = yTagBoolean
result.tags["tag:yaml.org,2002:float"] = yTagFloat
result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp
result.tags["tag:yaml.org,2002:value"] = yTagValue
result.tags["tag:yaml.org,2002:binary"] = yTagBinary
result.tags["!nim:field"] = yTagNimField
result.tags["!nim:nil:string"] = yTagNimNilString
result.tags["!nim:nil:seq"] = yTagNimNilSeq
result.tags[y"str"] = yTagString
result.tags[y"null"] = yTagNull
result.tags[y"bool"] = yTagBoolean
result.tags[y"float"] = yTagFloat
result.tags[y"timestamp"] = yTagTimestamp
result.tags[y"value"] = yTagValue
result.tags[y"binary"] = yTagBinary
result.tags[n"field"] = yTagNimField
result.tags[n"nil:string"] = yTagNimNilString
result.tags[n"nil:seq"] = yTagNimNilSeq
var
serializationTagLibrary* = initSerializationTagLibrary() ## \
@ -262,27 +266,56 @@ static:
# standard YAML tags used by serialization
registeredUris.add("!")
registeredUris.add("?")
registeredUris.add("tag:yaml.org,2002:str")
registeredUris.add("tag:yaml.org,2002:null")
registeredUris.add("tag:yaml.org,2002:bool")
registeredUris.add("tag:yaml.org,2002:float")
registeredUris.add("tag:yaml.org,2002:timestamp")
registeredUris.add("tag:yaml.org,2002:value")
registeredUris.add("tag:yaml.org,2002:binary")
registeredUris.add(y"str")
registeredUris.add(y"null")
registeredUris.add(y"bool")
registeredUris.add(y"float")
registeredUris.add(y"timestamp")
registeredUris.add(y"value")
registeredUris.add(y"binary")
# special tags used by serialization
registeredUris.add("!nim:field")
registeredUris.add("!nim:nil:string")
registeredUris.add("!nim:nil:seq")
registeredUris.add(n"field")
registeredUris.add(n"nil:string")
registeredUris.add(n"nil:seq")
# tags for Nim's standard types
setTagUri(char, "!nim:system:char", yTagNimChar)
setTagUri(int8, "!nim:system:int8", yTagNimInt8)
setTagUri(int16, "!nim:system:int16", yTagNimInt16)
setTagUri(int32, "!nim:system:int32", yTagNimInt32)
setTagUri(int64, "!nim:system:int64", yTagNimInt64)
setTagUri(uint8, "!nim:system:uint8", yTagNimUInt8)
setTagUri(uint16, "!nim:system:uint16", yTagNimUInt16)
setTagUri(uint32, "!nim:system:uint32", yTagNimUInt32)
setTagUri(uint64, "!nim:system:uint64", yTagNimUInt64)
setTagUri(float32, "!nim:system:float32", yTagNimFloat32)
setTagUri(float64, "!nim:system:float64", yTagNimFloat64)
setTagUri(char, n"system:char", yTagNimChar)
setTagUri(int8, n"system:int8", yTagNimInt8)
setTagUri(int16, n"system:int16", yTagNimInt16)
setTagUri(int32, n"system:int32", yTagNimInt32)
setTagUri(int64, n"system:int64", yTagNimInt64)
setTagUri(uint8, n"system:uint8", yTagNimUInt8)
setTagUri(uint16, n"system:uint16", yTagNimUInt16)
setTagUri(uint32, n"system:uint32", yTagNimUInt32)
setTagUri(uint64, n"system:uint64", yTagNimUInt64)
setTagUri(float32, n"system:float32", yTagNimFloat32)
setTagUri(float64, n"system:float64", yTagNimFloat64)
proc registerHandle*(tagLib: TagLibrary, handle, prefix: string) =
## Registers a handle for a prefix. When presenting any tag that starts with
## this prefix, the handle is used instead. Also causes the presenter to
## output a TAG directive for the handle.
taglib.tagHandles[prefix] = handle
proc searchHandle*(tagLib: TagLibrary, tag: string):
tuple[handle: string, len: int] {.raises: [].} =
## search in the registered tag handles for one whose prefix matches the start
## of the given tag. If multiple registered handles match, the one with the
## longest prefix is returned. If no registered handle matches, (nil, 0) is
## returned.
result.len = 0
for key, value in tagLib.tagHandles:
if key.len > result.len:
if tag.startsWith(key):
result.len = key.len
result.handle = value
iterator handles*(tagLib: TagLibrary): tuple[prefix, handle: string] =
## iterate over registered tag handles that may be used as shortcuts
## (e.g. ``!n!`` for ``tag:nimyaml.org,2016:``)
for key, value in tagLib.tagHandles: yield (key, value)
proc nimTag*(suffix: string): string =
## prepends NimYAML's tag repository prefix to the given suffix. For example,
## ``nimTag("system:char")`` yields ``"tag:nimyaml.org,2016:system:char"``.
nimyamlTagRepositoryPrefix & suffix