Compare commits

...

4 Commits

Author SHA1 Message Date
Emery Hemingway fd498c6457 Add a sugar module 2024-04-22 13:22:01 +02:00
Emery Hemingway a83ca8b31c Cleanup examples 2024-04-22 13:21:41 +02:00
Emery Hemingway ea698bedcc Add integer converter 2024-04-22 11:24:35 +02:00
Emery Hemingway 8d48ae60e9 Make compatible with nimNoLibc 2024-04-22 11:07:52 +02:00
9 changed files with 40 additions and 29 deletions

View File

@ -1,6 +1,6 @@
# Package # Package
version = "20240312" version = "20240422"
author = "Emery Hemingway" author = "Emery Hemingway"
description = "data model and serialization format" description = "data model and serialization format"
license = "Unlicense" license = "Unlicense"

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[options, sets, sequtils, strutils, tables, typetraits] import std/[assertions, options, sets, sequtils, strutils, tables, typetraits]
from std/algorithm import sort from std/algorithm import sort
from std/json import escapeJson, escapeJsonUnquoted from std/json import escapeJson, escapeJsonUnquoted
import bigints import bigints
@ -335,6 +335,9 @@ template unpreservable*() {.pragma.}
## as its native type. ## as its native type.
## Unpreservability is asserted at runtime. ## Unpreservability is asserted at runtime.
converter preserve*(i: SomeInteger): Value =
Value(kind: pkRegister, register: BiggestInt i)
proc toPreserves*[T](x: T): Value {.gcsafe.} = proc toPreserves*[T](x: T): Value {.gcsafe.} =
## Serializes ``x`` to Preserves. Can be customized by defining ## Serializes ``x`` to Preserves. Can be customized by defining
## ``toPreservesHook(x: T; E: typedesc)`` in the calling scope. ## ``toPreservesHook(x: T; E: typedesc)`` in the calling scope.
@ -565,7 +568,7 @@ proc fromPreserves*[T](v: var T; pr: Value): bool =
type Foo {.preservesRecord: "foo".} = object type Foo {.preservesRecord: "foo".} = object
x, y: int x, y: int
var foo: Foo var foo: Foo
assert(fromPreserve(foo, parsePreserves("""<foo 1 2>"""))) assert(fromPreserves(foo, parsePreserves("""<foo 1 2>""")))
assert(foo.x == 1) assert(foo.x == 1)
assert(foo.y == 2) assert(foo.y == 2)
when T is Value: when T is Value:
@ -843,9 +846,9 @@ func step*(pr: Value; path: varargs[Value, toPreserves]): Option[Value] =
## Works for sequences, records, and dictionaries. ## Works for sequences, records, and dictionaries.
runnableExamples: runnableExamples:
import std/options import std/options
assert step(parsePreserves("""<foo 1 2>"""), 1.toPreserve) == some(2.toPreserve) assert step(parsePreserves("""<foo 1 2>"""), 1.toPreserves) == some(2.toPreserves)
assert step(parsePreserves("""{ foo: 1 bar: 2}"""), "foo".toSymbol) == some(1.toPreserve) assert step(parsePreserves("""{ foo: 1 bar: 2}"""), "foo".toSymbol) == some(1.toPreserves)
assert step(parsePreserves("""[ ]"""), 1.toPreserve) == none(Value) assert step(parsePreserves("""[ ]"""), 1.toPreserves) == none(Value)
result = some(pr) result = some(pr)
for index in path: for index in path:
if result.isSome: if result.isSome:

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[endians, options, streams, strutils] import std/[assertions, endians, options, streams, strutils]
import bigints import bigints
import ./decoding, ./parsing, ./values import ./decoding, ./parsing, ./values

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[endians, streams] import std/[assertions, endians, streams]
import bigints import bigints
import ./values import ./values

View File

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import std/macros import std/[assertions, macros]
const const
nnkPragmaCallKinds = {nnkExprColonExpr, nnkCall, nnkCallStrLit} nnkPragmaCallKinds = {nnkExprColonExpr, nnkCall, nnkCallStrLit}

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[base64, options, parseutils, strutils, unicode] import std/[assertions, base64, options, parseutils, strutils, unicode]
from std/sequtils import insert from std/sequtils import insert
import bigints, npeg import bigints, npeg

View File

@ -1,7 +1,9 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[base64, endians, math, sequtils, streams, strutils] import std/[assertions, base64, endians, sequtils, streams, strutils]
when not defined(nimNoLibc):
import std/math
import bigints import bigints
import ./values import ./values
@ -42,6 +44,15 @@ proc writeSymbol(stream: Stream; sym: string) =
writeEscaped(stream, sym, '|') writeEscaped(stream, sym, '|')
write(stream, '|') write(stream, '|')
proc writeFloatBytes(stream: Stream; f: float) =
var buf: array[8, byte]
bigEndian64(addr buf[0], addr f)
write(stream, "#xd\"")
for b in buf:
write(stream, hexAlphabet[b shr 4])
write(stream, hexAlphabet[b and 0xf])
write(stream, '"')
proc writeText*(stream: Stream; pr: Value; mode = textPreserves) = proc writeText*(stream: Stream; pr: Value; mode = textPreserves) =
## Encode Preserves to a `Stream` as text. ## Encode Preserves to a `Stream` as text.
if pr.embedded: write(stream, "#:") if pr.embedded: write(stream, "#:")
@ -51,17 +62,14 @@ proc writeText*(stream: Stream; pr: Value; mode = textPreserves) =
of false: write(stream, "#f") of false: write(stream, "#f")
of true: write(stream, "#t") of true: write(stream, "#t")
of pkFloat: of pkFloat:
case pr.float.classify: when defined(nimNoLibc):
of fcNormal, fcZero, fcNegZero: writeFloatBytes(stream, pr.float)
write(stream, $pr.float) # IEE754-to-decimal is non-trivial
else: else:
var buf: array[8, byte] if pr.float.classify in {fcNormal, fcZero, fcNegZero}:
bigEndian64(addr buf[0], addr pr.float) write(stream, $pr.float)
write(stream, "#xd\"") else:
for b in buf: writeFloatBytes(stream, pr.float)
write(stream, hexAlphabet[b shr 4])
write(stream, hexAlphabet[b and 0xf])
write(stream, '"')
of pkRegister: of pkRegister:
write(stream, $pr.register) write(stream, $pr.register)
of pkBigInt: of pkBigInt:

View File

@ -1,8 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[algorithm, hashes, math, options, sets, sequtils, tables] import std/[algorithm, hashes, options, sets, sequtils, tables]
import bigints import bigints
type type
@ -80,11 +79,6 @@ type
## Object refs embedded in Preserves `Value`s must inherit from `EmbeddedObj`. ## Object refs embedded in Preserves `Value`s must inherit from `EmbeddedObj`.
## At the moment this is just an alias to `RootObj` but this may change in the future. ## At the moment this is just an alias to `RootObj` but this may change in the future.
func `===`[T: SomeFloat](a, b: T): bool =
## Compare where Nan == NaN.
let class = a.classify
(class == b.classify) and ((class notin {fcNormal,fcSubnormal}) or (a == b))
func `==`*(x, y: Value): bool = func `==`*(x, y: Value): bool =
## Check `x` and `y` for equivalence. ## Check `x` and `y` for equivalence.
if x.kind == y.kind and x.embedded == y.embedded: if x.kind == y.kind and x.embedded == y.embedded:
@ -92,7 +86,7 @@ func `==`*(x, y: Value): bool =
of pkBoolean: of pkBoolean:
result = x.bool == y.bool result = x.bool == y.bool
of pkFloat: of pkFloat:
result = x.float === y.float result = cast[uint64](x.float) == cast[uint64](y.float)
of pkRegister: of pkRegister:
result = x.register == y.register result = x.register == y.register
of pkBigInt: of pkBigInt:

6
src/preserves/sugar.nim Normal file
View File

@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import ../preserves, ./private/macros
proc `%`*(n: SomeInteger): Value {.inline.} = n.toPreserves