Skip to content

Commit c1915bf

Browse files
committed
Started work on support for writing
1 parent 2d240d1 commit c1915bf

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

binaryparse.nim

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,64 @@ proc createReadStatement(
252252
offset = offset mod 8
253253

254254

255+
proc createWriteStatement(
256+
field: NimNode,
257+
info: tuple[size: BiggestInt, kind: NimNode, custom: NimNode],
258+
offset: var BiggestInt, stream: NimNode): NimNode {.compileTime.} =
259+
let
260+
size = info.size
261+
kind = info.kind
262+
custom = info.custom
263+
if custom != nil:
264+
result = (quote do:
265+
raise newException(AssertionError, "Custom writers not implemented")
266+
)
267+
elif info.kind.kind == nnkIdent and $info.kind.ident == "string":
268+
if offset != 0:
269+
raise newException(AssertionError, "Strings must be on byte boundry")
270+
if size == 0:
271+
result = (quote do:
272+
`stream`.write(`field`)
273+
)
274+
else:
275+
result = (quote do:
276+
if `size` != `field`.len:
277+
raise newException(AssertionError, "String of given size not matching")
278+
`stream`.write(`field`)
279+
)
280+
else:
281+
let
282+
bitInfo = getBitInfo(size, offset)
283+
write = bitInfo.read
284+
skip = bitInfo.skip
285+
shift = bitInfo.shift
286+
mask = bitInfo.mask
287+
result = newStmtList()
288+
if write == skip:
289+
result.add(quote do:
290+
if `stream`.writeData(`field`.addr, `write`) != `write`:
291+
raise newException(IOError,
292+
"Unable to write the requested amount of bytes from file")
293+
)
294+
else:
295+
result.add(quote do:
296+
var tmp: `kind`
297+
if `stream`.peekData(tmp.addr, `write`) != `write`:
298+
raise newException(IOError,
299+
"Unable to write the requested amount of bytes from file")
300+
tmp = tmp or (`field` shr `shift`) and `mask`
301+
if `stream`.writeData(tmp.addr, `write`) != `write`:
302+
raise newException(IOError,
303+
"Unable to write the requested amount of bytes from file")
304+
)
305+
if skip != 0 and skip != write:
306+
result.add(quote do:
307+
`stream`.setPosition(`stream`.getPosition() - (`write` - `skip`))
308+
)
309+
offset += size
310+
offset = offset mod 8
311+
312+
255313
macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
256314
## The main macro in this module. It takes the ``name`` of the procedure to
257315
## create along with a block on the format described above and creates a
@@ -262,6 +320,7 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
262320
stream = genSym(nskParam)
263321
var
264322
inner = newStmtList()
323+
writer = newStmtList()
265324
tupleMeat = nnkTupleTy.newNimNode
266325
i = 0
267326
field = 0
@@ -299,6 +358,9 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
299358
inner.add(quote do:
300359
var `sym`: `kind`
301360
)
361+
writer.add(quote do:
362+
var `sym`: `kind` = `magic`
363+
)
302364
dec field
303365
else:
304366
sym = (quote do: `res`[`field`])
@@ -309,6 +371,7 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
309371
if $info.kind == "string":
310372
info.size = ($magic).len
311373
inner.add(createReadStatement(sym, info, offset, stream))
374+
writer.add(createWriteStatement(sym, info, offset, stream))
312375
inner.add(quote do:
313376
if `sym` != `magic`:
314377
raise newException(MagicError,
@@ -424,6 +487,11 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
424487
(quote do: `res`[`field`]), info, offset, stream
425488
)
426489
)
490+
writer.add(
491+
createWriteStatement(
492+
(quote do: `res`[`field`]), info, offset, stream
493+
)
494+
)
427495
else:
428496
discard
429497
inc i
@@ -435,6 +503,7 @@ macro createParser*(name: untyped, paramsAndDef: varargs[untyped]): untyped =
435503
result[3].add p
436504

437505
echo result.toStrLit
506+
echo writer.toStrLit
438507

439508
when isMainModule:
440509
createParser(list, size: uint16):

0 commit comments

Comments
 (0)