Added explicit raises pragma to present()

* Added YamlPresenter*Error exceptions
 * Added raises pragma to present()
 * catch exceptions from YamlStream and Stream in present() and
   put them as cause into YamlPresenter*Error
 * Added loadToJson() proc
 * Give "~" the type hint yTypeNull
 * Always output "null" for yTagNull/yTypeNull scalars when
   presenter is in JSON mode
This commit is contained in:
Felix Krause 2016-01-05 19:58:46 +01:00
parent 18753b1a4a
commit f3f6f5de9e
5 changed files with 259 additions and 169 deletions

View File

@ -213,8 +213,6 @@ Output:
- Add type hints for more scalar types - Add type hints for more scalar types
* Parser: * Parser:
- Properly handle leading spaces in block scalars - Properly handle leading spaces in block scalars
- Add an optional warning callback instead of yielding `yamlWarning` tokens,
which are a pain to handle for the caller.
* Serialization: * Serialization:
- Support for more standard library types - Support for more standard library types
- Support for ref and ptr types - Support for ref and ptr types

View File

@ -154,4 +154,10 @@ proc constructJson*(s: YamlStream): seq[JsonNode] =
val: anchors[event.aliasTarget])) val: anchors[event.aliasTarget]))
levels[levels.high].key = nil levels[levels.high].key = nil
else: else:
discard # will never happen discard # will never happen
proc loadToJson*(s: Stream): seq[JsonNode] =
var
parser = newParser(coreTagLibrary())
events = parser.parse(s)
return constructJson(events)

View File

@ -79,7 +79,7 @@ type
ythLowerOF, ythLowerOF,
ythLowerTR, ythLowerTRU, ythLowerTR, ythLowerTRU,
ythLowerYE, ythLowerYE,
ythPointLowerIN, ythPointLowerN, ythPointLowerNA, ythPointLowerIN, ythPointLowerN, ythPointLowerNA,
ythMinus, yth0, ythInt, ythDecimal, ythNumE, ythNumEPlusMinus, ythMinus, yth0, ythInt, ythDecimal, ythNumE, ythNumEPlusMinus,
@ -269,6 +269,8 @@ macro typeHintStateMachine(c: untyped, content: untyped): stmt =
template advanceTypeHint(ch: char) {.dirty.} = template advanceTypeHint(ch: char) {.dirty.} =
typeHintStateMachine ch: typeHintStateMachine ch:
of '~':
ythInitial => ythNULL
of '.': of '.':
[yth0, ythInt] => ythDecimal [yth0, ythInt] => ythDecimal
[ythInitial, ythMinus] => ythPoint [ythInitial, ythMinus] => ythPoint

View File

@ -12,113 +12,137 @@ type
dFlowSequenceItem, dFlowImplicitMapStart, dFlowExplicitMapStart, dFlowSequenceItem, dFlowImplicitMapStart, dFlowExplicitMapStart,
dFlowSequenceStart dFlowSequenceStart
proc needsEscaping(scalar: string): bool = proc needsEscaping(scalar: string): bool {.raises: [].} =
scalar.len == 0 or scalar.len == 0 or
scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%', scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%',
'\x0A', '\c'}) != -1 '\x0A', '\c'}) != -1
proc writeDoubleQuoted(scalar: string, s: Stream) = proc writeDoubleQuoted(scalar: string, s: Stream)
s.write('"') {.raises: [YamlPresenterOutputError].} =
for c in scalar: try:
if c == '"': s.write('"')
s.write('\\') for c in scalar:
s.write(c) if c == '"':
s.write('"') s.write('\\')
s.write(c)
s.write('"')
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
template safeWrite(s: string or char) {.dirty.} =
try:
target.write(s)
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
proc startItem(target: Stream, style: YamlPresentationStyle, indentation: int, proc startItem(target: Stream, style: YamlPresentationStyle, indentation: int,
state: var DumperState) = state: var DumperState) {.raises: [YamlPresenterOutputError].} =
case state try:
of dBlockExplicitMapValue: case state
target.write('\x0A') of dBlockExplicitMapValue:
target.write(repeat(' ', indentation))
target.write("? ")
state = dBlockExplicitMapKey
of dBlockExplicitMapKey:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write(": ")
state = dBlockExplicitMapValue
of dBlockImplicitMapValue:
target.write('\x0A')
target.write(repeat(' ', indentation))
state = dBlockImplicitMapKey
of dBlockImplicitMapKey:
target.write(": ")
state = dBlockImplicitMapValue
of dFlowExplicitMapKey:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write(": ")
state = dFlowExplicitMapValue
of dFlowExplicitMapValue:
target.write(",\x0A")
target.write(repeat(' ', indentation))
target.write("? ")
state = dFlowExplicitMapKey
of dFlowImplicitMapStart:
if style == ypsJson:
target.write("\x0A")
target.write(repeat(' ', indentation))
state = dFlowImplicitMapKey
of dFlowExplicitMapStart:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write("? ")
state = dFlowExplicitMapKey
of dFlowImplicitMapKey:
target.write(": ")
state = dFlowImplicitMapValue
of dFlowImplicitMapValue:
if style == ypsJson:
target.write(",\x0A")
target.write(repeat(' ', indentation))
else:
target.write(", ")
state = dFlowImplicitMapKey
of dBlockSequenceItem:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write("- ")
of dFlowSequenceStart:
case style
of ypsMinimal, ypsDefault:
discard
of ypsCanonical, ypsJson:
target.write('\x0A') target.write('\x0A')
target.write(repeat(' ', indentation)) target.write(repeat(' ', indentation))
of ypsBlockOnly: target.write("? ")
discard # can never happen state = dBlockExplicitMapKey
state = dFlowSequenceItem of dBlockExplicitMapKey:
of dFlowSequenceItem: target.write('\x0A')
case style target.write(repeat(' ', indentation))
of ypsMinimal, ypsDefault: target.write(": ")
target.write(", ") state = dBlockExplicitMapValue
of ypsCanonical, ypsJson: of dBlockImplicitMapValue:
target.write('\x0A')
target.write(repeat(' ', indentation))
state = dBlockImplicitMapKey
of dBlockImplicitMapKey:
target.write(": ")
state = dBlockImplicitMapValue
of dFlowExplicitMapKey:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write(": ")
state = dFlowExplicitMapValue
of dFlowExplicitMapValue:
target.write(",\x0A") target.write(",\x0A")
target.write(repeat(' ', indentation)) target.write(repeat(' ', indentation))
of ypsBlockOnly: target.write("? ")
discard # can never happen state = dFlowExplicitMapKey
of dFlowImplicitMapStart:
if style == ypsJson:
target.write("\x0A")
target.write(repeat(' ', indentation))
state = dFlowImplicitMapKey
of dFlowExplicitMapStart:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write("? ")
state = dFlowExplicitMapKey
of dFlowImplicitMapKey:
target.write(": ")
state = dFlowImplicitMapValue
of dFlowImplicitMapValue:
if style == ypsJson:
target.write(",\x0A")
target.write(repeat(' ', indentation))
else:
target.write(", ")
state = dFlowImplicitMapKey
of dBlockSequenceItem:
target.write('\x0A')
target.write(repeat(' ', indentation))
target.write("- ")
of dFlowSequenceStart:
case style
of ypsMinimal, ypsDefault:
discard
of ypsCanonical, ypsJson:
target.write('\x0A')
target.write(repeat(' ', indentation))
of ypsBlockOnly:
discard # can never happen
state = dFlowSequenceItem
of dFlowSequenceItem:
case style
of ypsMinimal, ypsDefault:
target.write(", ")
of ypsCanonical, ypsJson:
target.write(",\x0A")
target.write(repeat(' ', indentation))
of ypsBlockOnly:
discard # can never happen
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
proc writeTagAndAnchor(target: Stream, tag: TagId, tagLib: YamlTagLibrary, proc writeTagAndAnchor(target: Stream, tag: TagId, tagLib: YamlTagLibrary,
anchor: AnchorId) = anchor: AnchorId) {.raises:[YamlPresenterOutputError].} =
if tag notin [yTagQuestionMark, yTagExclamationMark]: try:
let tagUri = tagLib.uri(tag) if tag notin [yTagQuestionMark, yTagExclamationMark]:
if tagUri.startsWith(tagLib.secondaryPrefix): let tagUri = tagLib.uri(tag)
target.write("!!") if tagUri.startsWith(tagLib.secondaryPrefix):
target.write(tagUri[18..^1]) target.write("!!")
target.write(tagUri[18..^1])
target.write(' ')
elif tagUri.startsWith("!"):
target.write(tagUri)
target.write(' ')
else:
target.write("!<")
target.write(tagUri)
target.write("> ")
if anchor != yAnchorNone:
target.write("&")
# TODO: properly select an anchor
target.write(cast[byte]('a') + cast[byte](anchor))
target.write(' ') target.write(' ')
elif tagUri.startsWith("!"): except:
target.write(tagUri) var e = newException(YamlPresenterOutputError, "")
target.write(' ') e.cause = getCurrentException()
else: raise e
target.write("!<")
target.write(tagUri)
target.write("> ")
if anchor != yAnchorNone:
target.write("&")
# TODO: properly select an anchor
target.write(cast[byte]('a') + cast[byte](anchor))
target.write(' ')
proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary, proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
style: YamlPresentationStyle = ypsDefault, style: YamlPresentationStyle = ypsDefault,
@ -129,10 +153,15 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
while true: while true:
while cached.len > 0: while cached.len > 0:
yield cached.dequeue() yield cached.dequeue()
let item = s() try:
if finished(s): let item = s()
break if finished(s):
cached.enqueue(item) break
cached.enqueue(item)
except:
var e = newException(YamlPresenterStreamError, "")
e.cause = getCurrentException()
raise e
indentation = 0 indentation = 0
levels = newSeq[DumperState]() levels = newSeq[DumperState]()
@ -141,14 +170,20 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
of yamlStartDocument: of yamlStartDocument:
if style != ypsJson: if style != ypsJson:
# TODO: tag directives # TODO: tag directives
target.write("%YAML 1.2\x0A") try:
if tagLib.secondaryPrefix != yamlTagRepositoryPrefix: target.write("%YAML 1.2\x0A")
target.write("%TAG !! " & tagLib.secondaryPrefix & '\x0A') if tagLib.secondaryPrefix != yamlTagRepositoryPrefix:
target.write("--- ") target.write("%TAG !! " &
tagLib.secondaryPrefix & '\x0A')
target.write("--- ")
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
of yamlScalar: of yamlScalar:
if levels.len == 0: if levels.len == 0:
if style != ypsJson: if style != ypsJson:
target.write('\x0A') safeWrite('\x0A')
else: else:
startItem(target, style, indentation, levels[levels.high]) startItem(target, style, indentation, levels[levels.high])
if style != ypsJson: if style != ypsJson:
@ -159,18 +194,18 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
if item.scalarTag in [yTagQuestionMark, yTagBoolean] and if item.scalarTag in [yTagQuestionMark, yTagBoolean] and
item.scalarType in [yTypeBoolTrue, yTypeBoolFalse]: item.scalarType in [yTypeBoolTrue, yTypeBoolFalse]:
if item.scalarType == yTypeBoolTrue: if item.scalarType == yTypeBoolTrue:
target.write("true") safeWrite("true")
else: else:
target.write("false") safeWrite("false")
elif item.scalarTag in [yTagQuestionMark, yTagNull] and elif item.scalarTag in [yTagQuestionMark, yTagNull] and
item.scalarType == yTypeNull: item.scalarType == yTypeNull:
target.write("null") safeWrite("null")
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
item.scalarType in [yTypeFloatInf, yTypeFloatNaN]: item.scalarType in [yTypeFloatInf, yTypeFloatNaN]:
raise newException(YamlPresenterError, raise newException(YamlPresenterJsonError,
"Infinity and not-a-number values cannot be presented as JSON!") "Infinity and not-a-number values cannot be presented as JSON!")
else: else:
target.write(item.scalarContent) safeWrite(item.scalarContent)
elif style == ypsCanonical or item.scalarContent.needsEscaping or elif style == ypsCanonical or item.scalarContent.needsEscaping or
(style == ypsJson and (style == ypsJson and
(item.scalarTag notin [yTagQuestionMark, yTagInteger, yTagFloat, (item.scalarTag notin [yTagQuestionMark, yTagInteger, yTagFloat,
@ -180,37 +215,47 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
yTypeNull]))): yTypeNull]))):
writeDoubleQuoted(item.scalarContent, target) writeDoubleQuoted(item.scalarContent, target)
else: else:
target.write(item.scalarContent) safeWrite(item.scalarContent)
of yamlAlias: of yamlAlias:
assert levels.len > 0 assert levels.len > 0
startItem(target, style, indentation, levels[levels.high]) startItem(target, style, indentation, levels[levels.high])
target.write('*') try:
target.write(cast[byte]('a') + cast[byte](item.aliasTarget)) target.write('*')
target.write(cast[byte]('a') + cast[byte](item.aliasTarget))
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
of yamlStartSequence: of yamlStartSequence:
var nextState: DumperState var nextState: DumperState
case style case style
of ypsDefault: of ypsDefault:
var length = 0 var length = 0
while true: while true:
let next = s() try:
assert (not finished(s)) let next = s()
cached.enqueue(next) assert (not finished(s))
case next.kind cached.enqueue(next)
of yamlScalar: case next.kind
length += 2 + next.scalarContent.len of yamlScalar:
of yamlAlias: length += 2 + next.scalarContent.len
length += 6 of yamlAlias:
of yamlEndSequence: length += 6
break of yamlEndSequence:
else: break
length = int.high else:
break length = int.high
break
except:
var e = newException(YamlPresenterStreamError, "")
e.cause = getCurrentException()
raise e
nextState = if length <= 60: dFlowSequenceStart else: nextState = if length <= 60: dFlowSequenceStart else:
dBlockSequenceItem dBlockSequenceItem
of ypsJson: of ypsJson:
if levels[levels.high] in if levels[levels.high] in
[dFlowImplicitMapStart, dFlowImplicitMapValue]: [dFlowImplicitMapStart, dFlowImplicitMapValue]:
raise newException(YamlPresenterError, raise newException(YamlPresenterJsonError,
"Cannot have sequence as map key in JSON output!") "Cannot have sequence as map key in JSON output!")
nextState = dFlowSequenceStart nextState = dFlowSequenceStart
of ypsMinimal, ypsCanonical: of ypsMinimal, ypsCanonical:
@ -227,7 +272,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
if style != ypsJson: if style != ypsJson:
writeTagAndAnchor(target, writeTagAndAnchor(target,
item.seqTag, tagLib, item.seqAnchor) item.seqTag, tagLib, item.seqAnchor)
target.write('\x0A') safeWrite('\x0A')
indentation += indentationStep indentation += indentationStep
else: else:
startItem(target, style, indentation, levels[levels.high]) startItem(target, style, indentation, levels[levels.high])
@ -237,7 +282,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
indentation += indentationStep indentation += indentationStep
if nextState == dFlowSequenceStart: if nextState == dFlowSequenceStart:
target.write('[') safeWrite('[')
if levels.len > 0 and style in [ypsJson, ypsCanonical] and if levels.len > 0 and style in [ypsJson, ypsCanonical] and
levels[levels.high] in levels[levels.high] in
[dBlockExplicitMapKey, dBlockExplicitMapValue, [dBlockExplicitMapKey, dBlockExplicitMapValue,
@ -251,19 +296,24 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
of ypsDefault: of ypsDefault:
var length = 0 var length = 0
while true: while true:
let next = s() try:
assert (not finished(s)) let next = s()
cached.enqueue(next) assert (not finished(s))
case next.kind cached.enqueue(next)
of yamlScalar: case next.kind
length += 2 + next.scalarContent.len of yamlScalar:
of yamlAlias: length += 2 + next.scalarContent.len
length += 6 of yamlAlias:
of yamlEndMap: length += 6
break of yamlEndMap:
else: break
length = int.high else:
break length = int.high
break
except:
var e = newException(YamlPresenterStreamError, "")
e.cause = getCurrentException()
raise e
nextState = if length <= 60: dFlowImplicitMapStart else: nextState = if length <= 60: dFlowImplicitMapStart else:
if item.mapMayHaveKeyObjects: if item.mapMayHaveKeyObjects:
dBlockExplicitMapValue else: dBlockImplicitMapValue dBlockExplicitMapValue else: dBlockImplicitMapValue
@ -275,7 +325,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
of ypsJson: of ypsJson:
if levels[levels.high] in if levels[levels.high] in
[dFlowImplicitMapStart, dFlowImplicitMapValue]: [dFlowImplicitMapStart, dFlowImplicitMapValue]:
raise newException(YamlPresenterError, raise newException(YamlPresenterJsonError,
"Cannot have map as map key in JSON output!") "Cannot have map as map key in JSON output!")
nextState = dFlowImplicitMapStart nextState = dFlowImplicitMapStart
of ypsBlockOnly: of ypsBlockOnly:
@ -290,7 +340,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
item.mapTag, tagLib, item.mapAnchor) item.mapTag, tagLib, item.mapAnchor)
else: else:
if style != ypsJson: if style != ypsJson:
target.write('\x0A') safeWrite('\x0A')
writeTagAndAnchor(target, writeTagAndAnchor(target,
item.mapTag, tagLib, item.mapAnchor) item.mapTag, tagLib, item.mapAnchor)
indentation += indentationStep indentation += indentationStep
@ -310,7 +360,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
indentation += indentationStep indentation += indentationStep
if nextState in [dFlowImplicitMapStart, dFlowExplicitMapStart]: if nextState in [dFlowImplicitMapStart, dFlowExplicitMapStart]:
target.write('{') safeWrite('{')
if levels.len > 0 and style in [ypsJson, ypsCanonical] and if levels.len > 0 and style in [ypsJson, ypsCanonical] and
levels[levels.high] in levels[levels.high] in
[dBlockExplicitMapKey, dBlockExplicitMapValue, [dBlockExplicitMapKey, dBlockExplicitMapValue,
@ -325,12 +375,17 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
of dFlowSequenceItem: of dFlowSequenceItem:
case style case style
of ypsDefault, ypsMinimal, ypsBlockOnly: of ypsDefault, ypsMinimal, ypsBlockOnly:
target.write(']') safeWrite(']')
of ypsJson, ypsCanonical: of ypsJson, ypsCanonical:
indentation -= indentationStep indentation -= indentationStep
target.write('\x0A') try:
target.write(repeat(' ', indentation)) target.write('\x0A')
target.write(']') target.write(repeat(' ', indentation))
target.write(']')
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
if levels.len == 0 or levels[levels.high] notin if levels.len == 0 or levels[levels.high] notin
[dBlockExplicitMapKey, dBlockExplicitMapValue, [dBlockExplicitMapKey, dBlockExplicitMapValue,
dBlockImplicitMapKey, dBlockImplicitMapValue, dBlockImplicitMapKey, dBlockImplicitMapValue,
@ -343,7 +398,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
dBlockImplicitMapKey, dBlockImplicitMapValue, dBlockImplicitMapKey, dBlockImplicitMapValue,
dBlockSequenceItem]: dBlockSequenceItem]:
indentation -= indentationStep indentation -= indentationStep
target.write(']') safeWrite(']')
of dBlockSequenceItem: of dBlockSequenceItem:
discard discard
else: else:
@ -355,12 +410,17 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
of dFlowImplicitMapValue, dFlowExplicitMapValue: of dFlowImplicitMapValue, dFlowExplicitMapValue:
case style case style
of ypsDefault, ypsMinimal, ypsBlockOnly: of ypsDefault, ypsMinimal, ypsBlockOnly:
target.write('}') safeWrite('}')
of ypsJson, ypsCanonical: of ypsJson, ypsCanonical:
indentation -= indentationStep indentation -= indentationStep
target.write('\x0A') try:
target.write(repeat(' ', indentation)) target.write('\x0A')
target.write('}') target.write(repeat(' ', indentation))
target.write('}')
except:
var e = newException(YamlPresenterOutputError, "")
e.cause = getCurrentException()
raise e
if levels.len == 0 or levels[levels.high] notin if levels.len == 0 or levels[levels.high] notin
[dBlockExplicitMapKey, dBlockExplicitMapValue, [dBlockExplicitMapKey, dBlockExplicitMapValue,
dBlockImplicitMapKey, dBlockImplicitMapValue, dBlockImplicitMapKey, dBlockImplicitMapValue,
@ -373,18 +433,23 @@ proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
dBlockImplicitMapKey, dBlockImplicitMapValue, dBlockImplicitMapKey, dBlockImplicitMapValue,
dBlockSequenceItem]: dBlockSequenceItem]:
indentation -= indentationStep indentation -= indentationStep
target.write('}') safeWrite('}')
of dBlockImplicitMapValue, dBlockExplicitMapValue: of dBlockImplicitMapValue, dBlockExplicitMapValue:
discard discard
else: else:
assert false assert false
indentation -= indentationStep indentation -= indentationStep
of yamlEndDocument: of yamlEndDocument:
let next = s() try:
if finished(s): let next = s()
break if finished(s):
target.write("...\x0A") break
cached.enqueue(next) cached.enqueue(next)
except:
var e = newException(YamlPresenterStreamError, "")
e.cause = getCurrentException()
raise e
safeWrite("...\x0A")
proc transform*(input: Stream, output: Stream, style: YamlPresentationStyle, proc transform*(input: Stream, output: Stream, style: YamlPresentationStyle,
indentationStep: int = 2) = indentationStep: int = 2) =

View File

@ -227,15 +227,27 @@ type
## Some elements in this list are vague. For a detailed description of a ## Some elements in this list are vague. For a detailed description of a
## valid YAML character stream, see the YAML specification. ## valid YAML character stream, see the YAML specification.
YamlPresenterError* = object of Exception YamlPresenterJsonError* = object of Exception
## Exception that may be raised by the YAML presenter. Currently, the ## Exception that may be raised by the YAML presenter when it is
## only ocassion this exception may be raised is when the presenter is
## instructed to output JSON, but is unable to do so. This may occur if: ## instructed to output JSON, but is unable to do so. This may occur if:
## ##
## - The given `YamlStream <#YamlStream>`_ contains a map which has any ## - The given `YamlStream <#YamlStream>`_ contains a map which has any
## non-scalar type as key. ## non-scalar type as key.
## - Any float scalar bears a ``NaN`` or positive/negative infinity ## - Any float scalar bears a ``NaN`` or positive/negative infinity
## value ## value
YamlPresenterOutputError* = object of Exception
## Exception that may be raised by the YAML presenter. This occurs if
## writing character data to the output stream raises any exception. The
## exception that has been catched is retrievable from ``cause``.
cause*: ref Exception
YamlPresenterStreamError* = object of Exception
## Exception that may be raised by the YAML presenter. This occurs if
## an exception is raised while retrieving the next item from a
## `YamlStream <#YamlStream>`_. The exception that has been catched is
## retrievable from ``cause``.
cause*: ref Exception
const const
# failsafe schema # failsafe schema
@ -372,8 +384,8 @@ proc parse*(parser: YamlSequentialParser, s: Stream):
proc constructJson*(s: YamlStream): seq[JsonNode] proc constructJson*(s: YamlStream): seq[JsonNode]
## Construct an in-memory JSON tree from a YAML event stream. The stream may ## Construct an in-memory JSON tree from a YAML event stream. The stream may
## not contain any tags apart from those in ``coreTagLibrary``. Anchors and ## not contain any tags apart from those in ``coreTagLibrary``. Anchors and
## aliases will be resolved. Maps in the input must not contain ## aliases will be resolved. Maps in the input must not contain
## non-scalars as keys. Each element of the result represents one document ## non-scalars as keys. Each element of the result represents one document
## in the YAML stream. ## in the YAML stream.
## ##
@ -383,10 +395,17 @@ proc constructJson*(s: YamlStream): seq[JsonNode]
## of the JSON specification. Nim's JSON implementation currently does not ## of the JSON specification. Nim's JSON implementation currently does not
## check for these values and will output invalid JSON when rendering one ## check for these values and will output invalid JSON when rendering one
## of these values into a JSON character stream. ## of these values into a JSON character stream.
proc loadToJson*(s: Stream): seq[JsonNode]
## Uses `YamlSequentialParser <#YamlSequentialParser>`_ and
## `constructJson <#constructJson>`_ to construct an in-memory JSON tree
## from a YAML character stream.
proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary, proc present*(s: YamlStream, target: Stream, tagLib: YamlTagLibrary,
style: YamlPresentationStyle = ypsDefault, style: YamlPresentationStyle = ypsDefault,
indentationStep: int = 2) indentationStep: int = 2) {.raises: [YamlPresenterJsonError,
YamlPresenterOutputError,
YamlPresenterStreamError].}
## Convert ``s`` to a YAML character stream and write it to ``target``. ## Convert ``s`` to a YAML character stream and write it to ``target``.
proc transform*(input: Stream, output: Stream, style: YamlPresentationStyle, proc transform*(input: Stream, output: Stream, style: YamlPresentationStyle,