Skip to content

Commit 1989b1b

Browse files
committed
* ErlAtom is now distinct string
* ErlCharlist is now represented with seq[char] * ErlBinary is now represented with seq[byte]
1 parent 452df6a commit 1989b1b

File tree

4 files changed

+65
-60
lines changed

4 files changed

+65
-60
lines changed

nimler/bindings/erl_nif.nim

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import std/hashes
12
import ../erl_sys_info
23

34
const dep_header_name = "erl_nif.h"
@@ -279,14 +280,26 @@ func enif_now_time*(a1: ptr ErlNifEnv): ErlNifTerm {.c_dep_proc, min_nif_version
279280
func enif_fprintf*(a1: File; a2: cstring): bool {.varargs, c_dep_proc.}
280281
func enif_snprintf*(a1: ptr char, a2: cuint; a3: cstring): bool {.varargs, c_dep_proc, min_nif_version(2, 11).}
281282

282-
proc `==`*(a, b: ErlNifTerm): bool {.borrow.}
283-
284-
func `$`*(x: ErlNifTerm): string =
283+
proc `==`*(a, b: ErlNifTerm): bool =
284+
enif_is_identical(a, b)
285+
proc hash*(x: ErlNifTerm): Hash {.borrow.}
286+
proc `$`*(x: ErlNifTerm): string =
285287
when (nifMajor, nifMinor) >= (2, 11):
286-
let str_len = 100.cuint
288+
let str_len = 100
287289
result = newString(str_len)
288-
if not enif_snprintf(result[0].addr, str_len, "ErlNifTerm:%T", x):
289-
result = "ErlNifTerm"
290+
if enif_snprintf(result[0].addr, str_len.cuint, "ErlNifTerm:%T", x):
291+
var i = 0
292+
while result[i] != '\0': inc(i)
293+
result.setLen(i)
294+
if result.len == str_len.int - 1:
295+
result[^3 ..< result.len] = "..."
290296
else:
291297
result = "ErlNifTerm"
292298

299+
type ErlAtom* = distinct string
300+
301+
proc `$`*(x: ErlAtom): string {.borrow.}
302+
proc `==`*(a: ErlAtom, b: ErlAtom): bool {.borrow.}
303+
proc hash*(x: ErlAtom): Hash {.borrow.}
304+
proc len*(x: ErlAtom): int {.borrow.}
305+

nimler/codec.nim

+39-47
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import std/macros
22
import std/typetraits
33
import std/tables
4-
import std/hashes
54
import bindings/erl_nif
65

76
import std/options
@@ -11,17 +10,10 @@ using
1110
env: ptr ErlNifEnv
1211
term: ErlNifTerm
1312

14-
type
15-
ErlAtom* = object
16-
val*: string
17-
ErlCharlist* = seq[char]
18-
ErlBinary* = ErlNifBinary
19-
20-
const AtomOk* = ErlAtom(val: "ok")
21-
const AtomError* = ErlAtom(val: "error")
22-
const AtomTrue* = ErlAtom(val: "true")
23-
const AtomFalse* = ErlAtom(val: "false")
24-
const AtomMapEncodeException = ErlAtom(val: "nimler: fail to encode map")
13+
const AtomOk* = ErlAtom("ok")
14+
const AtomError* = ErlAtom("error")
15+
const AtomTrue* = ErlAtom("true")
16+
const AtomFalse* = ErlAtom("false")
2517

2618
macro generic_params(T: typedesc): untyped =
2719
result = newNimNode(nnkTupleConstr)
@@ -43,10 +35,6 @@ macro generic_params(T: typedesc): untyped =
4335
else:
4436
error "wrong kind: " & $impl.kind
4537

46-
func hash*(a: ErlAtom): Hash {.inline.} =
47-
result = a.val.hash
48-
result = !$result
49-
5038
# int
5139
func from_term*(env; term; T: typedesc[int]): Option[T] {.inline.} =
5240
var res: int
@@ -115,27 +103,27 @@ func from_term*(env; term; T: typedesc[ErlAtom]): Option[T] {.inline.} =
115103
var atom_len: cuint
116104
if enif_get_atom_length(env, term, addr(atom_len), ERL_NIF_LATIN1):
117105
let buf_len = atom_len + 1
118-
var atom = ErlAtom(val: newString(atom_len))
119-
if enif_get_atom(env, term, addr(atom.val[0]), buf_len, ERL_NIF_LATIN1) == cint(buf_len):
120-
result = some(atom)
106+
var atom = newString(atom_len)
107+
if enif_get_atom(env, term, addr(atom[0]), buf_len, ERL_NIF_LATIN1) == cint(buf_len):
108+
result = some(ErlAtom(atom))
121109

122110
func to_term*(env; V: ErlAtom): ErlNifTerm {.inline.} =
123111
var res: ErlNifTerm
124-
if enif_make_existing_atom_len(env, V.val, len(V.val).csize_t, addr(res)):
112+
if enif_make_existing_atom_len(env, V.cstring, len(V).csize_t, addr(res)):
125113
result = res
126114
else:
127-
result = enif_make_atom_len(env, V.val, len(V.val).csize_t)
115+
result = enif_make_atom_len(env, V.cstring, len(V).csize_t)
128116

129117
# charlist
130-
func from_term*(env; term; T: typedesc[ErlCharlist]): Option[T] {.inline.} =
118+
func from_term*(env; term; T: typedesc[seq[char]]): Option[T] {.inline.} =
131119
var string_len: cuint
132120
if enif_get_list_length(env, term, addr(string_len)):
133121
let buf_len = string_len + 1
134122
var string_buf = newSeq[char](string_len)
135123
if enif_get_string(env, term, addr(string_buf[0]), buf_len, ERL_NIF_LATIN1) == cint(buf_len):
136124
result = some(string_buf)
137125

138-
func to_term*(env; V: ErlCharlist): ErlNifTerm {.inline.} =
126+
func to_term*(env; V: seq[char]): ErlNifTerm {.inline.} =
139127
enif_make_string_len(env, V, ERL_NIF_LATIN1)
140128

141129
# string
@@ -155,16 +143,21 @@ func to_term*(env; V: string): ErlNifTerm {.inline.} =
155143
result = term
156144

157145
# binary
158-
func from_term*(env; term; T: typedesc[ErlBinary]): Option[T] {.inline.} =
159-
var bin: ErlNifBinary
160-
if enif_inspect_binary(env, term, addr(bin)):
146+
func from_term*(env; term; T: typedesc[seq[byte]]): Option[T] {.inline.} =
147+
var erl_bin: ErlNifBinary
148+
if enif_inspect_binary(env, term, addr(erl_bin)):
149+
var bin = newSeq[byte](erl_bin.size)
150+
copyMem(addr(bin[0]), erl_bin.data, erl_bin.size)
161151
result = some(bin)
162152

163-
func to_term*(env; V: ErlBinary): ErlNifTerm {.inline.} =
164-
enif_make_binary(env, unsafeAddr(V))
153+
func to_term*(env; V: seq[byte]): ErlNifTerm {.inline.} =
154+
var term: ErlNifTerm
155+
var bin = cast[ptr byte](enif_make_new_binary(env, len(V).csize_t, term.addr))
156+
copyMem(bin, unsafeAddr(V[0]), len(V))
157+
result = term
165158

166159
# list
167-
func from_term*(env; term; T: typedesc[seq]): Option[T] {.inline.} =
160+
func from_term*(env; term; T: typedesc[seq]): Option[T] =
168161
if not enif_is_list(env, term):
169162
return none(T)
170163
var res: T
@@ -179,7 +172,7 @@ func from_term*(env; term; T: typedesc[seq]): Option[T] {.inline.} =
179172
cursor = tail
180173
return some(res)
181174

182-
func to_term*(env; V: seq): ErlNifTerm {.inline.} =
175+
func to_term*(env; V: seq): ErlNifTerm =
183176
var v = newSeqOfCap[ErlNifTerm](V.len)
184177
for el in V:
185178
v.add(env.to_term(el))
@@ -204,19 +197,17 @@ func from_term*(env; term; T: typedesc[tuple]): Option[T] =
204197
return some(res)
205198

206199
macro to_term*(env: typed; V: tuple): untyped =
207-
case V.kind:
208-
of nnkSym:
209-
let tup_len = V.getTypeImpl().len
210-
result = newCall("enif_make_tuple", env, newLit(tup_len))
211-
for i in 0 ..< tup_len:
212-
let v = quote do: `V`[`i`]
213-
result.add(newCall("to_term", env, v))
214-
of nnkTupleConstr:
215-
result = quote do:
216-
let erl_tup = `V`
217-
to_term(env, erl_tup)
218-
else:
219-
error "wrong kind: " & $V.kind
200+
expectKind(V, {nnkSym, nnkTupleConstr})
201+
if V.kind == nnkSym:
202+
let tup_len = V.getTypeImpl().len
203+
result = newCall("enif_make_tuple", env, newLit(tup_len))
204+
for i in 0 ..< tup_len:
205+
let v = quote do: `V`[`i`]
206+
result.add(newCall("to_term", env, v))
207+
elif V.kind == nnkTupleConstr:
208+
result = quote do:
209+
let erl_tup = `V`
210+
to_term(env, erl_tup)
220211

221212
# map/table
222213
func from_term*(env; term; T: typedesc[Table]): Option[T] =
@@ -243,10 +234,10 @@ func to_term*(env; V: Table): ErlNifTerm =
243234
for k, v in V:
244235
keys.add(env.to_term(k))
245236
vals.add(env.to_term(v))
246-
var map: ErlNifTerm
247-
if not enif_make_map_from_arrays(env, addr(keys[0]), addr(vals[0]), cuint(keys.len), addr(map)):
248-
return enif_raise_exception(env, env.to_term(AtomMapEncodeException))
249-
return map
237+
var res: ErlNifTerm
238+
if not enif_make_map_from_arrays(env, addr(keys[0]), addr(vals[0]), cuint(keys.len), addr(res)):
239+
return enif_raise_exception(env, env.to_term(ErlAtom("fail to encode map")))
240+
return res
250241

251242
# result
252243
template result_tuple*(env; res_type: ErlnifTerm; terms: varargs[ErlNifTerm]): untyped =
@@ -256,3 +247,4 @@ template ok*(env; terms: varargs[ErlNifTerm]): untyped =
256247
result_tuple(env, env.to_term(AtomOk), terms)
257248

258249
template error*(env; terms: varargs[ErlNifTerm]): untyped =
250+
result_tuple(env, env.to_term(AtomError), terms)

tests/codec/nif.nim

+6-6
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ func codec_double(env; argc; argv): ErlNifTerm {.nif, arity: 1.} =
4747

4848
func codec_atom(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
4949
let a1 = env.from_term(argv[0], ErlAtom).get()
50-
doAssert(a1 == ErlAtom(val: "test"))
50+
doAssert(a1 == ErlAtom("test"))
5151
return env.to_term(a1)
5252

5353
func codec_charlist(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
54-
let a1 = env.from_term(argv[0], ErlCharlist).get()
54+
let a1 = env.from_term(argv[0], seq[char]).get()
5555
doAssert(a1 == @"test")
56-
doAssert(env.from_term(env.to_term(@"test2"), ErlCharlist).get() == @"test2")
56+
doAssert(env.from_term(env.to_term(@"test2"), seq[char]).get() == @"test2")
5757
return env.to_term(a1)
5858

5959
func codec_string(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
@@ -63,8 +63,8 @@ func codec_string(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
6363
return env.to_term(a1)
6464

6565
func codec_binary(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
66-
let a1 = env.from_term(argv[0], ErlBinary).get()
67-
doAssert(cast[cstring](a1.data) == "test".cstring)
66+
let a1 = env.from_term(argv[0], seq[byte]).get()
67+
doAssert(a1 == @[116.byte, 101, 115, 116, 0])
6868
return env.to_term(a1)
6969

7070
func codec_list_int(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
@@ -85,7 +85,7 @@ func codec_tuple(env, argc, argv): ErlNifTerm {.nif, arity: 1.} =
8585
return env.to_term(a1)
8686

8787
func codec_map(env, argc, argv): ErlNifTerm {.nif, arity: 3.} =
88-
let a1 = env.from_term(argv[0], Table[ErlCharlist, int]).get()
88+
let a1 = env.from_term(argv[0], Table[seq[char], int]).get()
8989
let a2 = env.from_term(argv[1], Table[string, int]).get()
9090
let a3 = env.from_term(argv[2], Table[ErlAtom, string]).get()
9191
return env.to_term((a1, a2, a3))

tests/message/NimlerWrapper.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ defmodule NimlerMessage do
44

55
def send_message(_,_), do: exit(:nif_library_not_loaded)
66
def send_message_caller(_), do: exit(:nif_library_not_loaded)
7-
end
7+
end

0 commit comments

Comments
 (0)