pax_global_header00006660000000000000000000000064126765305670014533gustar00rootroot0000000000000052 comment=f9b9f8f7aa27725f5cabb699bd9099ca7ce09143 xdr-2.0.1/000077500000000000000000000000001267653056700123305ustar00rootroot00000000000000xdr-2.0.1/.gitignore000066400000000000000000000000151267653056700143140ustar00rootroot00000000000000coverage.out xdr-2.0.1/.travis.yml000066400000000000000000000010161267653056700144370ustar00rootroot00000000000000language: go go: - tip install: - export PATH=$PATH:$HOME/gopath/bin - go get golang.org/x/tools/cover - go get github.com/mattn/goveralls script: - ./generate.sh - go test -coverprofile=coverage.out after_success: - goveralls -coverprofile=coverage.out -service=travis-ci -package=calmh/xdr -repotoken="$COVERALLS_TOKEN" env: global: secure: SmgnrGfp2zLrA44ChRMpjPeujubt9veZ8Fx/OseMWECmacyV5N/TuDhzIbwo6QwV4xB0sBacoPzvxQbJRVjNKsPiSu72UbcQmQ7flN4Tf7nW09tSh1iW8NgrpBCq/3UYLoBu2iPBEBKm93IK0aGNAKs6oEkB0fU27iTVBwiTXOY= xdr-2.0.1/LICENSE000066400000000000000000000020431267653056700133340ustar00rootroot00000000000000Copyright (C) 2014 Jakob Borg. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. xdr-2.0.1/README.md000066400000000000000000000011211267653056700136020ustar00rootroot00000000000000xdr === [![Build Status](https://img.shields.io/circleci/project/calmh/xdr.svg?style=flat-square)](https://circleci.com/gh/calmh/xdr) [![Coverage Status](https://img.shields.io/coveralls/calmh/xdr.svg?style=flat)](https://coveralls.io/r/calmh/xdr?branch=master) [![API Documentation](http://img.shields.io/badge/api-Godoc-blue.svg?style=flat)](http://godoc.org/github.com/calmh/xdr) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://opensource.org/licenses/MIT) This is an XDR marshalling/unmarshalling library. It uses code generation and not reflection. xdr-2.0.1/bench_test.go000066400000000000000000000020221267653056700147710ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. package xdr_test import "testing" type XDRBenchStruct struct { I1 uint64 I2 uint32 I3 uint16 I4 uint8 Bs0 []byte // max:128 Bs1 []byte Is0 []int32 S0 string // max:128 S1 string } var res []byte // not to be optimized away var s = XDRBenchStruct{ I1: 42, I2: 43, I3: 44, I4: 45, Bs0: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, Bs1: []byte{11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, Is0: []int32{23, 43}, S0: "Hello World! String one.", S1: "Hello World! String two.", } func BenchmarkThisMarshal(b *testing.B) { for i := 0; i < b.N; i++ { res, _ = s.MarshalXDR() } b.ReportAllocs() } func BenchmarkThisUnmarshal(b *testing.B) { bs := s.MustMarshalXDR() var t XDRBenchStruct for i := 0; i < b.N; i++ { err := t.UnmarshalXDR(bs) if err != nil { b.Fatal(err) } } b.ReportAllocs() } xdr-2.0.1/bench_xdr_test.go000066400000000000000000000110261267653056700156520ustar00rootroot00000000000000// ************************************************************ // This file is automatically generated by genxdr. Do not edit. // ************************************************************ package xdr_test import ( "github.com/calmh/xdr" ) /* XDRBenchStruct Structure: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + I1 (64 bits) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | I2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 16 zero bits | I3 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 24 zero bits | I4 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ Bs0 (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ Bs1 (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number of Is0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / | Is0 (n items) | / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ S0 (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ S1 (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct XDRBenchStruct { unsigned hyper I1; unsigned int I2; unsigned int I3; unsigned int I4; opaque Bs0<128>; opaque Bs1<>; int Is0<>; string S0<128>; string S1<>; } */ func (o XDRBenchStruct) XDRSize() int { return 8 + 4 + 4 + 4 + 4 + len(o.Bs0) + xdr.Padding(len(o.Bs0)) + 4 + len(o.Bs1) + xdr.Padding(len(o.Bs1)) + 4 + len(o.Is0)*4 + 4 + len(o.S0) + xdr.Padding(len(o.S0)) + 4 + len(o.S1) + xdr.Padding(len(o.S1)) } func (o XDRBenchStruct) MarshalXDR() ([]byte, error) { buf := make([]byte, o.XDRSize()) m := &xdr.Marshaller{Data: buf} return buf, o.MarshalXDRInto(m) } func (o XDRBenchStruct) MustMarshalXDR() []byte { bs, err := o.MarshalXDR() if err != nil { panic(err) } return bs } func (o XDRBenchStruct) MarshalXDRInto(m *xdr.Marshaller) error { m.MarshalUint64(o.I1) m.MarshalUint32(o.I2) m.MarshalUint16(o.I3) m.MarshalUint8(o.I4) if l := len(o.Bs0); l > 128 { return xdr.ElementSizeExceeded("Bs0", l, 128) } m.MarshalBytes(o.Bs0) m.MarshalBytes(o.Bs1) m.MarshalUint32(uint32(len(o.Is0))) for i := range o.Is0 { m.MarshalUint32(uint32(o.Is0[i])) } if l := len(o.S0); l > 128 { return xdr.ElementSizeExceeded("S0", l, 128) } m.MarshalString(o.S0) m.MarshalString(o.S1) return m.Error } func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error { u := &xdr.Unmarshaller{Data: bs} return o.UnmarshalXDRFrom(u) } func (o *XDRBenchStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { o.I1 = u.UnmarshalUint64() o.I2 = u.UnmarshalUint32() o.I3 = u.UnmarshalUint16() o.I4 = u.UnmarshalUint8() o.Bs0 = u.UnmarshalBytesMax(128) o.Bs1 = u.UnmarshalBytes() _Is0Size := int(u.UnmarshalUint32()) if _Is0Size < 0 { return xdr.ElementSizeExceeded("Is0", _Is0Size, 0) } else if _Is0Size == 0 { o.Is0 = nil } else { if _Is0Size <= len(o.Is0) { o.Is0 = o.Is0[:_Is0Size] } else { o.Is0 = make([]int32, _Is0Size) } for i := range o.Is0 { o.Is0[i] = int32(u.UnmarshalUint32()) } } o.S0 = u.UnmarshalStringMax(128) o.S1 = u.UnmarshalString() return u.Error } xdr-2.0.1/circle.yml000066400000000000000000000000541267653056700143130ustar00rootroot00000000000000dependencies: post: - ./generate.sh xdr-2.0.1/cmd/000077500000000000000000000000001267653056700130735ustar00rootroot00000000000000xdr-2.0.1/cmd/genxdr/000077500000000000000000000000001267653056700143625ustar00rootroot00000000000000xdr-2.0.1/cmd/genxdr/main.go000066400000000000000000000325061267653056700156430ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. package main import ( "bytes" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" "io" "log" "os" "regexp" "strconv" "strings" "text/template" ) type fieldInfo struct { Name string IsBasic bool // handled by one the native Read/WriteUint64 etc functions IsSlice bool // field is a slice of FieldType FieldType string // original type of field, i.e. "int" Encoder string // the encoder name, i.e. "Uint64" for Read/WriteUint64 Convert string // what to convert to when encoding, i.e. "uint64" Max int // max size for slices and strings Submax int // max size for strings inside slices } type structInfo struct { Name string Fields []fieldInfo } func (i structInfo) SizeExpr() string { var xdrSizes = map[string]int{ "int8": 4, "uint8": 4, "int16": 4, "uint16": 4, "int32": 4, "uint32": 4, "int64": 8, "uint64": 8, "int": 8, "bool": 4, } var terms []string nl := "" for _, f := range i.Fields { if size := xdrSizes[f.FieldType]; size > 0 { if f.IsSlice { terms = append(terms, nl+"4+len(o."+f.Name+")*"+strconv.Itoa(size)) } else { terms = append(terms, strconv.Itoa(size)) } } else { switch f.FieldType { case "string", "[]byte": if f.IsSlice { terms = append(terms, nl+"4+xdr.SizeOfSlice(o."+f.Name+")") } else { terms = append(terms, nl+"4+len(o."+f.Name+")+xdr.Padding(len(o."+f.Name+"))") } default: if f.IsSlice { terms = append(terms, nl+"4+xdr.SizeOfSlice(o."+f.Name+")") } else { terms = append(terms, nl+"o."+f.Name+".XDRSize()") } } } nl = "\n" } return strings.Join(terms, "+") } var headerData = `// ************************************************************ // This file is automatically generated by genxdr. Do not edit. // ************************************************************ package {{.Package}} import ( "github.com/calmh/xdr" ) ` var encoderData = ` func (o {{.Name}}) XDRSize() int { return {{.SizeExpr}} }//+n func (o {{.Name}}) MarshalXDR() ([]byte, error) { buf:= make([]byte, o.XDRSize()) m := &xdr.Marshaller{Data: buf} return buf, o.MarshalXDRInto(m) }//+n func (o {{.Name}}) MustMarshalXDR() []byte { bs, err := o.MarshalXDR() if err != nil { panic(err) } return bs }//+n func (o {{.Name}}) MarshalXDRInto(m *xdr.Marshaller) error { {{range $fi := .Fields}} {{if $fi.IsSlice}} {{template "marshalSlice" $fi}} {{else}} {{template "marshalValue" $fi}} {{end}} {{end}} return m.Error }//+n {{define "marshalValue"}} {{if ne .Convert ""}} m.Marshal{{.Encoder}}({{.Convert}}(o.{{.Name}})) {{else if .IsBasic}} {{if ge .Max 1}} if l := len(o.{{.Name}}); l > {{.Max}} { return xdr.ElementSizeExceeded("{{.Name}}", l, {{.Max}}) } {{end}} m.Marshal{{.Encoder}}(o.{{.Name}}) {{else}} if err := o.{{.Name}}.MarshalXDRInto(m); err != nil { return err } {{end}} {{end}} {{define "marshalSlice"}} {{if ge .Max 1}} if l := len(o.{{.Name}}); l > {{.Max}} { return xdr.ElementSizeExceeded("{{.Name}}", l, {{.Max}}) } {{end}} m.MarshalUint32(uint32(len(o.{{.Name}}))) for i := range o.{{.Name}} { {{if ne .Convert ""}} m.Marshal{{.Encoder}}({{.Convert}}(o.{{.Name}}[i])) {{else if .IsBasic}} m.Marshal{{.Encoder}}(o.{{.Name}}[i]) {{else}} if err := o.{{.Name}}[i].MarshalXDRInto(m); err != nil { return err } {{end}} } {{end}} func (o *{{.Name}}) UnmarshalXDR(bs []byte) error { u := &xdr.Unmarshaller{Data: bs} return o.UnmarshalXDRFrom(u) } func (o *{{.Name}}) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { {{range $fi := .Fields}} {{if $fi.IsSlice}} {{template "unmarshalSlice" $fi}} {{else}} {{template "unmarshalValue" $fi}} {{end}} {{end}} return u.Error }//+n {{define "unmarshalValue"}} {{if ne .Convert ""}} o.{{.Name}} = {{.FieldType}}(u.Unmarshal{{.Encoder}}()) {{else if .IsBasic}} {{if ge .Max 1}} o.{{.Name}} = u.Unmarshal{{.Encoder}}Max({{.Max}}) {{else}} o.{{.Name}} = u.Unmarshal{{.Encoder}}() {{end}} {{else}} (&o.{{.Name}}).UnmarshalXDRFrom(u) {{end}} {{end}} {{define "unmarshalSlice"}} _{{.Name}}Size := int(u.UnmarshalUint32()) if _{{.Name}}Size < 0 { return xdr.ElementSizeExceeded("{{.Name}}", _{{.Name}}Size, {{.Max}}) } else if _{{.Name}}Size == 0 { o.{{.Name}} = nil } else { {{if ge .Max 1}} if _{{.Name}}Size > {{.Max}} { return xdr.ElementSizeExceeded("{{.Name}}", _{{.Name}}Size, {{.Max}}) } {{end}} if _{{.Name}}Size <= len(o.{{.Name}}) { {{if eq .FieldType "string"}} for i := _{{.Name}}Size; i < len(o.{{.Name}}); i++ { o.{{.Name}}[i] = "" } {{end}} {{if eq .FieldType "[]byte"}} for i := _{{.Name}}Size; i < len(o.{{.Name}}); i++ { o.{{.Name}}[i] = nil } {{end}} o.{{.Name}} = o.{{.Name}}[:_{{.Name}}Size] } else { o.{{.Name}} = make([]{{.FieldType}}, _{{.Name}}Size) } for i := range o.{{.Name}} { {{if ne .Convert ""}} o.{{.Name}}[i] = {{.FieldType}}(u.Unmarshal{{.Encoder}}()) {{else if .IsBasic}} {{if ge .Submax 1}} o.{{.Name}}[i] = u.Unmarshal{{.Encoder}}Max({{.Submax}}) {{else}} o.{{.Name}}[i] = u.Unmarshal{{.Encoder}}() {{end}} {{else}} (&o.{{.Name}}[i]).UnmarshalXDRFrom(u) {{end}} } } {{end}} ` var ( encodeTpl = template.Must(template.New("encoder").Parse(encoderData)) headerTpl = template.Must(template.New("header").Parse(headerData)) ) var emptyTypeTpl = template.Must(template.New("encoder").Parse(` func (o {{.Name}}) XDRSize() int { return 0 } func (o {{.Name}}) MarshalXDR() ([]byte, error) { return nil, nil }//+n func (o {{.Name}}) MustMarshalXDR() []byte { return nil }//+n func (o {{.Name}}) MarshalXDRInto(m *xdr.Marshaller) error { return nil }//+n func (o *{{.Name}}) UnmarshalXDR(bs []byte) error { return nil }//+n func (o *{{.Name}}) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { return nil }//+n `)) var maxRe = regexp.MustCompile(`(?:\Wmax:)(\d+)(?:\s*,\s*(\d+))?`) type typeSet struct { Type string Encoder string } var xdrEncoders = map[string]typeSet{ "int8": typeSet{"uint8", "Uint8"}, "uint8": typeSet{"", "Uint8"}, "int16": typeSet{"uint16", "Uint16"}, "uint16": typeSet{"", "Uint16"}, "int32": typeSet{"uint32", "Uint32"}, "uint32": typeSet{"", "Uint32"}, "int64": typeSet{"uint64", "Uint64"}, "uint64": typeSet{"", "Uint64"}, "int": typeSet{"uint64", "Uint64"}, "string": typeSet{"", "String"}, "[]byte": typeSet{"", "Bytes"}, "bool": typeSet{"", "Bool"}, } func handleStruct(t *ast.StructType) []fieldInfo { var fs []fieldInfo for _, sf := range t.Fields.List { if len(sf.Names) == 0 { // We don't handle anonymous fields continue } fn := sf.Names[0].Name var max1, max2 int if sf.Comment != nil { c := sf.Comment.List[0].Text m := maxRe.FindStringSubmatch(c) if len(m) >= 2 { max1, _ = strconv.Atoi(m[1]) } if len(m) >= 3 { max2, _ = strconv.Atoi(m[2]) } if strings.Contains(c, "noencode") { continue } } var f fieldInfo switch ft := sf.Type.(type) { case *ast.Ident: tn := ft.Name if enc, ok := xdrEncoders[tn]; ok { f = fieldInfo{ Name: fn, IsBasic: true, FieldType: tn, Encoder: enc.Encoder, Convert: enc.Type, Max: max1, Submax: max2, } } else { f = fieldInfo{ Name: fn, IsBasic: false, FieldType: tn, Max: max1, Submax: max2, } } case *ast.ArrayType: if ft.Len != nil { // We don't handle arrays continue } tn := ft.Elt.(*ast.Ident).Name if enc, ok := xdrEncoders["[]"+tn]; ok { f = fieldInfo{ Name: fn, IsBasic: true, FieldType: "[]" + tn, Encoder: enc.Encoder, Convert: enc.Type, Max: max1, Submax: max2, } } else if enc, ok := xdrEncoders[tn]; ok { f = fieldInfo{ Name: fn, IsBasic: true, IsSlice: true, FieldType: tn, Encoder: enc.Encoder, Convert: enc.Type, Max: max1, Submax: max2, } } else { f = fieldInfo{ Name: fn, IsSlice: true, FieldType: tn, Max: max1, Submax: max2, } } case *ast.SelectorExpr: f = fieldInfo{ Name: fn, FieldType: ft.Sel.Name, Max: max1, Submax: max2, } } fs = append(fs, f) } return fs } func generateCode(output io.Writer, s structInfo) { var buf bytes.Buffer var err error if len(s.Fields) == 0 { // This is an empty type. We can create a quite simple codec for it. err = emptyTypeTpl.Execute(&buf, s) } else { // Generate with the default template. err = encodeTpl.Execute(&buf, s) } if err != nil { panic(err) } bs := regexp.MustCompile(`(\s*\n)+`).ReplaceAll(buf.Bytes(), []byte("\n")) bs = bytes.Replace(bs, []byte("//+n"), []byte("\n"), -1) output.Write(bs) } func uncamelize(s string) string { return regexp.MustCompile("[a-z][A-Z]").ReplaceAllStringFunc(s, func(camel string) string { return camel[:1] + " " + camel[1:] }) } func generateDiagram(output io.Writer, s structInfo) { sn := s.Name fs := s.Fields fmt.Fprintln(output, sn+" Structure:") if len(fs) == 0 { fmt.Fprintln(output, "(contains no fields)") fmt.Fprintln(output) fmt.Fprintln(output) return } fmt.Fprintln(output) fmt.Fprintln(output, " 0 1 2 3") fmt.Fprintln(output, " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1") line := "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+" fmt.Fprintln(output, line) for _, f := range fs { tn := f.FieldType name := uncamelize(f.Name) suffix := "" if f.IsSlice { fmt.Fprintf(output, "| %s |\n", center("Number of "+name, 61)) fmt.Fprintln(output, line) suffix = " (n items)" fmt.Fprintf(output, "/ %s /\n", center("", 61)) } switch tn { case "bool": fmt.Fprintf(output, "| %s |V|\n", center(name+" (V=0 or 1)", 59)) case "int16", "uint16": fmt.Fprintf(output, "| %s | %s |\n", center("16 zero bits", 29), center(name, 29)) case "int8", "uint8": fmt.Fprintf(output, "| %s | %s |\n", center("24 zero bits", 45), center(name, 13)) case "int32", "uint32": fmt.Fprintf(output, "| %s |\n", center(name+suffix, 61)) case "int64", "uint64": fmt.Fprintf(output, "| %-61s |\n", "") fmt.Fprintf(output, "+ %s +\n", center(name+" (64 bits)", 61)) fmt.Fprintf(output, "| %-61s |\n", "") case "string", "[]byte": fmt.Fprintf(output, "/ %61s /\n", "") fmt.Fprintf(output, "\\ %s \\\n", center(name+" (length + padded data)", 61)) fmt.Fprintf(output, "/ %61s /\n", "") default: if f.IsSlice { tn = "Zero or more " + tn + " Structures" fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61)) } else { tn = tn + " Structure" fmt.Fprintf(output, "/ %s /\n", center("", 61)) fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61)) fmt.Fprintf(output, "/ %s /\n", center("", 61)) } } if f.IsSlice { fmt.Fprintf(output, "/ %s /\n", center("", 61)) } fmt.Fprintln(output, line) } fmt.Fprintln(output) fmt.Fprintln(output) } func generateXdr(output io.Writer, s structInfo) { sn := s.Name fs := s.Fields fmt.Fprintf(output, "struct %s {\n", sn) for _, f := range fs { tn := f.FieldType fn := f.Name suf := "" l := "" if f.Max > 0 { l = strconv.Itoa(f.Max) } if f.IsSlice { suf = "<" + l + ">" } switch tn { case "int8", "int16", "int32": fmt.Fprintf(output, "\tint %s%s;\n", fn, suf) case "uint8", "uint16", "uint32": fmt.Fprintf(output, "\tunsigned int %s%s;\n", fn, suf) case "int64": fmt.Fprintf(output, "\thyper %s%s;\n", fn, suf) case "uint64": fmt.Fprintf(output, "\tunsigned hyper %s%s;\n", fn, suf) case "string": fmt.Fprintf(output, "\tstring %s<%s>;\n", fn, l) case "[]byte": fmt.Fprintf(output, "\topaque %s<%s>;\n", fn, l) default: fmt.Fprintf(output, "\t%s %s%s;\n", tn, fn, suf) } } fmt.Fprintln(output, "}") fmt.Fprintln(output) } func center(s string, w int) string { w -= len(s) l := w / 2 r := l if l+r < w { r++ } return strings.Repeat(" ", l) + s + strings.Repeat(" ", r) } func inspector(structs *[]structInfo) func(ast.Node) bool { return func(n ast.Node) bool { switch n := n.(type) { case *ast.TypeSpec: switch t := n.Type.(type) { case *ast.StructType: name := n.Name.Name fs := handleStruct(t) *structs = append(*structs, structInfo{name, fs}) } return false default: return true } } } func main() { outputFile := flag.String("o", "", "Output file, blank for stdout") flag.Parse() fname := flag.Arg(0) fset := token.NewFileSet() f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments) if err != nil { log.Fatal(err) } var structs []structInfo i := inspector(&structs) ast.Inspect(f, i) buf := new(bytes.Buffer) headerTpl.Execute(buf, map[string]string{"Package": f.Name.Name}) for _, s := range structs { fmt.Fprintf(buf, "\n/*\n\n") generateDiagram(buf, s) generateXdr(buf, s) fmt.Fprintf(buf, "*/\n") generateCode(buf, s) } bs, err := format.Source(buf.Bytes()) if err != nil { log.Print(buf.String()) log.Fatal(err) } var output io.Writer = os.Stdout if *outputFile != "" { fd, err := os.Create(*outputFile) if err != nil { log.Fatal(err) } output = fd } output.Write(bs) } xdr-2.0.1/common.go000066400000000000000000000027411267653056700141530ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. package xdr import ( "fmt" "reflect" ) var padBytes = []byte{0, 0, 0} // Pad returns the number of bytes that should be added to an item of length l // bytes to conform to the XDR padding standard. This function is used by the // generated marshalling code. func Padding(l int) int { d := l % 4 if d == 0 { return 0 } return 4 - d } // ElementSizeExceeded returns an error describing the violated size // constraint. This function is used by the generated marshalling code. func ElementSizeExceeded(field string, size, limit int) error { return fmt.Errorf("%s exceeds size limit; %d > %d", field, size, limit) } type XDRSizer interface { XDRSize() int } // SizeOfSlice returns the XDR encoded size of the given []T. Supported types // for T are string, []byte and types implementing XDRSizer. SizeOfSlice // panics if the parameter is not a slice or if T is not one of the supported // types. This function is used by the generated marshalling code. func SizeOfSlice(ss interface{}) int { l := 0 switch ss := ss.(type) { case []string: for _, s := range ss { l += 4 + len(s) + Padding(len(s)) } case [][]byte: for _, s := range ss { l += 4 + len(s) + Padding(len(s)) } default: v := reflect.ValueOf(ss) for i := 0; i < v.Len(); i++ { l += v.Index(i).Interface().(XDRSizer).XDRSize() } } return l } xdr-2.0.1/doc.go000066400000000000000000000003571267653056700134310ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. // Package xdr implements an XDR (RFC 4506) marshaller/unmarshaller. package xdr xdr-2.0.1/encdec_test.go000066400000000000000000000122701267653056700151410ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. package xdr_test import ( "bytes" "io" "log" "math/rand" "reflect" "testing" "testing/quick" "github.com/calmh/xdr" ) // Contains all supported types type TestStruct struct { B bool I int I8 int8 UI8 uint8 I16 int16 UI16 uint16 I32 int32 UI32 uint32 I64 int64 UI64 uint64 BS []byte // max:1024 S string // max:1024 C Opaque SS []string // max:1024 ES EmptyStruct OS OtherStruct OSs []OtherStruct } func (s1 TestStruct) TestEquals(s2 TestStruct) bool { if s1.B != s2.B { log.Printf("B differ; %v != %v", s1.B, s2.B) return false } if s1.I != s2.I { log.Printf("I differ; %d != %d", s1.I, s2.I) return false } if s1.I8 != s2.I8 { log.Printf("I8 differ; %d != %d", s1.I8, s2.I8) return false } if s1.UI8 != s2.UI8 { log.Printf("UI8 differ; %d != %d", s1.UI8, s2.UI8) return false } if s1.I16 != s2.I16 { log.Printf("I16 differ; %d != %d", s1.I16, s2.I16) return false } if s1.UI16 != s2.UI16 { log.Printf("UI16 differ; %d != %d", s1.UI16, s2.UI16) return false } if s1.I32 != s2.I32 { log.Printf("I32 differ; %d != %d", s1.I32, s2.I32) return false } if s1.UI32 != s2.UI32 { log.Printf("UI32 differ; %d != %d", s1.UI32, s2.UI32) return false } if s1.I64 != s2.I64 { log.Printf("I64 differ; %d != %d", s1.I64, s2.I64) return false } if s1.UI64 != s2.UI64 { log.Printf("UI64 differ; %d != %d", s1.UI64, s2.UI64) return false } if !bytes.Equal(s1.BS, s2.BS) { log.Println("BS differ") return false } if s1.S != s2.S { log.Printf("S differ; %q != %q", s1.S, s2.S) return false } if s1.C != s2.C { log.Printf("C differ; %q != %q", s1.C, s2.C) return false } if len(s1.SS) != len(s2.SS) { log.Printf("len(SS) differ; %q != %q", len(s1.SS), len(s2.SS)) return false } for i := range s1.SS { if s1.SS[i] != s2.SS[i] { log.Printf("SS[%d] differ; %q != %q", i, s1.SS[i], s2.SS[i]) return false } } if s1.OS != s2.OS { log.Printf("OS differ; %q != %q", s1.OS, s2.OS) return false } if len(s1.OSs) != len(s2.OSs) { log.Printf("len(OSs) differ; %q != %q", len(s1.OSs), len(s2.OSs)) return false } for i := range s1.OSs { if s1.OSs[i] != s2.OSs[i] { log.Printf("OSs[%d] differ; %q != %q", i, s1.OSs[i], s2.OSs[i]) return false } } return true } type EmptyStruct struct { } type OtherStruct struct { F1 uint32 F2 string } type Opaque [32]byte func (u *Opaque) XDRSize() int { return 32 } func (u *Opaque) MarshalXDRInto(m *xdr.Marshaller) error { m.MarshalRaw(u[:]) return m.Error } func (o *Opaque) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { copy((*o)[:], u.UnmarshalRaw(32)) return u.Error } func (Opaque) Generate(rand *rand.Rand, size int) reflect.Value { var u Opaque for i := range u[:] { u[i] = byte(rand.Int()) } return reflect.ValueOf(u) } func TestEncDec(t *testing.T) { fn := func(t0 TestStruct) bool { bs, err := t0.MarshalXDR() if err != nil { t.Fatal(err) } var t1 TestStruct err = t1.UnmarshalXDR(bs) if err != nil { t.Fatal(err) } return t0.TestEquals(t1) } if err := quick.Check(fn, nil); err != nil { t.Error(err) } } func TestMarshalShortBuffer(t *testing.T) { var s TestStruct buf := make([]byte, s.XDRSize()) if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf}); err != nil { t.Fatal("Unexpected error", err) } if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf[1:]}); err != io.ErrShortBuffer { t.Fatal("Expected io.ErrShortBuffer, got", err) } } func TestUnmarshalUnexpectedEOF(t *testing.T) { var s TestStruct buf := make([]byte, s.XDRSize()) if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf}); err != nil { t.Fatal("Unexpected error", err) } if err := s.UnmarshalXDR(buf[:len(buf)-1]); err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u := &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalRaw(4) if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalString() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalBytes() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalBool() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalUint8() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalUint16() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:3]} u.UnmarshalUint32() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } u = &xdr.Unmarshaller{Data: buf[:7]} u.UnmarshalUint64() if err := u.Error; err != io.ErrUnexpectedEOF { t.Fatal("Expected io.ErrUnexpectedEOF, got", err) } } xdr-2.0.1/encdec_xdr_test.go000066400000000000000000000230231267653056700160140ustar00rootroot00000000000000// ************************************************************ // This file is automatically generated by genxdr. Do not edit. // ************************************************************ package xdr_test import ( "github.com/calmh/xdr" ) /* TestStruct Structure: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | B (V=0 or 1) |V| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ int Structure \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 24 zero bits | I8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 24 zero bits | UI8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 16 zero bits | I16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 16 zero bits | UI16 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | I32 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | UI32 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + I64 (64 bits) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + UI64 (64 bits) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ BS (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ S (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ Opaque Structure \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number of SS | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / / \ SS (length + padded data) \ / / / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ EmptyStruct Structure \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ OtherStruct Structure \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Number of OSs | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ Zero or more OtherStruct Structures \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct TestStruct { bool B; int I; int I8; unsigned int UI8; int I16; unsigned int UI16; int I32; unsigned int UI32; hyper I64; unsigned hyper UI64; opaque BS<1024>; string S<1024>; Opaque C; string SS<1024>; EmptyStruct ES; OtherStruct OS; OtherStruct OSs<>; } */ func (o TestStruct) XDRSize() int { return 4 + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + len(o.BS) + xdr.Padding(len(o.BS)) + 4 + len(o.S) + xdr.Padding(len(o.S)) + o.C.XDRSize() + 4 + xdr.SizeOfSlice(o.SS) + o.ES.XDRSize() + o.OS.XDRSize() + 4 + xdr.SizeOfSlice(o.OSs) } func (o TestStruct) MarshalXDR() ([]byte, error) { buf := make([]byte, o.XDRSize()) m := &xdr.Marshaller{Data: buf} return buf, o.MarshalXDRInto(m) } func (o TestStruct) MustMarshalXDR() []byte { bs, err := o.MarshalXDR() if err != nil { panic(err) } return bs } func (o TestStruct) MarshalXDRInto(m *xdr.Marshaller) error { m.MarshalBool(o.B) m.MarshalUint64(uint64(o.I)) m.MarshalUint8(uint8(o.I8)) m.MarshalUint8(o.UI8) m.MarshalUint16(uint16(o.I16)) m.MarshalUint16(o.UI16) m.MarshalUint32(uint32(o.I32)) m.MarshalUint32(o.UI32) m.MarshalUint64(uint64(o.I64)) m.MarshalUint64(o.UI64) if l := len(o.BS); l > 1024 { return xdr.ElementSizeExceeded("BS", l, 1024) } m.MarshalBytes(o.BS) if l := len(o.S); l > 1024 { return xdr.ElementSizeExceeded("S", l, 1024) } m.MarshalString(o.S) if err := o.C.MarshalXDRInto(m); err != nil { return err } if l := len(o.SS); l > 1024 { return xdr.ElementSizeExceeded("SS", l, 1024) } m.MarshalUint32(uint32(len(o.SS))) for i := range o.SS { m.MarshalString(o.SS[i]) } if err := o.ES.MarshalXDRInto(m); err != nil { return err } if err := o.OS.MarshalXDRInto(m); err != nil { return err } m.MarshalUint32(uint32(len(o.OSs))) for i := range o.OSs { if err := o.OSs[i].MarshalXDRInto(m); err != nil { return err } } return m.Error } func (o *TestStruct) UnmarshalXDR(bs []byte) error { u := &xdr.Unmarshaller{Data: bs} return o.UnmarshalXDRFrom(u) } func (o *TestStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { o.B = u.UnmarshalBool() o.I = int(u.UnmarshalUint64()) o.I8 = int8(u.UnmarshalUint8()) o.UI8 = u.UnmarshalUint8() o.I16 = int16(u.UnmarshalUint16()) o.UI16 = u.UnmarshalUint16() o.I32 = int32(u.UnmarshalUint32()) o.UI32 = u.UnmarshalUint32() o.I64 = int64(u.UnmarshalUint64()) o.UI64 = u.UnmarshalUint64() o.BS = u.UnmarshalBytesMax(1024) o.S = u.UnmarshalStringMax(1024) (&o.C).UnmarshalXDRFrom(u) _SSSize := int(u.UnmarshalUint32()) if _SSSize < 0 { return xdr.ElementSizeExceeded("SS", _SSSize, 1024) } else if _SSSize == 0 { o.SS = nil } else { if _SSSize > 1024 { return xdr.ElementSizeExceeded("SS", _SSSize, 1024) } if _SSSize <= len(o.SS) { for i := _SSSize; i < len(o.SS); i++ { o.SS[i] = "" } o.SS = o.SS[:_SSSize] } else { o.SS = make([]string, _SSSize) } for i := range o.SS { o.SS[i] = u.UnmarshalString() } } (&o.ES).UnmarshalXDRFrom(u) (&o.OS).UnmarshalXDRFrom(u) _OSsSize := int(u.UnmarshalUint32()) if _OSsSize < 0 { return xdr.ElementSizeExceeded("OSs", _OSsSize, 0) } else if _OSsSize == 0 { o.OSs = nil } else { if _OSsSize <= len(o.OSs) { o.OSs = o.OSs[:_OSsSize] } else { o.OSs = make([]OtherStruct, _OSsSize) } for i := range o.OSs { (&o.OSs[i]).UnmarshalXDRFrom(u) } } return u.Error } /* EmptyStruct Structure: (contains no fields) struct EmptyStruct { } */ func (o EmptyStruct) XDRSize() int { return 0 } func (o EmptyStruct) MarshalXDR() ([]byte, error) { return nil, nil } func (o EmptyStruct) MustMarshalXDR() []byte { return nil } func (o EmptyStruct) MarshalXDRInto(m *xdr.Marshaller) error { return nil } func (o *EmptyStruct) UnmarshalXDR(bs []byte) error { return nil } func (o *EmptyStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { return nil } /* OtherStruct Structure: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | F1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / \ F2 (length + padded data) \ / / +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ struct OtherStruct { unsigned int F1; string F2<>; } */ func (o OtherStruct) XDRSize() int { return 4 + 4 + len(o.F2) + xdr.Padding(len(o.F2)) } func (o OtherStruct) MarshalXDR() ([]byte, error) { buf := make([]byte, o.XDRSize()) m := &xdr.Marshaller{Data: buf} return buf, o.MarshalXDRInto(m) } func (o OtherStruct) MustMarshalXDR() []byte { bs, err := o.MarshalXDR() if err != nil { panic(err) } return bs } func (o OtherStruct) MarshalXDRInto(m *xdr.Marshaller) error { m.MarshalUint32(o.F1) m.MarshalString(o.F2) return m.Error } func (o *OtherStruct) UnmarshalXDR(bs []byte) error { u := &xdr.Unmarshaller{Data: bs} return o.UnmarshalXDRFrom(u) } func (o *OtherStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error { o.F1 = u.UnmarshalUint32() o.F2 = u.UnmarshalString() return u.Error } xdr-2.0.1/generate.sh000077500000000000000000000002131267653056700144550ustar00rootroot00000000000000#!/bin/sh go run cmd/genxdr/main.go -- bench_test.go > bench_xdr_test.go go run cmd/genxdr/main.go -- encdec_test.go > encdec_xdr_test.go xdr-2.0.1/marshaller.go000066400000000000000000000061211267653056700150110ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code // is governed by an MIT-style license that can be found in the LICENSE file. package xdr import "io" // The Marshaller is a thin wrapper around a byte buffer. The buffer must be // of sufficient size to hold the complete marshalled object, or an // io.ErrShortBuffer error will result. The Marshal... methods don't // individually return an error - the intention is that multiple fields are // marshalled in rapid succession, followed by a check of the Error field on // the Marshaller. type Marshaller struct { Data []byte Error error offset int } // MarshalRaw copies the raw bytes to the buffer, without a size prefix or // padding. This is suitable for appending data already in XDR format from // another source. func (m *Marshaller) MarshalRaw(bs []byte) { if m.Error != nil { return } if len(m.Data) < m.offset+len(bs) { m.Error = io.ErrShortBuffer return } m.offset += copy(m.Data[m.offset:], bs) } // MarshalString appends the string to the buffer, with a size prefix and // correct padding. func (m *Marshaller) MarshalString(s string) { if m.Error != nil { return } if len(m.Data) < m.offset+4+len(s)+Padding(len(s)) { m.Error = io.ErrShortBuffer return } m.MarshalUint32(uint32(len(s))) m.offset += copy(m.Data[m.offset:], s) m.offset += copy(m.Data[m.offset:], padBytes[:Padding(len(s))]) } // MarshalString appends the bytes to the buffer, with a size prefix and // correct padding. func (m *Marshaller) MarshalBytes(bs []byte) { if m.Error != nil { return } if len(m.Data) < m.offset+4+len(bs)+Padding(len(bs)) { m.Error = io.ErrShortBuffer return } m.MarshalUint32(uint32(len(bs))) m.offset += copy(m.Data[m.offset:], bs) m.offset += copy(m.Data[m.offset:], padBytes[:Padding(len(bs))]) } // MarshalString appends the bool to the buffer, as an uint32. func (m *Marshaller) MarshalBool(v bool) { if v { m.MarshalUint8(1) } else { m.MarshalUint8(0) } } // MarshalString appends the uint8 to the buffer, as an uint32. func (m *Marshaller) MarshalUint8(v uint8) { m.MarshalUint32(uint32(v)) } // MarshalString appends the uint16 to the buffer, as an uint32. func (m *Marshaller) MarshalUint16(v uint16) { m.MarshalUint32(uint32(v)) } // MarshalString appends the uint32 to the buffer. func (m *Marshaller) MarshalUint32(v uint32) { if m.Error != nil { return } if len(m.Data) < m.offset+4 { m.Error = io.ErrShortBuffer return } m.Data[m.offset+0] = byte(v >> 24) m.Data[m.offset+1] = byte(v >> 16) m.Data[m.offset+2] = byte(v >> 8) m.Data[m.offset+3] = byte(v) m.offset += 4 } // MarshalString appends the uint64 to the buffer. func (m *Marshaller) MarshalUint64(v uint64) { if m.Error != nil { return } if len(m.Data) < m.offset+8 { m.Error = io.ErrShortBuffer return } m.Data[m.offset+0] = byte(v >> 56) m.Data[m.offset+1] = byte(v >> 48) m.Data[m.offset+2] = byte(v >> 40) m.Data[m.offset+3] = byte(v >> 32) m.Data[m.offset+4] = byte(v >> 24) m.Data[m.offset+5] = byte(v >> 16) m.Data[m.offset+6] = byte(v >> 8) m.Data[m.offset+7] = byte(v) m.offset += 8 } xdr-2.0.1/unmarshal.go000066400000000000000000000050741267653056700146570ustar00rootroot00000000000000// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file). // All rights reserved. Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. package xdr import "io" type Unmarshaller struct { Error error Data []byte } func (u *Unmarshaller) UnmarshalRaw(l int) []byte { if u.Error != nil { return nil } if len(u.Data) < l { u.Error = io.ErrUnexpectedEOF return nil } v := u.Data[:l] u.Data = u.Data[l:] return v } func (u *Unmarshaller) UnmarshalString() string { return u.UnmarshalStringMax(0) } func (u *Unmarshaller) UnmarshalStringMax(max int) string { buf := u.UnmarshalBytesMax(max) if len(buf) == 0 || u.Error != nil { return "" } return string(buf) } func (u *Unmarshaller) UnmarshalBytes() []byte { return u.UnmarshalBytesMax(0) } func (u *Unmarshaller) UnmarshalBytesMax(max int) []byte { if u.Error != nil { return nil } if len(u.Data) < 4 { u.Error = io.ErrUnexpectedEOF return nil } l := int(u.Data[3]) | int(u.Data[2])<<8 | int(u.Data[1])<<16 | int(u.Data[0])<<24 if l == 0 { u.Data = u.Data[4:] return nil } if l < 0 || max > 0 && l > max { // l may be negative on 32 bit builds u.Error = ElementSizeExceeded("bytes field", l, max) return nil } if len(u.Data) < l+4 { u.Error = io.ErrUnexpectedEOF return nil } v := u.Data[4 : 4+l] u.Data = u.Data[4+l+Padding(l):] return v } func (u *Unmarshaller) UnmarshalBool() bool { return u.UnmarshalUint8() != 0 } func (u *Unmarshaller) UnmarshalUint8() uint8 { if u.Error != nil { return 0 } if len(u.Data) < 4 { u.Error = io.ErrUnexpectedEOF return 0 } v := uint8(u.Data[3]) u.Data = u.Data[4:] return v } func (u *Unmarshaller) UnmarshalUint16() uint16 { if u.Error != nil { return 0 } if len(u.Data) < 4 { u.Error = io.ErrUnexpectedEOF return 0 } v := uint16(u.Data[3]) | uint16(u.Data[2])<<8 u.Data = u.Data[4:] return v } func (u *Unmarshaller) UnmarshalUint32() uint32 { if u.Error != nil { return 0 } if len(u.Data) < 4 { u.Error = io.ErrUnexpectedEOF return 0 } v := uint32(u.Data[3]) | uint32(u.Data[2])<<8 | uint32(u.Data[1])<<16 | uint32(u.Data[0])<<24 u.Data = u.Data[4:] return v } func (u *Unmarshaller) UnmarshalUint64() uint64 { if u.Error != nil { return 0 } if len(u.Data) < 8 { u.Error = io.ErrUnexpectedEOF return 0 } v := uint64(u.Data[7]) | uint64(u.Data[6])<<8 | uint64(u.Data[5])<<16 | uint64(u.Data[4])<<24 | uint64(u.Data[3])<<32 | uint64(u.Data[2])<<40 | uint64(u.Data[1])<<48 | uint64(u.Data[0])<<56 u.Data = u.Data[8:] return v }