Skip to content

Instantly share code, notes, and snippets.

@treeform
Created May 17, 2018 23:33
Show Gist options
  • Save treeform/eab4d05013d0953cbec580466e1018d7 to your computer and use it in GitHub Desktop.
Save treeform/eab4d05013d0953cbec580466e1018d7 to your computer and use it in GitHub Desktop.
#[
kiwi is a packed key value table/dictinary/associate-arrays like objects that is packed into a single buffer.
kiwis don't optimize key access, but its pretty fast to do a liner scan if your kiwi is less then 100 elements.
]#
type
Kiwi* = object
arr: seq[uint8]
proc newKiwi*(): Kiwi =
result.arr = newSeq[uint8]()
proc `[]=`*(kiwi: var Kiwi, key, value: string) =
assert key.len <= 0xFFFF
assert value.len <= 0xFFFF
# pack key
kiwi.arr.add(uint8(key.len and 0x00FF))
kiwi.arr.add(uint8(uint16(key.len and 0xFF00) shr 8))
for c in key:
kiwi.arr.add(uint8(c))
# pack value
kiwi.arr.add(uint8(value.len and 0x00FF))
kiwi.arr.add(uint8(uint16(value.len and 0xFF00) shr 8))
for c in value:
kiwi.arr.add(uint8(c))
proc `[]`*(kiwi: var Kiwi, key: string): string =
var i = 0
while i < kiwi.arr.len:
let keyLen = int(kiwi.arr[i]) + int(kiwi.arr[i+1]) shr 8
i += 2
var
j = i
foundKey = true
for c in key:
if char(kiwi.arr[j]) != c:
foundKey = false
break
inc j
i += keylen
let valueLen = int(kiwi.arr[i]) + int(kiwi.arr[i+1]) shr 8
i += 2
if foundKey:
result = newStringOfCap(valueLen)
for j in 0..<valueLen:
result &= char(kiwi.arr[i+j])
return
else:
i += valueLen
iterator items*(kiwi: Kiwi): tuple[k: string, v: string] =
var i = 0
while i < kiwi.arr.len:
let keyLen = int(kiwi.arr[i]) + int(kiwi.arr[i+1]) shr 85
i += 2
var key = newStringOfCap(keyLen)
for j in 0..<keyLen:
key &= char(kiwi.arr[i+j])
i += keylen
let valueLen = int(kiwi.arr[i]) + int(kiwi.arr[i+1]) shr 8
i += 2
var value = newStringOfCap(valueLen)
for j in 0..<valueLen:
value &= char(kiwi.arr[i+j])
yield (k:key, v:value)
i += valueLen
proc `$`*(kiwi: Kiwi): string =
result = "{"
var first = true
for k, v in kiwi.items:
if not first:
result &= ", "
result &= k & ": " & v
first = false
result &= "}"
import json
proc `%`*(kiwi: Kiwi): JsonNode =
result = newJObject()
for k, v in kiwi.items:
result[k] = newJString(v)
when isMainModule:
var kv = newKiwi()
kv["foo"] = "bar"
kv["1234"] = "abcd"
echo kv["foo"]
echo kv["1234"]
for k, v in kv.items:
echo k, ": ", v
echo kv
var a = "hi there"
var b = a
a[2] = '-'
echo a
echo b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment