Commit 67cc55ab authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent c49c72d0
...@@ -4,8 +4,8 @@ package neo ...@@ -4,8 +4,8 @@ package neo
// XXX move imports out of here // XXX move imports out of here
import ( import (
//"encoding/binary" "encoding/binary"
//"math" "math"
) )
const ( const (
...@@ -125,7 +125,6 @@ type Address struct { ...@@ -125,7 +125,6 @@ type Address struct {
// return n // return n
// } // }
/*
// A SHA1 hash // A SHA1 hash
type Checksum [20]byte type Checksum [20]byte
...@@ -133,11 +132,9 @@ type Checksum [20]byte ...@@ -133,11 +132,9 @@ type Checksum [20]byte
// Zero value means "invalid id" (<-> None in py.PPTID) // Zero value means "invalid id" (<-> None in py.PPTID)
type PTid uint64 // XXX move to common place ? type PTid uint64 // XXX move to common place ?
type Float64 float64
// NOTE py.None encodes as '\xff' * 8 (-> we use NaN for None) // NOTE py.None encodes as '\xff' * 8 (-> we use NaN for None)
// NOTE '\xff' * 8 represents FP NaN but many other NaN bits representation exist // NOTE '\xff' * 8 represents FP NaN but many other NaN bits representation exist
// func (f Float64) NEOEncode(b []byte) int {
func float64_NEOEncode(f float64, b []byte) { func float64_NEOEncode(f float64, b []byte) {
var fu uint64 var fu uint64
if !math.IsNaN(f) { if !math.IsNaN(f) {
...@@ -150,19 +147,19 @@ func float64_NEOEncode(f float64, b []byte) { ...@@ -150,19 +147,19 @@ func float64_NEOEncode(f float64, b []byte) {
binary.BigEndian.PutUint64(b, fu) binary.BigEndian.PutUint64(b, fu)
} }
//func (f *Float64) NEODecode(b []byte) int {
func float64_NEODecode(b []byte) float64 { func float64_NEODecode(b []byte) float64 {
fu := binary.BigEndian.Uint64(b) fu := binary.BigEndian.Uint64(b)
return math.Float64frombits(fu) return math.Float64frombits(fu)
} }
/*
// NOTE original NodeList = []NodeInfo // NOTE original NodeList = []NodeInfo
type NodeInfo struct { type NodeInfo struct {
NodeType NodeType
Address Address
UUID UUID
NodeState NodeState
IdTimestamp Float64 IdTimestamp float64
} }
//type CellList []struct { //type CellList []struct {
...@@ -219,7 +216,7 @@ type RequestIdentification struct { ...@@ -219,7 +216,7 @@ type RequestIdentification struct {
UUID UUID UUID UUID
Address // where requesting node is also accepting connections Address // where requesting node is also accepting connections
Name string Name string
IdTimestamp Float64 IdTimestamp float64
} }
// XXX -> ReplyIdentification? RequestIdentification.Answer somehow ? // XXX -> ReplyIdentification? RequestIdentification.Answer somehow ?
......
...@@ -43,9 +43,9 @@ var info = &types.Info{ ...@@ -43,9 +43,9 @@ var info = &types.Info{
Defs: make(map[*ast.Ident]types.Object), Defs: make(map[*ast.Ident]types.Object),
} }
// complete position of a node // complete position of something with .Pos()
func pos(n ast.Node) token.Position { func pos(x interface { Pos() token.Pos }) token.Position {
return fset.Position(n.Pos()) return fset.Position(x.Pos())
} }
func main() { func main() {
...@@ -194,120 +194,174 @@ func (b *Buffer) Printfln(format string, a ...interface{}) (n int, err error) { ...@@ -194,120 +194,174 @@ func (b *Buffer) Printfln(format string, a ...interface{}) (n int, err error) {
} }
func gendecode(typespec *ast.TypeSpec) string { // state of decode codegen
buf := Buffer{} type decoder struct {
emit := buf.Printfln buf Buffer // buffer for generated code
n int // current decode position in data
typename := typespec.Name.Name }
t := typespec.Type.(*ast.StructType) // must be
emit("func (p *%s) NEODecode(data []byte) (int, error) {", typename)
n := 0 // current decode pos in data
for _, fieldv := range t.Fields.List { func (d *decoder) emit(format string, a ...interface{}) {
// type B struct { ... } fmt.Fprintf(&d.buf, format+"\n", a...)
// }
// type A struct {
// x, y int <- fieldv
// B <- fieldv
// embedding: change `B` -> `B B` (field type must be Ident)
fieldnamev := fieldv.Names
if fieldnamev == nil {
fieldnamev = []*ast.Ident{fieldv.Type.(*ast.Ident)}
}
// decode basic fixed types (not string) // emit code for decode basic fixed types (not string), but do not assign it
decodeBasic := func(typ *types.Basic) string { func (d *decoder) decodedBasic (obj types.Object, typ *types.Basic) string {
bdec, ok := basicDecode[typ.Kind()] bdec, ok := basicDecode[typ.Kind()]
if !ok { if !ok {
log.Fatalf("%v: basic type %v not supported", pos(fieldv), typ) log.Fatalf("%v: basic type %v not supported", pos(obj), typ)
} }
dataptr := fmt.Sprintf("data[%v:]", n) dataptr := fmt.Sprintf("data[%v:]", d.n)
decoded := fmt.Sprintf(bdec.decode, dataptr) decoded := fmt.Sprintf(bdec.decode, dataptr)
n += bdec.wireSize d.n += bdec.wireSize
return decoded return decoded
} }
emitstrbytes := func(fieldname string) {
emit("{ l := %v", decodeBasic(types.Typ[types.Uint32]))
emit("data = data[%v:]", n)
emit("if len(data) < l { return 0, ErrDecodeOverflow }")
emit("p.%v = string(data[:l])", fieldname)
emit("data = data[l:]")
emit("}")
n = 0
}
for _, fieldname := range fieldnamev { // emit code for decode next string or []byte
fieldtype := info.Types[fieldv.Type].Type func (d *decoder) emitstrbytes(assignto string) {
switch u := fieldtype.Underlying().(type) { // len u32
// we are processing: <fieldname> <fieldtype> // [len]byte
d.emit("{ l := %v", d.decodedBasic(nil, types.Typ[types.Uint32]))
d.emit("data = data[%v:]", d.n)
d.emit("if len(data) < l { return 0, ErrDecodeOverflow }")
d.emit("%v = string(data[:l])", assignto)
d.emit("data = data[l:]")
d.emit("}")
d.n = 0
}
// bool, uint32, string, ... // top-level driver for emitting decode code for obj/type
func (d *decoder) emitobjtype(assignto string, obj types.Object, typ types.Type) {
switch u := typ.Underlying().(type) {
case *types.Basic: case *types.Basic:
if u.Kind() == types.String { if u.Kind() == types.String {
emitstrbytes(fieldname.Name) d.emitstrbytes(assignto)
continue break
} }
emit("p.%s = %s", fieldname, decodeBasic(u)) d.emit("%s = %s", assignto, d.decodedBasic(obj, u))
case *types.Slice:
// TODO
case *types.Map:
// TODO
//case *types.Slice:
// // TODO
// TODO types.Struct //case *types.Map:
// // TODO
case *types.Struct:
for i := 0; i < u.NumFields(); i++ {
v := u.Field(i)
d.emitobjtype(assignto + "." + v.Name(), v, v.Type())
}
/* default:
log.Fatalf("%v: %v has unsupported type %v (%v)", pos(obj),
// simple types like uint16 obj.Name(), typ, u)
case *ast.Ident:
// TODO
// array or slice
case *ast.ArrayType:
if fieldtype.Len != nil {
log.Fatalf("%s: TODO arrays not suported", pos(fieldtype))
} }
}
eltsize := wiresize(fieldtype.Elt) // TODO
// len u32 // generate decoder func for a type declaration typespec
// [len] items func gendecode(typespec *ast.TypeSpec) string {
emit("length = Uint32(data[%s:])", n) d := decoder{}
n += 4 // prologue
emit("for ; length != 0; length-- {") d.emit("func (p *%s) NEODecode(data []byte) (int, error) {", typespec.Name.Name)
emit("}")
//n := 0
//t := typespec.Type.(*ast.StructType) // must be
// type & object which refers to this type
typ := info.Types[typespec.Type].Type
obj := info.Defs[typespec.Name]
// map d.emitobjtype("p", obj, typ)
case *ast.MapType:
// len u32
// [len] key, value
emit("length = Uint32(data[%s:])", n)
n += 4
keysize := wiresize(fieldtype.Key) d.emit("return %v /* + TODO variable part */, nil", d.n)
valsize := wiresize(fieldtype.Value) d.emit("}")
return d.buf.String()
// XXX *ast.StructType ?
*/
default: // for _, fieldv := range t.Fields.List {
log.Fatalf("%v: field %v has unsupported type %v", pos(fieldv), fieldname, fieldtype) // // type B struct { ... }
} // //
} // // type A struct {
} // // x, y int <- fieldv
// // B <- fieldv
//
// // embedding: change `B` -> `B B` (field type must be Ident)
// fieldnamev := fieldv.Names
// if fieldnamev == nil {
// fieldnamev = []*ast.Ident{fieldv.Type.(*ast.Ident)}
// }
//
//
// for _, fieldname := range fieldnamev {
// fieldtype := info.Types[fieldv.Type].Type
//
// switch u := fieldtype.Underlying().(type) {
// // we are processing: <fieldname> <fieldtype>
//
// // bool, uint32, string, ...
// case *types.Basic:
// if u.Kind() == types.String {
// emitstrbytes(fieldname.Name)
// continue
// }
//
// emit("p.%s = %s", fieldname, decodeBasic(u))
//
// case *types.Slice:
// // TODO
//
// case *types.Map:
// // TODO
//
//
// //case *types.Struct:
// // TODO
//
//
//
// /*
//
// // simple types like uint16
// case *ast.Ident:
// // TODO
//
// // array or slice
// case *ast.ArrayType:
// if fieldtype.Len != nil {
// log.Fatalf("%s: TODO arrays not suported", pos(fieldtype))
// }
//
// eltsize := wiresize(fieldtype.Elt) // TODO
//
// // len u32
// // [len] items
// emit("length = Uint32(data[%s:])", n)
// n += 4
// emit("for ; length != 0; length-- {")
// emit("}")
//
//
//
// // map
// case *ast.MapType:
// // len u32
// // [len] key, value
// emit("length = Uint32(data[%s:])", n)
// n += 4
//
// keysize := wiresize(fieldtype.Key)
// valsize := wiresize(fieldtype.Value)
//
// // XXX *ast.StructType ?
// */
//
// default:
// log.Fatalf("%v: field %v has unsupported type %v (%v)", pos(fieldv),
// fieldname, fieldtype, u)
// }
// }
// }
emit("return %v /* + TODO variable part */, nil", n)
emit("}")
return buf.String()
} }
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