wire9

package module
v0.0.0-...-764124a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2017 License: BSD-3-Clause Imports: 17 Imported by: 0

README

Wire9

Protocol Boilerplate Generator

Overview

  • Build & Install
  • Write wire definitions
  • Run wire9 executable
    • Generates structs
    • Generates ReadBinary and WriteBinary implementations

Install

Build wire9/wire9

wire9 -f output_wire9.go (packagename | .)

Wire Definitions

wire definitions are defined with a comment starting with '//wire9'

//wire9 TypeName MemberName[Width,Type,Endian] ...

//wire9 Dot1 q0[8] q1[8]
//wire9 Dot2 q0[8,int64] q1[,int64]
//wire9 Dot3 q0[8,int64,BE] q1[8,,BE]

At least one Width or Type must be defined per member. Endianness defaults to LE (little-endian).

Example 1: Conformant types

A conformant type is a type that is described by the value of another type, usually this type is an aggregate (i.e., a slice) and conforms to the length specified by a preceeding value.

Members preceeding other members in wire definitions may indicate the width of the members they preceed.

package main

//wire9  bstr n[4] data[n]

go:generate wire9 -f main_wire9.go .

func main(){
  bs := &bstr{}
  bs.ReadBinary(os.Stdin) 
  // Reads in 0x0500000041
  // Final value
  // &bstr{n: 5, data: "A"}
}

Example 2: Nested conformant types

A batch request (two conformant types)

package main

//wire9 bstr  n[4] data[n]
//wire9 batch n[4] strings[n,[]bstr]

go:generate wire9 -f main_wire9.go .

func main(){
  bs := &batch{}
  bs.ReadBinary(os.Stdin) 
  // Reads in: 0x03000000010000004101000000410100000041
  // Final value
  // &batch{
      n: 3,
      data: []bstr{
         bstr{n: 1, data: "A"}
         bstr{n: 1, data: "B"}
         bstr{n: 1, data: "C"}
      }
}

Documentation

Overview

Package wire9 provides a boilerplate protocol generator. Wire9 parses wire definitions from a go package or source file. It generates structs and methods according to the given definition.

To use wire9, run the standalone command line program on a go package directory containing wire definitions.

go install github.com/as/wire9/cmd
cd $GOPATH/src/github.com/as/wire9/
wire9 -f example/0/ex_wire9.go example/0/

Wire Definitions:

A wire definition begins with a slash comment and wire9 prefix. There is no space between the slashes and prefix. The prefix is followed by a struct name and a variadic list of fields.

//wire9 struct⁰ field⁰[width,type,endian] ... fieldⁿ[width,type,endian]

A field becomes the name of a struct field. Next, a [bracket-enclosed], comma-seperated list of field options: width, type, and endian.

field⁰[width,type,endian]

Width is a field's binary width. Its value is an integer constant, a previously-defined numeric field, or empty.

Types specify a field's type. This affects the type value in the final struct field, numeric and fixed types may have empty widths.

Endian specifies byte-order (LE or BE), which stand for Little-Endian and Big-Endian. Little-Endian is the default value.

The width and type are interpreted one of three ways depending on other values in the field options:

  1. Width is a numeric literal A. Type is empty: If width is 1, 2, 4, or 8, type is byte, uint16, uint32, and uint64, respectively. Otherwise type is []byte.

    B. Type is identifier: The type represents a fixed width struct, numeric value, or slice type. The width must match the fixed types binary width or be the number of expected slice elements.

  2. Width is identifier A. Type is empty: Type is implicitly []byte. The width represents the number of bytes to expect in the slice.

    B. Type is identifier: The type represents a slice type. The width is the number of expected elements in the slice.

  3. Width is empty A. Type is a fixed-width struct, number, or implements the Wire interface.

    Examples:

    //wire9 Ex1A Time[8] IP[4] Port[2] n[1] //wire9 Ex1B Time[8,uint64] IP[4,uint32] Port[2,uint16] n[1,byte]

    //wire9 Ex2A n[1] URL[n] //wire9 Ex2B n[1] URL[n,[]byte]

    //wire9 Ex3A p[,image.Point] size[,int64] reply[,Ex2A]

    //wire9 Git index[4,,BE] ...

Example:

The wire definition for a two-byte length-prefixed string:

//wire9 Bstr  n[2] data[n]

Generates the following struct and (fully-implemented) methods:

type Bstr struct {
	n    uint16
	data []byte
}
func (z *Bstr) ReadBinary(r io.Reader) (err error)
func (z Bstr)  WriteBinary(w io.Writer) (err error)

This example defines four common length-prefixed strings

//wire9 Pstr  n[1] data[n]
//wire9 Bstr  n[2] data[n]
//wire9 Dstr  n[4] data[n]
//wire9 Qstr  n[8] data[n]

The following construction builds on the last example. The value of the four 4-byte integers set the expected number of slice elements for each corresponding length-prefixed string.

//wire9 BurstRX np[4] nb[4] nd[4] nq[4] SP[np,[]Pstr] SB[nb,[]Bstr] SD[nd,[]Dstr] SQ[nq,[]Qstr]

Trivia:

The goal of this package is to save time when implementing custom protocols, such as Microsoft RDP. The package's original purpose was to take the Plan 9 draw(3) manual page and generate Go for parsing the messages written to the data file.

Index

Constants

This section is empty.

Variables

View Source
var Flags = map[string]bool{}
View Source
var Nesting nesting

Nesting tracks the level of expression nesting during code generation

Functions

func Access

func Access(a ast.Expr) string

Access returns the named field's accessor expression as a string

func Array

func Array(f ast.Expr) (ok bool)

Array returns true if f is an array type

func ByteArray

func ByteArray(f ast.Expr) (ok bool)

ByteArray returns true if f is an array of bytes

func ByteSlice

func ByteSlice(f ast.Expr) (ok bool)

ByteSlice returns true if f a slice of bytes

func Clean

func Clean(src []byte) []byte

Clean examines scopes in input src and removes unnecessary braces. It returns the clean copy. The src is assumed to be valid, error-free Go source.

func Coherent

func Coherent(f ast.Expr) (ok bool)

Coherent returns true if f is not an aggregate (slice or array) type

func Custom

func Custom(f ast.Expr) bool

Custom returns true if f is not a builtin type

func CustomSlice

func CustomSlice(f ast.Expr) (ok bool)

CustomSlice returns true if f is not a builtin type, and is a slice

func Endian

func Endian(m ast.Node) (string, error)

Endian returns the endianness of a field. TODO: return an error if the field can't have an endian value.

func FromFiles

func FromFiles(files []string, dups DupMap, dofmt bool) ([]byte, error)

FromFiles produces wire9 structures and functions by reading wire definitions from files. Dofmt controls gofmt operation.

func Literal

func Literal(f ast.Expr) (ok bool)

Literal returns true if f is not a builtin type, and is a slice

func NewCleaner

func NewCleaner() *cleaner

func NewParser

func NewParser(fset *token.FileSet, line string, dups DupMap) (p *parser, err error)

NewParser returns an initialized parser.

func Numeric

func Numeric(f ast.Expr) (ok bool)

Numeric returns true if f is a builtin numeric type

func Selector

func Selector(f ast.Expr) string

Selector returns the syntax for selecting an element of f. If f is not an array or slice, the field is returned as is.

func Slice

func Slice(f ast.Expr) (ok bool)

Slice returns true if f is a slice type

func SliceOf

func SliceOf(f ast.Expr) ast.Expr

SliceOf returns the syntax of f as a slice element

func String

func String(f ast.Expr) (ok bool)

String returns f's string representation

func TypeFromWidth

func TypeFromWidth(w ast.Expr) (ast.Expr, error)

TypeFromWidth determines the type by the width

func TypeString

func TypeString(f interface{}) string

TypeString returns the named field's type as a string

func WasSet

func WasSet(s string) bool

func WidthOf

func WidthOf(ts *ast.TypeSpec, f *ast.Field) (s string, err error)

WidthOf returns the named field's width as a string

func WireFile

func WireFile(file interface{}) bool

WireFile returns true if file contains "_wire9". The file's underlying type must be string or os.FileInfo.

Types

type Dup

type Dup struct {
	// contains filtered or unexported fields
}

Dup marks the type of duplicate found in the original source code. A that a wire definition would likely conflict with.

type DupMap

type DupMap map[Dup]*ast.Ident

Dup marks the type of duplicate found in the original source code. A that a wire definition would likely conflict with.

func DupFind

func DupFind(n ast.Node) DupMap

Dupfind walks the AST looking for structs and method sets that could conflict with a wire definition.

func (DupMap) Merge

func (v DupMap) Merge(v2 DupMap)

func (DupMap) Visit

func (v DupMap) Visit(n ast.Node) ast.Visitor

Visit traverses the AST

type File

type File struct {
	Name    string
	Structs []*ast.TypeSpec
}

File struct. TODO: Revise

type Info

type Info struct {
	Width        ast.Expr
	Endian       binary.ByteOrder
	Flag         WidthFlag
	FromGoSource bool
}

Info holds type information for a field parsed with wire9

type Mode

type Mode uint

A Mode value is a set of flags (or 0). They control the amount of source code parsed and other optional parser functionality.

const (
	PackageClauseOnly Mode             = 1 << iota // stop parsing after package clause
	ImportsOnly                                    // stop parsing after import declarations
	ParseComments                                  // parse comments and add them to AST
	Trace                                          // print a trace of parsed productions
	DeclarationErrors                              // report declaration errors
	SpuriousErrors                                 // same as AllErrors, for backward-compatibility
	AllErrors         = SpuriousErrors             // report all errors (not just the first 10 on different lines)
)

Parser flags

type Package

type Package struct {
	Info     *types.Info
	Path     string
	Files    []string
	ASTFiles []*ast.File
	Data     []byte
	Fset     *token.FileSet
	Pkg      *types.Package
	DupMap   DupMap
}

Package is a box for AST, wire9 and package type information.

func FromPackage

func FromPackage(pkg *Package, dofmt bool) (wire *Package, err error)

FromPackage produces wire9 structures and functions via from a Package opened with OpenPackage.

func OpenPackage

func OpenPackage(path string, dowires bool) (pkg *Package, err error)

OpenPackage opens the package at path. It returns a partialy-initialized Package containing initialized ASTFiles, Fset, and Files.

func (*Package) Check

func (p *Package) Check(conf *types.Config) (*types.Info, error)

Check runs a type checker on the package using config.

type Source

type Source struct {
	Files []*File

	Structs []*ast.TypeSpec
	DupMap
	// contains filtered or unexported fields
}

Source files. TODO: Revise

func ParseFiles

func ParseFiles(fs []string, dups DupMap) (src *Source, err error)

ParseFiles parses files listed in fs and extracts all sys comments. It returns source files and their list of wire9 expressions

func (*Source) Eval

func (src *Source) Eval(line string, dups DupMap) (st *ast.TypeSpec, err error)

Eval parses and processes a line of input as a wire definition. The definition must start with a double slash and follow the format given in the package description comment.

func (*Source) Generate

func (src *Source) Generate(w io.Writer) error

Generate outputs source file from a source set src.

func (*Source) Parse

func (src *Source) Parse(name string) ([]*ast.TypeSpec, error)

Parse parses the named file and produces a list of type specifications

func (*Source) ParseLine

func (src *Source) ParseLine(line string) (*ast.TypeSpec, error)

ParseLine parses and processes a line of input as a wire definition. TODO: Consolidate

type TypeInfo

type TypeInfo struct {
	Nstructs map[string]ast.TypeSpec
	// contains filtered or unexported fields
}

TypeInfo collects Info structures for every wire definition (struct)

var TInfo *TypeInfo

func NewTypeInfo

func NewTypeInfo() *TypeInfo

NewTypeInfo returns an initialized *TypeInfo

func (*TypeInfo) Add

func (t *TypeInfo) Add(nstruct *ast.TypeSpec, field *ast.Field, i *Info)

Add associates a named struct field with an *Info structure.

func (*TypeInfo) Get

func (t *TypeInfo) Get(nstruct *ast.TypeSpec, field *ast.Field) (i *Info)

Get returns an *Info field for a named struct field.

func (*TypeInfo) NamedStruct

func (t *TypeInfo) NamedStruct(n string) ast.TypeSpec

type WidthFlag

type WidthFlag int

WidthFlag describes a width associated with a Go type.

const (
	WidthLit WidthFlag = 1 << iota
	WidthVar
	WidthBad
)

WidthFlag values

func (WidthFlag) On

func (w WidthFlag) On(bits WidthFlag) bool

On returns true is bits are set

Directories

Path Synopsis
example
0
MACHINE GENERATED BY 'go generate' COMMAND TO EDIT A TYPE OR METHOD, COPY IT TO ANOTHER FILE IN THE PACKAGE
MACHINE GENERATED BY 'go generate' COMMAND TO EDIT A TYPE OR METHOD, COPY IT TO ANOTHER FILE IN THE PACKAGE
1
MACHINE GENERATED BY 'go generate' COMMAND TO EDIT A TYPE OR METHOD, COPY IT TO ANOTHER FILE IN THE PACKAGE
MACHINE GENERATED BY 'go generate' COMMAND TO EDIT A TYPE OR METHOD, COPY IT TO ANOTHER FILE IN THE PACKAGE
Package varint provides the varint type V. V knows how to write and read its binary encoded representation from a reader or writer
Package varint provides the varint type V. V knows how to write and read its binary encoded representation from a reader or writer

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL