Support int, uint and float types.

This commit is contained in:
Felix Krause 2016-04-04 20:44:16 +02:00
parent 6ad7e33bb5
commit 58b9b92895
3 changed files with 64 additions and 42 deletions

View File

@ -47,15 +47,19 @@ further configuration.
Scalar Types
------------
The following integer types are supported by NimYAML: ``int8``, ``int16``,
``int32``, ``int64``, ``uint8``, ``uint16``, ``uint32``, ``uint64``. Note that
the ``int`` type is *not* supported, since its sice varies based on the target
operation system. This makes it unfit for usage within NimYAML, because a value
might not round-trip between a binary for a 32-bit OS and another binary for a
64-bit OS. The same goes for ``uint``.
The following integer types are supported by NimYAML: ``int``, ``int8``,
``int16``, ``int32``, ``int64``, ``uint8``, ``uint16``, ``uint32``, ``uint64``.
Note that the ``int`` type has a variable size dependent on the target
operation system. To make sure that it round-trips properly between 32-bit and
64-bit operating systems, it will be converted to an ``int32`` during loading
and dumping. This will raise an exception for values outside of the range
``int32.low .. int32.high``! If you define the types you serialize yourself,
always consider using an integer type with explicit length. The same goes for
``uint``.
The floating point types ``float32`` and ``float64`` are also supported, but
``float`` is not, for the same reason.
The floating point types ``float``, ``float32`` and ``float64`` are also
supported. There is currently no problem with ``float``, because it is always a
``float64``.
``string`` is supported and one of the few Nim types which directly map to a
standard YAML type. ``char`` is also supported.

View File

@ -28,7 +28,7 @@ proc safeTagUri(id: TagId): string {.raises: [].} =
if uri.len > 0 and uri[0] == '!': return uri[1..uri.len - 1]
else: return uri
except KeyError:
# cannot happen (theoretically, you known)
# cannot happen (theoretically, you know)
assert(false)
template constructScalarItem*(s: var YamlStream, i: expr,
@ -74,9 +74,11 @@ proc constructObject*[T: int8|int16|int32|int64](
template constructObject*(s: var YamlStream, c: ConstructionContext,
result: var int) =
## calling this will raise a compiler error because ``int`` is not supported
{.fatal: "The length of `int` is platform dependent. Use int[8|16|32|64].".}
discard
## constructs an integer of architecture-defined length by loading it into
## int32 and then converting it.
var i32Result: int32
constructObject(s, c, i32Result)
result = int(i32Result)
proc representObject*[T: int8|int16|int32|int64](value: T, ts: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} =
@ -86,9 +88,11 @@ proc representObject*[T: int8|int16|int32|int64](value: T, ts: TagStyle,
template representObject*(value: int, tagStyle: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream =
## calling this will raise a compiler error because ``int`` is not supported
{.fatal: "The length of `int` is platform dependent. Use int[8|16|32|64].".}
discard
## represent an integer of architecture-defined length by casting it to int32.
## on 64-bit systems, this may cause a type conversion error.
# currently, sizeof(int) is at least sizeof(int32).
representObject(int32(value), tagStyle, c, tag)
{.push overflowChecks: on.}
proc parseBiggestUInt(s: string): uint64 =
@ -108,11 +112,11 @@ proc constructObject*[T: uint8|uint16|uint32|uint64](
template constructObject*(s: var YamlStream, c: ConstructionContext,
result: var uint) =
## calling this will raise a compiler error because ``uint`` is not
## supported
{.fatal:
"The length of `uint` is platform dependent. Use uint[8|16|32|64].".}
discard
## represent an unsigned integer of architecture-defined length by loading it
## into uint32 and then converting it.
var u32Result: uint32
constructObject(s, c, u32Result)
result= uint(u32Result)
proc representObject*[T: uint8|uint16|uint32|uint64](value: T, ts: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} =
@ -122,13 +126,11 @@ proc representObject*[T: uint8|uint16|uint32|uint64](value: T, ts: TagStyle,
template representObject*(value: uint, ts: TagStyle, c: SerializationContext,
tag: TagId): RawYamlStream =
## calling this will raise a compiler error because ``uint`` is not
## supported
{.fatal:
"The length of `uint` is platform dependent. Use uint[8|16|32|64].".}
discard
## represent an unsigned integer of architecture-defined length by casting it
## to int32. on 64-bit systems, this may cause a type conversion error.
representObject(uint32(value), tagStyle, c, tag)
proc constructObject*[T: float32|float64](
proc constructObject*[T: float|float32|float64](
s: var YamlStream, c: ConstructionContext, result: var T)
{.raises: [YamlConstructionError, YamlStreamError].} =
## construct a float value from a YAML scalar
@ -144,13 +146,7 @@ proc constructObject*[T: float32|float64](
raise newException(YamlConstructionError,
"Cannot construct to float: " & item.scalarContent)
template constructObject*(s: var YamlStream, c: ConstructionContext,
result: var float) =
## calling this will raise a compiler error because ``float`` is not
## supported
{.fatal: "The length of `float` is platform dependent. Use float[32|64].".}
proc representObject*[T: float32|float64](value: T, ts: TagStyle,
proc representObject*[T: float|float32|float64](value: T, ts: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} =
## represents a float value as YAML scalar
result = iterator(): YamlStreamEvent =
@ -162,12 +158,6 @@ proc representObject*[T: float32|float64](value: T, ts: TagStyle,
else: asString = $value
yield scalarEvent(asString, tag, yAnchorNone)
template representObject*(value: float, tagStyle: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream =
## calling this will result in a compiler error because ``float`` is not
## supported
{.fatal: "The length of `float` is platform dependent. Use float[32|64].".}
proc yamlTag*(T: typedesc[bool]): TagId {.inline, raises: [].} = yTagBoolean
proc constructObject*(s: var YamlStream, c: ConstructionContext,

View File

@ -25,7 +25,10 @@ type
value: string
next: ref Node
BetterInt = int
BetterInt = distinct int
proc `$`(v: BetterInt): string {.borrow.}
proc `==`(l, r: BetterInt): bool {.borrow.}
setTagUriForType(TrafficLight, "!tl")
setTagUriForType(Node, "!example.net:Node")
@ -65,6 +68,31 @@ suite "Serialization":
setup:
let blockOnly = defineOptions(style=psBlockOnly)
test "Serialization: Load integer without fixed length":
var input = newStringStream("-4247")
var result: int
load(input, result)
assert result == -4247, "result is " & $result
input = newStringStream($(int64(int32.high) + 1'i64))
var gotException = false
try: load(input, result)
except: gotException = true
assert gotException, "Expected exception, got none."
test "Serialization: Dump integer without fixed length":
var input = -4247
var output = newStringStream()
dump(input, output, tsNone, asTidy, blockOnly)
assertStringEqual "%YAML 1.2\n--- \n\"-4247\"", output.data
when sizeof(int) == sizeof(int64):
input = int(int32.high) + 1
var gotException = false
try: dump(input, output, tsNone, asTidy, blockOnly)
except: gotException = true
assert gotException, "Expected exception, got none."
test "Serialization: Load string sequence":
let input = newStringStream(" - a\n - b")
var result: seq[string]
@ -330,8 +358,8 @@ next:
var result: seq[BetterInt]
load(input, result)
assert(result.len == 2)
assert(result[0] == 2)
assert(result[1] == 3)
assert(result[0] == 2.BetterInt)
assert(result[1] == 3.BetterInt)
test "Serialization: Custom representObject":
let input = @[1.BetterInt, 9998887.BetterInt, 98312.BetterInt]