Skip to content

Commit

Permalink
0.1.0: impl standard type support
Browse files Browse the repository at this point in the history
  • Loading branch information
disruptek committed Sep 6, 2020
1 parent 6da7aa8 commit 07a3a83
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 19 deletions.
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@ Making some assumptions (ie. that our types aren't changing) allows...
- predictably _idiomatic_ API
- **hard to misuse**

It's _fairly_ hard to misuse, but it's not fully optimized yet. In some cases,
it's much faster than the standard json module. In a few, it's a little slower.
It's _fairly_ hard to misuse, but it's not fully optimized yet. In most cases,
it's faster than the standard library's `json` module. In rare cases, you may
find it a little slower.

The main advantage is that you get JSON encoding of tuples, objects, and
Static values known at compile-time such as constants or macro outputs are
serialized at compile-time. This is orders of magnitude faster than the
standard library.

But the main advantage is that you get JSON encoding of tuples, objects, and
iterators "for free" -- no serialization to implement and no duplication of
data.

Everything is type-checked, too, so there will be no runtime serialization
exceptions.

And, if you _want_ to implement custom serialization, it's now trivial to do
so for individual types.
And, if you _want_ to implement custom serialization, it's now trivial to do so
for individual types. You can also implement custom compile-time serialization.

## Usage

Expand Down Expand Up @@ -89,10 +94,18 @@ type
let b = B(x: 3, y: "sup")
let c: C = @[ B(x: 1), B(x: 2), B(x: 3) ]
const a = B(x: 4, y: "compile-time!")
func jason(n: B): Json =
## my special json encoding for B
if n.x mod 2 == 0: jason"even"
else: jason"odd"
macro jason(n: static[B]): Json =
## compile-time json encoding is free!
newCall(ident"Json", newLit(n.jason.string))
echo a.jason # "even"
echo b.jason # "odd"
echo c.jason # ["odd","even","odd"]
```
Expand Down
26 changes: 17 additions & 9 deletions jason.nim
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ proc join(a: openArray[Json]; sep = Json""): Json =
# these are copied from stdlib so that we can be certain we match output
# without having to import json and all of its dependencies... i know.

proc escapeJsonUnquoted(s: string; result: var string) =
proc escapeJsonUnquoted(s: string; result: var string) {.used.} =
## Converts a string `s` to its JSON representation without quotes.
## Appends to ``result``.
for c in s:
Expand Down Expand Up @@ -91,14 +91,6 @@ macro jason*(s: string): Json =
let escapist = bindSym "escapeJson"
result = json newCall(escapist, s)

macro jason*(s: static[string]): Json =
## Escapes a static string to form "JSON".
runnableExamples:
const g = "goats"
assert jason(g) == """"goats""""

result = json newLit(escapeJson s)

macro jason*(b: bool): Json =
## Produce a JSON boolean, either `true` or `false`.
runnableExamples:
Expand All @@ -121,6 +113,22 @@ func jason*(f: SomeFloat): Json =
## Render any Nim float as a JSON number.
result = Json($f)

when not defined(nimdoc):
macro jason*(j: static[string]): Json = json newLit(j.jason.string)
macro jason*(j: static[bool]): Json = json newLit(j.jason.string)
macro jason*(j: static[int]): Json = json newLit(j.jason.string)
macro jason*(j: static[int8]): Json = json newLit(j.jason.string)
macro jason*(j: static[int16]): Json = json newLit(j.jason.string)
macro jason*(j: static[int32]): Json = json newLit(j.jason.string)
macro jason*(j: static[int64]): Json = json newLit(j.jason.string)
macro jason*(j: static[uint]): Json = json newLit(j.jason.string)
macro jason*(j: static[uint8]): Json = json newLit(j.jason.string)
macro jason*(j: static[uint16]): Json = json newLit(j.jason.string)
macro jason*(j: static[uint32]): Json = json newLit(j.jason.string)
macro jason*(j: static[uint64]): Json = json newLit(j.jason.string)
macro jason*(j: static[float]): Json = json newLit(j.jason.string)
macro jason*(j: static[float32]): Json = json newLit(j.jason.string)

proc composeWithComma(parent: NimNode; js: NimNode): NimNode =
# whether we need to add a comma before the next element
let adder = bindSym "add"
Expand Down
2 changes: 1 addition & 1 deletion jason.nimble
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "0.0.3"
version = "0.1.0"
author = "disruptek"
description = "compile-time json"
license = "MIT"
Expand Down
14 changes: 10 additions & 4 deletions tests/test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,19 @@ testes:
B = object
x: int
y: string
C = seq[B]

const a = B(x: 4, y: "compile-time!")
let b = B(x: 3, y: "sup")
let c: C = @[ B(x: 1), B(x: 2), B(x: 3) ]

func jason(n: B): Json =
if n.x == 3:
jason"odd"
else:
jason"even"
if n.x mod 2 == 0: jason"even"
else: jason"odd"

macro jason(n: static[B]): Json =
newCall(ident"Json", newLit(n.jason.string))

check a.jason == """"even""""
check b.jason == """"odd""""
check c.jason == """["odd","even","odd"]"""

0 comments on commit 07a3a83

Please sign in to comment.