mirror of https://github.com/status-im/NimYAML.git
changed TagId to Tag. removed JS stuff that wasn't working anyway.
This commit is contained in:
parent
6238104622
commit
aa65c066d5
|
@ -118,7 +118,7 @@ template yieldEvent() {.dirty.} =
|
|||
yield curEvent
|
||||
inEvent = false
|
||||
|
||||
template setTag(t: TagId) {.dirty.} =
|
||||
template setTag(t: Tag) {.dirty.} =
|
||||
case curEvent.kind
|
||||
of yamlStartSeq: curEvent.seqProperties.tag = t
|
||||
of yamlStartMap: curEvent.mapProperties.tag = t
|
||||
|
@ -133,8 +133,8 @@ template setAnchor(a: Anchor) {.dirty.} =
|
|||
of yamlAlias: curEvent.aliasTarget = a
|
||||
else: discard
|
||||
|
||||
template curTag(): TagId =
|
||||
var foo: TagId
|
||||
template curTag(): Tag =
|
||||
var foo: Tag
|
||||
case curEvent.kind
|
||||
of yamlStartSeq: foo = curEvent.seqProperties.tag
|
||||
of yamlStartMap: foo = curEvent.mapProperties.tag
|
||||
|
@ -143,7 +143,7 @@ template curTag(): TagId =
|
|||
$curEvent.kind & " may not have a tag")
|
||||
foo
|
||||
|
||||
template setCurTag(val: TagId) =
|
||||
template setCurTag(val: Tag) =
|
||||
case curEvent.kind
|
||||
of yamlStartSeq: curEvent.seqProperties.tag = val
|
||||
of yamlStartMap: curEvent.mapProperties.tag = val
|
||||
|
|
|
@ -71,7 +71,7 @@ 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: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
var
|
||||
val = $value
|
||||
i = val.len - 3
|
||||
|
|
146
yaml/data.nim
146
yaml/data.nim
|
@ -10,17 +10,8 @@ type
|
|||
## Anchor provides the operator `$` for converting to string, `==` for
|
||||
## comparison, and `hash` for usage in a hashmap.
|
||||
|
||||
TagId* = distinct int ## \
|
||||
## A ``TagId`` identifies a tag URI, like for example
|
||||
## ``"tag:yaml.org,2002:str"``. The URI corresponding to a ``TagId`` can
|
||||
## be queried from the `TagLibrary <#TagLibrary>`_ which was
|
||||
## used to create this ``TagId``; e.g. when you parse a YAML character
|
||||
## stream, the ``TagLibrary`` of the parser is the one which generates
|
||||
## the resulting ``TagId`` s.
|
||||
##
|
||||
## URI strings are mapped to ``TagId`` s for efficiency reasons (you
|
||||
## do not need to compare strings every time) and to be able to
|
||||
## discover unknown tag URIs early in the parsing process.
|
||||
Tag* = distinct string ## \
|
||||
## A ``Tag`` contains an URI, like for example ``"tag:yaml.org,2002:str"``.
|
||||
|
||||
ScalarStyle* = enum
|
||||
## Original style of the scalar (for input),
|
||||
|
@ -77,7 +68,21 @@ type
|
|||
|
||||
Mark* = tuple[line, column: Positive]
|
||||
|
||||
Properties* = tuple[anchor: Anchor, tag: TagId]
|
||||
Properties* = tuple[anchor: Anchor, tag: Tag]
|
||||
|
||||
const
|
||||
yamlTagRepositoryPrefix* = "tag:yaml.org,2002:"
|
||||
nimyamlTagRepositoryPrefix* = "tag:nimyaml.org,2016:"
|
||||
|
||||
proc defineTag*(uri: string): Tag =
|
||||
## defines a tag. Use this to optimize away copies of globally defined
|
||||
## Tags.
|
||||
result = uri.Tag
|
||||
#shallow(result.string) # doesn't work at compile-time
|
||||
|
||||
proc defineCoreTag*(name: string): Tag =
|
||||
## defines a tag in YAML's core namespace, ``tag:yaml.org,2002:``
|
||||
result = defineTag(yamlTagRepositoryPrefix & name)
|
||||
|
||||
const
|
||||
yAnchorNone*: Anchor = "".Anchor ## \
|
||||
|
@ -86,61 +91,36 @@ const
|
|||
defaultMark: Mark = (1.Positive, 1.Positive) ## \
|
||||
## used for events that are not generated from input.
|
||||
|
||||
yTagExclamationMark*: TagId = 0.TagId ## ``!`` non-specific tag
|
||||
yTagQuestionMark* : TagId = 1.TagId ## ``?`` non-specific tag
|
||||
yTagExclamationMark*: Tag = defineTag("!")
|
||||
yTagQuestionMark* : Tag = defineTag("?")
|
||||
|
||||
# failsafe schema
|
||||
|
||||
yTagString* : TagId = 2.TagId ## \
|
||||
## `!!str <http://yaml.org/type/str.html >`_ tag
|
||||
yTagSequence* : TagId = 3.TagId ## \
|
||||
## `!!seq <http://yaml.org/type/seq.html>`_ tag
|
||||
yTagMapping* : TagId = 4.TagId ## \
|
||||
## `!!map <http://yaml.org/type/map.html>`_ tag
|
||||
yTagString* = defineCoreTag("str")
|
||||
yTagSequence* = defineCoreTag("seq")
|
||||
yTagMapping* = defineCoreTag("map")
|
||||
|
||||
# json & core schema
|
||||
|
||||
yTagNull* : TagId = 5.TagId ## \
|
||||
## `!!null <http://yaml.org/type/null.html>`_ tag
|
||||
yTagBoolean* : TagId = 6.TagId ## \
|
||||
## `!!bool <http://yaml.org/type/bool.html>`_ tag
|
||||
yTagInteger* : TagId = 7.TagId ## \
|
||||
## `!!int <http://yaml.org/type/int.html>`_ tag
|
||||
yTagFloat* : TagId = 8.TagId ## \
|
||||
## `!!float <http://yaml.org/type/float.html>`_ tag
|
||||
yTagNull* = defineCoreTag("null")
|
||||
yTagBoolean* = defineCoreTag("bool")
|
||||
yTagInteger* = defineCoreTag("int")
|
||||
yTagFloat* = defineCoreTag("float")
|
||||
|
||||
# other language-independent YAML types (from http://yaml.org/type/ )
|
||||
|
||||
yTagOrderedMap* : TagId = 9.TagId ## \
|
||||
## `!!omap <http://yaml.org/type/omap.html>`_ tag
|
||||
yTagPairs* : TagId = 10.TagId ## \
|
||||
## `!!pairs <http://yaml.org/type/pairs.html>`_ tag
|
||||
yTagSet* : TagId = 11.TagId ## \
|
||||
## `!!set <http://yaml.org/type/set.html>`_ tag
|
||||
yTagBinary* : TagId = 12.TagId ## \
|
||||
## `!!binary <http://yaml.org/type/binary.html>`_ tag
|
||||
yTagMerge* : TagId = 13.TagId ## \
|
||||
## `!!merge <http://yaml.org/type/merge.html>`_ tag
|
||||
yTagTimestamp* : TagId = 14.TagId ## \
|
||||
## `!!timestamp <http://yaml.org/type/timestamp.html>`_ tag
|
||||
yTagValue* : TagId = 15.TagId ## \
|
||||
## `!!value <http://yaml.org/type/value.html>`_ tag
|
||||
yTagYaml* : TagId = 16.TagId ## \
|
||||
## `!!yaml <http://yaml.org/type/yaml.html>`_ tag
|
||||
yTagOrderedMap* = defineCoreTag("omap")
|
||||
yTagPairs* = defineCoreTag("pairs")
|
||||
yTagSet* = defineCoreTag("set")
|
||||
yTagBinary* = defineCoreTag("binary")
|
||||
yTagMerge* = defineCoreTag("merge")
|
||||
yTagTimestamp* = defineCoreTag("timestamp")
|
||||
yTagValue* = defineCoreTag("value")
|
||||
yTagYaml* = defineCoreTag("yaml")
|
||||
|
||||
yTagNimField* : TagId = 100.TagId ## \
|
||||
## This tag is used in serialization for the name of a field of an
|
||||
## object. It may contain any string scalar that is a valid Nim symbol.
|
||||
# NimYAML specific tags
|
||||
|
||||
yFirstStaticTagId* : TagId = 1000.TagId ## \
|
||||
## The first ``TagId`` assigned by the ``setTagId`` templates.
|
||||
|
||||
yFirstCustomTagId* : TagId = 10000.TagId ## \
|
||||
## The first ``TagId`` which should be assigned to an URI that does not
|
||||
## exist in the ``YamlTagLibrary`` which is used for parsing.
|
||||
|
||||
yamlTagRepositoryPrefix* = "tag:yaml.org,2002:"
|
||||
nimyamlTagRepositoryPrefix* = "tag:nimyaml.org,2016:"
|
||||
yTagNimField* = defineTag(nimyamlTagRepositoryPrefix & "field")
|
||||
|
||||
proc properties*(event: Event): Properties =
|
||||
## returns the tag of the given event
|
||||
|
@ -186,7 +166,7 @@ proc startMapEvent*(style: CollectionStyle, props: Properties,
|
|||
mapStyle: style)
|
||||
|
||||
proc startMapEvent*(style: CollectionStyle = csAny,
|
||||
tag: TagId = yTagQuestionMark,
|
||||
tag: Tag = yTagQuestionMark,
|
||||
anchor: Anchor = yAnchorNone,
|
||||
startPos, endPos: Mark = defaultMark): Event {.inline.} =
|
||||
return startMapEvent(style, (anchor, tag), startPos, endPos)
|
||||
|
@ -204,7 +184,7 @@ proc startSeqEvent*(style: CollectionStyle,
|
|||
seqStyle: style)
|
||||
|
||||
proc startSeqEvent*(style: CollectionStyle = csAny,
|
||||
tag: TagId = yTagQuestionMark,
|
||||
tag: Tag = yTagQuestionMark,
|
||||
anchor: Anchor = yAnchorNone,
|
||||
startPos, endPos: Mark = defaultMark): Event {.inline.} =
|
||||
return startSeqEvent(style, (anchor, tag), startPos, endPos)
|
||||
|
@ -221,7 +201,7 @@ proc scalarEvent*(content: string, props: Properties,
|
|||
kind: yamlScalar, scalarProperties: props,
|
||||
scalarContent: content, scalarStyle: style)
|
||||
|
||||
proc scalarEvent*(content: string = "", tag: TagId = yTagQuestionMark,
|
||||
proc scalarEvent*(content: string = "", tag: Tag = yTagQuestionMark,
|
||||
anchor: Anchor = yAnchorNone,
|
||||
style: ScalarStyle = ssAny,
|
||||
startPos, endPos: Mark = defaultMark): Event {.inline.} =
|
||||
|
@ -231,34 +211,13 @@ proc aliasEvent*(target: Anchor, startPos, endPos: Mark = defaultMark): Event {.
|
|||
## creates a new event that represents a YAML alias
|
||||
result = Event(startPos: startPos, endPos: endPos, kind: yamlAlias, aliasTarget: target)
|
||||
|
||||
proc `==`*(left, right: Anchor): bool {.borrow, locks: 0.}
|
||||
proc `$`*(id: Anchor): string {.borrow, locks: 0.}
|
||||
proc hash*(id: Anchor): Hash {.borrow, locks: 0.}
|
||||
proc `==`*(left, right: Anchor): bool {.borrow.}
|
||||
proc `$`*(id: Anchor): string {.borrow.}
|
||||
proc hash*(id: Anchor): Hash {.borrow.}
|
||||
|
||||
proc `==`*(left, right: TagId): bool {.borrow, locks: 0.}
|
||||
proc hash*(id: TagId): Hash {.borrow, locks: 0.}
|
||||
|
||||
proc `$`*(id: TagId): string {.raises: [].} =
|
||||
case id
|
||||
of yTagQuestionMark: "?"
|
||||
of yTagExclamationMark: "!"
|
||||
of yTagString: "!!str"
|
||||
of yTagSequence: "!!seq"
|
||||
of yTagMapping: "!!map"
|
||||
of yTagNull: "!!null"
|
||||
of yTagBoolean: "!!bool"
|
||||
of yTagInteger: "!!int"
|
||||
of yTagFloat: "!!float"
|
||||
of yTagOrderedMap: "!!omap"
|
||||
of yTagPairs: "!!pairs"
|
||||
of yTagSet: "!!set"
|
||||
of yTagBinary: "!!binary"
|
||||
of yTagMerge: "!!merge"
|
||||
of yTagTimestamp: "!!timestamp"
|
||||
of yTagValue: "!!value"
|
||||
of yTagYaml: "!!yaml"
|
||||
of yTagNimField: "!nim:field"
|
||||
else: "<" & $int(id) & ">"
|
||||
proc `==`*(left, right: Tag): bool {.borrow.}
|
||||
proc `$`*(tag: Tag): string {.borrow.}
|
||||
proc hash*(tag: Tag): Hash {.borrow.}
|
||||
|
||||
proc `==`*(left: Event, right: Event): bool {.raises: [].} =
|
||||
## compares all existing fields of the given items
|
||||
|
@ -279,8 +238,8 @@ proc renderAttrs*(props: Properties, isPlain: bool = true): string =
|
|||
result = ""
|
||||
if props.anchor != yAnchorNone: result &= " &" & $props.anchor
|
||||
case props.tag
|
||||
of yTagQuestionmark: discard
|
||||
of yTagExclamationmark:
|
||||
of yTagQuestionMark: discard
|
||||
of yTagExclamationMark:
|
||||
if isPlain: result &= " <!>"
|
||||
else:
|
||||
result &= " <" & $props.tag & ">"
|
||||
|
@ -313,3 +272,14 @@ proc `$`*(event: Event): string {.raises: [].} =
|
|||
of ssFolded: result &= " >"
|
||||
result &= yamlTestSuiteEscape(event.scalarContent)
|
||||
of yamlAlias: result = "=ALI *" & $event.aliasTarget
|
||||
|
||||
type
|
||||
TypeID* = int ## unique ID of a type
|
||||
|
||||
var nextTypeID {.compileTime.}: TypeID
|
||||
|
||||
proc typeID*(T:typedesc): TypeID =
|
||||
const id = nextTypeID
|
||||
static:
|
||||
inc nextTypeID
|
||||
return id
|
80
yaml/dom.nim
80
yaml/dom.nim
|
@ -137,11 +137,8 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
|
|||
YamlNode {.raises: [YamlStreamError, YamlConstructionError].} =
|
||||
template addAnchor(c: ConstructionContext, target: Anchor) =
|
||||
if target != yAnchorNone:
|
||||
when defined(JS):
|
||||
{.emit: [c, """.refs.set(""", target, ", ", result, ");"].}
|
||||
else:
|
||||
yAssert(not c.refs.hasKey(target))
|
||||
c.refs[target] = cast[pointer](result)
|
||||
yAssert(not c.refs.hasKey(target))
|
||||
c.refs[target] = (id: typeID(YamlNode), p: cast[pointer](result))
|
||||
|
||||
var start: Event
|
||||
shallowCopy(start, s.next())
|
||||
|
@ -149,7 +146,7 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
|
|||
try:
|
||||
case start.kind
|
||||
of yamlStartMap:
|
||||
result = YamlNode(tag: tagLib.uri(start.mapProperties.tag),
|
||||
result = YamlNode(tag: $start.mapProperties.tag,
|
||||
kind: yMapping,
|
||||
fields: newTable[YamlNode, YamlNode]())
|
||||
while s.peek().kind != yamlEndMap:
|
||||
|
@ -162,7 +159,7 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
|
|||
discard s.next()
|
||||
addAnchor(c, start.mapProperties.anchor)
|
||||
of yamlStartSeq:
|
||||
result = YamlNode(tag: tagLib.uri(start.seqProperties.tag),
|
||||
result = YamlNode(tag: $start.seqProperties.tag,
|
||||
kind: ySequence,
|
||||
elems: newSeq[YamlNode]())
|
||||
while s.peek().kind != yamlEndSeq:
|
||||
|
@ -170,15 +167,12 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
|
|||
addAnchor(c, start.seqProperties.anchor)
|
||||
discard s.next()
|
||||
of yamlScalar:
|
||||
result = YamlNode(tag: tagLib.uri(start.scalarProperties.tag),
|
||||
result = YamlNode(tag: $start.scalarProperties.tag,
|
||||
kind: yScalar)
|
||||
shallowCopy(result.content, start.scalarContent)
|
||||
addAnchor(c, start.scalarProperties.anchor)
|
||||
of yamlAlias:
|
||||
when defined(JS):
|
||||
{.emit: [result, " = ", c, ".refs.get(", start.aliasTarget, ");"].}
|
||||
else:
|
||||
result = cast[YamlNode](c.refs[start.aliasTarget])
|
||||
result = cast[YamlNode](c.refs[start.aliasTarget].p)
|
||||
else: internalError("Malformed YamlStream")
|
||||
except KeyError:
|
||||
raise newException(YamlConstructionError,
|
||||
|
@ -213,44 +207,22 @@ proc loadDom*(s: Stream | string): YamlDocument
|
|||
proc serializeNode(n: YamlNode, c: SerializationContext, a: AnchorStyle,
|
||||
tagLib: TagLibrary) {.raises: [].}=
|
||||
var val = yAnchorNone
|
||||
when defined(JS):
|
||||
{.emit: ["""
|
||||
if (""", a, " != ", asNone, " && ", c, ".refs.has(", n, """) {
|
||||
""", val, " = ", c, ".refs.get(", n, """);
|
||||
if (""", c, ".refs.get(", n, ") == ", yAnchorNone, ") {"].}
|
||||
val = c.nextAnchorId
|
||||
{.emit: [c, """.refs.set(""", n, """, """, val, """);"""].}
|
||||
c.nextAnchorId = AnchorId(int(c.nextAnchorId) + 1)
|
||||
{.emit: "}".}
|
||||
let p = cast[pointer](n)
|
||||
if a != asNone and c.refs.hasKey(p):
|
||||
val = c.refs.getOrDefault(p).a
|
||||
if val == yAnchorNone:
|
||||
val = c.nextAnchorId.Anchor
|
||||
c.refs[p] = (val, false)
|
||||
nextAnchor(c.nextAnchorId, len(c.nextAnchorId) - 1)
|
||||
c.put(aliasEvent(val))
|
||||
return
|
||||
{.emit: "}".}
|
||||
else:
|
||||
let p = cast[pointer](n)
|
||||
if a != asNone and c.refs.hasKey(p):
|
||||
val = c.refs.getOrDefault(p)
|
||||
if val == yAnchorNone:
|
||||
val = c.nextAnchorId.Anchor
|
||||
c.refs[p] = val
|
||||
nextAnchor(c.nextAnchorId, len(c.nextAnchorId) - 1)
|
||||
c.put(aliasEvent(val))
|
||||
return
|
||||
var
|
||||
tagId: TagId
|
||||
anchor: Anchor
|
||||
if a == asAlways:
|
||||
if a != asNone:
|
||||
val = c.nextAnchorId.Anchor
|
||||
when defined(JS):
|
||||
{.emit: [c, ".refs.set(", n, ", ", val, ");"].}
|
||||
else:
|
||||
c.refs[p] = c.nextAnchorId.Anchor
|
||||
c.refs[p] = (c.nextAnchorId.Anchor, false)
|
||||
nextAnchor(c.nextAnchorId, len(c.nextAnchorId) - 1)
|
||||
else:
|
||||
when defined(JS):
|
||||
{.emit: [c, ".refs.set(", n, ", ", yAnchorNone, ");"].}
|
||||
else:
|
||||
c.refs[p] = yAnchorNone
|
||||
tagId = if tagLib.tags.hasKey(n.tag): tagLib.tags.getOrDefault(n.tag) else:
|
||||
let tag = if tagLib.tags.hasKey(n.tag): tagLib.tags.getOrDefault(n.tag) else:
|
||||
tagLib.registerUri(n.tag)
|
||||
case a
|
||||
of asNone: anchor = yAnchorNone
|
||||
|
@ -258,27 +230,25 @@ proc serializeNode(n: YamlNode, c: SerializationContext, a: AnchorStyle,
|
|||
of asAlways: anchor = val
|
||||
|
||||
case n.kind
|
||||
of yScalar: c.put(scalarEvent(n.content, tagId, anchor))
|
||||
of yScalar: c.put(scalarEvent(n.content, tag, anchor))
|
||||
of ySequence:
|
||||
c.put(startSeqEvent(csBlock, (anchor, tagId)))
|
||||
c.put(startSeqEvent(csBlock, (anchor, tag)))
|
||||
for item in n.elems:
|
||||
serializeNode(item, c, a, tagLib)
|
||||
c.put(endSeqEvent())
|
||||
of yMapping:
|
||||
c.put(startMapEvent(csBlock, (anchor, tagId)))
|
||||
c.put(startMapEvent(csBlock, (anchor, tag)))
|
||||
for key, value in n.fields.pairs:
|
||||
serializeNode(key, c, a, tagLib)
|
||||
serializeNode(value, c, a, tagLib)
|
||||
c.put(endMapEvent())
|
||||
|
||||
template processAnchoredEvent(target: untyped, c: SerializationContext) =
|
||||
var anchorId: Anchor
|
||||
when defined(JS):
|
||||
{.emit: [anchorId, " = ", c, ".refs.get(", target, ");"].}
|
||||
else:
|
||||
anchorId = c.refs.getOrDefault(cast[pointer](target.anchor))
|
||||
if anchorId != yAnchorNone: target.anchor = anchorId
|
||||
else: target.anchor = yAnchorNone
|
||||
proc processAnchoredEvent(target: var Properties, c: SerializationContext) =
|
||||
for key, val in c.refs:
|
||||
if val.a == target.anchor:
|
||||
if not val.referenced:
|
||||
target.anchor = yAnchorNone
|
||||
break
|
||||
|
||||
proc serialize*(doc: YamlDocument, tagLib: TagLibrary, a: AnchorStyle = asTidy):
|
||||
YamlStream {.raises: [].} =
|
||||
|
|
|
@ -212,7 +212,7 @@ proc generateError(c: Context, message: string):
|
|||
msg: message, parent: nil, mark: c.lex.curStartPos,
|
||||
lineContent: c.lex.currentLine())
|
||||
|
||||
proc parseTag(c: Context): TagId =
|
||||
proc parseTag(c: Context): Tag =
|
||||
let handle = c.lex.fullLexeme()
|
||||
var uri = c.resolveHandle(handle)
|
||||
if uri == "":
|
||||
|
@ -792,7 +792,7 @@ proc beforeBlockIndentation(c: Context, e: var Event): bool =
|
|||
elif c.levels[^1].state == beforeBlockIndentation:
|
||||
raise c.generateError("Unexpected double beforeBlockIndentation")
|
||||
else:
|
||||
raise c.generateError("Internal error (please report this bug)")
|
||||
raise c.generateError("Internal error (please report this bug): unexpected state at endBlockNode")
|
||||
c.popLevel()
|
||||
c.popLevel()
|
||||
case c.lex.cur
|
||||
|
|
|
@ -428,7 +428,7 @@ proc writeTagAndAnchor(c: Context, props: Properties) {.raises: [YamlPresenterOu
|
|||
let t = c.target
|
||||
try:
|
||||
if props.tag notin [yTagQuestionMark, yTagExclamationMark]:
|
||||
let tagUri = c.tagLib.uri(props.tag)
|
||||
let tagUri = $props.tag
|
||||
let (handle, length) = c.searchHandle(tagUri)
|
||||
if length > 0:
|
||||
t.append(handle)
|
||||
|
|
|
@ -25,16 +25,14 @@ export data, stream, macros, annotations, options
|
|||
type
|
||||
SerializationContext* = ref object
|
||||
## Context information for the process of serializing YAML from Nim values.
|
||||
when not defined(JS):
|
||||
refs*: Table[pointer, Anchor] # `pointer` does not work with JS
|
||||
refs*: Table[pointer, tuple[a: Anchor, referenced: bool]]
|
||||
style: AnchorStyle
|
||||
nextAnchorId*: string
|
||||
put*: proc(e: Event) {.raises: [], closure.}
|
||||
|
||||
ConstructionContext* = ref object
|
||||
## Context information for the process of constructing Nim values from YAML.
|
||||
when not defined(JS):
|
||||
refs*: Table[Anchor, pointer]
|
||||
refs*: Table[Anchor, tuple[id: TypeID, p: pointer]]
|
||||
|
||||
YamlConstructionError* = object of YamlLoadingError
|
||||
## Exception that may be raised when constructing data objects from a
|
||||
|
@ -88,42 +86,35 @@ proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext)
|
|||
|
||||
proc newConstructionContext*(): ConstructionContext =
|
||||
new(result)
|
||||
when defined(JS):
|
||||
{.emit: [result, """.refs = new Map();"""].}
|
||||
else:
|
||||
result.refs = initTable[Anchor, pointer]()
|
||||
result.refs = initTable[Anchor, tuple[id: TypeID, p: pointer]]()
|
||||
|
||||
proc newSerializationContext*(s: AnchorStyle,
|
||||
putImpl: proc(e: Event) {.raises: [], closure.}):
|
||||
SerializationContext =
|
||||
result = SerializationContext(style: s, nextAnchorId: "a",
|
||||
put: putImpl)
|
||||
when defined(JS):
|
||||
{.emit: [result, """.refs = new Map();"""].}
|
||||
else: result.refs = initTable[pointer, Anchor]()
|
||||
result.refs = initTable[pointer, tuple[a: Anchor, referenced: bool]]()
|
||||
|
||||
template presentTag*(t: typedesc, ts: TagStyle): TagId =
|
||||
## Get the TagId that represents the given type in the given style
|
||||
template presentTag*(t: typedesc, ts: TagStyle): Tag =
|
||||
## Get the Tag that represents the given type in the given style
|
||||
if ts == tsNone: yTagQuestionMark else: yamlTag(t)
|
||||
|
||||
proc lazyLoadTag(uri: string): TagId {.inline, raises: [].} =
|
||||
proc lazyLoadTag(uri: string): Tag {.inline, raises: [].} =
|
||||
try: result = serializationTagLibrary.tags[uri]
|
||||
except KeyError: result = serializationTagLibrary.registerUri(uri)
|
||||
|
||||
proc safeTagUri(id: TagId): string {.raises: [].} =
|
||||
proc safeTagUri(tag: Tag): string {.raises: [].} =
|
||||
try:
|
||||
var
|
||||
uri = serializationTagLibrary.uri(id)
|
||||
i = 0
|
||||
var uri = $tag
|
||||
# '!' 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)
|
||||
for i in countup(0, uri.len - 1):
|
||||
if uri[i] == ',': uri[i] = ';'
|
||||
return uri
|
||||
except KeyError: internalError("Unexpected KeyError for TagId " & $id)
|
||||
except KeyError:
|
||||
internalError("Unexpected KeyError for Tag " & $tag)
|
||||
|
||||
proc constructionError(s: YamlStream, mark: Mark, msg: string): ref YamlConstructionError =
|
||||
result = newException(YamlConstructionError, msg)
|
||||
|
@ -151,7 +142,7 @@ template constructScalarItem*(s: var YamlStream, i: untyped,
|
|||
e.parent = getCurrentException()
|
||||
raise e
|
||||
|
||||
proc yamlTag*(T: typedesc[string]): TagId {.inline, noSideEffect, raises: [].} =
|
||||
proc yamlTag*(T: typedesc[string]): Tag {.inline, noSideEffect, raises: [].} =
|
||||
yTagString
|
||||
|
||||
proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
||||
|
@ -162,7 +153,7 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
|||
result = item.scalarContent
|
||||
|
||||
proc representObject*(value: string, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) {.raises: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
## represents a string as YAML scalar
|
||||
c.put(scalarEvent(value, tag, yAnchorNone))
|
||||
|
||||
|
@ -217,12 +208,12 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
|||
result = int(i32Result)
|
||||
|
||||
proc representObject*[T: int8|int16|int32|int64](value: T, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) {.raises: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
## represents an integer value as YAML scalar
|
||||
c.put(scalarEvent($value, tag, yAnchorNone))
|
||||
|
||||
proc representObject*(value: int, tagStyle: TagStyle,
|
||||
c: SerializationContext, tag: TagId)
|
||||
c: SerializationContext, tag: Tag)
|
||||
{.raises: [YamlStreamError], inline.}=
|
||||
## represent an integer of architecture-defined length by casting it to int32.
|
||||
## on 64-bit systems, this may cause a RangeDefect.
|
||||
|
@ -265,12 +256,12 @@ when defined(JS):
|
|||
result = $BiggestInt(x)
|
||||
|
||||
proc representObject*[T: uint8|uint16|uint32|uint64](value: T, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) {.raises: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
## represents an unsigned integer value as YAML scalar
|
||||
c.put(scalarEvent($value, tag, yAnchorNone))
|
||||
|
||||
proc representObject*(value: uint, ts: TagStyle, c: SerializationContext,
|
||||
tag: TagId) {.raises: [YamlStreamError], inline.} =
|
||||
tag: Tag) {.raises: [YamlStreamError], inline.} =
|
||||
## represent an unsigned integer of architecture-defined length by casting it
|
||||
## to int32. on 64-bit systems, this may cause a RangeDefect.
|
||||
try: c.put(scalarEvent($uint32(value), tag, yAnchorNone))
|
||||
|
@ -299,7 +290,7 @@ proc constructObject*[T: float|float32|float64](
|
|||
escape(item.scalarContent))
|
||||
|
||||
proc representObject*[T: float|float32|float64](value: T, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) {.raises: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
## represents a float value as YAML scalar
|
||||
case value
|
||||
of Inf: c.put(scalarEvent(".inf", tag))
|
||||
|
@ -307,7 +298,7 @@ proc representObject*[T: float|float32|float64](value: T, ts: TagStyle,
|
|||
of NaN: c.put(scalarEvent(".nan", tag))
|
||||
else: c.put(scalarEvent($value, tag))
|
||||
|
||||
proc yamlTag*(T: typedesc[bool]): TagId {.inline, raises: [].} = yTagBoolean
|
||||
proc yamlTag*(T: typedesc[bool]): Tag {.inline, raises: [].} = yTagBoolean
|
||||
|
||||
proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
||||
result: var bool)
|
||||
|
@ -322,7 +313,7 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
|||
escape(item.scalarContent))
|
||||
|
||||
proc representObject*(value: bool, ts: TagStyle, c: SerializationContext,
|
||||
tag: TagId) {.raises: [].} =
|
||||
tag: Tag) {.raises: [].} =
|
||||
## represents a bool value as a YAML scalar
|
||||
c.put(scalarEvent(if value: "y" else: "n", tag, yAnchorNone))
|
||||
|
||||
|
@ -337,11 +328,11 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
|||
else: result = item.scalarContent[0]
|
||||
|
||||
proc representObject*(value: char, ts: TagStyle, c: SerializationContext,
|
||||
tag: TagId) {.raises: [].} =
|
||||
tag: Tag) {.raises: [].} =
|
||||
## represents a char value as YAML scalar
|
||||
c.put(scalarEvent("" & value, tag, yAnchorNone))
|
||||
|
||||
proc yamlTag*(T: typedesc[Time]): TagId {.inline, raises: [].} = yTagTimestamp
|
||||
proc yamlTag*(T: typedesc[Time]): Tag {.inline, raises: [].} = yTagTimestamp
|
||||
|
||||
proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
||||
result: var Time)
|
||||
|
@ -403,15 +394,15 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
|
|||
escape(item.scalarContent))
|
||||
|
||||
proc representObject*(value: Time, ts: TagStyle, c: SerializationContext,
|
||||
tag: TagId) {.raises: [ValueError].} =
|
||||
tag: Tag) {.raises: [ValueError].} =
|
||||
let tmp = value.utc()
|
||||
c.put(scalarEvent(tmp.format("yyyy-MM-dd'T'HH:mm:ss'Z'")))
|
||||
|
||||
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline, raises: [].} =
|
||||
proc yamlTag*[I](T: typedesc[seq[I]]): Tag {.inline, raises: [].} =
|
||||
let uri = nimTag("system:seq(" & safeTagUri(yamlTag(I)) & ')')
|
||||
result = lazyLoadTag(uri)
|
||||
|
||||
proc yamlTag*[I](T: typedesc[set[I]]): TagId {.inline, raises: [].} =
|
||||
proc yamlTag*[I](T: typedesc[set[I]]): Tag {.inline, raises: [].} =
|
||||
let uri = nimTag("system:set(" & safeTagUri(yamlTag(I)) & ')')
|
||||
result = lazyLoadTag(uri)
|
||||
|
||||
|
@ -444,7 +435,7 @@ proc constructObject*[T](s: var YamlStream, c: ConstructionContext,
|
|||
discard s.next()
|
||||
|
||||
proc representObject*[T](value: seq[T]|set[T], ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
## represents a Nim seq as YAML sequence
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
c.put(startSeqEvent(tag = tag))
|
||||
|
@ -452,7 +443,7 @@ proc representObject*[T](value: seq[T]|set[T], ts: TagStyle,
|
|||
representChild(item, childTagStyle, c)
|
||||
c.put(endSeqEvent())
|
||||
|
||||
proc yamlTag*[I, V](T: typedesc[array[I, V]]): TagId {.inline, raises: [].} =
|
||||
proc yamlTag*[I, V](T: typedesc[array[I, V]]): Tag {.inline, raises: [].} =
|
||||
const rangeName = name(I)
|
||||
let uri = nimTag("system:array(" & rangeName[6..rangeName.high()] & ';' &
|
||||
safeTagUri(yamlTag(V)) & ')')
|
||||
|
@ -475,7 +466,7 @@ proc constructObject*[I, T](s: var YamlStream, c: ConstructionContext,
|
|||
raise s.constructionError(event.startPos, "Too many array values")
|
||||
|
||||
proc representObject*[I, T](value: array[I, T], ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
## represents a Nim array as YAML sequence
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
c.put(startSeqEvent(tag = tag))
|
||||
|
@ -483,7 +474,7 @@ proc representObject*[I, T](value: array[I, T], ts: TagStyle,
|
|||
representChild(item, childTagStyle, c)
|
||||
c.put(endSeqEvent())
|
||||
|
||||
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
|
||||
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): Tag {.inline, raises: [].} =
|
||||
try:
|
||||
let uri = nimTag("tables:Table(" & safeTagUri(yamlTag(K)) & ';' &
|
||||
safeTagUri(yamlTag(V)) & ")")
|
||||
|
@ -512,7 +503,7 @@ proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext,
|
|||
discard s.next()
|
||||
|
||||
proc representObject*[K, V](value: Table[K, V], ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
## represents a Nim Table as YAML mapping
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
c.put(startMapEvent(tag = tag))
|
||||
|
@ -521,7 +512,7 @@ proc representObject*[K, V](value: Table[K, V], ts: TagStyle,
|
|||
representChild(value, childTagStyle, c)
|
||||
c.put(endMapEvent())
|
||||
|
||||
proc yamlTag*[K, V](T: typedesc[OrderedTable[K, V]]): TagId
|
||||
proc yamlTag*[K, V](T: typedesc[OrderedTable[K, V]]): Tag
|
||||
{.inline, raises: [].} =
|
||||
try:
|
||||
let uri = nimTag("tables:OrderedTable(" & safeTagUri(yamlTag(K)) & ';' &
|
||||
|
@ -557,7 +548,7 @@ proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext,
|
|||
discard s.next()
|
||||
|
||||
proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
c.put(startSeqEvent(tag = tag))
|
||||
for key, value in value.pairs:
|
||||
|
@ -568,13 +559,13 @@ proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
|
|||
c.put(endSeqEvent())
|
||||
|
||||
proc yamlTag*(T: typedesc[object|enum]):
|
||||
TagId {.inline, raises: [].} =
|
||||
Tag {.inline, raises: [].} =
|
||||
var uri = nimTag("custom:" & (typetraits.name(type(T))))
|
||||
try: serializationTagLibrary.tags[uri]
|
||||
except KeyError: serializationTagLibrary.registerUri(uri)
|
||||
|
||||
proc yamlTag*(T: typedesc[tuple]):
|
||||
TagId {.inline, raises: [].} =
|
||||
Tag {.inline, raises: [].} =
|
||||
var
|
||||
i: T
|
||||
uri = nimTag("tuple(")
|
||||
|
@ -999,7 +990,7 @@ macro genRepresentObject(t: typedesc, value, childTagStyle: typed) =
|
|||
inc(fieldIndex)
|
||||
|
||||
proc representObject*[O: object](value: O, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
## represents a Nim object or tuple as YAML mapping
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
when isVariantObject(getType(O)): c.put(startSeqEvent(tag = tag))
|
||||
|
@ -1009,7 +1000,7 @@ proc representObject*[O: object](value: O, ts: TagStyle,
|
|||
else: c.put(endMapEvent())
|
||||
|
||||
proc representObject*[O: tuple](value: O, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) =
|
||||
c: SerializationContext, tag: Tag) =
|
||||
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
|
||||
var fieldIndex = 0'i16
|
||||
c.put(startMapEvent(tag = tag))
|
||||
|
@ -1035,13 +1026,13 @@ proc constructObject*[O: enum](s: var YamlStream, c: ConstructionContext,
|
|||
raise ex
|
||||
|
||||
proc representObject*[O: enum](value: O, ts: TagStyle,
|
||||
c: SerializationContext, tag: TagId) {.raises: [].} =
|
||||
c: SerializationContext, tag: Tag) {.raises: [].} =
|
||||
## represents a Nim enum as YAML scalar
|
||||
c.put(scalarEvent($value, tag, yAnchorNone))
|
||||
|
||||
proc yamlTag*[O](T: typedesc[ref O]): TagId {.inline, raises: [].} = yamlTag(O)
|
||||
proc yamlTag*[O](T: typedesc[ref O]): Tag {.inline, raises: [].} = yamlTag(O)
|
||||
|
||||
macro constructImplicitVariantObject(s, m, c, r, possibleTagIds: untyped,
|
||||
macro constructImplicitVariantObject(s, m, c, r, possibleTags: untyped,
|
||||
t: typedesc) =
|
||||
let tDesc = getType(getType(t)[1])
|
||||
yAssert tDesc.kind == nnkObjectTy
|
||||
|
@ -1058,12 +1049,12 @@ macro constructImplicitVariantObject(s, m, c, r, possibleTagIds: untyped,
|
|||
)))
|
||||
case recCase[i][1].recListLen
|
||||
of 0:
|
||||
branch.add(infix(newIdentNode("yTagNull"), "in", possibleTagIds))
|
||||
branch.add(infix(newIdentNode("yTagNull"), "in", possibleTags))
|
||||
branchContent.add(newNimNode(nnkDiscardStmt).add(newCall("next", s)))
|
||||
of 1:
|
||||
let field = newDotExpr(r, newIdentNode($recCase[i][1].recListNode))
|
||||
branch.add(infix(
|
||||
newCall("yamlTag", newCall("type", field)), "in", possibleTagIds))
|
||||
newCall("yamlTag", newCall("type", field)), "in", possibleTags))
|
||||
branchContent.add(newCall("constructChild", s, c, field))
|
||||
else:
|
||||
block:
|
||||
|
@ -1074,8 +1065,7 @@ macro constructImplicitVariantObject(s, m, c, r, possibleTagIds: untyped,
|
|||
newCall(bindSym("constructionError"), s, m,
|
||||
infix(newStrLitNode("This value type does not map to any field in " &
|
||||
getTypeImpl(t)[1].repr & ": "), "&",
|
||||
newCall("uri", newIdentNode("serializationTagLibrary"),
|
||||
newNimNode(nnkBracketExpr).add(possibleTagIds, newIntLitNode(0)))
|
||||
newCall("$", newNimNode(nnkBracketExpr).add(possibleTags, newIntLitNode(0)))
|
||||
)
|
||||
))
|
||||
result.add(newNimNode(nnkElse).add(newNimNode(nnkTryStmt).add(
|
||||
|
@ -1111,45 +1101,45 @@ proc constructChild*[T](s: var YamlStream, c: ConstructionContext,
|
|||
when isImplicitVariantObject(T):
|
||||
when not canBeImplicit(T):
|
||||
{. fatal: "This type cannot be marked as implicit" .}
|
||||
var possibleTagIds = newSeq[TagId]()
|
||||
var possibleTags = newSeq[Tag]()
|
||||
case item.kind
|
||||
of yamlScalar:
|
||||
case item.scalarProperties.tag
|
||||
of yTagQuestionMark:
|
||||
case guessType(item.scalarContent)
|
||||
of yTypeInteger:
|
||||
possibleTagIds.add([yamlTag(int), yamlTag(int8), yamlTag(int16),
|
||||
possibleTags.add([yamlTag(int), yamlTag(int8), yamlTag(int16),
|
||||
yamlTag(int32), yamlTag(int64)])
|
||||
if item.scalarContent[0] != '-':
|
||||
possibleTagIds.add([yamlTag(uint), yamlTag(uint8), yamlTag(uint16),
|
||||
possibleTags.add([yamlTag(uint), yamlTag(uint8), yamlTag(uint16),
|
||||
yamlTag(uint32), yamlTag(uint64)])
|
||||
of yTypeFloat, yTypeFloatInf, yTypeFloatNaN:
|
||||
possibleTagIds.add([yamlTag(float), yamlTag(float32),
|
||||
possibleTags.add([yamlTag(float), yamlTag(float32),
|
||||
yamlTag(float64)])
|
||||
of yTypeBoolTrue, yTypeBoolFalse:
|
||||
possibleTagIds.add(yamlTag(bool))
|
||||
possibleTags.add(yamlTag(bool))
|
||||
of yTypeNull:
|
||||
raise s.constructionError(item.startPos, "not implemented!")
|
||||
of yTypeUnknown:
|
||||
possibleTagIds.add(yamlTag(string))
|
||||
possibleTags.add(yamlTag(string))
|
||||
of yTypeTimestamp:
|
||||
possibleTagIds.add(yamlTag(Time))
|
||||
possibleTags.add(yamlTag(Time))
|
||||
of yTagExclamationMark:
|
||||
possibleTagIds.add(yamlTag(string))
|
||||
possibleTags.add(yamlTag(string))
|
||||
else:
|
||||
possibleTagIds.add(item.scalarProperties.tag)
|
||||
possibleTags.add(item.scalarProperties.tag)
|
||||
of yamlStartMap:
|
||||
if item.mapProperties.tag in [yTagQuestionMark, yTagExclamationMark]:
|
||||
raise s.constructionError(item.startPos,
|
||||
"Complex value of implicit variant object type must have a tag.")
|
||||
possibleTagIds.add(item.mapProperties.tag)
|
||||
possibleTags.add(item.mapProperties.tag)
|
||||
of yamlStartSeq:
|
||||
if item.seqProperties.tag in [yTagQuestionMark, yTagExclamationMark]:
|
||||
raise s.constructionError(item.startPos,
|
||||
"Complex value of implicit variant object type must have a tag.")
|
||||
possibleTagIds.add(item.seqProperties.tag)
|
||||
possibleTags.add(item.seqProperties.tag)
|
||||
else: internalError("Unexpected item kind: " & $item.kind)
|
||||
constructImplicitVariantObject(s, item.startPos, c, result, possibleTagIds, T)
|
||||
constructImplicitVariantObject(s, item.startPos, c, result, possibleTags, T)
|
||||
else:
|
||||
case item.kind
|
||||
of yamlScalar:
|
||||
|
@ -1233,20 +1223,14 @@ proc constructChild*[O](s: var YamlStream, c: ConstructionContext,
|
|||
discard s.next()
|
||||
return
|
||||
elif e.kind == yamlAlias:
|
||||
when defined(JS):
|
||||
{.emit: [result, """ = """, c, """.refs.get(""", e.aliasTarget, """);"""].}
|
||||
else:
|
||||
result = cast[ref O](c.refs.getOrDefault(e.aliasTarget))
|
||||
result = cast[ref O](c.refs.getOrDefault(e.aliasTarget).p)
|
||||
discard s.next()
|
||||
return
|
||||
new(result)
|
||||
template removeAnchor(anchor: var Anchor) {.dirty.} =
|
||||
if anchor != yAnchorNone:
|
||||
when defined(JS):
|
||||
{.emit: [c, """.refs.set(""", anchor, """, """, result, """);"""].}
|
||||
else:
|
||||
yAssert(not c.refs.hasKey(anchor))
|
||||
c.refs[anchor] = cast[pointer](result)
|
||||
yAssert(not c.refs.hasKey(anchor))
|
||||
c.refs[anchor] = (0, cast[pointer](result))
|
||||
anchor = yAnchorNone
|
||||
|
||||
case e.kind
|
||||
|
@ -1280,50 +1264,33 @@ proc representChild*[O](value: ref O, ts: TagStyle, c: SerializationContext) =
|
|||
if isNil(value): c.put(scalarEvent("~", yTagNull))
|
||||
elif c.style == asNone: representChild(value[], ts, c)
|
||||
else:
|
||||
var val: Anchor
|
||||
when defined(JS):
|
||||
{.emit: ["""
|
||||
if (""", c, """.refs.has(""", value, """) {
|
||||
""", val, """ = """, c, """.refs.get(""", value, """);
|
||||
if (val == """, yAnchorNone, ") {"].}
|
||||
val = c.nextAnchorId
|
||||
{.emit: [c, """.refs.set(""", value, """, """, val, """);"""].}
|
||||
nextAnchor(c, len(c.nextAnchorId) - 1)
|
||||
{.emit: "}".}
|
||||
c.put(aliasEvent(val))
|
||||
var val: tuple[a: Anchor, referenced: bool]
|
||||
let p = cast[pointer](value)
|
||||
if c.refs.hasKey(p):
|
||||
val = c.refs.getOrDefault(p)
|
||||
yAssert(val.a != yAnchorNone)
|
||||
if not val.referenced:
|
||||
c.refs[p] = (val.a, true)
|
||||
c.put(aliasEvent(val.a))
|
||||
return
|
||||
else:
|
||||
let p = cast[pointer](value)
|
||||
if c.refs.hasKey(p):
|
||||
val = c.refs.getOrDefault(p)
|
||||
if val == yAnchorNone:
|
||||
val = c.nextAnchorId.Anchor
|
||||
c.refs[p] = val
|
||||
nextAnchor(c.nextAnchorId, len(c.nextAnchorId) - 1)
|
||||
c.put(aliasEvent(val))
|
||||
return
|
||||
if c.style == asAlways:
|
||||
val = c.nextAnchorId.Anchor
|
||||
when defined(JS):
|
||||
{.emit: [c, ".refs.set(", p, ", ", val, ");"].}
|
||||
else: c.refs[p] = val
|
||||
if c.style != asNone:
|
||||
val = (c.nextAnchorId.Anchor, false)
|
||||
c.refs[p] = val
|
||||
nextAnchor(c.nextAnchorId, len(c.nextAnchorId) - 1)
|
||||
else: c.refs[p] = yAnchorNone
|
||||
let
|
||||
a = if c.style == asAlways: val else: cast[Anchor](p)
|
||||
childTagStyle = if ts == tsAll: tsAll else: tsRootOnly
|
||||
origPut = c.put
|
||||
c.put = proc(e: Event) =
|
||||
var ex = e
|
||||
case ex.kind
|
||||
of yamlStartMap:
|
||||
ex.mapProperties.anchor = a
|
||||
ex.mapProperties.anchor = val.a
|
||||
if ts == tsNone: ex.mapProperties.tag = yTagQuestionMark
|
||||
of yamlStartSeq:
|
||||
ex.seqProperties.anchor = a
|
||||
ex.seqProperties.anchor = val.a
|
||||
if ts == tsNone: ex.seqProperties.tag = yTagQuestionMark
|
||||
of yamlScalar:
|
||||
ex.scalarProperties.anchor = a
|
||||
ex.scalarProperties.anchor = val.a
|
||||
if ts == tsNone and guessType(ex.scalarContent) != yTypeNull:
|
||||
ex.scalarProperties.tag = yTagQuestionMark
|
||||
else: discard
|
||||
|
@ -1401,6 +1368,10 @@ proc load*[K](input: Stream | string, target: var K)
|
|||
elif e.parent of YamlParserError: raise (ref YamlParserError)(e.parent)
|
||||
else: internalError("Unexpected exception: " & $e.parent.name)
|
||||
|
||||
proc loadAs*[K](input: string): K {.raises: [YamlConstructionError, IOError, YamlParserError].} =
|
||||
## Loads the given YAML input to a value of the type K and returns it
|
||||
load(input, result)
|
||||
|
||||
proc loadMultiDoc*[K](input: Stream | string, target: var seq[K]) =
|
||||
var
|
||||
parser = initYamlParser(serializationTagLibrary)
|
||||
|
@ -1427,10 +1398,10 @@ proc loadMultiDoc*[K](input: Stream | string, target: var seq[K]) =
|
|||
proc setAnchor(a: var Anchor, c: var SerializationContext)
|
||||
{.inline.} =
|
||||
if a != yAnchorNone:
|
||||
when defined(JS):
|
||||
{.emit: [a, """ = """, c, """.refs.get(""", a, """);"""].}
|
||||
else:
|
||||
a = c.refs.getOrDefault(cast[pointer](a))
|
||||
for key, val in c.refs:
|
||||
if val.a == a:
|
||||
if not val.referenced: a = yAnchorNone
|
||||
return
|
||||
|
||||
proc represent*[T](value: T, ts: TagStyle = tsRootOnly,
|
||||
a: AnchorStyle = asTidy): YamlStream =
|
||||
|
|
|
@ -28,29 +28,19 @@ type
|
|||
## them with `initFailsafeTagLibrary <#initFailsafeTagLibrary>`_,
|
||||
## `initCoreTagLibrary <#initCoreTagLibrary>`_ or
|
||||
## `initExtendedTagLibrary <#initExtendedTagLibrary>`_.
|
||||
tags*: Table[string, TagId]
|
||||
nextCustomTagId*: TagId
|
||||
tags*: Table[string, Tag]
|
||||
|
||||
proc initTagLibrary*(): TagLibrary {.raises: [].} =
|
||||
## initializes the ``tags`` table and sets ``nextCustomTagId`` to
|
||||
## ``yFirstCustomTagId``.
|
||||
new(result)
|
||||
result.tags = initTable[string, TagId]()
|
||||
result.tags = initTable[string, Tag]()
|
||||
|
||||
result.nextCustomTagId = yFirstCustomTagId
|
||||
|
||||
proc registerUri*(tagLib: TagLibrary, uri: string): TagId {.raises: [].} =
|
||||
proc registerUri*(tagLib: TagLibrary, uri: string): Tag {.raises: [].} =
|
||||
## registers a custom tag URI with a ``TagLibrary``. The URI will get
|
||||
## the ``TagId`` ``nextCustomTagId``, which will be incremented.
|
||||
tagLib.tags[uri] = tagLib.nextCustomTagId
|
||||
result = tagLib.nextCustomTagId
|
||||
tagLib.nextCustomTagId = cast[TagId](cast[int](tagLib.nextCustomTagId) + 1)
|
||||
|
||||
proc uri*(tagLib: TagLibrary, id: TagId): string {.raises: [KeyError].} =
|
||||
## retrieve the URI a ``TagId`` maps to.
|
||||
for iUri, iId in tagLib.tags.pairs:
|
||||
if iId == id: return iUri
|
||||
raise newException(KeyError, "Unknown tag id: " & $id)
|
||||
result = uri.Tag
|
||||
tagLib.tags[uri] = result
|
||||
|
||||
template y(suffix: string): string = yamlTagRepositoryPrefix & suffix
|
||||
template n(suffix: string): string = nimyamlTagRepositoryPrefix & suffix
|
||||
|
@ -114,7 +104,7 @@ proc initSerializationTagLibrary*(): TagLibrary =
|
|||
result.tags[n"field"] = yTagNimField
|
||||
|
||||
var
|
||||
serializationTagLibrary* = initSerializationTagLibrary() ## \
|
||||
serializationTagLibrary* {.compileTime.} = initSerializationTagLibrary() ## \
|
||||
## contains all local tags that are used for type serialization. Does
|
||||
## not contain any of the specific default tags for sequences or maps,
|
||||
## as those are not suited for Nim's static type system.
|
||||
|
@ -123,8 +113,6 @@ var
|
|||
## `serializable <#serializable,stmt,stmt>`_.
|
||||
|
||||
var
|
||||
nextStaticTagId {.compileTime.} = yFirstStaticTagId ## \
|
||||
## used for generating unique TagIds with ``setTagUri``.
|
||||
registeredUris {.compileTime.} = newSeq[string]() ## \
|
||||
## Since Table doesn't really work at compile time, we also store
|
||||
## registered URIs here to be able to generate a static compiler error
|
||||
|
@ -135,14 +123,11 @@ template setTagUri*(t: typedesc, uri: string) =
|
|||
## when loading and dumping values of this type.
|
||||
when uri in registeredUris:
|
||||
{. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .}
|
||||
const id {.genSym.} = nextStaticTagId
|
||||
const tag {.genSym.} = uri.Tag
|
||||
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
|
||||
serializationTagLibrary.tags[uri] = tag
|
||||
proc yamlTag*(T: typedesc[t]): Tag {.inline, raises: [].} = tag
|
||||
## autogenerated
|
||||
|
||||
template setTagUri*(t: typedesc, uri: string, idName: untyped) =
|
||||
|
@ -151,14 +136,11 @@ template setTagUri*(t: typedesc, uri: string, idName: untyped) =
|
|||
## necessary if you want to implement serialization / construction yourself.
|
||||
when uri in registeredUris:
|
||||
{. fatal: "[NimYAML] URI \"" & uri & "\" registered twice!" .}
|
||||
const idName* = nextStaticTagId
|
||||
const idName* = uri.Tag
|
||||
static:
|
||||
registeredUris.add(uri)
|
||||
nextStaticTagId = TagId(int(nextStaticTagId) + 1)
|
||||
when nextStaticTagId == yFirstCustomTagId:
|
||||
{.fatal: "Too many tags!".}
|
||||
serializationTagLibrary.tags[uri] = idName
|
||||
proc yamlTag*(T: typedesc[t]): TagId {.inline, raises: [].} = idName
|
||||
proc yamlTag*(T: typedesc[t]): Tag {.inline, raises: [].} = idName
|
||||
## autogenerated
|
||||
|
||||
static:
|
||||
|
|
|
@ -21,7 +21,7 @@ type Level = tuple[node: JsonNode, key: string, expKey: bool]
|
|||
proc initLevel(node: JsonNode): Level {.raises: [].} =
|
||||
(node: node, key: "", expKey: true)
|
||||
|
||||
proc jsonFromScalar(content: string, tag: TagId): JsonNode
|
||||
proc jsonFromScalar(content: string, tag: Tag): JsonNode
|
||||
{.raises: [YamlConstructionError].}=
|
||||
new(result)
|
||||
var mappedType: TypeHint
|
||||
|
|
Loading…
Reference in New Issue