Commit 346454a3 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 261f9303
This diff is collapsed.
...@@ -22,19 +22,46 @@ import ( ...@@ -22,19 +22,46 @@ import (
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token" "go/token"
"go/types"
"log"
) )
var _ = ast.Print // information about one packet type
type PacketType struct {
name string
msgCode uint16 // message code for this packet type - derived from type order number in source
}
var fset = token.NewFileSet()
var info = &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Uses: make(map[*ast.Ident]types.Object),
Defs: make(map[*ast.Ident]types.Object),
}
// complete position of a node
func pos(n ast.Node) {
return fset.Position(n.Pos())
}
func main() { func main() {
fset := token.NewFileSet() typeMap := map[string]*PacketType{} // XXX needed ?
// go through proto.go and collect packets type definitions
var mode parser.Mode = 0 // parser.Trace var mode parser.Mode = 0 // parser.Trace
f, err := parser.ParseFile(fset, "proto.go", nil, mode) f, err := parser.ParseFile(fset, "proto.go", nil, mode)
if err != nil { if err != nil {
panic(err) // XXX log log.Fatal(err) // parse error
} }
conf := types.Config{}
pkg, err := conf.Check("proto", fset, []*ast.File{f}, info)
if err != nil {
log.Fatal(err) // typecheck error
}
ncode := 0 ncode := 0
//ast.Print(fset, f) //ast.Print(fset, f)
...@@ -42,53 +69,132 @@ func main() { ...@@ -42,53 +69,132 @@ func main() {
for _, decl := range f.Decls { for _, decl := range f.Decls {
// we look for types (which can be only under GenDecl) // we look for types (which can be only under GenDecl)
gdecl, ok := decl.(*ast.GenDecl) gendecl, ok := decl.(*ast.GenDecl)
if !ok || gdecl.Tok != token.TYPE { if !ok || gendecl.Tok != token.TYPE {
continue continue
} }
for _, spec := range gdecl.Specs { for _, spec := range gendecl.Specs {
tspec := spec.(*ast.TypeSpec) // must be because tok = TYPE typespec := spec.(*ast.TypeSpec) // must be because tok = TYPE
tname := tspec.Name.Name typename := typespec.Name.Name
// we are only interested in struct types switch t := typespec.Type.(type) {
tstruct, ok := tspec.Type.(*ast.StructType) default:
if !ok { // we are only interested in struct types
continue continue
}
//fmt.Printf("\n%s:\n", tname) case *ast.StructType:
//fmt.Println(tstruct) //fmt.Printf("\n%s:\n", typename)
//ast.Print(fset, tstruct) //fmt.Println(t)
//ast.Print(fset, t)
if ncode != 0 { PacketType{name: typename, msgCode: ncode}
fmt.Println()
}
for _, fieldv := range tstruct.Fields.List { // if ncode != 0 {
// we only support simple types like uint16 // fmt.Println()
ftype, ok := fieldv.Type.(*ast.Ident) // }
if !ok {
// TODO log
// TODO proper error message
panic(fmt.Sprintf("%#v not supported", fieldv.Type))
}
if len(fieldv.Names) != 0 { for _, fieldv := range t.Fields.List {
for _, field := range fieldv.Names { // we only support simple types like uint16
fmt.Printf("%s(%d).%s\t%s\n", tname, ncode, field.Name, ftype) ftype, ok := fieldv.Type.(*ast.Ident)
if !ok {
// TODO log
// TODO proper error message
panic(fmt.Sprintf("%#v not supported", fieldv.Type))
} }
} else {
// no names means embedding
fmt.Printf("%s(%d).<%s>\n", tname, ncode, ftype)
}
}
ncode++ if len(fieldv.Names) != 0 {
for _, field := range fieldv.Names {
fmt.Printf("%s(%d).%s\t%s\n", typename, ncode, field.Name, ftype)
}
} else {
// no names means embedding
fmt.Printf("%s(%d).<%s>\n", typename, ncode, ftype)
}
}
ncode++
}
} }
//fmt.Println(gdecl) //fmt.Println(gdecl)
//ast.Print(fset, gdecl) //ast.Print(fset, gdecl)
} }
} }
// wiresize returns wire size of a type
// type must be of fixed size (e.g. not a slice or map)
// XXX ast.Expr -> ?
func wiresize(*ast.Expr) int {
// TODO
}
func gendecode(typespec *ast.TypeSpec) string {
buf := butes.Buffer{}
typename := typespec.Name.Name
t := typespec.Type.(*ast.StructType) // must be
fmt.Fprintf(&buf, "func (p *%s) NEODecode(data []byte) int {\n", typename)
n := 0 // current decode pos in data
for _, fieldv := t.Fields.List {
// 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 {
switch fieldtype := fieldv.Type.(type) {
// we are processing: <fieldname> <fieldtype>
// 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:
panic() // TODO
}
}
}
fmt.Fprintf(&buf, "}\n")
// TODO format.Source(buf.Bytes()) (XXX -> better at top-level for whole file)
return buf.String()
}
...@@ -63,7 +63,7 @@ func (stor *StorageApplication) ServeLink(ctx context.Context, link *NodeLink) { ...@@ -63,7 +63,7 @@ func (stor *StorageApplication) ServeLink(ctx context.Context, link *NodeLink) {
switch pkt.MsgCode { switch pkt.MsgCode {
case GetObject: case GetObject:
req := GetObject{} req := GetObject{}
err = req.Decode(pkt.Payload()) err = req.NEODecode(pkt.Payload())
if err != nil { if err != nil {
sendErr("malformed GetObject packet:", err) sendErr("malformed GetObject packet:", err)
} }
......
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