mirror of https://github.com/status-im/NimYAML.git
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:
parent
18753b1a4a
commit
f3f6f5de9e
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
@ -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
|
||||||
|
|
|
@ -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) =
|
||||||
|
|
33
yaml.nim
33
yaml.nim
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue