<commit_before>
package main

import (
	"encoding/json"
	"os"
)

const (
	// Default value.
	MinRabbits	= 1
	// Default value. The numbers of rabbits that exist
	// at any given time.
	MaxRabbits	= 15
	// Spawn chance for rabbits.
	SpawnChance	= 0.20

	// Chance to ascend deeper (closer to /). The weight
	// has to be fair, because ascending is very limited
	// and you only have one option.
	AscendChance	= 0.30

	// Chance to move twice instead of once.
	TwoStepChance	= 0.50
)

type directoryForest struct {
	// List of rabbits and their locations. Only one
	// rabbit per location.
	rabbits		map[string]*Rabbit
	// Number of rabbits seen.
	spottedCount	uint
	// Number of rabbits caught.
	caughtCount	uint
	// Number of rabbits killed. :(
	killedCount	uint
}

func newDirectoryForest() directoryForest {
	return directoryForest{
		map[string]*Rabbit{}, 0, 0, 0,
	}
}

// For a location to exist, the directory must exist.
func (f *directoryForest) LocationExists(loc string) bool {
	fi, err := os.Stat(loc)
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Returns a location near the passed location. Nearby is
// found by a small number of random directory changes. Will
// not be the same directory, unless it has to (can't ascend
// or descend).
//
// XXX: Currently this does not check if a rabbit already
// exists at the new location. So we just lose rabbits
// if one encounters another.
func (f *directoryForest) NearbyLocation(loc string) string {
	newloc := loc

	steps := 1
	if chance(TwoStepChance) {
		steps = 2
	}

tryagain:
	for i := 0; i < steps; i++ {
		// Can't move.
		if !canAscend(newloc) && !canDescend(newloc) {
			return newloc
		} else if chance(AscendChance) {
			if canAscend(newloc) {
				newloc = ascend(newloc)
			} else {
				newloc = randDescension(newloc)
			}
		} else {
			if canDescend(newloc) {
				newloc = randDescension(newloc)
			} else {
				newloc = ascend(newloc)
			}
		}
	}

	if newloc == loc {
		// Guaranteed to not be the same because you must
		// step twice to get to the same destination.
		steps = 1
		goto tryagain
	}

	return newloc

}

// A random faraway location. Rabbits typically start here
// and run here when they're fleeing.
func (f *directoryForest) FarawayLocation(loc string) string {
	newloc := baseLocation()
	triedagain := false

	steps := 1
	if chance(TwoStepChance) {
		steps = 2
	}

tryagain:
	for i := 0; i < steps; i++ {
		if canDescend(newloc) {
			newloc = randDescension(newloc)
		}
	}

	if newloc == loc && !triedagain {
		// Invert the steps. We can't get to the same
		// location with different steps.
		if steps == 1 {
			steps = 2
		} else if steps == 2 {
			steps = 1
		}
		triedagain = true
		goto tryagain
	}

	return newloc
}

// Returns true if a rabbit is here. Only useful for checking
// before performing an action.
func (f *directoryForest) IsRabbitHere() bool {
	loc, _ := os.Getwd()
	_, ok := f.rabbits[loc]
	return ok
}

// Anytime a location is entered, a check is performed. This
// function updates every rabbit and returns a rabbit if one
// is spotted.
func (f *directoryForest) PerformCheck() (spotted *Rabbit) {
	spotted = nil

	// We always check our current directory.
	loc, _ := os.Getwd()

	newrabbits := map[string]*Rabbit{}

	for _, r := range f.rabbits {
		r.DisturbanceAt(loc)

		if (r.CanMove()) {
			if r.JustSpotted() {
				if spotted != nil {
					// XXX: Shouldn't happen.
					//panic("Spotted two rabbits. Impossible.")
				}
				spotted = r
				f.spottedCount++
			}
			newrabbits[r.Location()] = r
		} else {
			if r.State() == Dead {
				f.killedCount++
			} else if r.State() == Caught {
				// Being caught is updated in the TryCatch.
			}
		}
	}

	f.rabbits = newrabbits

	// See if we should repopulate.
	f.repopulate()

	return
}

// Attempts to catch a rabbit if it's still where we are.
func (f *directoryForest) PerformCatch() bool {
	loc, _ := os.Getwd()

	rab, ok := f.rabbits[loc]

	if ok {
		delete(f.rabbits, rab.Location())
		succ := rab.TryCatch(loc)
		// We must update the table, else we can run into two rabbits.
		f.rabbits[rab.Location()] = rab
		f.caughtCount++
		return succ
	}

	return false
}

// Attempts to tag a rabbit if it's still where we are.
func (f *directoryForest) PerformTag(tag string) bool {
	loc, _ := os.Getwd()

	rab, ok := f.rabbits[loc]

	if ok {
		delete(f.rabbits, rab.Location())
		succ := rab.TryTag(loc, tag)
		// We must update the table, else we can run into two rabbits.
		f.rabbits[rab.Location()] = rab
		return succ
	}

	return false
}

// Repopulated the forest if under the minimum number of rabbits
// we want. Otherwise, chance a rabbit will spawn.
func (f *directoryForest) repopulate() {
	for len(f.rabbits) < MinRabbits {
		r := NewRabbit(f)
		f.rabbits[r.Location()] = &r
	}

	if chance(SpawnChance) {
		r := NewRabbit(f)
		f.rabbits[r.Location()] = &r
	}
}

type forest struct {
	Rabbits		map[string]*Rabbit
	SpottedCount	uint
	CaughtCount	uint
	KilledCount	uint
}

// These are implemented because we can't encode private fields.
func (f *directoryForest) UnmarshalJSON(b []byte) error {
	data := forest{}
	err := json.Unmarshal(b, &data)
	if err != nil {
		return err
	}
	f.rabbits = data.Rabbits
	f.spottedCount = data.SpottedCount
	f.caughtCount = data.CaughtCount
	f.killedCount = data.KilledCount

	// Circular reference. Couldn't marshal their home so
	// we do it here.
	for _, r := range f.rabbits {
		(&r).ChangeHome(f)
	}
	return nil
}

func (f *directoryForest) MarshalJSON() ([]byte, error) {
	return json.Marshal(&forest{
		Rabbits:	f.rabbits,
		SpottedCount:	f.spottedCount,
		CaughtCount:	f.caughtCount,
		KilledCount:	f.killedCount,
	})
}
<commit_msg>Fixed counting unsucessful catches.<commit_after>
package main

import (
	"encoding/json"
	"os"
)

const (
	// Default value.
	MinRabbits	= 1
	// Default value. The numbers of rabbits that exist
	// at any given time.
	MaxRabbits	= 15
	// Spawn chance for rabbits.
	SpawnChance	= 0.20

	// Chance to ascend deeper (closer to /). The weight
	// has to be fair, because ascending is very limited
	// and you only have one option.
	AscendChance	= 0.30

	// Chance to move twice instead of once.
	TwoStepChance	= 0.50
)

type directoryForest struct {
	// List of rabbits and their locations. Only one
	// rabbit per location.
	rabbits		map[string]*Rabbit
	// Number of rabbits seen.
	spottedCount	uint
	// Number of rabbits caught.
	caughtCount	uint
	// Number of rabbits killed. :(
	killedCount	uint
}

func newDirectoryForest() directoryForest {
	return directoryForest{
		map[string]*Rabbit{}, 0, 0, 0,
	}
}

// For a location to exist, the directory must exist.
func (f *directoryForest) LocationExists(loc string) bool {
	fi, err := os.Stat(loc)
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Returns a location near the passed location. Nearby is
// found by a small number of random directory changes. Will
// not be the same directory, unless it has to (can't ascend
// or descend).
//
// XXX: Currently this does not check if a rabbit already
// exists at the new location. So we just lose rabbits
// if one encounters another.
func (f *directoryForest) NearbyLocation(loc string) string {
	newloc := loc

	steps := 1
	if chance(TwoStepChance) {
		steps = 2
	}

tryagain:
	for i := 0; i < steps; i++ {
		// Can't move.
		if !canAscend(newloc) && !canDescend(newloc) {
			return newloc
		} else if chance(AscendChance) {
			if canAscend(newloc) {
				newloc = ascend(newloc)
			} else {
				newloc = randDescension(newloc)
			}
		} else {
			if canDescend(newloc) {
				newloc = randDescension(newloc)
			} else {
				newloc = ascend(newloc)
			}
		}
	}

	if newloc == loc {
		// Guaranteed to not be the same because you must
		// step twice to get to the same destination.
		steps = 1
		goto tryagain
	}

	return newloc

}

// A random faraway location. Rabbits typically start here
// and run here when they're fleeing.
func (f *directoryForest) FarawayLocation(loc string) string {
	newloc := baseLocation()
	triedagain := false

	steps := 1
	if chance(TwoStepChance) {
		steps = 2
	}

tryagain:
	for i := 0; i < steps; i++ {
		if canDescend(newloc) {
			newloc = randDescension(newloc)
		}
	}

	if newloc == loc && !triedagain {
		// Invert the steps. We can't get to the same
		// location with different steps.
		if steps == 1 {
			steps = 2
		} else if steps == 2 {
			steps = 1
		}
		triedagain = true
		goto tryagain
	}

	return newloc
}

// Returns true if a rabbit is here. Only useful for checking
// before performing an action.
func (f *directoryForest) IsRabbitHere() bool {
	loc, _ := os.Getwd()
	_, ok := f.rabbits[loc]
	return ok
}

// Anytime a location is entered, a check is performed. This
// function updates every rabbit and returns a rabbit if one
// is spotted.
func (f *directoryForest) PerformCheck() (spotted *Rabbit) {
	spotted = nil

	// We always check our current directory.
	loc, _ := os.Getwd()

	newrabbits := map[string]*Rabbit{}

	for _, r := range f.rabbits {
		r.DisturbanceAt(loc)

		if (r.CanMove()) {
			if r.JustSpotted() {
				if spotted != nil {
					// XXX: Shouldn't happen.
					//panic("Spotted two rabbits. Impossible.")
				}
				spotted = r
				f.spottedCount++
			}
			newrabbits[r.Location()] = r
		} else {
			if r.State() == Dead {
				f.killedCount++
			} else if r.State() == Caught {
				// Being caught is updated in the TryCatch.
			}
		}
	}

	f.rabbits = newrabbits

	// See if we should repopulate.
	f.repopulate()

	return
}

// Attempts to catch a rabbit if it's still where we are.
func (f *directoryForest) PerformCatch() bool {
	loc, _ := os.Getwd()

	rab, ok := f.rabbits[loc]

	if ok {
		delete(f.rabbits, rab.Location())
		succ := rab.TryCatch(loc)
		// We must update the table, else we can run into two rabbits.
		f.rabbits[rab.Location()] = rab
		if succ {
			f.caughtCount++
		}
		return succ
	}

	return false
}

// Attempts to tag a rabbit if it's still where we are.
func (f *directoryForest) PerformTag(tag string) bool {
	loc, _ := os.Getwd()

	rab, ok := f.rabbits[loc]

	if ok {
		delete(f.rabbits, rab.Location())
		succ := rab.TryTag(loc, tag)
		// We must update the table, else we can run into two rabbits.
		f.rabbits[rab.Location()] = rab
		return succ
	}

	return false
}

// Repopulated the forest if under the minimum number of rabbits
// we want. Otherwise, chance a rabbit will spawn.
func (f *directoryForest) repopulate() {
	for len(f.rabbits) < MinRabbits {
		r := NewRabbit(f)
		f.rabbits[r.Location()] = &r
	}

	if chance(SpawnChance) {
		r := NewRabbit(f)
		f.rabbits[r.Location()] = &r
	}
}

type forest struct {
	Rabbits		map[string]*Rabbit
	SpottedCount	uint
	CaughtCount	uint
	KilledCount	uint
}

// These are implemented because we can't encode private fields.
func (f *directoryForest) UnmarshalJSON(b []byte) error {
	data := forest{}
	err := json.Unmarshal(b, &data)
	if err != nil {
		return err
	}
	f.rabbits = data.Rabbits
	f.spottedCount = data.SpottedCount
	f.caughtCount = data.CaughtCount
	f.killedCount = data.KilledCount

	// Circular reference. Couldn't marshal their home so
	// we do it here.
	for _, r := range f.rabbits {
		(&r).ChangeHome(f)
	}
	return nil
}

func (f *directoryForest) MarshalJSON() ([]byte, error) {
	return json.Marshal(&forest{
		Rabbits:	f.rabbits,
		SpottedCount:	f.spottedCount,
		CaughtCount:	f.caughtCount,
		KilledCount:	f.killedCount,
	})
}
<|endoftext|>


<commit_before>// Package formam implements functions to decode values of a html's form.
package formam

import (
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
)

const TAG_NAME = "formam"

// A pathMap holds the values of a map with its key and values correspondent
type pathMap struct {
	m reflect.Value

	key   string
	value reflect.Value
}

// a pathMaps holds the values for  each key
type pathMaps []*pathMap

// find find and get the value by the given key
func (ma pathMaps) find(id reflect.Value, key string) *pathMap {
	for _, v := range ma {
		if v.m == id && v.key == key {
			return v
		}
	}
	return nil
}

// A decoder holds the values from form, the 'reflect' value of main struct
// and the 'reflect' value of current path
type decoder struct {
	main reflect.Value
	curr reflect.Value

	maps pathMaps

	field string
	value string
	index int
}

// Decode decode the url.Values into struct provided by argument
func Decode(vv url.Values, dst interface{}) error {
	main := reflect.ValueOf(dst)
	if main.Kind() != reflect.Ptr || main.Elem().Kind() != reflect.Struct {
		return errors.New("formam: is not a pointer to struct")
	}
	d := &decoder{main: main.Elem()}
	for k, v := range vv {
		d.field = k
		d.value = v[0]
		if err := d.begin(); err != nil {
			return err
		}
	}
	for _, v := range d.maps {
		v.m.SetMapIndex(reflect.ValueOf(v.key), v.value)
	}
	d.maps = []*pathMap{}
	return nil
}

// decode prepare the current path to walk through it
func (d *decoder) begin() (err error) {
	d.curr = d.main
	fields := strings.Split(d.field, ".")
	for i, field := range fields {
		b := strings.IndexAny(field, "[")
		if b != -1 {
			// is a array
			e := strings.IndexAny(field, "]")
			if e == -1 {
				return errors.New("formam: bad syntax array")
			}
			d.field = field[:b]
			if d.index, err = strconv.Atoi(field[b+1 : e]); err != nil {
				return errors.New("formam: the index of array not is a number")
			}
			if len(fields) == i+1 {
				return d.end()
			}
			if d.curr, err = d.walk(); err != nil {
				return
			}
		} else {
			// not is a array
			d.field = field
			d.index = -1
			if len(fields) == i+1 {
				return d.end()
			}
			if d.curr, err = d.walk(); err != nil {
				return
			}
		}
	}
	return
}

// walk traverse the current path until to the last field
func (d *decoder) walk() (reflect.Value, error) {
	switch d.curr.Kind() {
	case reflect.Struct:
		if err := d.findField(); err != nil {
			return d.curr, err
		}
	case reflect.Map:
		d.currentMap()
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.walk()
	}
	if d.index != -1 {
		// should be a array...
		switch d.curr.Kind() {
		case reflect.Slice, reflect.Array:
			if d.curr.Len() <= d.index {
				d.expandSlice()
			}
			d.curr = d.curr.Index(d.index)
		default:
			return d.curr, fmt.Errorf("formam: the field \"%v\" has a index for array but it is not", d.field)
		}
	}
	return d.curr, nil
}

// end find the last field for decode its value correspondent
func (d *decoder) end() error {
	if d.curr.Kind() == reflect.Struct {
		if err := d.findField(); err != nil {
			return err
		}
	}
	if d.value == "" {
		return nil
	}
	return d.decode()
}

// decode set the value in its field
func (d *decoder) decode() error {
	switch d.curr.Kind() {
	case reflect.Map:
		d.currentMap()
		return d.decode()
	case reflect.Slice, reflect.Array:
		if d.curr.Len() <= d.index {
			d.expandSlice()
		}
		d.curr = d.curr.Index(d.index)
		return d.decode()
	case reflect.String:
		d.curr.SetString(d.value)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if num, err := strconv.ParseInt(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid signed integer number", d.field)
		} else {
			d.curr.SetInt(num)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if num, err := strconv.ParseUint(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid unsigned integer number", d.field)
		} else {
			d.curr.SetUint(num)
		}
	case reflect.Float32, reflect.Float64:
		if num, err := strconv.ParseFloat(d.value, d.curr.Type().Bits()); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid float number", d.field)
		} else {
			d.curr.SetFloat(num)
		}
	case reflect.Bool:
		switch d.value {
		case "true", "on", "1":
			d.curr.SetBool(true)
		case "false", "0":
			d.curr.SetBool(false)
		default:
			return fmt.Errorf("formam: the value \"%v\" is not a valid boolean", d.field)
		}
	case reflect.Interface:
		d.curr.Set(reflect.ValueOf(d.value))
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.decode()
	default:
		return fmt.Errorf("formam: not supported type for field \"%v\"", d.field)
	}
	return nil
}

// findField find a field by its name, if it is not found,
// then retry the search examining the tag "formam" of every field of struct
func (d *decoder) findField() error {
	num := d.curr.NumField()
	for i := 0; i < num; i++ {
		field := d.curr.Type().Field(i)
		if field.Name == d.field {
			// check if the field's name is equal
			d.curr = d.curr.Field(i)
			return nil
		} else if field.Anonymous {
			// if the field is a anonymous struct, then iterate over its fields
			d.curr = d.curr.FieldByIndex(field.Index)
			return d.findField()
		} else if d.field == field.Tag.Get(TAG_NAME) {
			// is not found yet, then retry by its tag name "formam"
			d.curr = d.curr.Field(i)
			return nil
		}
	}
	return fmt.Errorf("formam: not found the field \"%v\"", d.field)
}

// expandSlice expand the length and capacity of the current slice
func (d *decoder) expandSlice() {
	sli := reflect.MakeSlice(d.curr.Type(), d.index+1, d.index+1)
	reflect.Copy(sli, d.curr)
	d.curr.Set(sli)
}

// currentMap get in d.curr the map concrete for decode the current value
func (d *decoder) currentMap() {
	typ := d.curr.Type()
	if d.curr.IsNil() {
		d.curr.Set(reflect.MakeMap(typ))
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v})
		d.curr = v
	} else if a := d.maps.find(d.curr, d.field); a == nil {
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v})
		d.curr = v
	} else {
		d.curr = a.value
	}
}
<commit_msg>clean code<commit_after>// Package formam implements functions to decode values of a html's form.
package formam

import (
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
)

const TAG_NAME = "formam"

// A pathMap holds the values of a map with its key and values correspondent
type pathMap struct {
	m reflect.Value

	key   string
	value reflect.Value
}

// a pathMaps holds the values for  each key
type pathMaps []*pathMap

// find find and get the value by the given key
func (ma pathMaps) find(id reflect.Value, key string) *pathMap {
	for _, v := range ma {
		if v.m == id && v.key == key {
			return v
		}
	}
	return nil
}

// A decoder holds the values from form, the 'reflect' value of main struct
// and the 'reflect' value of current path
type decoder struct {
	main reflect.Value
	curr reflect.Value

	maps pathMaps

	field string
	value string
	index int
}

// Decode decode the url.Values into struct provided by argument
func Decode(vs url.Values, dst interface{}) error {
	main := reflect.ValueOf(dst)
	if main.Kind() != reflect.Ptr || main.Elem().Kind() != reflect.Struct {
		return errors.New("formam: is not a pointer to struct")
	}
	d := &decoder{main: main.Elem()}
	for k, v := range vs {
		d.field = k
		d.value = v[0]
		if err := d.begin(); err != nil {
			return err
		}
	}
	for _, v := range d.maps {
		v.m.SetMapIndex(reflect.ValueOf(v.key), v.value)
	}
	d.maps = []*pathMap{}
	return nil
}

// begin prepare the current path to walk through it
func (d *decoder) begin() (err error) {
	d.curr = d.main
	fields := strings.Split(d.field, ".")
	for i, field := range fields {
		b := strings.IndexAny(field, "[")
		if b != -1 {
			// is a array
			e := strings.IndexAny(field, "]")
			if e == -1 {
				return errors.New("formam: bad syntax array")
			}
			d.field = field[:b]
			if d.index, err = strconv.Atoi(field[b+1 : e]); err != nil {
				return errors.New("formam: the index of array not is a number")
			}
			if len(fields) == i+1 {
				return d.end()
			}
			if d.curr, err = d.walk(); err != nil {
				return
			}
		} else {
			// not is a array
			d.field = field
			d.index = -1
			if len(fields) == i+1 {
				return d.end()
			}
			if d.curr, err = d.walk(); err != nil {
				return
			}
		}
	}
	return
}

// walk traverse the current path until to the last field
func (d *decoder) walk() (reflect.Value, error) {
	switch d.curr.Kind() {
	case reflect.Struct:
		if err := d.findField(); err != nil {
			return d.curr, err
		}
	case reflect.Map:
		d.currentMap()
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.walk()
	}
	if d.index != -1 {
		// should be a array...
		switch d.curr.Kind() {
		case reflect.Slice, reflect.Array:
			if d.curr.Len() <= d.index {
				d.expandSlice()
			}
			d.curr = d.curr.Index(d.index)
		default:
			return d.curr, fmt.Errorf("formam: the field \"%v\" has a index for array but it is not", d.field)
		}
	}
	return d.curr, nil
}

// end find the last field for decode its value correspondent
func (d *decoder) end() error {
	if d.curr.Kind() == reflect.Struct {
		if err := d.findField(); err != nil {
			return err
		}
	}
	if d.value == "" {
		return nil
	}
	return d.decode()
}

// decode set the value in its field
func (d *decoder) decode() error {
	switch d.curr.Kind() {
	case reflect.Map:
		d.currentMap()
		return d.decode()
	case reflect.Slice, reflect.Array:
		if d.curr.Len() <= d.index {
			d.expandSlice()
		}
		d.curr = d.curr.Index(d.index)
		return d.decode()
	case reflect.String:
		d.curr.SetString(d.value)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if num, err := strconv.ParseInt(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid signed integer number", d.field)
		} else {
			d.curr.SetInt(num)
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if num, err := strconv.ParseUint(d.value, 10, 64); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid unsigned integer number", d.field)
		} else {
			d.curr.SetUint(num)
		}
	case reflect.Float32, reflect.Float64:
		if num, err := strconv.ParseFloat(d.value, d.curr.Type().Bits()); err != nil {
			return fmt.Errorf("formam: the value \"%v\" should be a valid float number", d.field)
		} else {
			d.curr.SetFloat(num)
		}
	case reflect.Bool:
		switch d.value {
		case "true", "on", "1":
			d.curr.SetBool(true)
		case "false", "0":
			d.curr.SetBool(false)
		default:
			return fmt.Errorf("formam: the value \"%v\" is not a valid boolean", d.field)
		}
	case reflect.Interface:
		d.curr.Set(reflect.ValueOf(d.value))
	case reflect.Ptr:
		d.curr.Set(reflect.New(d.curr.Type().Elem()))
		d.curr = d.curr.Elem()
		return d.decode()
	default:
		return fmt.Errorf("formam: not supported type for field \"%v\"", d.field)
	}
	return nil
}

// findField find a field by its name, if it is not found,
// then retry the search examining the tag "formam" of every field of struct
func (d *decoder) findField() error {
	num := d.curr.NumField()
	for i := 0; i < num; i++ {
		field := d.curr.Type().Field(i)
		if field.Name == d.field {
			// check if the field's name is equal
			d.curr = d.curr.Field(i)
			return nil
		} else if field.Anonymous {
			// if the field is a anonymous struct, then iterate over its fields
			d.curr = d.curr.FieldByIndex(field.Index)
			return d.findField()
		} else if d.field == field.Tag.Get(TAG_NAME) {
			// is not found yet, then retry by its tag name "formam"
			d.curr = d.curr.Field(i)
			return nil
		}
	}
	return fmt.Errorf("formam: not found the field \"%v\"", d.field)
}

// expandSlice expand the length and capacity of the current slice
func (d *decoder) expandSlice() {
	sli := reflect.MakeSlice(d.curr.Type(), d.index+1, d.index+1)
	reflect.Copy(sli, d.curr)
	d.curr.Set(sli)
}

// currentMap get in d.curr the map concrete for decode the current value
func (d *decoder) currentMap() {
	typ := d.curr.Type()
	if d.curr.IsNil() {
		d.curr.Set(reflect.MakeMap(typ))
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v})
		d.curr = v
	} else if a := d.maps.find(d.curr, d.field); a == nil {
		v := reflect.New(typ.Elem()).Elem()
		d.maps = append(d.maps, &pathMap{d.curr, d.field, v})
		d.curr = v
	} else {
		d.curr = a.value
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mesh

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/golang/glog"
	"github.com/weaveworks/mesh"
	"k8s.io/kops/protokube/pkg/gossip"
)

type MeshGossiper struct {
	seeds gossip.SeedProvider

	router *mesh.Router
	peer   *peer

	version uint64

	lastSnapshot *gossip.GossipStateSnapshot
}

func NewMeshGossiper(listen string, channelName string, nodeName string, password []byte, seeds gossip.SeedProvider) (*MeshGossiper, error) {

	connLimit := 64
	gossipDnsConnLimit := os.Getenv("GOSSIP_DNS_CONN_LIMIT")
	if gossipDnsConnLimit != "" {
		limit, err := strconv.Atoi(gossipDnsConnLimit)
		if err != nil {
			return nil, fmt.Errorf("cannot parse env GOSSIP_DNS_CONN_LIMIT value: %v, err:%v", gossipDnsConnLimit, err)
		}
		connLimit = limit
	}

	glog.Infof("gossip dns connection limit is:%d", connLimit)

	meshConfig := mesh.Config{
		ProtocolMinVersion: mesh.ProtocolMinVersion,
		Password:           password,
		ConnLimit:          connLimit,
		PeerDiscovery:      true,
		//TrustedSubnets:     []*net.IPNet{},
	}

	{
		host, portString, err := net.SplitHostPort(listen)
		if err != nil {
			return nil, fmt.Errorf("cannot parse -listen flag: %v", listen)
		}
		port, err := strconv.Atoi(portString)
		if err != nil {
			return nil, fmt.Errorf("cannot parse -listen flag: %v", listen)
		}
		meshConfig.Host = host
		meshConfig.Port = port
	}

	meshName, err := mesh.PeerNameFromUserInput(nodeName)
	if err != nil {
		return nil, fmt.Errorf("error parsing peer name: %v", err)
	}

	nickname := nodeName
	logger := &glogLogger{}
	router := mesh.NewRouter(meshConfig, meshName, nickname, mesh.NullOverlay{}, logger)

	peer := newPeer(meshName)
	gossip := router.NewGossip(channelName, peer)
	peer.register(gossip)

	gossiper := &MeshGossiper{
		seeds:  seeds,
		router: router,
		peer:   peer,
	}
	return gossiper, nil
}

func (g *MeshGossiper) Start() error {
	//glog.Infof("mesh router starting (%s)", *meshListen)
	g.router.Start()

	defer func() {
		glog.Infof("mesh router stopping")
		g.router.Stop()
	}()

	g.runSeeding()

	return nil
}

func (g *MeshGossiper) runSeeding() {
	for {
		glog.V(2).Infof("Querying for seeds")

		seeds, err := g.seeds.GetSeeds()
		if err != nil {
			glog.Warningf("error getting seeds: %v", err)
			time.Sleep(1 * time.Minute)
			continue
		}

		glog.Infof("Got seeds: %s", seeds)
		// TODO: Include ourselves?  Exclude ourselves?

		removeOthers := false
		errors := g.router.ConnectionMaker.InitiateConnections(seeds, removeOthers)

		if len(errors) != 0 {
			for _, err := range errors {
				glog.Infof("error connecting to seeds: %v", err)
			}

			time.Sleep(1 * time.Minute)
			continue
		}

		glog.V(2).Infof("Seeding successful")

		// Reseed periodically, just in case of partitions
		// TODO: Make it so that only one node polls, or at least statistically get close
		time.Sleep(60 * time.Minute)
	}
}

func (g *MeshGossiper) Snapshot() *gossip.GossipStateSnapshot {
	return g.peer.snapshot()
}

func (g *MeshGossiper) UpdateValues(removeKeys []string, putEntries map[string]string) error {
	glog.V(2).Infof("UpdateValues: remove=%s, put=%s", removeKeys, putEntries)
	return g.peer.updateValues(removeKeys, putEntries)
}
<commit_msg>Remove gossip connection limit entirely<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mesh

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/golang/glog"
	"github.com/weaveworks/mesh"
	"k8s.io/kops/protokube/pkg/gossip"
)

type MeshGossiper struct {
	seeds gossip.SeedProvider

	router *mesh.Router
	peer   *peer

	version uint64

	lastSnapshot *gossip.GossipStateSnapshot
}

func NewMeshGossiper(listen string, channelName string, nodeName string, password []byte, seeds gossip.SeedProvider) (*MeshGossiper, error) {

	connLimit := 0 // 0 means no limit
	gossipDnsConnLimit := os.Getenv("GOSSIP_DNS_CONN_LIMIT")
	if gossipDnsConnLimit != "" {
		limit, err := strconv.Atoi(gossipDnsConnLimit)
		if err != nil {
			// Continue with the default value
			glog.Warningf("cannot parse env GOSSIP_DNS_CONN_LIMIT value %q", gossipDnsConnLimit)
		} else {
			connLimit = limit
		}
	}

	glog.Infof("gossip dns connection limit is:%d", connLimit)

	meshConfig := mesh.Config{
		ProtocolMinVersion: mesh.ProtocolMinVersion,
		Password:           password,
		ConnLimit:          connLimit,
		PeerDiscovery:      true,
		//TrustedSubnets:     []*net.IPNet{},
	}

	{
		host, portString, err := net.SplitHostPort(listen)
		if err != nil {
			return nil, fmt.Errorf("cannot parse -listen flag: %v", listen)
		}
		port, err := strconv.Atoi(portString)
		if err != nil {
			return nil, fmt.Errorf("cannot parse -listen flag: %v", listen)
		}
		meshConfig.Host = host
		meshConfig.Port = port
	}

	meshName, err := mesh.PeerNameFromUserInput(nodeName)
	if err != nil {
		return nil, fmt.Errorf("error parsing peer name: %v", err)
	}

	nickname := nodeName
	logger := &glogLogger{}
	router := mesh.NewRouter(meshConfig, meshName, nickname, mesh.NullOverlay{}, logger)

	peer := newPeer(meshName)
	gossip := router.NewGossip(channelName, peer)
	peer.register(gossip)

	gossiper := &MeshGossiper{
		seeds:  seeds,
		router: router,
		peer:   peer,
	}
	return gossiper, nil
}

func (g *MeshGossiper) Start() error {
	//glog.Infof("mesh router starting (%s)", *meshListen)
	g.router.Start()

	defer func() {
		glog.Infof("mesh router stopping")
		g.router.Stop()
	}()

	g.runSeeding()

	return nil
}

func (g *MeshGossiper) runSeeding() {
	for {
		glog.V(2).Infof("Querying for seeds")

		seeds, err := g.seeds.GetSeeds()
		if err != nil {
			glog.Warningf("error getting seeds: %v", err)
			time.Sleep(1 * time.Minute)
			continue
		}

		glog.Infof("Got seeds: %s", seeds)
		// TODO: Include ourselves?  Exclude ourselves?

		removeOthers := false
		errors := g.router.ConnectionMaker.InitiateConnections(seeds, removeOthers)

		if len(errors) != 0 {
			for _, err := range errors {
				glog.Infof("error connecting to seeds: %v", err)
			}

			time.Sleep(1 * time.Minute)
			continue
		}

		glog.V(2).Infof("Seeding successful")

		// Reseed periodically, just in case of partitions
		// TODO: Make it so that only one node polls, or at least statistically get close
		time.Sleep(60 * time.Minute)
	}
}

func (g *MeshGossiper) Snapshot() *gossip.GossipStateSnapshot {
	return g.peer.snapshot()
}

func (g *MeshGossiper) UpdateValues(removeKeys []string, putEntries map[string]string) error {
	glog.V(2).Infof("UpdateValues: remove=%s, put=%s", removeKeys, putEntries)
	return g.peer.updateValues(removeKeys, putEntries)
}
<|endoftext|>


<commit_before>package assemble

import (
	"reflect"
	"testing"
)

type ptestcase struct {
	in  string
	out []instruction
}

func TestGenerateMov(t *testing.T) {
	tests := []ptestcase{
		ptestcase{"MOV R0, R3", []instruction{tworeg{xor, 0, 0}, tworeg{add, 0, 3}}},
	}
	for _, test := range tests {
		out := generateMov(test.in).translate()
		if !reflect.DeepEqual(out, test.out) {
			t.Error("Got", out, "expected", test.out)
		}
	}
}
<commit_msg>Loadi for sure works<commit_after>package assemble

import (
	"reflect"
	"testing"
)

type ptestcase struct {
	in  string
	out []instruction
}

func TestGenerateMov(t *testing.T) {
	tests := []ptestcase{
		ptestcase{"MOV R0, R3", []instruction{tworeg{xor, 0, 0}, tworeg{add, 0, 3}}},
	}
	for _, test := range tests {
		out := generateMov(test.in).translate()
		if !reflect.DeepEqual(out, test.out) {
			t.Error("Got", out, "expected", test.out)
		}
	}
}

func TestGenerateLoadi(t *testing.T) {
	tests := []ptestcase{
		ptestcase{"LOADI 0xFF", []instruction{loadi{true, 0xF}, loadi{false, 0xF}}},
		ptestcase{"LOADI 0xF0", []instruction{loadi{true, 0x0}, loadi{false, 0xF}}},
	}
	for _, test := range tests {
		out := generateLoadi(test.in).translate()
		if !reflect.DeepEqual(out, test.out) {
			t.Error("Got", out, "expected", test.out)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 Arne Roomann-Kurrik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package twittergo

import (
	"bytes"
	"fmt"
	"net/http"
	"testing"
	"time"
)

type Body struct {
	*bytes.Buffer
}

func NewBody(body string) *Body {
	return &Body{
		Buffer: bytes.NewBufferString(body),
	}
}

func (b *Body) Close() error {
	return nil
}

func getResponse(code int, body string) *http.Response {
	var resp = &http.Response{}
	resp.Body = NewBody(body)
	resp.Header = http.Header(map[string][]string{})
	resp.StatusCode = code
	return resp
}

func TestRateLimitError(t *testing.T) {
	// Setup
	var body = `{"errors":[{"message":"Rate limit exceeded","code":88}]}`
	var resp = getResponse(429, body)
	resp.Status = "Too Many Requests"
	resp.Header = http.Header(map[string][]string{
		"Content-Length":         []string{"56"},
		"X-Rate-Limit-Limit":     []string{"180"},
		"X-Rate-Limit-Remaining": []string{"0"},
		"X-Rate-Limit-Reset":     []string{"1369331745"},
	})

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		rle      RateLimitError
		ok       bool
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if rle, ok = err.(RateLimitError); !ok {
		t.Fatalf("Expected a RateLimitError error")
	}
	if !rle.Reset.Equal(time.Unix(1369331745, 0)) {
		t.Errorf("Reset not parsed correctly, got %v", rle.Reset)
	}
	if rle.Remaining != 0 {
		t.Errorf("Remaining not parsed correctly, got %v", rle.Remaining)
	}
	if rle.Limit != 180 {
		t.Errorf("Limit not parsed correctly, got %v", rle.Limit)
	}
}

func TestErrorsError(t *testing.T) {
	// Setup
	var err1 = `{"code":187,"message":"Status is a duplicate"}`
	var err2 = `{"message":"Rate limit exceeded","code":88}`
	var body = fmt.Sprintf(`{"errors":[%v,%v]}`, err1, err2)
	var resp = getResponse(403, body)
	resp.Status = "Forbidden"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		errs     Errors
		ok       bool
		code     int64
		msg      string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if errs, ok = err.(Errors); !ok {
		t.Fatalf("Expected a RateLimitError error")
	}
	if len(errs.Errors()) != 2 {
		t.Fatalf("Expected 2 errors to be parsed")
	}
	code = errs.Errors()[0].Code()
	if code != 187 {
		t.Errorf("Expected 187, got %v", code)
	}
	msg = errs.Errors()[0].Message()
	if msg != "Status is a duplicate" {
		t.Errorf("Got incorrect dupe status text: %v", msg)
	}
	code = errs.Errors()[1].Code()
	if code != 88 {
		t.Errorf("Expected 88, got %v", code)
	}
	msg = errs.Errors()[1].Message()
	if msg != "Rate limit exceeded" {
		t.Errorf("Got incorrect rle text: %v", msg)
	}
}

func TestNonJSONErrorWith500(t *testing.T) {
	// Setup
	var body = `<!DOCTYPE html><html><body>Foo</body></html>`
	var resp = getResponse(500, body)
	resp.Status = "Server Error"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		ok       bool
		err_str  string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if _, ok = err.(RateLimitError); ok {
		t.Fatalf("Error should not parse to a RateLimitError error")
	}
	if _, ok = err.(Errors); ok {
		t.Fatalf("Error should not parse to a Errors error (ugh)")
	}
	err_str = fmt.Sprintf("%v", err)
	if err_str != body {
		t.Errorf("Error should be text of response body")
	}
}

func TestNonJSONErrorWith502(t *testing.T) {
	// Setup
	var body = `<!DOCTYPE html><html><body>Foo</body></html>`
	var resp = getResponse(502, body)
	resp.Status = "Bad Gateway"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		ok       bool
		err_str  string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if _, ok = err.(RateLimitError); ok {
		t.Fatalf("Error should not parse to a RateLimitError error")
	}
	if _, ok = err.(Errors); ok {
		t.Fatalf("Error should not parse to a Errors error (ugh)")
	}
	err_str = fmt.Sprintf("%v", err)
	if err_str != body {
		t.Errorf("Error should be text of response body")
	}
}

<commit_msg>Update test copyright date.<commit_after>// Copyright 2013 Arne Roomann-Kurrik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package twittergo

import (
	"bytes"
	"fmt"
	"net/http"
	"testing"
	"time"
)

type Body struct {
	*bytes.Buffer
}

func NewBody(body string) *Body {
	return &Body{
		Buffer: bytes.NewBufferString(body),
	}
}

func (b *Body) Close() error {
	return nil
}

func getResponse(code int, body string) *http.Response {
	var resp = &http.Response{}
	resp.Body = NewBody(body)
	resp.Header = http.Header(map[string][]string{})
	resp.StatusCode = code
	return resp
}

func TestRateLimitError(t *testing.T) {
	// Setup
	var body = `{"errors":[{"message":"Rate limit exceeded","code":88}]}`
	var resp = getResponse(429, body)
	resp.Status = "Too Many Requests"
	resp.Header = http.Header(map[string][]string{
		"Content-Length":         []string{"56"},
		"X-Rate-Limit-Limit":     []string{"180"},
		"X-Rate-Limit-Remaining": []string{"0"},
		"X-Rate-Limit-Reset":     []string{"1369331745"},
	})

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		rle      RateLimitError
		ok       bool
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if rle, ok = err.(RateLimitError); !ok {
		t.Fatalf("Expected a RateLimitError error")
	}
	if !rle.Reset.Equal(time.Unix(1369331745, 0)) {
		t.Errorf("Reset not parsed correctly, got %v", rle.Reset)
	}
	if rle.Remaining != 0 {
		t.Errorf("Remaining not parsed correctly, got %v", rle.Remaining)
	}
	if rle.Limit != 180 {
		t.Errorf("Limit not parsed correctly, got %v", rle.Limit)
	}
}

func TestErrorsError(t *testing.T) {
	// Setup
	var err1 = `{"code":187,"message":"Status is a duplicate"}`
	var err2 = `{"message":"Rate limit exceeded","code":88}`
	var body = fmt.Sprintf(`{"errors":[%v,%v]}`, err1, err2)
	var resp = getResponse(403, body)
	resp.Status = "Forbidden"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		errs     Errors
		ok       bool
		code     int64
		msg      string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if errs, ok = err.(Errors); !ok {
		t.Fatalf("Expected a RateLimitError error")
	}
	if len(errs.Errors()) != 2 {
		t.Fatalf("Expected 2 errors to be parsed")
	}
	code = errs.Errors()[0].Code()
	if code != 187 {
		t.Errorf("Expected 187, got %v", code)
	}
	msg = errs.Errors()[0].Message()
	if msg != "Status is a duplicate" {
		t.Errorf("Got incorrect dupe status text: %v", msg)
	}
	code = errs.Errors()[1].Code()
	if code != 88 {
		t.Errorf("Expected 88, got %v", code)
	}
	msg = errs.Errors()[1].Message()
	if msg != "Rate limit exceeded" {
		t.Errorf("Got incorrect rle text: %v", msg)
	}
}

func TestNonJSONErrorWith500(t *testing.T) {
	// Setup
	var body = `<!DOCTYPE html><html><body>Foo</body></html>`
	var resp = getResponse(500, body)
	resp.Status = "Server Error"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		ok       bool
		err_str  string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if _, ok = err.(RateLimitError); ok {
		t.Fatalf("Error should not parse to a RateLimitError error")
	}
	if _, ok = err.(Errors); ok {
		t.Fatalf("Error should not parse to a Errors error (ugh)")
	}
	err_str = fmt.Sprintf("%v", err)
	if err_str != body {
		t.Errorf("Error should be text of response body")
	}
}

func TestNonJSONErrorWith502(t *testing.T) {
	// Setup
	var body = `<!DOCTYPE html><html><body>Foo</body></html>`
	var resp = getResponse(502, body)
	resp.Status = "Bad Gateway"
	resp.Header.Set("Content-Length", fmt.Sprintf("%v", len(body)))

	// Test
	var (
		api_resp *APIResponse
		tweet    *Tweet
		err      error
		ok       bool
		err_str  string
	)
	api_resp = (*APIResponse)(resp)
	tweet = &Tweet{}
	err = api_resp.Parse(tweet)
	if err == nil {
		t.Fatalf("Expected an error in Parse")
	}
	if _, ok = err.(RateLimitError); ok {
		t.Fatalf("Error should not parse to a RateLimitError error")
	}
	if _, ok = err.(Errors); ok {
		t.Fatalf("Error should not parse to a Errors error (ugh)")
	}
	err_str = fmt.Sprintf("%v", err)
	if err_str != body {
		t.Errorf("Error should be text of response body")
	}
}

<|endoftext|>


<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglematchers

import (
	"errors"
	"fmt"
	"reflect"
	"regexp"
)

// MatchesRegexp returns a matcher that matches strings and byte slices whose
// contents match the supplide regular expression. The semantics are those of
// regexp.Match. In particular, that means the match is not implicitly anchored
// to the ends of the string: MatchesRegexp("bar") will match "foo bar baz".
func MatchesRegexp(pattern string) Matcher {
	re, err := regexp.Compile(pattern)
	if err != nil {
		panic("MatchesRegexp: " + err.Error())
	}

	return &matchesRegexpMatcher{re}
}

type matchesRegexpMatcher struct {
	re *regexp.Regexp
}

func (m *matchesRegexpMatcher) Description() string {
	return fmt.Sprintf("matches regexp \"%s\"", m.re.String())
}

func (m *matchesRegexpMatcher) Matches(c interface{}) (err error) {
	v := reflect.ValueOf(c)
	isString := v.Kind() == reflect.String
	isByteSlice := v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Uint8

	err = errors.New("")

	switch {
	case isString:
		if m.re.MatchString(v.String()) {
			err = nil
		}

	case isByteSlice:
		if m.re.Match(v.Bytes()) {
			err = nil
		}

	default:
		err = NewFatalError("which is not a string or []byte")
	}

	return
}
<commit_msg>Fixed a typo.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglematchers

import (
	"errors"
	"fmt"
	"reflect"
	"regexp"
)

// MatchesRegexp returns a matcher that matches strings and byte slices whose
// contents match the supplied regular expression. The semantics are those of
// regexp.Match. In particular, that means the match is not implicitly anchored
// to the ends of the string: MatchesRegexp("bar") will match "foo bar baz".
func MatchesRegexp(pattern string) Matcher {
	re, err := regexp.Compile(pattern)
	if err != nil {
		panic("MatchesRegexp: " + err.Error())
	}

	return &matchesRegexpMatcher{re}
}

type matchesRegexpMatcher struct {
	re *regexp.Regexp
}

func (m *matchesRegexpMatcher) Description() string {
	return fmt.Sprintf("matches regexp \"%s\"", m.re.String())
}

func (m *matchesRegexpMatcher) Matches(c interface{}) (err error) {
	v := reflect.ValueOf(c)
	isString := v.Kind() == reflect.String
	isByteSlice := v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Uint8

	err = errors.New("")

	switch {
	case isString:
		if m.re.MatchString(v.String()) {
			err = nil
		}

	case isByteSlice:
		if m.re.Match(v.Bytes()) {
			err = nil
		}

	default:
		err = NewFatalError("which is not a string or []byte")
	}

	return
}
<|endoftext|>


<commit_before>package httpserver

import (
	"net/http"
	"strconv"

	"github.com/prometheus/client_golang/prometheus"

	"github.com/linkedin/Burrow/core/protocol"

	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	consumerTotalLagGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_lag_total",
			Help: "The sum of all partition current lag values for the group",
		},
		[]string{"cluster", "consumer_group"},
	)

	consumerStatusGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_status",
			Help: "The status of the consumer group. It is calculated from the highest status for the individual partitions. Statuses are an index list from NOTFOUND, OK, WARN, ERR, STOP, STALL, REWIND",
		},
		[]string{"cluster", "consumer_group"},
	)

	consumerPartitionCurrentOffset = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_current_offset",
			Help: "Latest offset that Burrow is storing for this partition",
		},
		[]string{"cluster", "consumer_group", "topic", "partition"},
	)

	consumerPartitionLagGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_partition_lag",
			Help: "Number of messages the consumer group is behind by for a partition as reported by Burrow",
		},
		[]string{"cluster", "consumer_group", "topic", "partition"},
	)

	topicPartitionOffsetGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_topic_partition_offset",
			Help: "Latest offset the topic that Burrow is storing for this partition",
		},
		[]string{"cluster", "topic", "partition"},
	)
)

func (hc *Coordinator) handlePrometheusMetrics() http.HandlerFunc {
	promHandler := promhttp.Handler()

	return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		for _, cluster := range listClusters(hc.App) {
			for _, consumer := range listConsumers(hc.App, cluster) {
				consumerStatus := getFullConsumerStatus(hc.App, cluster, consumer)

				if consumerStatus == nil ||
					consumerStatus.Status == protocol.StatusNotFound ||
					consumerStatus.Complete < 1.0 {
					continue
				}

				labels := map[string]string{
					"cluster":        cluster,
					"consumer_group": consumer,
				}

				consumerTotalLagGauge.With(labels).Set(float64(consumerStatus.TotalLag))
				consumerStatusGauge.With(labels).Set(float64(consumerStatus.Status))

				for _, partition := range consumerStatus.Partitions {
					if partition.Complete < 1.0 {
						continue
					}

					labels := map[string]string{
						"cluster":        cluster,
						"consumer_group": consumer,
						"topic":          partition.Topic,
						"partition":      strconv.FormatInt(int64(partition.Partition), 10),
					}

					consumerPartitionCurrentOffset.With(labels).Set(float64(partition.End.Offset))
					consumerPartitionLagGauge.With(labels).Set(float64(partition.CurrentLag))
				}
			}

			// Topics
			for _, topic := range listTopics(hc.App, cluster) {
				for partitionNumber, offset := range getTopicDetail(hc.App, cluster, topic) {
					topicPartitionOffsetGauge.With(map[string]string{
						"cluster":   cluster,
						"topic":     topic,
						"partition": strconv.FormatInt(int64(partitionNumber), 10),
					}).Set(float64(offset))
				}
			}
		}

		promHandler.ServeHTTP(resp, req)
	})
}

func listClusters(app *protocol.ApplicationContext) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchClusters,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func listConsumers(app *protocol.ApplicationContext, cluster string) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchConsumers,
		Cluster:     cluster,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func getFullConsumerStatus(app *protocol.ApplicationContext, cluster, consumer string) *protocol.ConsumerGroupStatus {
	request := &protocol.EvaluatorRequest{
		Cluster: cluster,
		Group:   consumer,
		ShowAll: true,
		Reply:   make(chan *protocol.ConsumerGroupStatus),
	}
	app.EvaluatorChannel <- request
	response := <-request.Reply
	return response
}

func listTopics(app *protocol.ApplicationContext, cluster string) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchTopics,
		Cluster:     cluster,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func getTopicDetail(app *protocol.ApplicationContext, cluster, topic string) []int64 {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchTopic,
		Cluster:     cluster,
		Topic:       topic,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []int64{}
	}

	return response.([]int64)
}
<commit_msg>fix metric reporting<commit_after>package httpserver

import (
	"net/http"
	"strconv"

	"github.com/prometheus/client_golang/prometheus"

	"github.com/linkedin/Burrow/core/protocol"

	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	consumerTotalLagGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_lag_total",
			Help: "The sum of all partition current lag values for the group",
		},
		[]string{"cluster", "consumer_group"},
	)

	consumerStatusGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_status",
			Help: "The status of the consumer group. It is calculated from the highest status for the individual partitions. Statuses are an index list from NOTFOUND, OK, WARN, ERR, STOP, STALL, REWIND",
		},
		[]string{"cluster", "consumer_group"},
	)

	consumerPartitionCurrentOffset = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_current_offset",
			Help: "Latest offset that Burrow is storing for this partition",
		},
		[]string{"cluster", "consumer_group", "topic", "partition"},
	)

	consumerPartitionLagGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_consumer_partition_lag",
			Help: "Number of messages the consumer group is behind by for a partition as reported by Burrow",
		},
		[]string{"cluster", "consumer_group", "topic", "partition"},
	)

	topicPartitionOffsetGauge = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "burrow_kafka_topic_partition_offset",
			Help: "Latest offset the topic that Burrow is storing for this partition",
		},
		[]string{"cluster", "topic", "partition"},
	)
)

func (hc *Coordinator) handlePrometheusMetrics() http.HandlerFunc {
	promHandler := promhttp.Handler()

	return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		for _, cluster := range listClusters(hc.App) {
			for _, consumer := range listConsumers(hc.App, cluster) {
				consumerStatus := getFullConsumerStatus(hc.App, cluster, consumer)

				if consumerStatus == nil ||
					consumerStatus.Status == protocol.StatusNotFound {
					continue
				}

				labels := map[string]string{
					"cluster":        cluster,
					"consumer_group": consumer,
				}

				consumerTotalLagGauge.With(labels).Set(float64(consumerStatus.TotalLag))
				consumerStatusGauge.With(labels).Set(float64(consumerStatus.Status))

				for _, partition := range consumerStatus.Partitions {

					labels := map[string]string{
						"cluster":        cluster,
						"consumer_group": consumer,
						"topic":          partition.Topic,
						"partition":      strconv.FormatInt(int64(partition.Partition), 10),
					}

					consumerPartitionLagGauge.With(labels).Set(float64(partition.CurrentLag))

					if partition.Complete >= 1.0 {
						consumerPartitionCurrentOffset.With(labels).Set(float64(partition.End.Offset))
					}
				}
			}

			// Topics
			for _, topic := range listTopics(hc.App, cluster) {
				for partitionNumber, offset := range getTopicDetail(hc.App, cluster, topic) {
					topicPartitionOffsetGauge.With(map[string]string{
						"cluster":   cluster,
						"topic":     topic,
						"partition": strconv.FormatInt(int64(partitionNumber), 10),
					}).Set(float64(offset))
				}
			}
		}

		promHandler.ServeHTTP(resp, req)
	})
}

func listClusters(app *protocol.ApplicationContext) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchClusters,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func listConsumers(app *protocol.ApplicationContext, cluster string) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchConsumers,
		Cluster:     cluster,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func getFullConsumerStatus(app *protocol.ApplicationContext, cluster, consumer string) *protocol.ConsumerGroupStatus {
	request := &protocol.EvaluatorRequest{
		Cluster: cluster,
		Group:   consumer,
		ShowAll: true,
		Reply:   make(chan *protocol.ConsumerGroupStatus),
	}
	app.EvaluatorChannel <- request
	response := <-request.Reply
	return response
}

func listTopics(app *protocol.ApplicationContext, cluster string) []string {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchTopics,
		Cluster:     cluster,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []string{}
	}

	return response.([]string)
}

func getTopicDetail(app *protocol.ApplicationContext, cluster, topic string) []int64 {
	request := &protocol.StorageRequest{
		RequestType: protocol.StorageFetchTopic,
		Cluster:     cluster,
		Topic:       topic,
		Reply:       make(chan interface{}),
	}
	app.StorageChannel <- request
	response := <-request.Reply
	if response == nil {
		return []int64{}
	}

	return response.([]int64)
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package amass

import (
	"regexp"
	"strings"
	"time"

	"github.com/OWASP/Amass/amass/utils"
)

type timesRequest struct {
	Subdomain string
	Times     chan int
}

// NameService is the Service that handles all newly discovered names
// within the architecture. This is achieved by receiving all the RESOLVED events.
type NameService struct {
	BaseService

	filter      *utils.StringFilter
	timesChan   chan *timesRequest
	releases    chan struct{}
	completions chan time.Time
	sanityRE    *regexp.Regexp
}

// NewNameService requires the enumeration configuration and event bus as parameters.
// The object returned is initialized, but has not yet been started.
func NewNameService(e *Enumeration) *NameService {
	max := e.Config.Timing.ToMaxFlow() + e.Config.Timing.ToReleasesPerSecond()
	ns := &NameService{
		filter:      utils.NewStringFilter(),
		timesChan:   make(chan *timesRequest, max),
		releases:    make(chan struct{}, max),
		completions: make(chan time.Time, max),
		sanityRE:    utils.AnySubdomainRegex(),
	}

	ns.BaseService = *NewBaseService(e, "Name Service", ns)
	return ns
}

// OnStart implements the Service interface
func (ns *NameService) OnStart() error {
	ns.BaseService.OnStart()

	go ns.processTimesRequests()
	go ns.processRequests()
	return nil
}

func (ns *NameService) processRequests() {
	var perSec []int
	var completionTimes []time.Time
	last := time.Now()
	t := time.NewTicker(time.Second)
	defer t.Stop()
	logTick := time.NewTicker(time.Minute)
	defer logTick.Stop()

	for {
		select {
		case <-ns.PauseChan():
			<-ns.ResumeChan()
		case <-ns.Quit():
			return
		case comp := <-ns.completions:
			completionTimes = append(completionTimes, comp)
		case <-t.C:
			var num int
			for _, com := range completionTimes {
				if com.After(last) {
					num++
				}
			}
			perSec = append(perSec, num)
			completionTimes = []time.Time{}
			last = time.Now()
		case <-logTick.C:
			num := len(perSec)
			var total int
			for _, s := range perSec {
				total += s
			}
			ns.Enum().Log.Printf("Average DNS names processed: %d/sec", total/num)
			perSec = []int{}
		case req := <-ns.RequestChan():
			go ns.performRequest(req)
		}
	}
}

func (ns *NameService) sendCompletionTime(t time.Time) {
	ns.completions <- t
}

func (ns *NameService) performRequest(req *Request) {
	ns.SetActive()
	ns.sendCompletionTime(time.Now())
	if ns.Enum().Config.Passive {
		if !ns.filter.Duplicate(req.Name) {
			ns.Enum().OutputEvent(&Output{
				Name:   req.Name,
				Domain: req.Domain,
				Tag:    req.Tag,
				Source: req.Source,
			})
		}
		return
	}
	ns.Enum().ResolveNameEvent(req)
}

// Resolved is called when a name has been resolved by the DNS Service.
func (ns *NameService) Resolved(req *Request) {
	ns.SetActive()

	if ns.Enum().Config.IsDomainInScope(req.Name) {
		go ns.checkSubdomain(req)
	}
	if req.Tag == DNS {
		ns.sendCompletionTime(time.Now())
	}
	ns.Enum().CheckedNameEvent(req)
	ns.SetActive()
}

func (ns *NameService) checkSubdomain(req *Request) {
	labels := strings.Split(req.Name, ".")
	num := len(labels)
	// Is this large enough to consider further?
	if num < 2 {
		return
	}
	// It cannot have fewer labels than the root domain name
	if num-1 < len(strings.Split(req.Domain, ".")) {
		return
	}
	// Do not further evaluate service subdomains
	if labels[1] == "_tcp" || labels[1] == "_udp" || labels[1] == "_tls" {
		return
	}

	sub := strings.Join(labels[1:], ".")
	ns.Enum().NewSubdomainEvent(&Request{
		Name:   sub,
		Domain: req.Domain,
		Tag:    req.Tag,
		Source: req.Source,
	}, ns.timesForSubdomain(sub))
}

func (ns *NameService) timesForSubdomain(sub string) int {
	times := make(chan int)

	ns.timesChan <- &timesRequest{
		Subdomain: sub,
		Times:     times,
	}
	return <-times
}

func (ns *NameService) processTimesRequests() {
	subdomains := make(map[string]int)

	for {
		select {
		case <-ns.Quit():
			return
		case req := <-ns.timesChan:
			times, ok := subdomains[req.Subdomain]
			if ok {
				times++
			} else {
				times = 1
			}
			subdomains[req.Subdomain] = times
			req.Times <- times
		}
	}
}
<commit_msg>fix #81 division by zero<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package amass

import (
	"regexp"
	"strings"
	"time"

	"github.com/OWASP/Amass/amass/utils"
)

type timesRequest struct {
	Subdomain string
	Times     chan int
}

// NameService is the Service that handles all newly discovered names
// within the architecture. This is achieved by receiving all the RESOLVED events.
type NameService struct {
	BaseService

	filter      *utils.StringFilter
	timesChan   chan *timesRequest
	releases    chan struct{}
	completions chan time.Time
	sanityRE    *regexp.Regexp
}

// NewNameService requires the enumeration configuration and event bus as parameters.
// The object returned is initialized, but has not yet been started.
func NewNameService(e *Enumeration) *NameService {
	max := e.Config.Timing.ToMaxFlow() + e.Config.Timing.ToReleasesPerSecond()
	ns := &NameService{
		filter:      utils.NewStringFilter(),
		timesChan:   make(chan *timesRequest, max),
		releases:    make(chan struct{}, max),
		completions: make(chan time.Time, max),
		sanityRE:    utils.AnySubdomainRegex(),
	}

	ns.BaseService = *NewBaseService(e, "Name Service", ns)
	return ns
}

// OnStart implements the Service interface
func (ns *NameService) OnStart() error {
	ns.BaseService.OnStart()

	go ns.processTimesRequests()
	go ns.processRequests()
	return nil
}

func (ns *NameService) processRequests() {
	var perSec []int
	var completionTimes []time.Time
	last := time.Now()
	t := time.NewTicker(time.Second)
	defer t.Stop()
	logTick := time.NewTicker(time.Minute)
	defer logTick.Stop()

	for {
		select {
		case <-ns.PauseChan():
			<-ns.ResumeChan()
		case <-ns.Quit():
			return
		case comp := <-ns.completions:
			completionTimes = append(completionTimes, comp)
		case <-t.C:
			var num int
			for _, com := range completionTimes {
				if com.After(last) {
					num++
				}
			}
			perSec = append(perSec, num)
			completionTimes = []time.Time{}
			last = time.Now()
		case <-logTick.C:
			num := len(perSec)
			var total int
			for _, s := range perSec {
				total += s
			}
			if num > 0 {
				ns.Enum().Log.Printf("Average DNS names processed: %d/sec", total/num)
			}
			perSec = []int{}
		case req := <-ns.RequestChan():
			go ns.performRequest(req)
		}
	}
}

func (ns *NameService) sendCompletionTime(t time.Time) {
	ns.completions <- t
}

func (ns *NameService) performRequest(req *Request) {
	ns.SetActive()
	ns.sendCompletionTime(time.Now())
	if ns.Enum().Config.Passive {
		if !ns.filter.Duplicate(req.Name) {
			ns.Enum().OutputEvent(&Output{
				Name:   req.Name,
				Domain: req.Domain,
				Tag:    req.Tag,
				Source: req.Source,
			})
		}
		return
	}
	ns.Enum().ResolveNameEvent(req)
}

// Resolved is called when a name has been resolved by the DNS Service.
func (ns *NameService) Resolved(req *Request) {
	ns.SetActive()

	if ns.Enum().Config.IsDomainInScope(req.Name) {
		go ns.checkSubdomain(req)
	}
	if req.Tag == DNS {
		ns.sendCompletionTime(time.Now())
	}
	ns.Enum().CheckedNameEvent(req)
	ns.SetActive()
}

func (ns *NameService) checkSubdomain(req *Request) {
	labels := strings.Split(req.Name, ".")
	num := len(labels)
	// Is this large enough to consider further?
	if num < 2 {
		return
	}
	// It cannot have fewer labels than the root domain name
	if num-1 < len(strings.Split(req.Domain, ".")) {
		return
	}
	// Do not further evaluate service subdomains
	if labels[1] == "_tcp" || labels[1] == "_udp" || labels[1] == "_tls" {
		return
	}

	sub := strings.Join(labels[1:], ".")
	ns.Enum().NewSubdomainEvent(&Request{
		Name:   sub,
		Domain: req.Domain,
		Tag:    req.Tag,
		Source: req.Source,
	}, ns.timesForSubdomain(sub))
}

func (ns *NameService) timesForSubdomain(sub string) int {
	times := make(chan int)

	ns.timesChan <- &timesRequest{
		Subdomain: sub,
		Times:     times,
	}
	return <-times
}

func (ns *NameService) processTimesRequests() {
	subdomains := make(map[string]int)

	for {
		select {
		case <-ns.Quit():
			return
		case req := <-ns.timesChan:
			times, ok := subdomains[req.Subdomain]
			if ok {
				times++
			} else {
				times = 1
			}
			subdomains[req.Subdomain] = times
			req.Times <- times
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var (
	packageName = flag.String("package", "main", "(Optional) Name of the package.")
	types       = flag.String("types", "", "Comma-separated list of type names, eg. 'int,string,CustomType'. The values can themselves be colon (:) separated to specify the names of entities in the generated, eg: int:I,string:Str,CustomType:CT.")
	outputName  = flag.String("filename", "fungen_auto.go", "Filename for generated package")
	testrun     = flag.Bool("test", false, "whether to display the generated code instead of writing out to a file.")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\tgen -package packageName -types Types\n")
	fmt.Fprintf(os.Stderr, "Example:\n")
	fmt.Fprintf(os.Stderr, "'gen -package mypackage -types string,int,customType,AnotherType' will create types 'stringList []string, intList []int, customTypeList []customType, AnotherTypeList []AnotherType' with the Map, Filter, Reduce, ReduceRight, Take, TakeWhile, Drop, DropWhile, Each, EachI methods on them. Additionally, methods named MapType1Type2 will be generated on these types for the remaining types. The package of the generated file will be 'mypackage' \n\n")
	fmt.Fprintf(os.Stderr, "'gen -types string,int:I,customType:CT,AnotherType:At' will create types 'stringList []string, IList []int, CTList []customType, AtList []AnotherType'. The 'stringList' type will have the Map, Filter, Reduce, ReduceRight, Take, TakeWhile, Drop, DropWhile, Each, EachI methods on it. Additionally, it will also have MapI, MapCt and MapAt methods. The package of the generated file will be 'main' \n\n")

	fmt.Fprintf(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	flag.Parse()

	if len(*types) == 0 {
		flag.Usage()
		os.Exit(2)
	}

	src := fmt.Sprintf(`// Package %[1]s - generated by fungen; DO NOT EDIT
            package %[1]s

            import "sync"

            `, *packageName)

	typeMap := getTypeMap(*types)

	for k1, v1 := range typeMap {
		src += generate(k1, v1+"List", typeMap)
		src = f(src)
	}

	if *testrun {
		fmt.Println(*outputName)
		fmt.Println(src)
	} else {
		err := ioutil.WriteFile(*outputName, []byte(src), 0644)
		if err != nil {
			log.Fatalf("writing output: %s", err)
		}
	}

}

func f(s string) string {
	formatted, err := format.Source([]byte(s))
	if err != nil {
		log.Fatal(err)
	}
	return string(formatted)
}

func getFileNameForTypes(t string, m map[string]string) string {
	if len(m) == 0 {
		return t
	}
	s := t
	for k, v := range m {
		if t == k {
			continue
		}
		s += "_" + v
	}
	return s
}

func getTypeMap(targets string) map[string]string {
	m := map[string]string{}
	if targets == "" {
		return m
	}

	targetParts := strings.Split(targets, ",")
	for _, t := range targetParts {
		tParts := strings.Split(t, ":")
		if len(tParts) == 1 {
			m[tParts[0]] = tParts[0]
		} else {
			m[tParts[0]] = tParts[1]
		}
	}

	return m
}

func generate(typeName, listname string, m map[string]string) string {
	code := ""
	code = fmt.Sprintf(`

            // %[2]s is the type for a list that holds members of type %[1]s
            type %[2]s []%[1]s
            `, typeName, listname)

	for k, v := range m {
		if k == typeName {
			code += getMapFunction(listname, typeName, k, "")
			code += getPMapFunction(listname, typeName, k, "")
		} else {
			code += getMapFunction(listname, typeName, k, v)
			code += getPMapFunction(listname, typeName, k, v)
		}

	}

	code += getFilterFunction(listname, typeName)
	code += getPFilterFunction(listname, typeName)
	code += getReduceFunction(listname, typeName)
	code += getReduceRightFunction(listname, typeName)
	code += getTakeFunction(listname, typeName)
	code += getTakeWhileFunction(listname, typeName)
	code += getDropFunction(listname, typeName)
	code += getDropWhileFunction(listname, typeName)
	code += getEachFunction(listname, typeName)
	code += getEachIFunction(listname, typeName)

	return code
}

func getMapFunction(listName, typeName, targetType, targetTypeName string) string {
	targetListName := targetType + "List"
	if targetTypeName == "" {
		targetListName = listName
	}

	return fmt.Sprintf(`
        // Map%[4]s is a method on %[1]s that takes a function of type %[2]s -> %[3]s and applies it to every member of %[1]s
        func (l %[1]s) Map%[4]s(f func(%[2]s) %[3]s) %[5]s {
            l2 := make(%[5]s, len(l))
            for i, t := range l {
                l2[i] = f(t)
            }
            return l2
        }
        `, listName, typeName, targetType, strings.Title(targetTypeName), targetListName)

}

func getPMapFunction(listName, typeName, targetType, targetTypeName string) string {
	targetListName := targetType + "List"
	if targetTypeName == "" {
		targetListName = listName
	}

	return fmt.Sprintf(`
        // PMap%[4]s is similar to Map%[4]s except that it executes the function on each member in parallel.
        func (l %[1]s) PMap%[4]s(f func(%[2]s) %[3]s) %[5]s {
            wg := sync.WaitGroup{}
            l2 := make(%[5]s, len(l))
            for i, t := range l {
                wg.Add(1)
                go func(i int, t %[2]s){
                    l2[i] = f(t)
                    wg.Done()
                }(i, t)
            }
            wg.Wait()
            return l2
        }
        `, listName, typeName, targetType, strings.Title(targetTypeName), targetListName)

}

func getFilterFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Filter is a method on %[1]s that takes a function of type %[2]s -> bool returns a list of type %[1]s which contains all members from the original list for which the function returned true
        func (l %[1]s) Filter(f func(%[2]s) bool) %[1]s {
            l2 := []%[2]s{}
            for _, t := range l {
                if f(t) {
                    l2 = append(l2, t)
                }
            }
            return l2
        }
        `, listName, typeName)
}

func getPFilterFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // PFilter is similar to the Filter method except that the filter is applied to all the elements in parallel. The order of resulting elements cannot be guaranteed.
        func (l %[1]s) PFilter(f func(%[2]s) bool) %[1]s {
            wg := sync.WaitGroup{}
            mutex := sync.Mutex{}
            l2 := []%[2]s{}
            for _, t := range l {
                wg.Add(1)
                go func(t %[2]s){
                    if f(t) {
                        mutex.Lock()
                        l2 = append(l2, t)
                        mutex.Unlock()
                    }
                    wg.Done()
                }(t)
            }
            wg.Wait()
            return l2
        }
        `, listName, typeName)
}

func getEachFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Each is a method on %[1]s that takes a function of type %[2]s -> void and applies the function to each member of the list and then returns the original list.
        func (l %[1]s) Each(f func(%[2]s)) %[1]s {
            for _, t := range l {
                f(t)
            }
            return l
        }
        `, listName, typeName)
}

func getEachIFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // EachI is a method on %[1]s that takes a function of type (int, %[2]s) -> void and applies the function to each member of the list and then returns the original list. The int parameter to the function is the index of the element.
        func (l %[1]s) EachI(f func(int, %[2]s)) %[1]s {
            for i, t := range l {
                f(i, t)
            }
            return l
        }
        `, listName, typeName)
}

func getDropWhileFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // DropWhile is a method on %[1]s that takes a function of type %[2]s -> bool and returns a list of type %[1]s which excludes the first members from the original list for which the function returned true
        func (l %[1]s) DropWhile(f func(%[2]s) bool) %[1]s {
            for i, t := range l {
                if !f(t) {
                    return l[i:]
                }
            }
            var l2 %[1]s
            return l2
        }
        `, listName, typeName)
}

func getTakeWhileFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // TakeWhile is a method on %[1]s that takes a function of type %[2]s -> bool and returns a list of type %[1]s which includes only the first members from the original list for which the function returned true
        func (l %[1]s) TakeWhile(f func(%[2]s) bool) %[1]s {
            for i, t := range l {
                if !f(t) {
                    return l[:i]
                }
            }
            return l
        }
        `, listName, typeName)
}

func getTakeFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Take is a method on %[1]s that takes an integer n and returns the first n elements of the original list. If the list contains fewer than n elements then the entire list is returned.
        func (l %[1]s) Take(n int) %[1]s {
            if len(l) >= n {
                return l[:n]
            }
            return l
        }
        `, listName, typeName)
}

func getDropFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Drop is a method on %[1]s that takes an integer n and returns all but the first n elements of the original list. If the list contains fewer than n elements then an empty list is returned.
        func (l %[1]s) Drop(n int) %[1]s {
            if len(l) >= n {
                return l[n:]
            }
            var l2 %[1]s
            return l2
        }
        `, listName, typeName)
}

func getReduceFunction(listName, typename string) string {
	return fmt.Sprintf(`
        // Reduce is a method on %[1]s that takes a function of type (%[2]s, %[2]s) -> %[2]s and returns a %[2]s which is the result of applying the function to all members of the original list starting from the first member
        func (l %[1]s) Reduce(t1 %[2]s, f func(%[2]s, %[2]s) %[2]s) %[2]s {
            for _, t := range l {
                t1 = f(t1, t)
            }
            return t1
        }
        `, listName, typename)
}

func getReduceRightFunction(listName, typename string) string {
	return fmt.Sprintf(`
        // ReduceRight is a method on %[1]s that takes a function of type (%[2]s, %[2]s) -> %[2]s and returns a %[2]s which is the result of applying the function to all members of the original list starting from the last member
        func (l %[1]s) ReduceRight(t1 %[2]s, f func(%[2]s, %[2]s) %[2]s) %[2]s {
            for i := len(l) - 1; i >= 0; i-- {
                t := l[i]
                t1 = f(t, t1)
            }
            return t1
        }
        `, listName, typename)
}
<commit_msg>Marked -filename as optional in the description<commit_after>package main

import (
	"flag"
	"fmt"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var (
	packageName = flag.String("package", "main", "(Optional) Name of the package.")
	types       = flag.String("types", "", "Comma-separated list of type names, eg. 'int,string,CustomType'. The values can themselves be colon (:) separated to specify the names of entities in the generated, eg: int:I,string:Str,CustomType:CT.")
	outputName  = flag.String("filename", "fungen_auto.go", "(Optional) Filename for generated package")
	testrun     = flag.Bool("test", false, "whether to display the generated code instead of writing out to a file.")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\tgen -package packageName -types Types\n")
	fmt.Fprintf(os.Stderr, "Example:\n")
	fmt.Fprintf(os.Stderr, "'gen -package mypackage -types string,int,customType,AnotherType' will create types 'stringList []string, intList []int, customTypeList []customType, AnotherTypeList []AnotherType' with the Map, Filter, Reduce, ReduceRight, Take, TakeWhile, Drop, DropWhile, Each, EachI methods on them. Additionally, methods named MapType1Type2 will be generated on these types for the remaining types. The package of the generated file will be 'mypackage' \n\n")
	fmt.Fprintf(os.Stderr, "'gen -types string,int:I,customType:CT,AnotherType:At' will create types 'stringList []string, IList []int, CTList []customType, AtList []AnotherType'. The 'stringList' type will have the Map, Filter, Reduce, ReduceRight, Take, TakeWhile, Drop, DropWhile, Each, EachI methods on it. Additionally, it will also have MapI, MapCt and MapAt methods. The package of the generated file will be 'main' \n\n")

	fmt.Fprintf(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	flag.Parse()

	if len(*types) == 0 {
		flag.Usage()
		os.Exit(2)
	}

	src := fmt.Sprintf(`// Package %[1]s - generated by fungen; DO NOT EDIT
            package %[1]s

            import "sync"

            `, *packageName)

	typeMap := getTypeMap(*types)

	for k1, v1 := range typeMap {
		src += generate(k1, v1+"List", typeMap)
		src = f(src)
	}

	if *testrun {
		fmt.Println(*outputName)
		fmt.Println(src)
	} else {
		err := ioutil.WriteFile(*outputName, []byte(src), 0644)
		if err != nil {
			log.Fatalf("writing output: %s", err)
		}
	}

}

func f(s string) string {
	formatted, err := format.Source([]byte(s))
	if err != nil {
		log.Fatal(err)
	}
	return string(formatted)
}

func getFileNameForTypes(t string, m map[string]string) string {
	if len(m) == 0 {
		return t
	}
	s := t
	for k, v := range m {
		if t == k {
			continue
		}
		s += "_" + v
	}
	return s
}

func getTypeMap(targets string) map[string]string {
	m := map[string]string{}
	if targets == "" {
		return m
	}

	targetParts := strings.Split(targets, ",")
	for _, t := range targetParts {
		tParts := strings.Split(t, ":")
		if len(tParts) == 1 {
			m[tParts[0]] = tParts[0]
		} else {
			m[tParts[0]] = tParts[1]
		}
	}

	return m
}

func generate(typeName, listname string, m map[string]string) string {
	code := ""
	code = fmt.Sprintf(`

            // %[2]s is the type for a list that holds members of type %[1]s
            type %[2]s []%[1]s
            `, typeName, listname)

	for k, v := range m {
		if k == typeName {
			code += getMapFunction(listname, typeName, k, "")
			code += getPMapFunction(listname, typeName, k, "")
		} else {
			code += getMapFunction(listname, typeName, k, v)
			code += getPMapFunction(listname, typeName, k, v)
		}

	}

	code += getFilterFunction(listname, typeName)
	code += getPFilterFunction(listname, typeName)
	code += getReduceFunction(listname, typeName)
	code += getReduceRightFunction(listname, typeName)
	code += getTakeFunction(listname, typeName)
	code += getTakeWhileFunction(listname, typeName)
	code += getDropFunction(listname, typeName)
	code += getDropWhileFunction(listname, typeName)
	code += getEachFunction(listname, typeName)
	code += getEachIFunction(listname, typeName)

	return code
}

func getMapFunction(listName, typeName, targetType, targetTypeName string) string {
	targetListName := targetType + "List"
	if targetTypeName == "" {
		targetListName = listName
	}

	return fmt.Sprintf(`
        // Map%[4]s is a method on %[1]s that takes a function of type %[2]s -> %[3]s and applies it to every member of %[1]s
        func (l %[1]s) Map%[4]s(f func(%[2]s) %[3]s) %[5]s {
            l2 := make(%[5]s, len(l))
            for i, t := range l {
                l2[i] = f(t)
            }
            return l2
        }
        `, listName, typeName, targetType, strings.Title(targetTypeName), targetListName)

}

func getPMapFunction(listName, typeName, targetType, targetTypeName string) string {
	targetListName := targetType + "List"
	if targetTypeName == "" {
		targetListName = listName
	}

	return fmt.Sprintf(`
        // PMap%[4]s is similar to Map%[4]s except that it executes the function on each member in parallel.
        func (l %[1]s) PMap%[4]s(f func(%[2]s) %[3]s) %[5]s {
            wg := sync.WaitGroup{}
            l2 := make(%[5]s, len(l))
            for i, t := range l {
                wg.Add(1)
                go func(i int, t %[2]s){
                    l2[i] = f(t)
                    wg.Done()
                }(i, t)
            }
            wg.Wait()
            return l2
        }
        `, listName, typeName, targetType, strings.Title(targetTypeName), targetListName)

}

func getFilterFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Filter is a method on %[1]s that takes a function of type %[2]s -> bool returns a list of type %[1]s which contains all members from the original list for which the function returned true
        func (l %[1]s) Filter(f func(%[2]s) bool) %[1]s {
            l2 := []%[2]s{}
            for _, t := range l {
                if f(t) {
                    l2 = append(l2, t)
                }
            }
            return l2
        }
        `, listName, typeName)
}

func getPFilterFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // PFilter is similar to the Filter method except that the filter is applied to all the elements in parallel. The order of resulting elements cannot be guaranteed.
        func (l %[1]s) PFilter(f func(%[2]s) bool) %[1]s {
            wg := sync.WaitGroup{}
            mutex := sync.Mutex{}
            l2 := []%[2]s{}
            for _, t := range l {
                wg.Add(1)
                go func(t %[2]s){
                    if f(t) {
                        mutex.Lock()
                        l2 = append(l2, t)
                        mutex.Unlock()
                    }
                    wg.Done()
                }(t)
            }
            wg.Wait()
            return l2
        }
        `, listName, typeName)
}

func getEachFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Each is a method on %[1]s that takes a function of type %[2]s -> void and applies the function to each member of the list and then returns the original list.
        func (l %[1]s) Each(f func(%[2]s)) %[1]s {
            for _, t := range l {
                f(t)
            }
            return l
        }
        `, listName, typeName)
}

func getEachIFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // EachI is a method on %[1]s that takes a function of type (int, %[2]s) -> void and applies the function to each member of the list and then returns the original list. The int parameter to the function is the index of the element.
        func (l %[1]s) EachI(f func(int, %[2]s)) %[1]s {
            for i, t := range l {
                f(i, t)
            }
            return l
        }
        `, listName, typeName)
}

func getDropWhileFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // DropWhile is a method on %[1]s that takes a function of type %[2]s -> bool and returns a list of type %[1]s which excludes the first members from the original list for which the function returned true
        func (l %[1]s) DropWhile(f func(%[2]s) bool) %[1]s {
            for i, t := range l {
                if !f(t) {
                    return l[i:]
                }
            }
            var l2 %[1]s
            return l2
        }
        `, listName, typeName)
}

func getTakeWhileFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // TakeWhile is a method on %[1]s that takes a function of type %[2]s -> bool and returns a list of type %[1]s which includes only the first members from the original list for which the function returned true
        func (l %[1]s) TakeWhile(f func(%[2]s) bool) %[1]s {
            for i, t := range l {
                if !f(t) {
                    return l[:i]
                }
            }
            return l
        }
        `, listName, typeName)
}

func getTakeFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Take is a method on %[1]s that takes an integer n and returns the first n elements of the original list. If the list contains fewer than n elements then the entire list is returned.
        func (l %[1]s) Take(n int) %[1]s {
            if len(l) >= n {
                return l[:n]
            }
            return l
        }
        `, listName, typeName)
}

func getDropFunction(listName, typeName string) string {
	return fmt.Sprintf(`
        // Drop is a method on %[1]s that takes an integer n and returns all but the first n elements of the original list. If the list contains fewer than n elements then an empty list is returned.
        func (l %[1]s) Drop(n int) %[1]s {
            if len(l) >= n {
                return l[n:]
            }
            var l2 %[1]s
            return l2
        }
        `, listName, typeName)
}

func getReduceFunction(listName, typename string) string {
	return fmt.Sprintf(`
        // Reduce is a method on %[1]s that takes a function of type (%[2]s, %[2]s) -> %[2]s and returns a %[2]s which is the result of applying the function to all members of the original list starting from the first member
        func (l %[1]s) Reduce(t1 %[2]s, f func(%[2]s, %[2]s) %[2]s) %[2]s {
            for _, t := range l {
                t1 = f(t1, t)
            }
            return t1
        }
        `, listName, typename)
}

func getReduceRightFunction(listName, typename string) string {
	return fmt.Sprintf(`
        // ReduceRight is a method on %[1]s that takes a function of type (%[2]s, %[2]s) -> %[2]s and returns a %[2]s which is the result of applying the function to all members of the original list starting from the last member
        func (l %[1]s) ReduceRight(t1 %[2]s, f func(%[2]s, %[2]s) %[2]s) %[2]s {
            for i := len(l) - 1; i >= 0; i-- {
                t := l[i]
                t1 = f(t, t1)
            }
            return t1
        }
        `, listName, typename)
}
<|endoftext|>


<commit_before>/*
Package rmsd implements a version of the Kabsch algorithm that is described
in detail here: http://cnx.org/content/m11608/latest/

A convenience function for computing the RMSD of residue ranges from two PDB
files is also provided.
*/
package rmsd
<commit_msg>Make first sentence a bit more descriptive. And don't put a link in the first sentence.<commit_after>/*
Package rmsd implements a version of the Kabsch algorithm to compute the
minimal RMSD between two equal length sets of atoms. The exact algorithm
implement is described in detail here: http://cnx.org/content/m11608/latest/.

A convenience function for computing the RMSD of residue ranges from two PDB
files is also provided.
*/
package rmsd
<|endoftext|>


<commit_before>// Copyright 2017 The go-vm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vmware

import (
	"github.com/go-vm/vmware/vmrun"
)

const fusionApp = "fusion"

// Fusion represents a VMware Fusion application.
type Fusion struct {
	vmx string
}

// NewFusion return the new Fusion.
func NewFusion(vmx string) *Fusion {
	return &Fusion{
		vmx: vmx,
	}
}

// Start start a VM or Team.
func (f *Fusion) Start(gui bool) error {
	return vmrun.Start(fusionApp, f.vmx, gui)
}

// ShutDown wrap of stop command with hard.
func (f *Fusion) ShutDown() error {
	return vmrun.Stop(fusionApp, f.vmx, true)
}

// Halt wrap of stop command with soft.
func (f *Fusion) Halt() error {
	return vmrun.Stop(fusionApp, f.vmx, false)
}

// Reset reset a VM or Team.
func (f *Fusion) Reset() error {
	return vmrun.Reset(fusionApp, f.vmx, true)
}

// Restart restart a VM uses wrap of reset command with soft.
func (f *Fusion) Restart() error {
	return vmrun.Reset(fusionApp, f.vmx, false)
}

// Suspend Suspend a VM or Team.
func (f *Fusion) Suspend(hard bool) error {
	return vmrun.Suspend(fusionApp, f.vmx, hard)
}

// Pause pause a VM.
func (f *Fusion) Pause() error {
	return vmrun.Pause(fusionApp, f.vmx)
}

// Unpause unpause a VM.
func (f *Fusion) Unpause(vmx string) error {
	return vmrun.Unpause(fusionApp, f.vmx)
}

// ListSnapshots list all snapshots in a VM.
func (f *Fusion) ListSnapshots() ([]string, int, error) {
	return vmrun.ListSnapshots(fusionApp, f.vmx)
}

// Snapshot create a snapshot of a VM.
func (f *Fusion) Snapshot(snapshotName string) error {
	return vmrun.Snapshot(fusionApp, f.vmx, snapshotName)
}

// DeleteSnapshot remove a snapshot from a VM.
func (f *Fusion) DeleteSnapshot(snapshotName string, deleteChildren bool) error {
	return vmrun.DeleteSnapshot(fusionApp, f.vmx, snapshotName, deleteChildren)
}

// RevertToSnapshot set VM state to a snapshot.
func (f *Fusion) RevertToSnapshot(snapshotName string) error {
	return vmrun.RevertToSnapshot(fusionApp, f.vmx, snapshotName)
}

// RunProgramInGuest run a program in Guest OS.
func (f *Fusion) RunProgramInGuest(username, password string, config vmrun.RunProgramInGuestConfig, cmdPath string, cmdArgs ...string) error {
	return vmrun.RunProgramInGuest(fusionApp, f.vmx, username, password, config, cmdPath, cmdArgs...)
}

// FileExistsInGuest check if a file exists in Guest OS.
func (f *Fusion) FileExistsInGuest(username, password string, filename string) bool {
	return vmrun.FileExistsInGuest(fusionApp, f.vmx, username, password, filename)
}

// DirectoryExistsInGuest check if a directory exists in Guest OS.
func (f *Fusion) DirectoryExistsInGuest(username, password string, dir string) bool {
	return vmrun.DirectoryExistsInGuest(fusionApp, f.vmx, username, password, dir)
}

// SetSharedFolderState modify a Host-Guest shared folder.
func (f *Fusion) SetSharedFolderState(shareName, hostPath string, writable bool) error {
	return vmrun.SetSharedFolderState(fusionApp, f.vmx, shareName, hostPath, writable)
}

// AddSharedFolder add a Host-Guest shared folder.
func (f *Fusion) AddSharedFolder(shareName, newHostPath string) error {
	return vmrun.AddSharedFolder(fusionApp, f.vmx, shareName, newHostPath)
}

// RemoveSharedFolder remove a Host-Guest shared folder.
func (f *Fusion) RemoveSharedFolder(shareName string) error {
	return vmrun.RemoveSharedFolder(fusionApp, f.vmx, shareName)
}

// EnableSharedFolders enable shared folders in Guest.
func (f *Fusion) EnableSharedFolders(runtime bool) error {
	return vmrun.EnableSharedFolders(fusionApp, f.vmx, runtime)
}

// DisableSharedFolders disable shared folders in Guest.
func (f *Fusion) DisableSharedFolders(runtime bool) error {
	return vmrun.DisableSharedFolders(fusionApp, f.vmx, runtime)
}

func (f *Fusion) ListProcessesInGuest(username, password string) ([]vmrun.ListProcessesInGuestInfo, error) {
	return vmrun.ListProcessesInGuest(fusionApp, f.vmx, username, password)
}

func (f *Fusion) KillProcessInGuest(username, password string, pid int) error {
	return vmrun.KillProcessInGuest(fusionApp, f.vmx, username, password, pid)
}
<commit_msg>fusion: fix arg format on FileExistsInGuest & DirectoryExistsInGuest<commit_after>// Copyright 2017 The go-vm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vmware

import (
	"github.com/go-vm/vmware/vmrun"
)

const fusionApp = "fusion"

// Fusion represents a VMware Fusion application.
type Fusion struct {
	vmx string
}

// NewFusion return the new Fusion.
func NewFusion(vmx string) *Fusion {
	return &Fusion{
		vmx: vmx,
	}
}

// Start start a VM or Team.
func (f *Fusion) Start(gui bool) error {
	return vmrun.Start(fusionApp, f.vmx, gui)
}

// ShutDown wrap of stop command with hard.
func (f *Fusion) ShutDown() error {
	return vmrun.Stop(fusionApp, f.vmx, true)
}

// Halt wrap of stop command with soft.
func (f *Fusion) Halt() error {
	return vmrun.Stop(fusionApp, f.vmx, false)
}

// Reset reset a VM or Team.
func (f *Fusion) Reset() error {
	return vmrun.Reset(fusionApp, f.vmx, true)
}

// Restart restart a VM uses wrap of reset command with soft.
func (f *Fusion) Restart() error {
	return vmrun.Reset(fusionApp, f.vmx, false)
}

// Suspend Suspend a VM or Team.
func (f *Fusion) Suspend(hard bool) error {
	return vmrun.Suspend(fusionApp, f.vmx, hard)
}

// Pause pause a VM.
func (f *Fusion) Pause() error {
	return vmrun.Pause(fusionApp, f.vmx)
}

// Unpause unpause a VM.
func (f *Fusion) Unpause(vmx string) error {
	return vmrun.Unpause(fusionApp, f.vmx)
}

// ListSnapshots list all snapshots in a VM.
func (f *Fusion) ListSnapshots() ([]string, int, error) {
	return vmrun.ListSnapshots(fusionApp, f.vmx)
}

// Snapshot create a snapshot of a VM.
func (f *Fusion) Snapshot(snapshotName string) error {
	return vmrun.Snapshot(fusionApp, f.vmx, snapshotName)
}

// DeleteSnapshot remove a snapshot from a VM.
func (f *Fusion) DeleteSnapshot(snapshotName string, deleteChildren bool) error {
	return vmrun.DeleteSnapshot(fusionApp, f.vmx, snapshotName, deleteChildren)
}

// RevertToSnapshot set VM state to a snapshot.
func (f *Fusion) RevertToSnapshot(snapshotName string) error {
	return vmrun.RevertToSnapshot(fusionApp, f.vmx, snapshotName)
}

// RunProgramInGuest run a program in Guest OS.
func (f *Fusion) RunProgramInGuest(username, password string, config vmrun.RunProgramInGuestConfig, cmdPath string, cmdArgs ...string) error {
	return vmrun.RunProgramInGuest(fusionApp, f.vmx, username, password, config, cmdPath, cmdArgs...)
}

// FileExistsInGuest check if a file exists in Guest OS.
func (f *Fusion) FileExistsInGuest(username, password, filename string) bool {
	return vmrun.FileExistsInGuest(fusionApp, f.vmx, username, password, filename)
}

// DirectoryExistsInGuest check if a directory exists in Guest OS.
func (f *Fusion) DirectoryExistsInGuest(username, password, dir string) bool {
	return vmrun.DirectoryExistsInGuest(fusionApp, f.vmx, username, password, dir)
}

// SetSharedFolderState modify a Host-Guest shared folder.
func (f *Fusion) SetSharedFolderState(shareName, hostPath string, writable bool) error {
	return vmrun.SetSharedFolderState(fusionApp, f.vmx, shareName, hostPath, writable)
}

// AddSharedFolder add a Host-Guest shared folder.
func (f *Fusion) AddSharedFolder(shareName, newHostPath string) error {
	return vmrun.AddSharedFolder(fusionApp, f.vmx, shareName, newHostPath)
}

// RemoveSharedFolder remove a Host-Guest shared folder.
func (f *Fusion) RemoveSharedFolder(shareName string) error {
	return vmrun.RemoveSharedFolder(fusionApp, f.vmx, shareName)
}

// EnableSharedFolders enable shared folders in Guest.
func (f *Fusion) EnableSharedFolders(runtime bool) error {
	return vmrun.EnableSharedFolders(fusionApp, f.vmx, runtime)
}

// DisableSharedFolders disable shared folders in Guest.
func (f *Fusion) DisableSharedFolders(runtime bool) error {
	return vmrun.DisableSharedFolders(fusionApp, f.vmx, runtime)
}

func (f *Fusion) ListProcessesInGuest(username, password string) ([]vmrun.ListProcessesInGuestInfo, error) {
	return vmrun.ListProcessesInGuest(fusionApp, f.vmx, username, password)
}

func (f *Fusion) KillProcessInGuest(username, password string, pid int) error {
	return vmrun.KillProcessInGuest(fusionApp, f.vmx, username, password, pid)
}
<|endoftext|>