Commit fc0cf8de authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 93447c73
...@@ -48,7 +48,7 @@ can do a good job the work is delegated to it. ...@@ -48,7 +48,7 @@ can do a good job the work is delegated to it.
-------- --------
TODO also types registry tables XXX also types registry tables are generated - document
*/ */
...@@ -173,7 +173,7 @@ import ( ...@@ -173,7 +173,7 @@ import (
} }
} }
// now packet types registry // now generate packet types registry
buf.emit("\n// registry of packet types") buf.emit("\n// registry of packet types")
buf.emit("var pktTypeRegistry = map[int]reflect.Type {") // XXX key -> PktCode ? buf.emit("var pktTypeRegistry = map[int]reflect.Type {") // XXX key -> PktCode ?
...@@ -190,7 +190,7 @@ import ( ...@@ -190,7 +190,7 @@ import (
buf.emit("}") buf.emit("}")
// format & emit generated code // format & output generated code
code, err := format.Source(buf.Bytes()) code, err := format.Source(buf.Bytes())
if err != nil { if err != nil {
panic(err) // should not happen panic(err) // should not happen
...@@ -423,7 +423,7 @@ func (o *OverflowCheck) AddExpr(format string, a ...interface{}) { ...@@ -423,7 +423,7 @@ func (o *OverflowCheck) AddExpr(format string, a ...interface{}) {
// sizer generates code to compute encoded size of a packet // sizer generates code to compute encoded size of a packet
// //
// when type is recursively walked, for every case symbolic size is added appropriately. // when type is recursively walked, for every case symbolic size is added appropriately.
// in case when it was needed to generate loops runtime accumulator variable is additionally used. // in case when it was needed to generate loops, runtime accumulator variable is additionally used.
// result is: symbolic size + (optionally) runtime accumulator. // result is: symbolic size + (optionally) runtime accumulator.
type sizer struct { type sizer struct {
commonCodeGen commonCodeGen
...@@ -436,7 +436,7 @@ type sizer struct { ...@@ -436,7 +436,7 @@ type sizer struct {
// no overflow checks are generated as by NEOEncoder interface provided data // no overflow checks are generated as by NEOEncoder interface provided data
// buffer should have at least NEOEncodedLen() length (the size computed by sizer). // buffer should have at least NEOEncodedLen() length (the size computed by sizer).
// //
// the code emitted is of kind: // the code emitted looks like:
// //
// encode<typ1>(data[n1:], path1) // encode<typ1>(data[n1:], path1)
// encode<typ2>(data[n2:], path2) // encode<typ2>(data[n2:], path2)
...@@ -451,11 +451,11 @@ type encoder struct { ...@@ -451,11 +451,11 @@ type encoder struct {
// when type is recursively walked, for every case code to decode next item from // when type is recursively walked, for every case code to decode next item from
// `data[n:]` is generated. // `data[n:]` is generated.
// //
// overflow checks and, when convenient, nread updates are grouped and emitted // overflow checks and nread updates are grouped and emitted so that they are
// so that they are performed in the beginning of greedy fixed-wire-size // performed in the beginning of greedy fixed-wire-size blocks - checking /
// blocks - checking as much as possible to do ahead in one go. // updating as much as possible to do ahead in one go.
// //
// the code emitted is of kind: // the code emitted looks like:
// //
// if len(data) < wireSize(typ1) + wireSize(typ2) + ... { // if len(data) < wireSize(typ1) + wireSize(typ2) + ... {
// goto overflow // goto overflow
...@@ -519,8 +519,8 @@ func (e *encoder) generatedCode() string { ...@@ -519,8 +519,8 @@ func (e *encoder) generatedCode() string {
} }
// XXX place? naming? // XXX place? naming?
// data <- data[pos:] // data = data[n:]
// pos <- 0 // n = 0
func (d *decoder) resetPos() { func (d *decoder) resetPos() {
if d.n != 0 { if d.n != 0 {
d.emit("data = data[%v:]", d.n) d.emit("data = data[%v:]", d.n)
...@@ -528,18 +528,20 @@ func (d *decoder) resetPos() { ...@@ -528,18 +528,20 @@ func (d *decoder) resetPos() {
} }
} }
// mark current place for delayed insertion of overflow check code // mark current place for insertion of overflow check code
// //
// delayed: because we go forward in decode path scanning ahead as far as we // The check will be acutally inserted later.
// can - until first seeing variable-size encoded something, and then - knowing //
// fixed size would be to read - insert checking condition for accumulated size // later: because first we go forward in decode path scanning ahead as far as
// to here-marked overflow checkpoint. // we can - until first seeing variable-size encoded something, and then -
// knowing fixed size would be to read - insert checking condition for
// accumulated size to here-marked overflow checkpoint.
// //
// so overflowCheck does: // so overflowCheck does:
// 1. emit overflow checking code for previous overflow checkpoint // 1. emit overflow checking code for previous overflow checkpoint
// 2. mark current place as next overflow checkpoint to eventually emit // 2. mark current place as next overflow checkpoint to eventually emit
// //
// it is inserted // it has to be inserted
// - before reading a variable sized item // - before reading a variable sized item
// - in the beginning of a loop inside (via overflowCheckLoopEntry) // - in the beginning of a loop inside (via overflowCheckLoopEntry)
// - right after loop exit (via overflowCheckLoopExit) // - right after loop exit (via overflowCheckLoopExit)
...@@ -559,8 +561,9 @@ func (d *decoder) overflowCheck() { ...@@ -559,8 +561,9 @@ func (d *decoder) overflowCheck() {
// otherwise accumulate into var(nread) at runtime. // otherwise accumulate into var(nread) at runtime.
// we do not break runtime accumulation into numeric & symbolic // we do not break runtime accumulation into numeric & symbolic
// parts, because just above whole expression num + symbolic // parts, because just above whole expression num + symbolic
// was just given to compiler so compiler should have it just computed. // was given to compiler as a whole so compiler should have it
// XXX recheck ^^^ actually good with the compiler // just computed fully.
// XXX recheck ^^^ is actually good with the compiler
if d.overflow.checkSize.IsNumeric() { if d.overflow.checkSize.IsNumeric() {
d.nread += d.overflow.checkSize.num d.nread += d.overflow.checkSize.num
} else { } else {
...@@ -574,7 +577,7 @@ func (d *decoder) overflowCheck() { ...@@ -574,7 +577,7 @@ func (d *decoder) overflowCheck() {
d.buf.Reset() d.buf.Reset()
} }
// overflowCheck variant that should be called at the beginning of a loop inside // overflowCheck variant that should be inserted at the beginning of a loop inside
func (d *decoder) overflowCheckLoopEntry() { func (d *decoder) overflowCheckLoopEntry() {
if d.overflow.checked { if d.overflow.checked {
return return
...@@ -582,13 +585,13 @@ func (d *decoder) overflowCheckLoopEntry() { ...@@ -582,13 +585,13 @@ func (d *decoder) overflowCheckLoopEntry() {
d.overflowCheck() d.overflowCheck()
// upon entering a loop organize new nread, because what was statically // upon entering a loop organize new nread, because what will be statically
// read inside loop should be multiplied by loop len in parent context. // read inside loop should be multiplied by loop len in parent context.
d.nreadStk = append(d.nreadStk, d.nread) d.nreadStk = append(d.nreadStk, d.nread)
d.nread = 0 d.nread = 0
} }
// overflowCheck variant that should be called right after loop exit // overflowCheck variant that should be inserted right after loop exit
func (d *decoder) overflowCheckLoopExit(loopLenExpr string) { func (d *decoder) overflowCheckLoopExit(loopLenExpr string) {
if d.overflow.checked { if d.overflow.checked {
return return
...@@ -628,6 +631,7 @@ func (d *decoder) generatedCode() string { ...@@ -628,6 +631,7 @@ func (d *decoder) generatedCode() string {
code.emit("return %v, nil", retexpr) code.emit("return %v, nil", retexpr)
// `goto overflow` is not used only for empty structs // `goto overflow` is not used only for empty structs
// NOTE for >0 check actual X in StdSizes{X} does not particularly matter
if (&types.StdSizes{8, 8}).Sizeof(d.typ) > 0 { if (&types.StdSizes{8, 8}).Sizeof(d.typ) > 0 {
code.emit("\noverflow:") code.emit("\noverflow:")
code.emit("return 0, ErrDecodeOverflow") code.emit("return 0, ErrDecodeOverflow")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment