package main import ( "fmt" "log" ) func (f *SingleField) Define(c *Context) { c.Putln("%s %s", f.SrcName(), f.Type.SrcName()) } func ReadSimpleSingleField(c *Context, name string, typ Type) { switch t := typ.(type) { case *Resource: c.Putln("%s = get32(buf[b:])", name) case *TypeDef: switch t.Size().Eval() { case 1: c.Putln("%s = %s(buf[b])", name, t.SrcName()) case 2: c.Putln("%s = %s(get16(buf[b:]))", name, t.SrcName()) case 4: c.Putln("%s = %s(get32(buf[b:]))", name, t.SrcName()) case 8: c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName()) } 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 switch t.Size().Eval() { case 1: val = fmt.Sprintf("buf[b]") case 2: val = fmt.Sprintf("get16(buf[b:])") case 4: val = fmt.Sprintf("get32(buf[b:])") case 8: val = fmt.Sprintf("get64(buf[b:])") } // We need to convert base types if they aren't uintXX or byte ty := t.SrcName() if ty != "byte" && ty != "uint16" && ty != "uint32" && ty != "uint64" { val = fmt.Sprintf("%s(%s)", ty, val) } c.Putln("%s = %s", name, val) default: log.Panicf("Cannot read field '%s' as a simple field with %T type.", name, typ) } c.Putln("b += %s", typ.Size()) } func (f *SingleField) Read(c *Context) { switch t := f.Type.(type) { case *Resource: ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) case *TypeDef: ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) case *Base: ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) case *Struct: c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName()) c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName()) 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: log.Panicf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) } } func WriteSimpleSingleField(c *Context, name string, typ Type) { switch t := typ.(type) { case *Resource: c.Putln("put32(buf[b:], uint32(%s))", name) case *TypeDef: switch t.Size().Eval() { case 1: c.Putln("buf[b] = byte(%s)", name) case 2: c.Putln("put16(buf[b:], uint16(%s))", name) case 4: c.Putln("put32(buf[b:], uint32(%s))", name) case 8: c.Putln("put64(buf[b:], uint64(%s))", name) } 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() { case 1: if t.SrcName() != "byte" { c.Putln("buf[b] = byte(%s)", name) } else { c.Putln("buf[b] = %s", name) } case 2: if t.SrcName() != "uint16" { c.Putln("put16(buf[b:], uint16(%s))", name) } else { c.Putln("put16(buf[b:], %s)", name) } case 4: if t.SrcName() != "uint32" { c.Putln("put32(buf[b:], uint32(%s))", name) } else { c.Putln("put32(buf[b:], %s)", name) } case 8: if t.SrcName() != "uint64" { c.Putln("put64(buf[b:], uint64(%s))", name) } else { c.Putln("put64(buf[b:], %s)", name) } } default: log.Fatalf("Cannot read field '%s' as a simple field with %T type.", name, typ) } c.Putln("b += %s", typ.Size()) } func (f *SingleField) Write(c *Context) { switch t := f.Type.(type) { case *Resource: ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) case *TypeDef: ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) case *Base: 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: c.Putln("{") c.Putln("structBytes := v.%s.Bytes()", f.SrcName()) c.Putln("copy(buf[b:], structBytes)") c.Putln("b += pad(len(structBytes))") c.Putln("}") default: log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) } }