import endian type uoffset* = uint32 ## offset in to the buffer soffset* = int32 ## offset from start of table, to a vtable voffset* = uint16 ## offset from start of table to value type Offsets* = uoffset | soffset | voffset type Vtable* = object Bytes*: seq[byte] Pos*: uoffset using this: Vtable func GetVal*[T](b: ptr seq[byte]): T {.inline.} = when T is float64: result = cast[T](GetVal[uint64](b)) elif T is float32: result = cast[T](GetVal[uint32](b)) elif T is string: result = cast[T](b[]) else: if b[].len < T.sizeof: b[].setLen T.sizeof result = cast[ptr T](unsafeAddr b[][0])[] template Get*[T](this; off: uoffset): T = var seq = this.Bytes[off..^1] GetVal[T](addr seq) template Get*[T](this; off: soffset): T = var seq = this.Bytes[off..^1] GetVal[T](addr seq) template Get*[T](this; off: voffset): T = var seq = this.Bytes[off..^1] GetVal[T](addr seq) func WriteVal*[T: not SomeFloat](b: var openArray[byte]; off: uoffset; n: T) {.inline.} = when sizeof(T) == 8: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 4: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 2: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 1: b[off] = n.uint8 else: discard #littleEndianX(addr b[off], unsafeAddr n, T.sizeof) #{.error:"shouldnt appear".} func WriteVal*[T: not SomeFloat](b: var seq[byte]; off: uoffset; n: T) {.inline.} = when sizeof(T) == 8: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 4: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 2: littleEndianX(addr b[off], unsafeAddr n, T.sizeof) elif sizeof(T) == 1: b[off] = n.uint8 else: discard #littleEndianX(addr b[off], unsafeAddr n, T.sizeof) #{.error:"shouldnt appear".} func WriteVal*[T: SomeFloat](b: var openArray[byte]; off: uoffset; n: T) {.inline.} = when T is float64: WriteVal(b, off, cast[uint64](n)) elif T is float32: WriteVal(b, off, cast[uint32](n)) func WriteVal*[T: SomeFloat](b: var seq[byte]; off: uoffset; n: T) {.inline.} = when T is float64: WriteVal(b, off, cast[uint64](n)) elif T is float32: WriteVal(b, off, cast[uint32](n)) func Offset*(this; off: voffset): voffset = let vtable = (this.Pos - this.Get[:uoffset](this.Pos)).voffset let vtableEnd = this.Get[:voffset](vtable) if off < vtableEnd: return this.Get[:voffset](vtable + off) return 0 func Indirect*(this; off: uoffset): uoffset = result = off + this.Get[:uoffset](off) func VectorLen*(this; off: uoffset): int = var newoff: uoffset = off + this.Pos newoff += this.Get[:uoffset](newoff) return this.Get[:uoffset](newoff).int func Vector*(this; off: uoffset): uoffset = let newoff: uoffset = off + this.Pos var x: uoffset = newoff + this.Get[:uoffset](newoff) x += (uoffset.sizeof).uoffset result = x func Union*(this; off: uoffset): Vtable = let newoff: uoffset = off + this.Pos result.Pos = newoff + this.Get[:uoffset](newoff) result.Bytes = this.Bytes func GetSlot*[T](this; slot: voffset; d: T): T = let off = this.Offset(slot) if off == 0: return d return this.Get[T](this.Pos + off) func GetOffsetSlot*[T: Offsets](this; slot: voffset; d: T): T = let off = this.Offset(slot) if off == 0: return d return off func ByteVector*(this; off: uoffset): seq[byte] = let newoff: uoffset = off + this.Get[:uoffset](off) start = newoff + (uoffset.sizeof).uoffset var newseq = this.Bytes[newoff..^1] let length = GetVal[uoffset](addr newseq) result = this.Bytes[start..