@@ -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+
255313macro 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
439508when isMainModule :
440509 createParser (list, size: uint16 ):
0 commit comments