Thanks for @LeFF to discovering that thread, with it the code becomes:
import macros
type
estring = distinct string
proc `xor`*(x, y: char): char {.magic: "BitxorI", noSideEffect.}
proc fnv32a*[T:
string|openArray[char]|openArray[uint8]|openArray[int8]](data: T): int32 =
result = -18652613'i32
for b in items(data):
result = result xor int32(ord(b))
result = result *% 16777619
proc decodeStr*(s: estring, key: int32): string =
var s = string(s)
var k = key
result = newString(s.len)
for i in s.low .. s.high:
result[i] = s[i]
result[i] = result[i] xor chr(uint8(k and 0xFF))
result[i] = result[i] xor chr(uint8((k shr 8) and 0xFF))
result[i] = result[i] xor chr(uint8((k shr 16) and 0xFF))
result[i] = result[i] xor chr(uint8((k shr 24) and 0xFF))
k = k +% 1
proc encodeStr*(s: string, key: int32): estring =
estring(decodeStr(estring(s), key))
var encodedCounter {.compiletime.}: int32 = fnv32a(CompileTime &
CompileDate) and 0x7FFFFFFF
# term rewriting macro
macro encrypt*{s}(s: string{lit}): untyped =
var encodedStr = encodeStr($s, encodedCounter)
result = quote do:
decodeStr(estring(`encodedStr`), `encodedCounter`)
encodedCounter = (encodedCounter *% 16777619) and 0x7FFFFFFF
# test-case
echo "hello"
Run
Or you could even import this code from other modules and all string literals
in them will automatically get encrypted :)