From 29352fa4fe1a9a91f300a11179f362049c786b3c Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Mon, 10 Oct 2016 20:16:54 +0200 Subject: [PATCH] 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 --- doc/snippets/quickstart/00/01-out.yaml | 3 +- doc/snippets/quickstart/02/01-out.yaml | 19 ++-- doc/snippets/quickstart/03/01-out.yaml | 3 +- doc/snippets/quickstart/04/01-in.yaml | 7 +- doc/snippets/quickstart/05/01-out.yaml | 7 +- doc/snippets/quickstart/08/00/00-code.nim | 2 +- doc/snippets/quickstart/08/00/01-in.yaml | 3 +- doc/snippets/quickstart/08/01/00-code.nim | 2 +- doc/snippets/quickstart/08/01/01-in.yaml | 3 +- test/tserialization.nim | 74 ++++++------ yaml/presenter.nim | 21 ++-- yaml/serialization.nim | 35 +++--- yaml/taglib.nim | 131 ++++++++++++++-------- 13 files changed, 181 insertions(+), 129 deletions(-) diff --git a/doc/snippets/quickstart/00/01-out.yaml b/doc/snippets/quickstart/00/01-out.yaml index 207ff5c..ae95158 100644 --- a/doc/snippets/quickstart/00/01-out.yaml +++ b/doc/snippets/quickstart/00/01-out.yaml @@ -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 diff --git a/doc/snippets/quickstart/02/01-out.yaml b/doc/snippets/quickstart/02/01-out.yaml index 89d97a6..c2919ff 100644 --- a/doc/snippets/quickstart/02/01-out.yaml +++ b/doc/snippets/quickstart/02/01-out.yaml @@ -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" } ] diff --git a/doc/snippets/quickstart/03/01-out.yaml b/doc/snippets/quickstart/03/01-out.yaml index 4762270..ee3adbd 100644 --- a/doc/snippets/quickstart/03/01-out.yaml +++ b/doc/snippets/quickstart/03/01-out.yaml @@ -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 diff --git a/doc/snippets/quickstart/04/01-in.yaml b/doc/snippets/quickstart/04/01-in.yaml index 78d163b..9c99c16 100644 --- a/doc/snippets/quickstart/04/01-in.yaml +++ b/doc/snippets/quickstart/04/01-in.yaml @@ -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 \ No newline at end of file +right: *b diff --git a/doc/snippets/quickstart/05/01-out.yaml b/doc/snippets/quickstart/05/01-out.yaml index b3c155a..16710fc 100644 --- a/doc/snippets/quickstart/05/01-out.yaml +++ b/doc/snippets/quickstart/05/01-out.yaml @@ -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] diff --git a/doc/snippets/quickstart/08/00/00-code.nim b/doc/snippets/quickstart/08/00/00-code.nim index 4bf5947..7be0d02 100644 --- a/doc/snippets/quickstart/08/00/00-code.nim +++ b/doc/snippets/quickstart/08/00/00-code.nim @@ -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 diff --git a/doc/snippets/quickstart/08/00/01-in.yaml b/doc/snippets/quickstart/08/00/01-in.yaml index aae04fc..7923272 100644 --- a/doc/snippets/quickstart/08/00/01-in.yaml +++ b/doc/snippets/quickstart/08/00/01-in.yaml @@ -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 \ No newline at end of file diff --git a/doc/snippets/quickstart/08/01/00-code.nim b/doc/snippets/quickstart/08/01/00-code.nim index 59b0f84..15046ee 100644 --- a/doc/snippets/quickstart/08/01/00-code.nim +++ b/doc/snippets/quickstart/08/01/00-code.nim @@ -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) diff --git a/doc/snippets/quickstart/08/01/01-in.yaml b/doc/snippets/quickstart/08/01/01-in.yaml index 8164e19..10fff1b 100644 --- a/doc/snippets/quickstart/08/01/01-in.yaml +++ b/doc/snippets/quickstart/08/01/01-in.yaml @@ -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} \ No newline at end of file +- !n!demo:Person {name: Trillian} \ No newline at end of file diff --git a/test/tserialization.nim b/test/tserialization.nim index 861dbc0..4432626 100644 --- a/test/tserialization.nim +++ b/test/tserialization.nim @@ -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("! \"\"") 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("! \"\"") 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("!\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") + "--- !\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 diff --git a/yaml/presenter.nim b/yaml/presenter.nim index f5b9537..9dd1151 100644 --- a/yaml/presenter.nim +++ b/yaml/presenter.nim @@ -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, "") diff --git a/yaml/serialization.nim b/yaml/serialization.nim index 756b52e..52cdcb1 100644 --- a/yaml/serialization.nim +++ b/yaml/serialization.nim @@ -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) diff --git a/yaml/taglib.nim b/yaml/taglib.nim index e077ef8..1d34232 100644 --- a/yaml/taglib.nim +++ b/yaml/taglib.nim @@ -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) \ No newline at end of file +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 \ No newline at end of file