Skip to content

Commit 33afd7d

Browse files
authored
adds fromNif procs to nifply and supports enum and object types (#1217)
1 parent 6adeec8 commit 33afd7d

File tree

3 files changed

+178
-10
lines changed

3 files changed

+178
-10
lines changed

lib/std/nifply.nim

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import ../../src/lib/nifbuilder
1+
import std/assertions
2+
import ../../src/lib/[nifbuilder, nifreader]
23

3-
export open, close, extract
4+
export close, extract
45

56
proc internalTypeName*[T](x: typedesc[T]): string {.magic: "InternalTypeName", noSideEffect.}
67

@@ -10,6 +11,12 @@ iterator internalFieldPairs*[T: tuple|object](x: T): tuple[key: string, val: unt
1011
type
1112
NifBuilder* = Builder
1213

14+
proc nifBuilderOpen*(filename: string; compact = false): Builder =
15+
nifbuilder.open(filename, compact)
16+
17+
proc nifBuilderOpen*(sizeHint: int; compact = false): Builder =
18+
nifbuilder.open(sizeHint, compact)
19+
1320
proc toNif*(b: var NifBuilder; x: string) =
1421
b.addStrLit x
1522

@@ -24,4 +31,85 @@ proc toNif*(b: var NifBuilder; x: float) =
2431

2532
proc toNif*(b: var NifBuilder; x: bool) =
2633
b.addKeyw($x)
27-
discard
34+
35+
proc toNif*[E: enum](b: var NifBuilder; x: E) =
36+
b.withTree "conv":
37+
b.addSymbol internalTypeName(E)
38+
b.addUIntLit uint(x)
39+
40+
proc toNif*[O: object](b: var NifBuilder; x: O) =
41+
b.withTree "oconstr":
42+
b.addSymbol internalTypeName(O)
43+
for name, f in internalFieldPairs(x):
44+
b.withTree "kv":
45+
b.addSymbol name
46+
toNif b, f
47+
48+
type
49+
NifReader* = Reader
50+
51+
proc nifReaderOpen*(filename: string): Reader =
52+
nifreader.open(filename)
53+
54+
proc nifReaderOpenFromBuffer*(buf: sink string): Reader =
55+
nifreader.openFromBuffer(buf)
56+
57+
template expectTree(r: var NifReader; tag: string; body: untyped) =
58+
let t = r.next
59+
assert t.tk == ParLe
60+
assert t.s == tag
61+
body
62+
let t2 = r.next
63+
assert t2.tk == ParRi
64+
65+
proc expectSymbol(r: var NifReader; sym: string) =
66+
let t = r.next
67+
assert t.tk == Symbol
68+
assert t.s == sym
69+
70+
proc fromNif*[T: not typedesc](r: var NifReader; x: var T) {.untyped, inline.} =
71+
x = r.fromNif T
72+
73+
proc fromNif*(r: var NifReader; t: typedesc[string]): string =
74+
let t = r.next
75+
assert t.tk == StringLit
76+
result = $t.s
77+
78+
proc fromNif*(r: var NifReader; t: typedesc[int]): int =
79+
let t = r.next
80+
result = decodeInt t
81+
82+
proc fromNif*(r: var NifReader; t: typedesc[uint]): uint =
83+
let t = r.next
84+
result = decodeUInt t
85+
86+
proc fromNif*(r: var NifReader; t: typedesc[float]): float =
87+
let t = r.next
88+
result = decodeFloat t
89+
90+
proc fromNif*(r: var NifReader; t: typedesc[bool]): bool =
91+
let t = r.next
92+
93+
if t.s == "true":
94+
result = true
95+
elif t.s == "false":
96+
result = false
97+
else:
98+
assert false, "got unexpected token: " & $t.s
99+
100+
let t2 = r.next
101+
assert t2.tk == ParRi
102+
103+
proc fromNif*[E: enum](r: var NifReader; t: typedesc[E]): E =
104+
r.expectTree "conv":
105+
r.expectSymbol internalTypeName E
106+
let val = r.next
107+
result = E decodeUInt val
108+
109+
proc fromNif*[O: object](r: var NifReader; t: typedesc[O]): O =
110+
r.expectTree "oconstr":
111+
r.expectSymbol internalTypeName O
112+
for name, f in internalFieldPairs(result):
113+
r.expectTree "kv":
114+
r.expectSymbol name
115+
r.fromNif f

tests/nimony/stdlib/tnifply.nim

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import std/[nifply, syncio]
1+
import std/[assertions, nifply, syncio]
22

33
type
44
Foo = object
@@ -8,6 +8,16 @@ type
88
barFieldX: string
99
barFieldY: float
1010

11+
TestEnum = enum
12+
teX
13+
teY
14+
teZ
15+
16+
FooBar = object
17+
foo: Foo
18+
bar: Bar
19+
en: TestEnum
20+
1121
echo internalTypeName(Foo)
1222
echo internalTypeName(Bar)
1323

@@ -34,31 +44,87 @@ testInternalFieldPairs(y)
3444

3545
const DefaultBufSize = 8
3646
block:
37-
var b = open(DefaultBufSize)
47+
var b = nifBuilderOpen(DefaultBufSize)
3848
b.toNif "hello"
3949
echo b.extract
4050

4151
block:
42-
var b = open(DefaultBufSize)
52+
var b = nifBuilderOpen(DefaultBufSize)
4353
b.toNif 123
4454
echo b.extract
4555

4656
block:
47-
var b = open(DefaultBufSize)
57+
var b = nifBuilderOpen(DefaultBufSize)
4858
b.toNif 123'u
4959
echo b.extract
5060

5161
block:
52-
var b = open(DefaultBufSize)
62+
var b = nifBuilderOpen(DefaultBufSize)
5363
b.toNif 123.456
5464
echo b.extract
5565

5666
block:
57-
var b = open(DefaultBufSize)
67+
var b = nifBuilderOpen(DefaultBufSize)
5868
b.toNif true
5969
echo b.extract
6070

6171
block:
62-
var b = open(DefaultBufSize)
72+
var b = nifBuilderOpen(DefaultBufSize)
6373
b.toNif false
6474
echo b.extract
75+
76+
block:
77+
var b = nifBuilderOpen(DefaultBufSize)
78+
b.toNif teX
79+
echo b.extract
80+
81+
block:
82+
var b = nifBuilderOpen(DefaultBufSize)
83+
b.toNif Foo(fooFieldX: 123)
84+
b.toNif Bar(barFieldX: "bar field X", barFieldY: 321)
85+
b.toNif FooBar(foo: Foo(fooFieldX: 321), bar: Bar(barFieldX: "bar", barFieldY: 567.5), en: teY)
86+
echo b.extract
87+
88+
block:
89+
var b = nifBuilderOpen(DefaultBufSize)
90+
const TestString = "test string"
91+
b.toNif TestString
92+
const TestInt = 1234567
93+
b.toNif TestInt
94+
const TestUint = 1234567'u
95+
b.toNif TestUint
96+
const TestFloat = 0.125
97+
b.toNif TestFloat
98+
b.toNif false
99+
b.toNif true
100+
b.toNif teX
101+
b.toNif teY
102+
b.toNif teZ
103+
let testFoo = Foo(fooFieldX: 987)
104+
b.toNif testFoo
105+
let testBar = Bar(barFieldX: "bar field", barFieldY: 1.75)
106+
b.toNif testBar
107+
let testFooBar = FooBar(foo: Foo(fooFieldX: 4567), bar: Bar(barFieldX: "foobar", barFieldY: 2.625), en: teZ)
108+
b.toNif testFooBar
109+
110+
var r = nifReaderOpenFromBuffer(b.extract)
111+
assert r.fromNif(string) == TestString
112+
assert r.fromNif(int) == TestInt
113+
assert r.fromNif(uint) == TestUint
114+
assert r.fromNif(float) == TestFloat
115+
assert not r.fromNif(bool)
116+
assert r.fromNif(bool)
117+
assert r.fromNif(TestEnum) == teX
118+
assert r.fromNif(TestEnum) == teY
119+
assert r.fromNif(TestEnum) == teZ
120+
let readFoo = r.fromNif(Foo)
121+
assert readFoo.fooFieldX == testFoo.fooFieldX
122+
let readBar = r.fromNif(Bar)
123+
assert readBar.barFieldX == testBar.barFieldX
124+
assert readBar.barFieldY == testBar.barFieldY
125+
var readFooBar = default FooBar
126+
r.fromNif readFooBar
127+
assert readFooBar.foo.fooFieldX == testFooBar.foo.fooFieldX
128+
assert readFooBar.bar.barFieldX == testFooBar.bar.barFieldX
129+
assert readFooBar.bar.barFieldY == testFooBar.bar.barFieldY
130+
assert readFooBar.en == testFooBar.en

tests/nimony/stdlib/tnifply.output

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,17 @@ barFieldY.0.tni7snh9s = 456
1414
+123.456
1515
(true)
1616
(false)
17+
(conv TestEnum.0.tni7snh9s +0u)
18+
(oconstr Foo.0.tni7snh9s
19+
(kv fooFieldX.0.tni7snh9s +123))(oconstr Bar.0.tni7snh9s
20+
(kv barFieldX.0.tni7snh9s "bar field X")
21+
(kv barFieldY.0.tni7snh9s +321))(oconstr FooBar.0.tni7snh9s
22+
(kv foo.0.tni7snh9s
23+
(oconstr Foo.0.tni7snh9s
24+
(kv fooFieldX.0.tni7snh9s +321)))
25+
(kv bar.0.tni7snh9s
26+
(oconstr Bar.0.tni7snh9s
27+
(kv barFieldX.0.tni7snh9s "bar")
28+
(kv barFieldY.0.tni7snh9s +567.5)))
29+
(kv en.0.tni7snh9s
30+
(conv TestEnum.0.tni7snh9s +1u)))

0 commit comments

Comments
 (0)