unions, events and errors... oh my
This commit is contained in:
		@@ -9,6 +9,7 @@ type Field interface {
 | 
				
			|||||||
	Initialize(p *Protocol)
 | 
						Initialize(p *Protocol)
 | 
				
			||||||
	SrcName() string
 | 
						SrcName() string
 | 
				
			||||||
	XmlName() string
 | 
						XmlName() string
 | 
				
			||||||
 | 
						SrcType() string
 | 
				
			||||||
	Size() Size
 | 
						Size() Size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Define(c *Context)
 | 
						Define(c *Context)
 | 
				
			||||||
@@ -30,6 +31,10 @@ func (p *PadField) XmlName() string {
 | 
				
			|||||||
	panic("illegal to take XML name of a pad field")
 | 
						panic("illegal to take XML name of a pad field")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *PadField) SrcType() string {
 | 
				
			||||||
 | 
						panic("it is illegal to call SrcType on a SwitchField field")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *PadField) Size() Size {
 | 
					func (p *PadField) Size() Size {
 | 
				
			||||||
	return newFixedSize(p.Bytes)
 | 
						return newFixedSize(p.Bytes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -53,6 +58,10 @@ func (f *SingleField) XmlName() string {
 | 
				
			|||||||
	return f.xmlName
 | 
						return f.xmlName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *SingleField) SrcType() string {
 | 
				
			||||||
 | 
						return f.Type.SrcName()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SingleField) Size() Size {
 | 
					func (f *SingleField) Size() Size {
 | 
				
			||||||
	return f.Type.Size()
 | 
						return f.Type.Size()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -72,9 +81,9 @@ func (f *ListField) XmlName() string {
 | 
				
			|||||||
	return f.xmlName
 | 
						return f.xmlName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// func (f *ListField) Size() Size { 
 | 
					func (f *ListField) SrcType() string {
 | 
				
			||||||
	// return newExpressionSize(f.LengthExpr).Multiply(f.Type.Size()) 
 | 
						return fmt.Sprintf("[]%s", f.Type.SrcName())
 | 
				
			||||||
// } 
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ListField) Size() Size {
 | 
					func (f *ListField) Size() Size {
 | 
				
			||||||
	simpleLen := &Function{
 | 
						simpleLen := &Function{
 | 
				
			||||||
@@ -126,6 +135,10 @@ func (f *ExprField) XmlName() string {
 | 
				
			|||||||
	return f.xmlName
 | 
						return f.xmlName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *ExprField) SrcType() string {
 | 
				
			||||||
 | 
						return f.Type.SrcName()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ExprField) Size() Size {
 | 
					func (f *ExprField) Size() Size {
 | 
				
			||||||
	return f.Type.Size()
 | 
						return f.Type.Size()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -150,6 +163,10 @@ func (f *ValueField) XmlName() string {
 | 
				
			|||||||
	panic("it is illegal to call XmlName on a ValueField field")
 | 
						panic("it is illegal to call XmlName on a ValueField field")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *ValueField) SrcType() string {
 | 
				
			||||||
 | 
						return f.MaskType.SrcName()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ValueField) Size() Size {
 | 
					func (f *ValueField) Size() Size {
 | 
				
			||||||
	return f.MaskType.Size()
 | 
						return f.MaskType.Size()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -174,6 +191,10 @@ func (f *SwitchField) XmlName() string {
 | 
				
			|||||||
	panic("it is illegal to call XmlName on a SwitchField field")
 | 
						panic("it is illegal to call XmlName on a SwitchField field")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *SwitchField) SrcType() string {
 | 
				
			||||||
 | 
						panic("it is illegal to call SrcType on a SwitchField field")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// XXX: This is a bit tricky. The size has to be represented as a non-concrete
 | 
					// XXX: This is a bit tricky. The size has to be represented as a non-concrete
 | 
				
			||||||
// expression that finds *which* bitcase fields are included, and sums the
 | 
					// expression that finds *which* bitcase fields are included, and sums the
 | 
				
			||||||
// sizes of those fields.
 | 
					// sizes of those fields.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,18 +22,36 @@ func (e *ErrorCopy) Define(c *Context) {
 | 
				
			|||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	c.Putln("type %s %s", e.ErrType(), e.Old.(*Error).ErrType())
 | 
						c.Putln("type %s %s", e.ErrType(), e.Old.(*Error).ErrType())
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType())
 | 
					
 | 
				
			||||||
	c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName())
 | 
						// Read defines a function that transforms a byte slice into this
 | 
				
			||||||
	c.Putln("}")
 | 
						// error struct.
 | 
				
			||||||
	c.Putln("")
 | 
						e.Read(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write defines a function that transoforms this error struct into
 | 
				
			||||||
 | 
						// a byte slice.
 | 
				
			||||||
 | 
						e.Write(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Makes sure that this error type is an Error interface.
 | 
				
			||||||
	c.Putln("func (err %s) ImplementsError() { }", e.ErrType())
 | 
						c.Putln("func (err %s) ImplementsError() { }", e.ErrType())
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	c.Putln("func (err %s) Bytes() []byte {", e.ErrType())
 | 
					
 | 
				
			||||||
	c.Putln("return (%s)(err).Bytes()", e.Old.(*Error).ErrType())
 | 
						// Let's the XGB know how to read this error.
 | 
				
			||||||
	c.Putln("}")
 | 
					 | 
				
			||||||
	c.Putln("")
 | 
					 | 
				
			||||||
	c.Putln("func init() {")
 | 
						c.Putln("func init() {")
 | 
				
			||||||
	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.SrcName())
 | 
						c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.SrcName())
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *ErrorCopy) Read(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType())
 | 
				
			||||||
 | 
						c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *ErrorCopy) Write(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("func (err %s) Bytes() []byte {", e.ErrType())
 | 
				
			||||||
 | 
						c.Putln("return (%s)(err).Bytes()", e.Old.(*Error).ErrType())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,14 +3,75 @@ package main
 | 
				
			|||||||
// Event types
 | 
					// Event types
 | 
				
			||||||
func (e *Event) Define(c *Context) {
 | 
					func (e *Event) Define(c *Context) {
 | 
				
			||||||
	c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number)
 | 
						c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number)
 | 
				
			||||||
 | 
						c.Putln("// Size: %s", e.Size())
 | 
				
			||||||
 | 
						c.Putln("type %s struct {", e.EvType())
 | 
				
			||||||
 | 
						c.Putln("Sequence uint16")
 | 
				
			||||||
 | 
						for _, field := range e.Fields {
 | 
				
			||||||
 | 
							field.Define(c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read defines a function that transforms a byte slice into this
 | 
				
			||||||
 | 
						// event struct.
 | 
				
			||||||
 | 
						e.Read(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write defines a function that transoforms this event struct into
 | 
				
			||||||
 | 
						// a byte slice.
 | 
				
			||||||
 | 
						e.Write(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Makes sure that this event type is an Event interface.
 | 
				
			||||||
 | 
						c.Putln("func (v %s) ImplementsEvent() { }", e.EvType())
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Let's the XGB event loop read this event.
 | 
				
			||||||
 | 
						c.Putln("func init() {")
 | 
				
			||||||
 | 
						c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *Event) Read(c *Context, prefix string) {
 | 
					func (e *Event) Read(c *Context) {
 | 
				
			||||||
	c.Putln("// Event read %s", e.SrcName())
 | 
						c.Putln("// Event read %s", e.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType())
 | 
				
			||||||
 | 
						c.Putln("v := %s{}", e.EvType())
 | 
				
			||||||
 | 
						c.Putln("b := 1 // don't read event number")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
						for i, field := range e.Fields {
 | 
				
			||||||
 | 
							if i == 1 && !e.NoSequence {
 | 
				
			||||||
 | 
								c.Putln("v.Sequence = get16(buf[b:])")
 | 
				
			||||||
 | 
								c.Putln("b += 2")
 | 
				
			||||||
 | 
								c.Putln("")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							field.Read(c)
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Putln("return v")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *Event) Write(c *Context, prefix string) {
 | 
					func (e *Event) Write(c *Context) {
 | 
				
			||||||
	c.Putln("// Event write %s", e.SrcName())
 | 
						c.Putln("// Event write %s", e.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func (v %s) Bytes() []byte {", e.EvType())
 | 
				
			||||||
 | 
						c.Putln("buf := make([]byte, %s)", e.Size())
 | 
				
			||||||
 | 
						c.Putln("b := 0")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
						c.Putln("// write event number")
 | 
				
			||||||
 | 
						c.Putln("buf[b] = %d", e.Number)
 | 
				
			||||||
 | 
						c.Putln("b += 1")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
						for i, field := range e.Fields {
 | 
				
			||||||
 | 
							if i == 1 && !e.NoSequence {
 | 
				
			||||||
 | 
								c.Putln("b += 2 // skip sequence number")
 | 
				
			||||||
 | 
								c.Putln("")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							field.Write(c)
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Putln("return buf")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EventCopy types
 | 
					// EventCopy types
 | 
				
			||||||
@@ -21,18 +82,36 @@ func (e *EventCopy) Define(c *Context) {
 | 
				
			|||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType())
 | 
						c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType())
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType())
 | 
					
 | 
				
			||||||
	c.Putln("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName())
 | 
						// Read defines a function that transforms a byte slice into this
 | 
				
			||||||
	c.Putln("}")
 | 
						// event struct.
 | 
				
			||||||
	c.Putln("")
 | 
						e.Read(c)
 | 
				
			||||||
	c.Putln("func (ev %s) ImplementsEvent() { }", e.EvType())
 | 
					
 | 
				
			||||||
	c.Putln("")
 | 
						// Write defines a function that transoforms this event struct into
 | 
				
			||||||
	c.Putln("func (ev %s) Bytes() []byte {", e.EvType())
 | 
						// a byte slice.
 | 
				
			||||||
	c.Putln("return (%s)(ev).Bytes()", e.Old.(*Event).EvType())
 | 
						e.Write(c)
 | 
				
			||||||
	c.Putln("}")
 | 
					
 | 
				
			||||||
 | 
						// Makes sure that this event type is an Event interface.
 | 
				
			||||||
 | 
						c.Putln("func (v %s) ImplementsEvent() { }", e.EvType())
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Let's the XGB event loop read this event.
 | 
				
			||||||
	c.Putln("func init() {")
 | 
						c.Putln("func init() {")
 | 
				
			||||||
	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName())
 | 
						c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName())
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EventCopy) Read(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType())
 | 
				
			||||||
 | 
						c.Putln("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EventCopy) Write(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("func (v %s) Bytes() []byte {", e.EvType())
 | 
				
			||||||
 | 
						c.Putln("return (%s)(ev).Bytes()", e.Old.(*Event).EvType())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,6 @@ func (f *ListField) Define(c *Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ListField) Read(c *Context) {
 | 
					func (f *ListField) Read(c *Context) {
 | 
				
			||||||
	c.Putln("")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch t := f.Type.(type) {
 | 
						switch t := f.Type.(type) {
 | 
				
			||||||
	case *Resource:
 | 
						case *Resource:
 | 
				
			||||||
		length := f.LengthExpr.Reduce("v.", "")
 | 
							length := f.LengthExpr.Reduce("v.", "")
 | 
				
			||||||
@@ -34,6 +32,10 @@ func (f *ListField) Read(c *Context) {
 | 
				
			|||||||
			c.Putln("}")
 | 
								c.Putln("}")
 | 
				
			||||||
			c.Putln("b = pad(b)")
 | 
								c.Putln("b = pad(b)")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						case *Union:
 | 
				
			||||||
 | 
							c.Putln("v.%s = make([]%s, %s)",
 | 
				
			||||||
 | 
								f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", ""))
 | 
				
			||||||
 | 
							c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 | 
				
			||||||
	case *Struct:
 | 
						case *Struct:
 | 
				
			||||||
		c.Putln("v.%s = make([]%s, %s)",
 | 
							c.Putln("v.%s = make([]%s, %s)",
 | 
				
			||||||
			f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", ""))
 | 
								f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", ""))
 | 
				
			||||||
@@ -45,8 +47,6 @@ func (f *ListField) Read(c *Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ListField) Write(c *Context) {
 | 
					func (f *ListField) Write(c *Context) {
 | 
				
			||||||
	c.Putln("")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch t := f.Type.(type) {
 | 
						switch t := f.Type.(type) {
 | 
				
			||||||
	case *Resource:
 | 
						case *Resource:
 | 
				
			||||||
		length := f.LengthExpr.Reduce("v.", "")
 | 
							length := f.LengthExpr.Reduce("v.", "")
 | 
				
			||||||
@@ -65,6 +65,8 @@ func (f *ListField) Write(c *Context) {
 | 
				
			|||||||
			c.Putln("}")
 | 
								c.Putln("}")
 | 
				
			||||||
			c.Putln("b = pad(b)")
 | 
								c.Putln("b = pad(b)")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						case *Union:
 | 
				
			||||||
 | 
							c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 | 
				
			||||||
	case *Struct:
 | 
						case *Struct:
 | 
				
			||||||
		c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 | 
							c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,16 @@ func ReadSimpleSingleField(c *Context, name string, typ Type) {
 | 
				
			|||||||
			c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName())
 | 
								c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case *Base:
 | 
						case *Base:
 | 
				
			||||||
 | 
							// If this is a bool, stop short and do something special.
 | 
				
			||||||
 | 
							if t.SrcName() == "bool" {
 | 
				
			||||||
 | 
								c.Putln("if buf[b] == 1 {")
 | 
				
			||||||
 | 
								c.Putln("%s = true", name)
 | 
				
			||||||
 | 
								c.Putln("} else {")
 | 
				
			||||||
 | 
								c.Putln("%s = false", name)
 | 
				
			||||||
 | 
								c.Putln("}")
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var val string
 | 
							var val string
 | 
				
			||||||
		switch t.Size().Eval() {
 | 
							switch t.Size().Eval() {
 | 
				
			||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
@@ -44,7 +54,7 @@ func ReadSimpleSingleField(c *Context, name string, typ Type) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		c.Putln("%s = %s", name, val)
 | 
							c.Putln("%s = %s", name, val)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		log.Fatalf("Cannot read field '%s' as a simple field with %T type.",
 | 
							log.Panicf("Cannot read field '%s' as a simple field with %T type.",
 | 
				
			||||||
			name, typ)
 | 
								name, typ)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,9 +72,11 @@ func (f *SingleField) Read(c *Context) {
 | 
				
			|||||||
	case *Struct:
 | 
						case *Struct:
 | 
				
			||||||
		c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName())
 | 
							c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName())
 | 
				
			||||||
		c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName())
 | 
							c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName())
 | 
				
			||||||
		c.Putln("")
 | 
						case *Union:
 | 
				
			||||||
 | 
							c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName())
 | 
				
			||||||
 | 
							c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName())
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
 | 
							log.Panicf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,6 +96,16 @@ func WriteSimpleSingleField(c *Context, name string, typ Type) {
 | 
				
			|||||||
			c.Putln("put64(buf[b:], uint64(%s))", name)
 | 
								c.Putln("put64(buf[b:], uint64(%s))", name)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case *Base:
 | 
						case *Base:
 | 
				
			||||||
 | 
							// If this is a bool, stop short and do something special.
 | 
				
			||||||
 | 
							if t.SrcName() == "bool" {
 | 
				
			||||||
 | 
								c.Putln("if %s {", name)
 | 
				
			||||||
 | 
								c.Putln("buf[b] = 1")
 | 
				
			||||||
 | 
								c.Putln("} else {")
 | 
				
			||||||
 | 
								c.Putln("buf[b] = 0")
 | 
				
			||||||
 | 
								c.Putln("}")
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch t.Size().Eval() {
 | 
							switch t.Size().Eval() {
 | 
				
			||||||
		case 1:
 | 
							case 1:
 | 
				
			||||||
			if t.SrcName() != "byte" {
 | 
								if t.SrcName() != "byte" {
 | 
				
			||||||
@@ -126,11 +148,17 @@ func (f *SingleField) Write(c *Context) {
 | 
				
			|||||||
		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t)
 | 
							ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t)
 | 
				
			||||||
	case *Base:
 | 
						case *Base:
 | 
				
			||||||
		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t)
 | 
							ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t)
 | 
				
			||||||
 | 
						case *Union:
 | 
				
			||||||
 | 
							c.Putln("{")
 | 
				
			||||||
 | 
							c.Putln("unionBytes := v.%s.Bytes()", f.SrcName())
 | 
				
			||||||
 | 
							c.Putln("copy(buf[b:], unionBytes)")
 | 
				
			||||||
 | 
							c.Putln("b += pad(len(unionBytes))")
 | 
				
			||||||
 | 
							c.Putln("}")
 | 
				
			||||||
	case *Struct:
 | 
						case *Struct:
 | 
				
			||||||
		c.Putln("{")
 | 
							c.Putln("{")
 | 
				
			||||||
		c.Putln("structBytes := v.%s.Bytes()", f.SrcName())
 | 
							c.Putln("structBytes := v.%s.Bytes()", f.SrcName())
 | 
				
			||||||
		c.Putln("copy(buf[b:], structBytes)")
 | 
							c.Putln("copy(buf[b:], structBytes)")
 | 
				
			||||||
		c.Putln("b += len(structBytes)")
 | 
							c.Putln("b += pad(len(structBytes))")
 | 
				
			||||||
		c.Putln("}")
 | 
							c.Putln("}")
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
 | 
							log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ func (s *Struct) Define(c *Context) {
 | 
				
			|||||||
	// Write function that reads bytes and produces this struct.
 | 
						// Write function that reads bytes and produces this struct.
 | 
				
			||||||
	s.Read(c)
 | 
						s.Read(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Write function that reads a list of this structs.
 | 
						// Write function that reads bytes and produces a list of this struct.
 | 
				
			||||||
	s.ReadList(c)
 | 
						s.ReadList(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Write function that writes bytes given this struct.
 | 
						// Write function that writes bytes given this struct.
 | 
				
			||||||
@@ -68,7 +68,7 @@ func (s *Struct) ReadList(c *Context) {
 | 
				
			|||||||
func (s *Struct) Write(c *Context) {
 | 
					func (s *Struct) Write(c *Context) {
 | 
				
			||||||
	c.Putln("// Struct write %s", s.SrcName())
 | 
						c.Putln("// Struct write %s", s.SrcName())
 | 
				
			||||||
	c.Putln("func (v %s) Bytes() []byte {", s.SrcName())
 | 
						c.Putln("func (v %s) Bytes() []byte {", s.SrcName())
 | 
				
			||||||
	c.Putln("buf := make([]byte, %s)", s.Size().Reduce("s.", ""))
 | 
						c.Putln("buf := make([]byte, %s)", s.Size().Reduce("v.", ""))
 | 
				
			||||||
	c.Putln("b := 0")
 | 
						c.Putln("b := 0")
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
	for _, field := range s.Fields {
 | 
						for _, field := range s.Fields {
 | 
				
			||||||
@@ -88,10 +88,11 @@ func (s *Struct) WriteList(c *Context) {
 | 
				
			|||||||
	c.Putln("for _, item := range list {")
 | 
						c.Putln("for _, item := range list {")
 | 
				
			||||||
	c.Putln("structBytes = item.Bytes()")
 | 
						c.Putln("structBytes = item.Bytes()")
 | 
				
			||||||
	c.Putln("copy(buf[b:], len(structBytes))")
 | 
						c.Putln("copy(buf[b:], len(structBytes))")
 | 
				
			||||||
	c.Putln("b += len(structBytes)")
 | 
						c.Putln("b += pad(len(structBytes))")
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("return b")
 | 
						c.Putln("return b")
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Struct) WriteListSize(c *Context) {
 | 
					func (s *Struct) WriteListSize(c *Context) {
 | 
				
			||||||
@@ -101,7 +102,7 @@ func (s *Struct) WriteListSize(c *Context) {
 | 
				
			|||||||
	c.Putln("for _, item := range list {")
 | 
						c.Putln("for _, item := range list {")
 | 
				
			||||||
	c.Putln("size += %s", s.Size().Reduce("item.", ""))
 | 
						c.Putln("size += %s", s.Size().Reduce("item.", ""))
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("return pad(size)")
 | 
						c.Putln("return size")
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,13 +3,143 @@ package main
 | 
				
			|||||||
// Union types
 | 
					// Union types
 | 
				
			||||||
func (u *Union) Define(c *Context) {
 | 
					func (u *Union) Define(c *Context) {
 | 
				
			||||||
	c.Putln("// Union definition %s", u.SrcName())
 | 
						c.Putln("// Union definition %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("// Note that to *create* a Union, you should *never* create")
 | 
				
			||||||
 | 
						c.Putln("// this struct directly (unless you know what you're doing).")
 | 
				
			||||||
 | 
						c.Putln("// Instead use one of the following constructors for '%s':",
 | 
				
			||||||
 | 
							u.SrcName())
 | 
				
			||||||
 | 
						for _, field := range u.Fields {
 | 
				
			||||||
 | 
							c.Putln("//     New%s%s(%s %s) %s", u.SrcName(), field.SrcName(),
 | 
				
			||||||
 | 
								field.SrcName(), field.SrcType(), u.SrcName())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Putln("type %s struct {", u.SrcName())
 | 
				
			||||||
 | 
						for _, field := range u.Fields {
 | 
				
			||||||
 | 
							field.Define(c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write functions for each field that create instances of this
 | 
				
			||||||
 | 
						// union using the corresponding field.
 | 
				
			||||||
 | 
						u.New(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write function that reads bytes and produces this union.
 | 
				
			||||||
 | 
						u.Read(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write function that reads bytes and produces a list of this union.
 | 
				
			||||||
 | 
						u.ReadList(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write function that writes bytes given this union.
 | 
				
			||||||
 | 
						u.Write(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write function that writes a list of this union.
 | 
				
			||||||
 | 
						u.WriteList(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write function that computes the size of a list of these unions.
 | 
				
			||||||
 | 
						u.WriteListSize(c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *Union) Read(c *Context, prefix string) {
 | 
					func (u *Union) New(c *Context) {
 | 
				
			||||||
 | 
						for _, field := range u.Fields {
 | 
				
			||||||
 | 
							c.Putln("// Union constructor for %s for field %s.",
 | 
				
			||||||
 | 
								u.SrcName(), field.SrcName())
 | 
				
			||||||
 | 
							c.Putln("func New%s%s(%s %s) %s {",
 | 
				
			||||||
 | 
								u.SrcName(), field.SrcName(), field.SrcName(),
 | 
				
			||||||
 | 
								field.SrcType(), u.SrcName())
 | 
				
			||||||
 | 
							c.Putln("var b int")
 | 
				
			||||||
 | 
							c.Putln("buf := make([]byte, %s)", u.Size())
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
							field.Write(c)
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
							c.Putln("// Create the Union type")
 | 
				
			||||||
 | 
							c.Putln("v := %s{}", u.SrcName())
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
							c.Putln("// Now copy buf into all fields")
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
							for _, field2 := range u.Fields {
 | 
				
			||||||
 | 
								c.Putln("b = 0 // always read the same bytes")
 | 
				
			||||||
 | 
								field2.Read(c)
 | 
				
			||||||
 | 
								c.Putln("")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.Putln("return v")
 | 
				
			||||||
 | 
							c.Putln("}")
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (u *Union) Read(c *Context) {
 | 
				
			||||||
	c.Putln("// Union read %s", u.SrcName())
 | 
						c.Putln("// Union read %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func Read%s(buf []byte, v *%s) int {", u.SrcName(), u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("var b int")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
						for _, field := range u.Fields {
 | 
				
			||||||
 | 
							c.Putln("b = 0 // re-read the same bytes")
 | 
				
			||||||
 | 
							field.Read(c)
 | 
				
			||||||
 | 
							c.Putln("")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Putln("return %s", u.Size())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *Union) Write(c *Context, prefix string) {
 | 
					func (u *Union) ReadList(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("// Union list read %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func Read%sList(buf []byte, dest []%s) int {",
 | 
				
			||||||
 | 
							u.SrcName(), u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("b := 0")
 | 
				
			||||||
 | 
						c.Putln("for i := 0; i < len(dest); i++ {")
 | 
				
			||||||
 | 
						c.Putln("dest[i] = %s{}", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("b += Read%s(buf[b:], &dest[i])", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("return pad(b)")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a bit tricky since writing from a Union implies that only
 | 
				
			||||||
 | 
					// the data inside ONE of the elements is actually written.
 | 
				
			||||||
 | 
					// However, we only currently support unions where every field has the
 | 
				
			||||||
 | 
					// *same* *fixed* size. Thus, we make sure to always read bytes into
 | 
				
			||||||
 | 
					// every field which allows us to simply pick the first field and write it.
 | 
				
			||||||
 | 
					func (u *Union) Write(c *Context) {
 | 
				
			||||||
	c.Putln("// Union write %s", u.SrcName())
 | 
						c.Putln("// Union write %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("// Each field in a union must contain the same data.")
 | 
				
			||||||
 | 
						c.Putln("// So simply pick the first field and write that to the wire.")
 | 
				
			||||||
 | 
						c.Putln("func (v %s) Bytes() []byte {", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("buf := make([]byte, %s)", u.Size().Reduce("v.", ""))
 | 
				
			||||||
 | 
						c.Putln("b := 0")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
						u.Fields[0].Write(c)
 | 
				
			||||||
 | 
						c.Putln("return buf")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (u *Union) WriteList(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("// Union list write %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func %sListBytes(buf []byte, list []%s) int {",
 | 
				
			||||||
 | 
							u.SrcName(), u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("b := 0")
 | 
				
			||||||
 | 
						c.Putln("var unionBytes []byte")
 | 
				
			||||||
 | 
						c.Putln("for _, item := range list {")
 | 
				
			||||||
 | 
						c.Putln("unionBytes = item.Bytes()")
 | 
				
			||||||
 | 
						c.Putln("copy(buf[b:], len(unionBytes))")
 | 
				
			||||||
 | 
						c.Putln("b += pad(len(unionBytes))")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("return b")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (u *Union) WriteListSize(c *Context) {
 | 
				
			||||||
 | 
						c.Putln("// Union list size %s", u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("func %sListSize(list []%s) int {", u.SrcName(), u.SrcName())
 | 
				
			||||||
 | 
						c.Putln("size := 0")
 | 
				
			||||||
 | 
						c.Putln("for _, item := range list {")
 | 
				
			||||||
 | 
						c.Putln("size += %s", u.Size().Reduce("item.", ""))
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("return size")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -191,7 +191,7 @@ func (e *Event) XmlName() string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *Event) Size() Size {
 | 
					func (e *Event) Size() Size {
 | 
				
			||||||
	panic("Cannot take size of Event type.")
 | 
						return newExpressionSize(&Value{v: 32})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *Event) Initialize(p *Protocol) {
 | 
					func (e *Event) Initialize(p *Protocol) {
 | 
				
			||||||
@@ -358,7 +358,7 @@ func (u *Union) Size() Size {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *Union) Initialize(p *Protocol) {
 | 
					func (u *Union) Initialize(p *Protocol) {
 | 
				
			||||||
	u.srcName = TypeSrcName(p, u)
 | 
						u.srcName = fmt.Sprintf("%sUnion", TypeSrcName(p, u))
 | 
				
			||||||
	for _, field := range u.Fields {
 | 
						for _, field := range u.Fields {
 | 
				
			||||||
		field.Initialize(p)
 | 
							field.Initialize(p)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user