slotted interface

master
Jordan Orelli 8 years ago
parent de885e32fc
commit efdf9e3d54

@ -19,8 +19,12 @@ type Class struct {
fieldNames map[string]int fieldNames map[string]int
} }
func (c *Class) New() *Entity { func (c *Class) New(serial int) *Entity {
return &Entity{Class: c} return &Entity{
Class: c,
slots: make([]interface{}, len(c.Fields)),
serial: serial,
}
} }
func (c Class) String() string { func (c Class) String() string {

@ -14,7 +14,9 @@ type decoder func(bit.Reader) interface{}
func newFieldDecoder(n *Namespace, f *Field) decoder { func newFieldDecoder(n *Namespace, f *Field) decoder {
Debug.Printf("new decoder: type: %s name: %s sendNode: %s\n\tbits: %d low: %v high: %v\n\tflags: %d serializer: %v serializerVersion: %v\n\tclass: %v encoder: %v", f._type, f.name, f.sendNode, f.bits, f.low, f.high, f.flags, f.serializer, f.serializerVersion, f.class, f.encoder) Debug.Printf("new decoder: type: %s name: %s sendNode: %s\n\tbits: %d low: %v high: %v\n\tflags: %d serializer: %v serializerVersion: %v\n\tclass: %v encoder: %v", f._type, f.name, f.sendNode, f.bits, f.low, f.high, f.flags, f.serializer, f.serializerVersion, f.class, f.encoder)
switch f._type.String() { typeName := f._type.String()
switch typeName {
case "bool": case "bool":
return decodeBool return decodeBool
case "uint8", "uint16", "uint32", "uint64", "Color": case "uint8", "uint16", "uint32", "uint64", "Color":
@ -33,7 +35,7 @@ func newFieldDecoder(n *Namespace, f *Field) decoder {
} }
switch { switch {
case strings.HasPrefix(f._type.String(), "CHandle"): case strings.HasPrefix(typeName, "CHandle"):
return decodeVarInt32 return decodeVarInt32
} }
return nil return nil

@ -36,7 +36,7 @@ const e_limit = 2048
// be used on the client. // be used on the client.
type Dict struct { type Dict struct {
*Namespace *Namespace
entities []Entity entities []*Entity
br *bit.BufReader br *bit.BufReader
sr *selectionReader sr *selectionReader
@ -49,7 +49,7 @@ type Dict struct {
func NewDict(sd *stbl.Dict) *Dict { func NewDict(sd *stbl.Dict) *Dict {
d := &Dict{ d := &Dict{
Namespace: new(Namespace), Namespace: new(Namespace),
entities: make([]Entity, e_limit), entities: make([]*Entity, e_limit),
br: new(bit.BufReader), br: new(bit.BufReader),
sr: new(selectionReader), sr: new(selectionReader),
base: sd.TableForName("instancebaseline"), base: sd.TableForName("instancebaseline"),
@ -65,7 +65,7 @@ func (d *Dict) createEntity(id int) error {
if len(d.Namespace.classes) == 0 { if len(d.Namespace.classes) == 0 {
return fmt.Errorf("unable to create entity %d: namespace has no classes", id) return fmt.Errorf("unable to create entity %d: namespace has no classes", id)
} }
d.br.ReadBits(17) // ??? serial := int(d.br.ReadBits(17))
classV := int(bit.ReadVarInt(d.br)) classV := int(bit.ReadVarInt(d.br))
className := d.classIds[classId] className := d.classIds[classId]
class := d.Class(className, classV) class := d.Class(className, classV)
@ -73,9 +73,9 @@ func (d *Dict) createEntity(id int) error {
return fmt.Errorf("unable to create entity %d: no class found for class name %s, version %d", className, classV) return fmt.Errorf("unable to create entity %d: no class found for class name %s, version %d", className, classV)
} }
Debug.Printf("create entity id: %d classId: %d className: %v class: %v\n", id, classId, className, class) Debug.Printf("create entity id: %d classId: %d className: %v class: %v\n", id, classId, className, class)
e := class.New() e := class.New(serial)
e.Read(d.br, d.sr) d.entities[id] = e
return nil return fillSlots(e, d.sr, d.br)
} }
func (d *Dict) getEntity(id int) *Entity { func (d *Dict) getEntity(id int) *Entity {
@ -83,7 +83,7 @@ func (d *Dict) getEntity(id int) *Entity {
Debug.Printf("edict refused getEntity request for invalid id %d", id) Debug.Printf("edict refused getEntity request for invalid id %d", id)
return nil return nil
} }
return &d.entities[id] return d.entities[id]
} }
func (d *Dict) updateEntity(id int) error { func (d *Dict) updateEntity(id int) error {
@ -92,7 +92,7 @@ func (d *Dict) updateEntity(id int) error {
if e == nil { if e == nil {
return fmt.Errorf("update entity %d refused: no such entity", id) return fmt.Errorf("update entity %d refused: no such entity", id)
} }
e.Read(d.br, d.sr) // e.Read(d.br, d.sr)
return nil return nil
} }
@ -101,7 +101,7 @@ func (d *Dict) deleteEntity(id int) error {
if id < 0 || id >= e_limit { if id < 0 || id >= e_limit {
return fmt.Errorf("delete entity %d refused: no such entity", id) return fmt.Errorf("delete entity %d refused: no such entity", id)
} }
d.entities[id] = Entity{} d.entities[id] = nil
return nil return nil
} }
@ -190,7 +190,7 @@ func (d *Dict) syncBaselines() {
} }
if c.baseline == nil { if c.baseline == nil {
c.baseline = c.New() c.baseline = c.New(-1)
} }
if e.Value == nil || len(e.Value) == 0 { if e.Value == nil || len(e.Value) == 0 {
@ -200,8 +200,8 @@ func (d *Dict) syncBaselines() {
d.br.SetSource(e.Value) d.br.SetSource(e.Value)
Debug.Printf("syncBaselines has new baseline for class %v", c) Debug.Printf("syncBaselines has new baseline for class %v", c)
if err := c.baseline.Read(d.br, d.sr); err != nil { if err := fillSlots(c.baseline, d.sr, d.br); err != nil {
Debug.Printf("syncBaselines failed to read a baseline: %v", err) Debug.Printf("syncBaselines failed to fill a baseline: %v", err)
continue continue
} }
} }

@ -1,47 +1,11 @@
package ent package ent
import (
"fmt"
"github.com/jordanorelli/hyperstone/bit"
)
type Entity struct { type Entity struct {
*Class *Class
serial int
slots []interface{} slots []interface{}
} }
func (e *Entity) Read(br bit.Reader, sr *selectionReader) error { func (e *Entity) getSlotValue(n int) interface{} { return e.slots[n] }
if e.Class == nil { func (e *Entity) setSlotValue(n int, v interface{}) { e.slots[n] = v }
return fmt.Errorf("unable to read entity: entity has no class") func (e *Entity) getSlotDecoder(n int) decoder { return e.Class.Fields[n].decoder }
}
Debug.Printf("entity %v read", e)
if err := sr.read(br, htree); err != nil {
return fmt.Errorf("unable to read entity: %v", err)
}
for _, s := range sr.selections() {
switch s.count {
case 0:
panic("field selection makes no sense")
case 1:
Debug.Printf("direct selection: %v", s.path())
field := e.Class.Fields[s.vals[0]]
Debug.Printf("field: %v", e.Class.Fields[s.vals[0]])
fn := field.decoder
if fn == nil {
Info.Fatalf("field has no decoder: %v", field)
}
v, err := fn(br), br.Err()
Debug.Printf("value: %v err: %v", v, err)
if err != nil {
Info.Fatalf("field decode error: %v", err)
}
default:
Debug.Printf("child selection: %v", s.path())
return fmt.Errorf("child selections aren't done yet")
}
}
return nil
}

@ -20,6 +20,9 @@ type Field struct {
class *Class // source class on which the field was originally defined class *Class // source class on which the field was originally defined
encoder *Symbol // binary encoder, named explicitly in protobuf encoder *Symbol // binary encoder, named explicitly in protobuf
decoder // decodes field values from a bit stream decoder // decodes field values from a bit stream
isTemplate bool // whether or not the field is a template type
templateType string
elemType string
} }
func (f Field) String() string { func (f Field) String() string {

@ -18,6 +18,31 @@ type selection struct {
func (s selection) path() []int { return s.vals[:s.count] } func (s selection) path() []int { return s.vals[:s.count] }
func (s selection) fill(dest slotted, br bit.Reader) error {
Debug.Printf("fill selection %v", s)
switch s.count {
case 0:
panic("selection makes no sense")
case 1:
fn := dest.getSlotDecoder(s.vals[0])
if fn == nil {
switch v := dest.(type) {
case *Entity:
Info.Fatalf("%v entity has no decoder for slot %d (%v)", v.Class, s.vals[0], v.Class.Fields[s.vals[0]])
default:
Info.Fatalf("slotted value %v has no decoder for slot %d", dest, s.vals[0])
}
}
val := fn(br)
old := dest.getSlotValue(s.vals[0])
dest.setSlotValue(s.vals[0], val)
Debug.Printf("%v -> %v", old, val)
return nil
default:
return fmt.Errorf("child selections aren't done yet")
}
}
// selectionReader reads a set of field selections off of the wire. the // selectionReader reads a set of field selections off of the wire. the
// selections are represented as arrays of slot positions to be traversed in // selections are represented as arrays of slot positions to be traversed in
// order to select an entity slot. // order to select an entity slot.
@ -33,25 +58,23 @@ type selectionReader struct {
all [1024]selection all [1024]selection
} }
func (r *selectionReader) read(br bit.Reader, n node) error { func (r *selectionReader) readSelections(br bit.Reader, n node) ([]selection, error) {
r.cur.count = 1 r.cur.count = 1
r.cur.vals[0] = -1 r.cur.vals[0] = -1
r.count = 0 r.count = 0
for fn := walk(n, br); fn != nil; fn = walk(n, br) { for fn := walk(n, br); fn != nil; fn = walk(n, br) {
if err := br.Err(); err != nil { if err := br.Err(); err != nil {
return fmt.Errorf("unable to read selection: bit reader error: %v", err) return nil, fmt.Errorf("unable to read selection: bit reader error: %v", err)
} }
fn(r, br) fn(r, br)
r.keep() r.keep()
} }
if err := br.Err(); err != nil { if err := br.Err(); err != nil {
return fmt.Errorf("unable to read selection: bit reader error: %v", err) return nil, fmt.Errorf("unable to read selection: bit reader error: %v", err)
} }
return nil return r.all[:r.count], nil
} }
func (r *selectionReader) selections() []selection { return r.all[:r.count] }
// adds i to the current selection // adds i to the current selection
func (r *selectionReader) add(i int) { func (r *selectionReader) add(i int) {
r.cur.vals[r.cur.count-1] += i r.cur.vals[r.cur.count-1] += i

@ -0,0 +1,25 @@
package ent
import (
"github.com/jordanorelli/hyperstone/bit"
)
type slotted interface {
getSlotValue(int) interface{}
setSlotValue(int, interface{})
getSlotDecoder(int) decoder
}
func fillSlots(dest slotted, sr *selectionReader, br bit.Reader) error {
selections, err := sr.readSelections(br, htree)
if err != nil {
return err
}
for _, s := range selections {
if err := s.fill(dest, br); err != nil {
return err
}
}
return nil
}
Loading…
Cancel
Save