mirror of
https://github.com/status-im/NimYAML.git
synced 2025-02-10 10:16:33 +00:00
Merge branch 'master' of github.com:flyx/NimYAML
This commit is contained in:
commit
daafa8b8e8
30
README.md
30
README.md
@ -26,7 +26,7 @@ a list:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
var
|
var
|
||||||
parser = newParser(coreTagLibrary())
|
parser = newYamlParser(initCoreTagLibrary())
|
||||||
events = parser.parse(newStringStream(input))
|
events = parser.parse(newStringStream(input))
|
||||||
|
|
||||||
for event in events():
|
for event in events():
|
||||||
@ -60,13 +60,13 @@ import yaml, streams
|
|||||||
proc example(): YamlStream =
|
proc example(): YamlStream =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
yield startDocEvent()
|
yield startDocEvent()
|
||||||
yield startMapEvent(mayHaveKeyObjects = false)
|
yield startMapEvent()
|
||||||
yield scalarEvent("an integer")
|
yield scalarEvent("an integer")
|
||||||
yield scalarEvent("42", tag = yTagInteger)
|
yield scalarEvent("42", tag = yTagInteger)
|
||||||
yield scalarEvent("a list")
|
yield scalarEvent("a list")
|
||||||
yield startSeqEvent(tag = yTagSequence)
|
yield startSeqEvent(tag = yTagSequence)
|
||||||
yield scalarEvent("item", tag = yTagString)
|
yield scalarEvent("item", tag = yTagString)
|
||||||
yield scalarEvent("no", tag = yTagBoolean, typeHint = yTypeBoolFalse)
|
yield scalarEvent("no", tag = yTagBoolean)
|
||||||
yield scalarEvent("")
|
yield scalarEvent("")
|
||||||
yield endSeqEvent()
|
yield endSeqEvent()
|
||||||
yield scalarEvent("a float")
|
yield scalarEvent("a float")
|
||||||
@ -74,11 +74,11 @@ proc example(): YamlStream =
|
|||||||
yield endMapEvent()
|
yield endMapEvent()
|
||||||
yield endDocEvent()
|
yield endDocEvent()
|
||||||
|
|
||||||
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpBlockOnly)
|
present(example(), newFileStream(stdout), initCoreTagLibrary(), psBlockOnly)
|
||||||
echo "\n\n"
|
echo "\n\n"
|
||||||
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpCanonical)
|
present(example(), newFileStream(stdout), initCoreTagLibrary(), psCanonical)
|
||||||
echo "\n\n"
|
echo "\n\n"
|
||||||
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpJson)
|
present(example(), newFileStream(stdout), initCoreTagLibrary(), psJson)
|
||||||
```
|
```
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
@ -129,7 +129,7 @@ a float: !!float 3.14159
|
|||||||
import yaml.serialization
|
import yaml.serialization
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
make_serializable:
|
serializable:
|
||||||
type
|
type
|
||||||
Person = object
|
Person = object
|
||||||
firstname, surname: string
|
firstname, surname: string
|
||||||
@ -162,7 +162,7 @@ assert persons[1].additionalAttributes["location"] == "Celle"
|
|||||||
|
|
||||||
# dumping
|
# dumping
|
||||||
|
|
||||||
dump(persons, newFileStream(stdout), ypsCanonical)
|
dump(persons, newFileStream(stdout), psCanonical)
|
||||||
```
|
```
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
@ -177,9 +177,9 @@ Output:
|
|||||||
? !!str "surname"
|
? !!str "surname"
|
||||||
: !!str "Pan",
|
: !!str "Pan",
|
||||||
? !!str "age"
|
? !!str "age"
|
||||||
: !!int "12",
|
: !nim:int "12",
|
||||||
? !!str "additionalAttributes"
|
? !!str "additionalAttributes"
|
||||||
: {
|
: !nim:Table(tag:yaml.org,2002:str,tag:yaml.org,2002:str) {
|
||||||
? !!str "canFly"
|
? !!str "canFly"
|
||||||
: !!str "yes",
|
: !!str "yes",
|
||||||
? !!str "location"
|
? !!str "location"
|
||||||
@ -192,9 +192,9 @@ Output:
|
|||||||
? !!str "surname"
|
? !!str "surname"
|
||||||
: !!str "Koch",
|
: !!str "Koch",
|
||||||
? !!str "age"
|
? !!str "age"
|
||||||
: !!int "23",
|
: !nim:int "23",
|
||||||
? !!str "additionalAttributes"
|
? !!str "additionalAttributes"
|
||||||
: {
|
: !nim:Table(tag:yaml.org,2002:str,tag:yaml.org,2002:str) {
|
||||||
? !!str "occupation"
|
? !!str "occupation"
|
||||||
: !!str "Hacker",
|
: !!str "Hacker",
|
||||||
? !!str "location"
|
? !!str "location"
|
||||||
@ -208,7 +208,7 @@ Output:
|
|||||||
|
|
||||||
* Documentation:
|
* Documentation:
|
||||||
- Document yaml.serialization
|
- Document yaml.serialization
|
||||||
* Lexer:
|
* Misc:
|
||||||
- Add type hints for more scalar types
|
- Add type hints for more scalar types
|
||||||
* Serialization:
|
* Serialization:
|
||||||
- Support for more standard library types
|
- Support for more standard library types
|
||||||
@ -225,10 +225,6 @@ Output:
|
|||||||
- Possibly use `genSym` for predefined and generated `yamlTag` procs because
|
- Possibly use `genSym` for predefined and generated `yamlTag` procs because
|
||||||
they are an implementation detail and should not be visible to the caller.
|
they are an implementation detail and should not be visible to the caller.
|
||||||
same goes for `lazyLoadTag` and `safeLoadUri`.
|
same goes for `lazyLoadTag` and `safeLoadUri`.
|
||||||
* General:
|
|
||||||
- Proper error handling (do not use `ValueError` for everything)
|
|
||||||
- Proper error handling, seriously
|
|
||||||
- Document exceptions with `raises` pragmas in code
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -8,11 +8,6 @@ task tests, "Run all tests":
|
|||||||
--verbosity:0
|
--verbosity:0
|
||||||
setCommand "c", "test/tests"
|
setCommand "c", "test/tests"
|
||||||
|
|
||||||
task lexerTests, "Run lexer tests":
|
|
||||||
--r
|
|
||||||
--verbosity:0
|
|
||||||
setCommand "c", "test/lexing"
|
|
||||||
|
|
||||||
task parserTests, "Run parser tests":
|
task parserTests, "Run parser tests":
|
||||||
--r
|
--r
|
||||||
--verbosity:0
|
--verbosity:0
|
||||||
@ -25,8 +20,8 @@ task serializationTests, "Run serialization tests":
|
|||||||
|
|
||||||
task documentation, "Generate documentation":
|
task documentation, "Generate documentation":
|
||||||
exec "mkdir -p docout"
|
exec "mkdir -p docout"
|
||||||
exec r"nim doc2 -o:docout/yaml.html yaml"
|
exec r"nim doc2 -o:docout/yaml.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml"
|
||||||
exec r"nim doc2 -o:docout/serialization.html yaml/serialization.nim"
|
exec r"nim doc2 -o:docout/serialization.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml/serialization.nim"
|
||||||
exec r"nim rst2html -o:docout/index.html doc/index.txt"
|
exec r"nim rst2html -o:docout/index.html doc/index.txt"
|
||||||
exec "cp doc/docutils.css doc/style.css doc/testing.html docout"
|
exec "cp doc/docutils.css doc/style.css doc/testing.html docout"
|
||||||
setCommand "nop"
|
setCommand "nop"
|
||||||
|
@ -66,6 +66,15 @@ html {
|
|||||||
background-color: rgba(252, 248, 244, 0.75);
|
background-color: rgba(252, 248, 244, 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* necessary for links to scroll to the right position */
|
||||||
|
dt:before {
|
||||||
|
margin-top: -50px;
|
||||||
|
height: 50px;
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
#testingground textarea {
|
#testingground textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -136,7 +136,7 @@ template handleObjectStart(k: YamlStreamEventKind) {.dirty.} =
|
|||||||
debug("started sequence at " & (if level.indentation == -1: $indentation else:
|
debug("started sequence at " & (if level.indentation == -1: $indentation else:
|
||||||
$level.indentation))
|
$level.indentation))
|
||||||
level.kind = fplSequence
|
level.kind = fplSequence
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
if level.indentation == -1:
|
if level.indentation == -1:
|
||||||
level.indentation = indentation
|
level.indentation = indentation
|
||||||
@ -183,7 +183,7 @@ template handleMapKeyIndicator() {.dirty.} =
|
|||||||
of fplMapValue:
|
of fplMapValue:
|
||||||
if level.indentation != indentation:
|
if level.indentation != indentation:
|
||||||
parserError("Invalid indentation of map key indicator")
|
parserError("Invalid indentation of map key indicator")
|
||||||
yield scalarEvent("", yTagQuestionmark, yAnchorNone)
|
yield scalarEvent("", yTagQuestionMark, yAnchorNone)
|
||||||
level.kind = fplMapKey
|
level.kind = fplMapKey
|
||||||
ancestry.add(level)
|
ancestry.add(level)
|
||||||
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
||||||
@ -205,16 +205,16 @@ template handleMapValueIndicator() {.dirty.} =
|
|||||||
of fplUnknown:
|
of fplUnknown:
|
||||||
if level.indentation == -1:
|
if level.indentation == -1:
|
||||||
handleObjectStart(yamlStartMap)
|
handleObjectStart(yamlStartMap)
|
||||||
yield scalarEvent("", yTagQuestionmark, yAnchorNone)
|
yield scalarEvent("", yTagQuestionMark, yAnchorNone)
|
||||||
else:
|
else:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
ancestry[ancestry.high].kind = fplMapValue
|
ancestry[ancestry.high].kind = fplMapValue
|
||||||
of fplMapKey:
|
of fplMapKey:
|
||||||
if level.indentation != indentation:
|
if level.indentation != indentation:
|
||||||
parserError("Invalid indentation of map key indicator")
|
parserError("Invalid indentation of map key indicator")
|
||||||
yield scalarEvent("", yTagQuestionmark, yAnchorNone)
|
yield scalarEvent("", yTagQuestionMark, yAnchorNone)
|
||||||
level.kind = fplMapValue
|
level.kind = fplMapValue
|
||||||
ancestry.add(level)
|
ancestry.add(level)
|
||||||
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
||||||
@ -238,14 +238,14 @@ template initDocValues() {.dirty.} =
|
|||||||
shorthands["!!"] = "tag:yaml.org,2002:"
|
shorthands["!!"] = "tag:yaml.org,2002:"
|
||||||
nextAnchorId = 0.AnchorId
|
nextAnchorId = 0.AnchorId
|
||||||
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
level = FastParseLevel(kind: fplUnknown, indentation: -1)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
|
|
||||||
template handleTagHandle() {.dirty.} =
|
template handleTagHandle() {.dirty.} =
|
||||||
startToken()
|
startToken()
|
||||||
if level.kind != fplUnknown:
|
if level.kind != fplUnknown:
|
||||||
parserError("Unexpected tag handle")
|
parserError("Unexpected tag handle")
|
||||||
if tag != yTagQuestionmark:
|
if tag != yTagQuestionMark:
|
||||||
parserError("Only one tag handle is allowed per node")
|
parserError("Only one tag handle is allowed per node")
|
||||||
content = ""
|
content = ""
|
||||||
var
|
var
|
||||||
@ -281,7 +281,7 @@ template handleAlias() {.dirty.} =
|
|||||||
startToken()
|
startToken()
|
||||||
if level.kind != fplUnknown:
|
if level.kind != fplUnknown:
|
||||||
parserError("Unexpected token")
|
parserError("Unexpected token")
|
||||||
if anchor != yAnchorNone or tag != yTagQuestionmark:
|
if anchor != yAnchorNone or tag != yTagQuestionMark:
|
||||||
parserError("Alias may not have anchor or tag")
|
parserError("Alias may not have anchor or tag")
|
||||||
content = ""
|
content = ""
|
||||||
p.lexer.anchorName(content)
|
p.lexer.anchorName(content)
|
||||||
@ -338,7 +338,7 @@ template handleBlockItemStart() {.dirty.} =
|
|||||||
level = FastParseLevel(kind: fplUnknown, indentation: indentation)
|
level = FastParseLevel(kind: fplUnknown, indentation: indentation)
|
||||||
of fplMapValue:
|
of fplMapValue:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
level.kind = fplMapKey
|
level.kind = fplMapKey
|
||||||
ancestry.add(level)
|
ancestry.add(level)
|
||||||
@ -1313,8 +1313,8 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
var stateAfter: FastParseState
|
var stateAfter: FastParseState
|
||||||
content = ""
|
content = ""
|
||||||
p.lexer.blockScalar(content, stateAfter)
|
p.lexer.blockScalar(content, stateAfter)
|
||||||
if tag == yTagQuestionmark:
|
if tag == yTagQuestionMark:
|
||||||
tag = yTagExclamationmark
|
tag = yTagExclamationMark
|
||||||
yield scalarEvent(content, tag, anchor)
|
yield scalarEvent(content, tag, anchor)
|
||||||
handleObjectEnd(stateAfter)
|
handleObjectEnd(stateAfter)
|
||||||
of '-':
|
of '-':
|
||||||
@ -1424,14 +1424,14 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
case level.kind
|
case level.kind
|
||||||
of fplMapValue:
|
of fplMapValue:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
level.kind = fplMapKey
|
level.kind = fplMapKey
|
||||||
of fplMapKey:
|
of fplMapKey:
|
||||||
if tag != yTagQuestionmark or anchor != yAnchorNone or
|
if tag != yTagQuestionMark or anchor != yAnchorNone or
|
||||||
explicitFlowKey:
|
explicitFlowKey:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
of fplSequence:
|
of fplSequence:
|
||||||
@ -1446,9 +1446,9 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
level = ancestry.pop()
|
level = ancestry.pop()
|
||||||
case level.kind
|
case level.kind
|
||||||
of fplSequence:
|
of fplSequence:
|
||||||
if tag != yTagQuestionmark or anchor != yAnchorNone:
|
if tag != yTagQuestionMark or anchor != yAnchorNone:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
of fplMapKey, fplMapValue:
|
of fplMapKey, fplMapValue:
|
||||||
startToken()
|
startToken()
|
||||||
@ -1463,17 +1463,17 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
case level.kind
|
case level.kind
|
||||||
of fplSequence:
|
of fplSequence:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
of fplMapValue:
|
of fplMapValue:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
level.kind = fplMapKey
|
level.kind = fplMapKey
|
||||||
explicitFlowKey = false
|
explicitFlowKey = false
|
||||||
of fplMapKey:
|
of fplMapKey:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
explicitFlowKey = false
|
explicitFlowKey = false
|
||||||
@ -1492,7 +1492,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
parserError("Unexpected token (expected ',')")
|
parserError("Unexpected token (expected ',')")
|
||||||
of fplMapKey:
|
of fplMapKey:
|
||||||
yield scalarEvent("", tag, anchor)
|
yield scalarEvent("", tag, anchor)
|
||||||
tag = yTagQuestionmark
|
tag = yTagQuestionMark
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
level.kind = fplMapValue
|
level.kind = fplMapValue
|
||||||
of fplUnknown, fplScalar:
|
of fplUnknown, fplScalar:
|
||||||
@ -1514,8 +1514,8 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
content = ""
|
content = ""
|
||||||
startToken()
|
startToken()
|
||||||
p.lexer.doubleQuotedScalar(content)
|
p.lexer.doubleQuotedScalar(content)
|
||||||
if tag == yTagQuestionmark:
|
if tag == yTagQuestionMark:
|
||||||
tag = yTagExclamationmark
|
tag = yTagExclamationMark
|
||||||
yield scalarEvent(content, tag, anchor)
|
yield scalarEvent(content, tag, anchor)
|
||||||
handleObjectEnd(fpFlowAfterObject)
|
handleObjectEnd(fpFlowAfterObject)
|
||||||
of '!':
|
of '!':
|
||||||
@ -1567,7 +1567,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
|||||||
of fplSequence:
|
of fplSequence:
|
||||||
discard
|
discard
|
||||||
of fplMapValue:
|
of fplMapValue:
|
||||||
yield scalarEvent("", yTagQuestionmark, yAnchorNone)
|
yield scalarEvent("", yTagQuestionMark, yAnchorNone)
|
||||||
level.kind = fplMapKey
|
level.kind = fplMapKey
|
||||||
explicitFlowKey = false
|
explicitFlowKey = false
|
||||||
of fplMapKey:
|
of fplMapKey:
|
||||||
|
@ -206,9 +206,9 @@ proc loadToJson*(s: Stream): seq[JsonNode] =
|
|||||||
raise e
|
raise e
|
||||||
except YamlConstructionStreamError:
|
except YamlConstructionStreamError:
|
||||||
let e = getCurrentException()
|
let e = getCurrentException()
|
||||||
if e.parent is IOError:
|
if e.parent of IOError:
|
||||||
raise cast[ref IOError](e.parent)
|
raise cast[ref IOError](e.parent)
|
||||||
elif e.parent is YamlParserError:
|
elif e.parent of YamlParserError:
|
||||||
raise cast[ref YamlParserError](e.parent)
|
raise cast[ref YamlParserError](e.parent)
|
||||||
else:
|
else:
|
||||||
# can never happen
|
# can never happen
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
||||||
|
import typetraits
|
||||||
|
|
||||||
type
|
type
|
||||||
DumperState = enum
|
DumperState = enum
|
||||||
dBlockExplicitMapKey, dBlockImplicitMapKey, dBlockMapValue,
|
dBlockExplicitMapKey, dBlockImplicitMapKey, dBlockMapValue,
|
||||||
@ -12,7 +14,7 @@ type
|
|||||||
dFlowSequenceStart
|
dFlowSequenceStart
|
||||||
|
|
||||||
proc needsEscaping(scalar: string): bool {.raises: [].} =
|
proc needsEscaping(scalar: string): bool {.raises: [].} =
|
||||||
scalar.len == 0 or
|
scalar.len == 0 or scalar[0] in ['@', '`'] or
|
||||||
scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%', '"',
|
scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%', '"',
|
||||||
'\'', '\x0A', '\c'}) != -1
|
'\'', '\x0A', '\c'}) != -1
|
||||||
|
|
||||||
@ -164,7 +166,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
|
|||||||
if finished(s):
|
if finished(s):
|
||||||
break
|
break
|
||||||
cached.enqueue(item)
|
cached.enqueue(item)
|
||||||
except:
|
except Exception:
|
||||||
var e = newException(YamlPresenterStreamError, "")
|
var e = newException(YamlPresenterStreamError, "")
|
||||||
e.parent = getCurrentException()
|
e.parent = getCurrentException()
|
||||||
raise e
|
raise e
|
||||||
@ -208,10 +210,16 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
|
|||||||
elif item.scalarTag in [yTagQuestionMark, yTagNull] and
|
elif item.scalarTag in [yTagQuestionMark, yTagNull] and
|
||||||
hint == yTypeNull:
|
hint == yTypeNull:
|
||||||
safeWrite("null")
|
safeWrite("null")
|
||||||
|
elif item.scalarTag in [yTagQuestionMark, yTagInteger] and
|
||||||
|
hint == yTypeInteger:
|
||||||
|
safeWrite(item.scalarContent)
|
||||||
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
|
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
|
||||||
hint in [yTypeFloatInf, yTypeFloatNaN]:
|
hint in [yTypeFloatInf, yTypeFloatNaN]:
|
||||||
raise newException(YamlPresenterJsonError,
|
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!")
|
||||||
|
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
|
||||||
|
hint == yTypeFloat:
|
||||||
|
safeWrite(item.scalarContent)
|
||||||
else:
|
else:
|
||||||
writeDoubleQuoted(item.scalarContent, target)
|
writeDoubleQuoted(item.scalarContent, target)
|
||||||
elif style == psCanonical or item.scalarContent.needsEscaping:
|
elif style == psCanonical or item.scalarContent.needsEscaping:
|
||||||
@ -251,7 +259,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
|
|||||||
else:
|
else:
|
||||||
length = high(int)
|
length = high(int)
|
||||||
break
|
break
|
||||||
except:
|
except Exception:
|
||||||
var e = newException(YamlPresenterStreamError, "")
|
var e = newException(YamlPresenterStreamError, "")
|
||||||
e.parent = getCurrentException()
|
e.parent = getCurrentException()
|
||||||
raise e
|
raise e
|
||||||
@ -316,7 +324,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
mps = mpNeedBlock
|
mps = mpNeedBlock
|
||||||
except:
|
except Exception:
|
||||||
var e = newException(YamlPresenterStreamError, "")
|
var e = newException(YamlPresenterStreamError, "")
|
||||||
e.parent = getCurrentException()
|
e.parent = getCurrentException()
|
||||||
raise e
|
raise e
|
||||||
@ -442,7 +450,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
|
|||||||
if finished(s):
|
if finished(s):
|
||||||
break
|
break
|
||||||
cached.enqueue(next)
|
cached.enqueue(next)
|
||||||
except:
|
except Exception:
|
||||||
var e = newException(YamlPresenterStreamError, "")
|
var e = newException(YamlPresenterStreamError, "")
|
||||||
e.parent = getCurrentException()
|
e.parent = getCurrentException()
|
||||||
raise e
|
raise e
|
||||||
@ -493,9 +501,9 @@ proc transform*(input: Stream, output: Stream, style: PresentationStyle,
|
|||||||
present(events, output, tagLib, style, indentationStep)
|
present(events, output, tagLib, style, indentationStep)
|
||||||
except YamlPresenterStreamError:
|
except YamlPresenterStreamError:
|
||||||
let e = getCurrentException()
|
let e = getCurrentException()
|
||||||
if e.parent is IOError:
|
if e.parent of IOError:
|
||||||
raise cast[ref IOError](e.parent)
|
raise cast[ref IOError](e.parent)
|
||||||
elif e.parent is YamlParserError:
|
elif e.parent of YamlParserError:
|
||||||
raise cast[ref YamlParserError](e.parent)
|
raise cast[ref YamlParserError](e.parent)
|
||||||
else:
|
else:
|
||||||
# never happens
|
# never happens
|
||||||
|
46
test/constructingJson.nim
Normal file
46
test/constructingJson.nim
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import "../yaml"
|
||||||
|
|
||||||
|
import unittest, json
|
||||||
|
|
||||||
|
proc wc(line, column: int, lineContent: string, message: string) =
|
||||||
|
echo "Warning (", line, ",", column, "): ", message, "\n", lineContent
|
||||||
|
|
||||||
|
proc ensureEqual(yamlIn, jsonIn: string) =
|
||||||
|
var
|
||||||
|
parser = newYamlParser(initCoreTagLibrary(), wc)
|
||||||
|
yamlResult = constructJson(parser.parse(newStringStream(yamlIn)))
|
||||||
|
jsonResult = parseJson(jsonIn)
|
||||||
|
assert yamlResult.len == 1
|
||||||
|
assert(jsonResult == yamlResult[0])
|
||||||
|
|
||||||
|
suite "Constructing JSON":
|
||||||
|
test "Constructing JSON: Simple Sequence":
|
||||||
|
ensureEqual("- 1\n- 2\n- 3", "[1, 2, 3]")
|
||||||
|
|
||||||
|
test "Constructing JSON: Simple Map":
|
||||||
|
ensureEqual("a: b\nc: d", """{"a": "b", "c": "d"}""")
|
||||||
|
|
||||||
|
test "Constructing JSON: Complex Structure":
|
||||||
|
ensureEqual("""
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
Foo:
|
||||||
|
- - a
|
||||||
|
- b
|
||||||
|
- c
|
||||||
|
- bla: blubb
|
||||||
|
Numbers, bools, special values:
|
||||||
|
- 1
|
||||||
|
- true
|
||||||
|
- ~
|
||||||
|
- 42.23
|
||||||
|
- no
|
||||||
|
""", """{
|
||||||
|
"Foo": [
|
||||||
|
[ "a", "b", "c"],
|
||||||
|
{ "bla": "blubb"}
|
||||||
|
],
|
||||||
|
"Numbers, bools, special values": [
|
||||||
|
1, true, null, 42.23, false
|
||||||
|
]
|
||||||
|
}""")
|
@ -1,7 +1,7 @@
|
|||||||
import "../yaml/serialization"
|
import "../yaml/serialization"
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
make_serializable:
|
serializable:
|
||||||
type
|
type
|
||||||
Person = object
|
Person = object
|
||||||
firstname, surname: string
|
firstname, surname: string
|
||||||
|
11
yaml.nim
11
yaml.nim
@ -27,7 +27,7 @@ type
|
|||||||
TypeHint* = enum
|
TypeHint* = enum
|
||||||
## A type hint can be computed from scalar content and tells you what
|
## A type hint can be computed from scalar content and tells you what
|
||||||
## NimYAML thinks the scalar's type is. It is generated by
|
## NimYAML thinks the scalar's type is. It is generated by
|
||||||
## `guessType <#guessType,string,TypeHint>`_ The first matching RegEx
|
## `guessType <#guessType,string>`_ The first matching RegEx
|
||||||
## in the following table will be the type hint of a scalar string.
|
## in the following table will be the type hint of a scalar string.
|
||||||
##
|
##
|
||||||
## You can use it to determine the type of YAML scalars that have a '?'
|
## You can use it to determine the type of YAML scalars that have a '?'
|
||||||
@ -118,14 +118,9 @@ type
|
|||||||
TagLibrary* = ref object
|
TagLibrary* = ref object
|
||||||
## A ``TagLibrary`` maps tag URIs to ``TagId`` s.
|
## A ``TagLibrary`` maps tag URIs to ``TagId`` s.
|
||||||
##
|
##
|
||||||
## Three tag libraries are provided with this module:
|
|
||||||
## `failsafeTagLibrary <#failsafeTagLibrary>`_,
|
|
||||||
## `coreTagLibrary <#coreTagLibrary>`_, and
|
|
||||||
## `extendedTagLibrary <#extendedTagLibrary>`_.
|
|
||||||
##
|
|
||||||
## When `YamlParser <#YamlParser>`_ encounters tags not existing in the
|
## When `YamlParser <#YamlParser>`_ encounters tags not existing in the
|
||||||
## tag library, it will use
|
## tag library, it will use
|
||||||
## `registerTagUri <#registerTagUri,TagLibrary,string,TagId>`_ to add
|
## `registerTagUri <#registerTagUri,TagLibrary,string>`_ to add
|
||||||
## the tag to the library.
|
## the tag to the library.
|
||||||
##
|
##
|
||||||
## You can base your tag library on common tag libraries by initializing
|
## You can base your tag library on common tag libraries by initializing
|
||||||
@ -148,7 +143,7 @@ type
|
|||||||
|
|
||||||
YamlParser* = ref object
|
YamlParser* = ref object
|
||||||
## A parser object. Retains its ``TagLibrary`` across calls to
|
## A parser object. Retains its ``TagLibrary`` across calls to
|
||||||
## `parse <#parse,YamlParser,Stream,YamlStream>`_. Can be used
|
## `parse <#parse,YamlParser,Stream>`_. Can be used
|
||||||
## to access anchor names while parsing a YAML character stream, but
|
## to access anchor names while parsing a YAML character stream, but
|
||||||
## only until the document goes out of scope (i.e. until
|
## only until the document goes out of scope (i.e. until
|
||||||
## ``yamlEndDocument`` is yielded).
|
## ``yamlEndDocument`` is yielded).
|
||||||
|
@ -6,18 +6,27 @@ type
|
|||||||
TagStyle* = enum
|
TagStyle* = enum
|
||||||
tsNone, tsRootOnly, tsAll
|
tsNone, tsRootOnly, tsAll
|
||||||
|
|
||||||
proc initSerializationTagLibrary(): TagLibrary =
|
const
|
||||||
|
yTagNimInt* = 100.TagId
|
||||||
|
yTagNimInt64* = 101.TagId
|
||||||
|
yTagNimFloat* = 102.TagId
|
||||||
|
yTagNimFloat64* = 103.TagId
|
||||||
|
|
||||||
|
proc initSerializationTagLibrary(): TagLibrary {.raises: [].} =
|
||||||
result = initTagLibrary()
|
result = initTagLibrary()
|
||||||
result.tags["!"] = yTagExclamationMark
|
result.tags["!"] = yTagExclamationMark
|
||||||
result.tags["?"] = yTagQuestionMark
|
result.tags["?"] = yTagQuestionMark
|
||||||
result.tags["tag:yaml.org,2002:str"] = yTagString
|
result.tags["tag:yaml.org,2002:str"] = yTagString
|
||||||
result.tags["tag:yaml.org,2002:null"] = yTagNull
|
result.tags["tag:yaml.org,2002:null"] = yTagNull
|
||||||
result.tags["tag:yaml.org,2002:bool"] = yTagBoolean
|
result.tags["tag:yaml.org,2002:bool"] = yTagBoolean
|
||||||
result.tags["tag:yaml.org,2002:int"] = yTagInteger
|
|
||||||
result.tags["tag:yaml.org,2002:float"] = yTagFloat
|
result.tags["tag:yaml.org,2002:float"] = yTagFloat
|
||||||
result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp
|
result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp
|
||||||
result.tags["tag:yaml.org,2002:value"] = yTagValue
|
result.tags["tag:yaml.org,2002:value"] = yTagValue
|
||||||
result.tags["tag:yaml.org,2002:binary"] = yTagBinary
|
result.tags["tag:yaml.org,2002:binary"] = yTagBinary
|
||||||
|
result.tags["!nim:int"] = yTagNimInt
|
||||||
|
result.tags["!nim:int64"] = yTagNimInt64
|
||||||
|
result.tags["!nim:float"] = yTagNimFloat
|
||||||
|
result.tags["!nim:float64"] = yTagNimFloat64
|
||||||
|
|
||||||
var
|
var
|
||||||
serializationTagLibrary* = initSerializationTagLibrary() ## \
|
serializationTagLibrary* = initSerializationTagLibrary() ## \
|
||||||
@ -26,11 +35,12 @@ var
|
|||||||
## as those are not suited for Nim's static type system.
|
## as those are not suited for Nim's static type system.
|
||||||
##
|
##
|
||||||
## Should not be modified manually. Will be extended by
|
## Should not be modified manually. Will be extended by
|
||||||
## `make_serializable <#make_serializable,stmt,stmt`_.
|
## `serializable <#serializable,stmt,stmt>`_.
|
||||||
|
|
||||||
|
|
||||||
static:
|
static:
|
||||||
iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode] =
|
iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode]
|
||||||
|
{.raises: [].} =
|
||||||
assert n.kind in [nnkRecList, nnkTupleTy]
|
assert n.kind in [nnkRecList, nnkTupleTy]
|
||||||
for identDefs in n.children:
|
for identDefs in n.children:
|
||||||
let numFields = identDefs.len - 2
|
let numFields = identDefs.len - 2
|
||||||
@ -42,13 +52,13 @@ static:
|
|||||||
template presentTag(t: typedesc, tagStyle: TagStyle): TagId =
|
template presentTag(t: typedesc, tagStyle: TagStyle): TagId =
|
||||||
if tagStyle == tsNone: yTagQuestionMark else: yamlTag(t)
|
if tagStyle == tsNone: yTagQuestionMark else: yamlTag(t)
|
||||||
|
|
||||||
proc lazyLoadTag*(uri: string): TagId {.inline.} =
|
proc lazyLoadTag*(uri: string): TagId {.inline, raises: [].} =
|
||||||
try:
|
try:
|
||||||
result = serializationTagLibrary.tags[uri]
|
result = serializationTagLibrary.tags[uri]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
result = serializationTagLibrary.registerUri(uri)
|
result = serializationTagLibrary.registerUri(uri)
|
||||||
|
|
||||||
macro make_serializable*(types: stmt): stmt =
|
macro serializable*(types: stmt): stmt =
|
||||||
assert types.kind == nnkTypeSection
|
assert types.kind == nnkTypeSection
|
||||||
result = newStmtList(types)
|
result = newStmtList(types)
|
||||||
for typedef in types.children:
|
for typedef in types.children:
|
||||||
@ -116,32 +126,36 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
newIdentDefs(newIdentNode("s"), newIdentNode("YamlStream")),
|
newIdentDefs(newIdentNode("s"), newIdentNode("YamlStream")),
|
||||||
newIdentDefs(newIdentNode("result"),
|
newIdentDefs(newIdentNode("result"),
|
||||||
newNimNode(nnkVarTy).add(tIdent))])
|
newNimNode(nnkVarTy).add(tIdent))])
|
||||||
|
constructProc[4] = newNimNode(nnkPragma).add(
|
||||||
|
newNimNode(nnkExprColonExpr).add(newIdentNode("raises"),
|
||||||
|
newNimNode(nnkBracket).add(
|
||||||
|
newIdentNode("YamlConstructionError"),
|
||||||
|
newIdentNode("YamlConstructionStreamError"))))
|
||||||
impl = quote do:
|
impl = quote do:
|
||||||
var event = s()
|
var event = s()
|
||||||
if finished(s) or event.kind != yamlStartMap:
|
if finished(s) or event.kind != yamlStartMap:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(YamlConstructionError, "Expected map start")
|
||||||
if event.mapTag != yTagQuestionMark and
|
if event.mapTag != yTagQuestionMark and
|
||||||
event.mapTag != yamlTag(type(`tIdent`)):
|
event.mapTag != yamlTag(type(`tIdent`)):
|
||||||
raise newException(ValueError, "Wrong tag for " & `tName`)
|
raise newException(YamlConstructionError,
|
||||||
|
"Wrong tag for " & `tName`)
|
||||||
event = s()
|
event = s()
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!")
|
|
||||||
while event.kind != yamlEndMap:
|
while event.kind != yamlEndMap:
|
||||||
assert event.kind == yamlScalar
|
assert event.kind == yamlScalar
|
||||||
assert event.scalarTag in [yTagQuestionMark, yTagString]
|
assert event.scalarTag in [yTagQuestionMark, yTagString]
|
||||||
case hash(event.scalarContent)
|
case event.scalarContent
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "Unknown key for " &
|
raise newException(YamlConstructionError,
|
||||||
`tName` & ": " & event.scalarContent)
|
"Unknown key for " & `tName` & ": " &
|
||||||
|
event.scalarContent)
|
||||||
event = s()
|
event = s()
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!")
|
|
||||||
var keyCase = impl[5][1][2]
|
var keyCase = impl[5][1][2]
|
||||||
assert keyCase.kind == nnkCaseStmt
|
assert keyCase.kind == nnkCaseStmt
|
||||||
for field in objectFields(recList):
|
for field in objectFields(recList):
|
||||||
let nameHash = hash($field.name.ident)
|
|
||||||
keyCase.insert(1, newNimNode(nnkOfBranch).add(
|
keyCase.insert(1, newNimNode(nnkOfBranch).add(
|
||||||
newIntLitNode(nameHash)).add(newStmtList(
|
newStrLitNode($field.name.ident)).add(newStmtList(
|
||||||
newCall("construct", [newIdentNode("s"), newDotExpr(
|
newCall("construct", [newIdentNode("s"), newDotExpr(
|
||||||
newIdentNode("result"), field.name)])
|
newIdentNode("result"), field.name)])
|
||||||
))
|
))
|
||||||
@ -158,6 +172,9 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
newIdentDefs(newIdentNode("tagStyle"),
|
newIdentDefs(newIdentNode("tagStyle"),
|
||||||
newIdentNode("TagStyle"),
|
newIdentNode("TagStyle"),
|
||||||
newIdentNode("tsNone"))])
|
newIdentNode("tsNone"))])
|
||||||
|
serializeProc[4] = newNimNode(nnkPragma).add(
|
||||||
|
newNimNode(nnkExprColonExpr).add(newIdentNode("raises"),
|
||||||
|
newNimNode(nnkBracket)))
|
||||||
var iterBody = newStmtList(
|
var iterBody = newStmtList(
|
||||||
newLetStmt(newIdentNode("childTagStyle"), newNimNode(nnkIfExpr).add(
|
newLetStmt(newIdentNode("childTagStyle"), newNimNode(nnkIfExpr).add(
|
||||||
newNimNode(nnkElifExpr).add(
|
newNimNode(nnkElifExpr).add(
|
||||||
@ -213,77 +230,98 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
serializeProc[6] = impl
|
serializeProc[6] = impl
|
||||||
result.add(serializeProc)
|
result.add(serializeProc)
|
||||||
|
|
||||||
proc prepend*(event: YamlStreamEvent, s: YamlStream): YamlStream =
|
proc prepend(event: YamlStreamEvent, s: YamlStream): YamlStream {.raises: [].} =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
yield event
|
yield event
|
||||||
for e in s():
|
for e in s():
|
||||||
yield e
|
yield e
|
||||||
|
|
||||||
proc yamlTag*(T: typedesc[string]): TagId {.inline.} = yTagString
|
proc safeTagUri*(id: TagId): string {.raises: [].} =
|
||||||
|
try:
|
||||||
proc safeTagUri*(id: TagId): string =
|
|
||||||
let uri = serializationTagLibrary.uri(id)
|
let uri = serializationTagLibrary.uri(id)
|
||||||
if uri.len > 0 and uri[0] == '!':
|
if uri.len > 0 and uri[0] == '!':
|
||||||
return uri[1..uri.len - 1]
|
return uri[1..uri.len - 1]
|
||||||
else:
|
else:
|
||||||
return uri
|
return uri
|
||||||
|
except KeyError:
|
||||||
|
# cannot happen (theoretically, you known)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
proc construct*(s: YamlStream, result: var string) =
|
template constructScalarItem(item: YamlStreamEvent, name: string, t: TagId,
|
||||||
let item = s()
|
content: stmt) =
|
||||||
|
try:
|
||||||
|
item = s()
|
||||||
|
except Exception:
|
||||||
|
var e = newException(YamlConstructionStreamError, "")
|
||||||
|
e.parent = getCurrentException()
|
||||||
|
raise e
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(YamlConstructionError, "Expected scalar")
|
||||||
if item.scalarTag notin [yTagQuestionMark, yTagExclamationMark, yTagString]:
|
if item.scalarTag notin [yTagQuestionMark, yTagExclamationMark, t]:
|
||||||
raise newException(ValueError, "Wrong tag for string.")
|
raise newException(YamlConstructionError, "Wrong tag for " & name)
|
||||||
|
try:
|
||||||
|
content
|
||||||
|
except YamlConstructionError:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
var e = newException(YamlConstructionError,
|
||||||
|
"Cannot construct to " & name & ": " & item.scalarContent)
|
||||||
|
e.parent = getCurrentException()
|
||||||
|
raise e
|
||||||
|
|
||||||
|
template safeNextEvent(e: YamlStreamEvent, s: YamlStream) =
|
||||||
|
try:
|
||||||
|
e = s()
|
||||||
|
except Exception:
|
||||||
|
var ex = newException(YamlConstructionStreamError, "")
|
||||||
|
ex.parent = getCurrentException()
|
||||||
|
raise ex
|
||||||
|
|
||||||
|
proc yamlTag*(T: typedesc[string]): TagId {.inline, raises: [].} = yTagString
|
||||||
|
|
||||||
|
proc construct*(s: YamlStream, result: var string)
|
||||||
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
|
var item: YamlStreamEvent
|
||||||
|
constructScalarItem(item, "string", yTagString):
|
||||||
result = item.scalarContent
|
result = item.scalarContent
|
||||||
|
|
||||||
proc serialize*(value: string,
|
proc serialize*(value: string,
|
||||||
tagStyle: TagStyle = tsNone): YamlStream =
|
tagStyle: TagStyle = tsNone): YamlStream {.raises: [].} =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
yield scalarEvent(value, presentTag(string, tagStyle), yAnchorNone)
|
yield scalarEvent(value, presentTag(string, tagStyle), yAnchorNone)
|
||||||
|
|
||||||
proc yamlTag*(T: typedesc[int]): TagId {.inline.} = yTagInteger
|
proc yamlTag*(T: typedesc[int]): TagId {.inline.} = yTagNimInt
|
||||||
|
|
||||||
proc construct*(s: YamlStream, result: var int) =
|
proc construct*(s: YamlStream, result: var int)
|
||||||
let item = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
if finished(s) or item.kind != yamlScalar:
|
var item: YamlStreamEvent
|
||||||
raise newException(ValueError, "Construction error!")
|
constructScalarItem(item, "int", yTagNimInt):
|
||||||
if item.scalarTag != yTagInteger and not (
|
|
||||||
item.scalarTag == yTagQuestionMark and
|
|
||||||
guessType(item.scalarContent) == yTypeInteger):
|
|
||||||
raise newException(ValueError, "Wrong scalar type for int.")
|
|
||||||
result = parseInt(item.scalarContent)
|
result = parseInt(item.scalarContent)
|
||||||
|
|
||||||
proc serialize*(value: int, tagStyle: TagStyle = tsNone): YamlStream =
|
proc serialize*(value: int, tagStyle: TagStyle = tsNone): YamlStream =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent {.raises: [].} =
|
||||||
yield scalarEvent($value, presentTag(int, tagStyle), yAnchorNone)
|
yield scalarEvent($value, presentTag(int, tagStyle), yAnchorNone)
|
||||||
|
|
||||||
proc yamlTag*(T: typedesc[int64]): TagId {.inline.} = yTagInteger
|
proc yamlTag*(T: typedesc[int64]): TagId {.inline, raises: [].} = yTagNimInt64
|
||||||
|
|
||||||
proc contruct*(s: YamlStream, result: var int64) =
|
proc contruct*(s: YamlStream, result: var int64)
|
||||||
let item = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
if finished(s) or item.kind != yamlScalar:
|
var item: YamlStreamEvent
|
||||||
raise newException(ValueError, "Construction error!")
|
constructScalarItem(item, "int64", yTagNimInt64):
|
||||||
if item.scalarTag != yTagInteger and not (
|
|
||||||
item.scalarTag == yTagQuestionMark and
|
|
||||||
guessType(item.scalarContent) == yTypeInteger):
|
|
||||||
raise newException(ValueError, "Wrong scalar type for int64.")
|
|
||||||
result = parseBiggestInt(item.scalarContent)
|
result = parseBiggestInt(item.scalarContent)
|
||||||
|
|
||||||
proc serialize*(value: int64, tagStyle: TagStyle = tsNone): YamlStream =
|
proc serialize*(value: int64, tagStyle: TagStyle = tsNone): YamlStream
|
||||||
|
{.raises: [].}=
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
yield scalarEvent($value, presentTag(int64, tagStyle), yAnchorNone)
|
yield scalarEvent($value, presentTag(int64, tagStyle), yAnchorNone)
|
||||||
|
|
||||||
proc yamlTag*(T: typedesc[float]): TagId {.inline.} = yTagFloat
|
proc yamlTag*(T: typedesc[float]): TagId {.inline, raises: [].} = yTagNimFloat
|
||||||
|
|
||||||
proc construct*(s: YamlStream, result: var float) =
|
proc construct*(s: YamlStream, result: var float)
|
||||||
let item = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
if finished(s) or item.kind != yamlScalar:
|
var item: YamlStreamEvent
|
||||||
raise newException(ValueError, "Construction error!")
|
constructScalarItem(item, "float", yTagNimFloat):
|
||||||
let hint = guessType(item.scalarContent)
|
let hint = guessType(item.scalarContent)
|
||||||
if item.scalarTag != yTagFloat and not (
|
|
||||||
item.scalarTag == yTagQuestionMark and
|
|
||||||
hint in [yTypeFloat, yTypeFloatInf, yTypeFloatNaN]):
|
|
||||||
raise newException(ValueError, "Wrong scalar type for float.")
|
|
||||||
case hint
|
case hint
|
||||||
of yTypeFloat:
|
of yTypeFloat:
|
||||||
result = parseFloat(item.scalarContent)
|
result = parseFloat(item.scalarContent)
|
||||||
@ -295,9 +333,11 @@ proc construct*(s: YamlStream, result: var float) =
|
|||||||
of yTypeFloatNaN:
|
of yTypeFloatNaN:
|
||||||
result = NaN
|
result = NaN
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "Wrong scalar type for float.")
|
raise newException(YamlConstructionError,
|
||||||
|
"Cannot construct to float: " & item.scalarContent)
|
||||||
|
|
||||||
proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream =
|
proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream
|
||||||
|
{.raises: [].}=
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
var
|
var
|
||||||
asString: string
|
asString: string
|
||||||
@ -312,57 +352,57 @@ proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream =
|
|||||||
asString = $value
|
asString = $value
|
||||||
yield scalarEvent(asString, presentTag(float, tagStyle), yAnchorNone)
|
yield scalarEvent(asString, presentTag(float, tagStyle), yAnchorNone)
|
||||||
|
|
||||||
proc yamlTag*(T: typedesc[bool]): TagId {.inline.} = yTagBoolean
|
proc yamlTag*(T: typedesc[bool]): TagId {.inline, raises: [].} = yTagBoolean
|
||||||
|
|
||||||
proc construct*(s: YamlStream, result: var bool) =
|
proc construct*(s: YamlStream, result: var bool)
|
||||||
let item = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
if finished(s) or item.kind != yamlScalar:
|
var item: YamlStreamEvent
|
||||||
raise newException(ValueError, "Construction error!")
|
constructScalarItem(item, "bool", yTagBoolean):
|
||||||
let hint = guessType(item.scalarContent)
|
case guessType(item.scalarContent)
|
||||||
case item.scalarTag
|
|
||||||
of yTagQuestionMark, yTagBoolean:
|
|
||||||
case hint
|
|
||||||
of yTypeBoolTrue:
|
of yTypeBoolTrue:
|
||||||
result = true
|
result = true
|
||||||
of yTypeBoolFalse:
|
of yTypeBoolFalse:
|
||||||
result = false
|
result = false
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
raise newException(YamlConstructionError,
|
||||||
"Not a boolean: " & item.scalarContent)
|
"Cannot construct to bool: " & item.scalarContent)
|
||||||
else:
|
|
||||||
raise newException(ValueError, "Wrong scalar type for bool")
|
|
||||||
|
|
||||||
proc serialize*(value: bool, tagStyle: TagStyle = tsNone): YamlStream =
|
proc serialize*(value: bool, tagStyle: TagStyle = tsNone): YamlStream
|
||||||
|
{.raises: [].}=
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
yield scalarEvent(if value: "y" else: "n", presentTag(bool, tagStyle),
|
yield scalarEvent(if value: "y" else: "n", presentTag(bool, tagStyle),
|
||||||
yAnchorNone)
|
yAnchorNone)
|
||||||
|
|
||||||
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline.} =
|
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline, raises: [].} =
|
||||||
let uri = "!nim:seq(" & safeTagUri(yamlTag(I)) & ")"
|
let uri = "!nim:seq(" & safeTagUri(yamlTag(I)) & ")"
|
||||||
result = lazyLoadTag(uri)
|
result = lazyLoadTag(uri)
|
||||||
|
|
||||||
proc construct*[T](s: YamlStream, result: var seq[T]) =
|
proc construct*[T](s: YamlStream, result: var seq[T])
|
||||||
var event = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
|
var event: YamlStreamEvent
|
||||||
|
safeNextEvent(event, s)
|
||||||
if finished(s) or event.kind != yamlStartSequence:
|
if finished(s) or event.kind != yamlStartSequence:
|
||||||
raise newException(ValueError, "Construction error!1")
|
raise newException(YamlConstructionError, "Expected sequence start")
|
||||||
if event.seqTag != yTagQuestionMark and
|
if event.seqTag notin [yTagQuestionMark, yamlTag(seq[T])]:
|
||||||
event.seqTag != yamlTag(seq[T]):
|
raise newException(YamlConstructionError, "Wrong tag for seq[T]")
|
||||||
raise newException(ValueError, "Wrong sequence type for seq[T]")
|
|
||||||
result = newSeq[T]()
|
result = newSeq[T]()
|
||||||
event = s()
|
safeNextEvent(event, s)
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!2")
|
|
||||||
while event.kind != yamlEndSequence:
|
while event.kind != yamlEndSequence:
|
||||||
var
|
var
|
||||||
item: T
|
item: T
|
||||||
events = prepend(event, s)
|
events = prepend(event, s)
|
||||||
|
try:
|
||||||
construct(events, item)
|
construct(events, item)
|
||||||
|
except:
|
||||||
|
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
|
||||||
|
assert(false)
|
||||||
result.add(item)
|
result.add(item)
|
||||||
event = s()
|
safeNextEvent(event, s)
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!3")
|
|
||||||
|
|
||||||
proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream =
|
proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream
|
||||||
|
{.raises: [].} =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
|
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
|
||||||
yield YamlStreamEvent(kind: yamlStartSequence,
|
yield YamlStreamEvent(kind: yamlStartSequence,
|
||||||
@ -374,41 +414,49 @@ proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream =
|
|||||||
yield event
|
yield event
|
||||||
yield YamlStreamEvent(kind: yamlEndSequence)
|
yield YamlStreamEvent(kind: yamlEndSequence)
|
||||||
|
|
||||||
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline.} =
|
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
|
||||||
|
try:
|
||||||
let
|
let
|
||||||
keyUri = serializationTagLibrary.uri(yamlTag(K))
|
keyUri = serializationTagLibrary.uri(yamlTag(K))
|
||||||
valueUri = serializationTagLibrary.uri(yamlTag(V))
|
valueUri = serializationTagLibrary.uri(yamlTag(V))
|
||||||
keyIdent = if keyUri[0] == '!': keyUri[1..keyUri.len - 1] else: keyUri
|
keyIdent = if keyUri[0] == '!': keyUri[1..keyUri.len - 1] else:
|
||||||
|
keyUri
|
||||||
valueIdent = if valueUri[0] == '!':
|
valueIdent = if valueUri[0] == '!':
|
||||||
valueUri[1..valueUri.len - 1] else: valueUri
|
valueUri[1..valueUri.len - 1] else: valueUri
|
||||||
uri = "!nim:Table(" & keyUri & "," & valueUri & ")"
|
uri = "!nim:Table(" & keyUri & "," & valueUri & ")"
|
||||||
result = lazyLoadTag(uri)
|
result = lazyLoadTag(uri)
|
||||||
|
except KeyError:
|
||||||
|
# cannot happen (theoretically, you known)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
proc construct*[K, V](s: YamlStream, result: var Table[K, V]) =
|
proc construct*[K, V](s: YamlStream, result: var Table[K, V])
|
||||||
var event = s()
|
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
|
||||||
|
var event: YamlStreamEvent
|
||||||
|
safeNextEvent(event, s)
|
||||||
if finished(s) or event.kind != yamlStartMap:
|
if finished(s) or event.kind != yamlStartMap:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(YamlConstructionError, "Expected map start")
|
||||||
if event.mapTag != yTagQuestionMark and
|
if event.mapTag notin [yTagQuestionMark, yamlTag(Table[K, V])]:
|
||||||
event.mapTag != yamlTag(Table[K, V]):
|
raise newException(YamlConstructionError, "Wrong tag for Table[K, V]")
|
||||||
raise newException(ValueError, "Wrong map type for Table[K, V]")
|
|
||||||
result = initTable[K, V]()
|
result = initTable[K, V]()
|
||||||
event = s()
|
safeNextEvent(event, s)
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!")
|
|
||||||
while event.kind != yamlEndMap:
|
while event.kind != yamlEndMap:
|
||||||
var
|
var
|
||||||
key: K
|
key: K
|
||||||
value: V
|
value: V
|
||||||
events = prepend(event, s)
|
events = prepend(event, s)
|
||||||
|
try:
|
||||||
construct(events, key)
|
construct(events, key)
|
||||||
construct(s, value)
|
construct(s, value)
|
||||||
|
except Exception:
|
||||||
|
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
|
||||||
|
assert(false)
|
||||||
result[key] = value
|
result[key] = value
|
||||||
event = s()
|
safeNextEvent(event, s)
|
||||||
if finished(s):
|
assert(not finished(s))
|
||||||
raise newException(ValueError, "Construction error!")
|
|
||||||
|
|
||||||
proc serialize*[K, V](value: Table[K, V],
|
proc serialize*[K, V](value: Table[K, V],
|
||||||
tagStyle: TagStyle = tsNone): YamlStream =
|
tagStyle: TagStyle = tsNone): YamlStream {.raises: [].} =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
|
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
|
||||||
yield YamlStreamEvent(kind: yamlStartMap,
|
yield YamlStreamEvent(kind: yamlStartMap,
|
||||||
@ -423,21 +471,50 @@ proc serialize*[K, V](value: Table[K, V],
|
|||||||
yield event
|
yield event
|
||||||
yield YamlStreamEvent(kind: yamlEndMap)
|
yield YamlStreamEvent(kind: yamlEndMap)
|
||||||
|
|
||||||
proc load*[K](input: Stream, target: var K) =
|
proc load*[K](input: Stream, target: var K)
|
||||||
|
{.raises: [YamlConstructionError, IOError, YamlParserError].} =
|
||||||
|
try:
|
||||||
var
|
var
|
||||||
tagLib = serializationTagLibrary
|
parser = newYamlParser(serializationTagLibrary)
|
||||||
events = parse(tagLib, input)
|
events = parser.parse(input)
|
||||||
assert events().kind == yamlStartDocument
|
assert events().kind == yamlStartDocument
|
||||||
construct(events, target)
|
construct(events, target)
|
||||||
assert events().kind == yamlEndDocument
|
assert events().kind == yamlEndDocument
|
||||||
|
except YamlConstructionError, IOError, YamlParserError:
|
||||||
|
raise
|
||||||
|
except YamlConstructionStreamError:
|
||||||
|
let e = cast[ref YamlConstructionError](getCurrentException())
|
||||||
|
if e.parent of IOError:
|
||||||
|
raise cast[ref IOError](e.parent)
|
||||||
|
elif e.parent of YamlParserError:
|
||||||
|
raise cast[ref YamlParserError](e.parent)
|
||||||
|
else:
|
||||||
|
assert(false)
|
||||||
|
except Exception:
|
||||||
|
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
|
||||||
|
assert(false)
|
||||||
|
|
||||||
proc dump*[K](value: K, target: Stream, style: PresentationStyle = psDefault,
|
proc dump*[K](value: K, target: Stream, style: PresentationStyle = psDefault,
|
||||||
tagStyle: TagStyle = tsRootOnly, indentationStep: int = 2) =
|
tagStyle: TagStyle = tsRootOnly, indentationStep: int = 2)
|
||||||
|
{.raises: [YamlConstructionError, YamlConstructionStreamError,
|
||||||
|
YamlPresenterJsonError, YamlPresenterOutputError].} =
|
||||||
var serialized = serialize(value,
|
var serialized = serialize(value,
|
||||||
if style == psCanonical: tsAll else: tagStyle)
|
if style == psCanonical: tsAll else: tagStyle)
|
||||||
var events = iterator(): YamlStreamEvent =
|
var events = iterator(): YamlStreamEvent =
|
||||||
yield YamlStreamEvent(kind: yamlStartDocument)
|
yield YamlStreamEvent(kind: yamlStartDocument)
|
||||||
for event in serialized():
|
while true:
|
||||||
|
var event: YamlStreamEvent
|
||||||
|
try:
|
||||||
|
event = serialized()
|
||||||
|
if finished(serialized): break
|
||||||
|
except Exception:
|
||||||
|
# serializing object does not raise any errors, so we can
|
||||||
|
# ignore this
|
||||||
|
assert(false)
|
||||||
yield event
|
yield event
|
||||||
yield YamlStreamEvent(kind: yamlEndDocument)
|
yield YamlStreamEvent(kind: yamlEndDocument)
|
||||||
|
try:
|
||||||
present(events, target, serializationTagLibrary, style, indentationStep)
|
present(events, target, serializationTagLibrary, style, indentationStep)
|
||||||
|
except YamlPresenterStreamError:
|
||||||
|
# serializing object does not raise any errors, so we can ignore this
|
||||||
|
assert(false)
|
Loading…
x
Reference in New Issue
Block a user