<commit_before>package goConfig

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/pkg/errors"
)

// Settings default
type Settings struct {
	// Path sets default config path
	Path string
	// File name of default config file
	File string
	// FileRequired config file required
	FileRequired bool
	// Tag set the main tag
	Tag string
	// TagDefault set tag default
	TagDefault string
	// TagDisabled used to not process an input
	TagDisabled string
	// EnvironmentVarSeparator separe names on environment variables
	EnvironmentVarSeparator string
}

// Setup Pointer to internal variables
var Setup *Settings

// ReflectFunc type used to create funcrions to parse struct and tags
type ReflectFunc func(
	field *reflect.StructField,
	value *reflect.Value,
	tag string) (err error)

var parseMap map[reflect.Kind]ReflectFunc

func init() {
	Setup = &Settings{
		Path:                    "./",
		File:                    "config.json",
		Tag:                     "cfg",
		TagDefault:              "cfgDefault",
		TagDisabled:             "-",
		EnvironmentVarSeparator: "_",
		FileRequired:            false,
	}

	parseMap = make(map[reflect.Kind]ReflectFunc)

	parseMap[reflect.Struct] = reflectStruct
	parseMap[reflect.Int] = reflectInt
	parseMap[reflect.String] = reflectString

}

// LoadJSON config file
func LoadJSON(config interface{}) (err error) {
	configFile := Setup.Path + Setup.File
	file, err := os.Open(configFile)
	if os.IsNotExist(err) && !Setup.FileRequired {
		err = nil
		return
	} else if err != nil {
		return
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	err = decoder.Decode(&config)
	if err != nil {
		return
	}

	return
}

// Load config file
func Load(config interface{}) (err error) {

	err = LoadJSON(config)
	if err != nil {
		return
	}

	err = parseTags(config, "")
	if err != nil {
		return
	}

	return
}

// Save config file
func Save(config interface{}) (err error) {
	_, err = os.Stat(Setup.Path)
	if os.IsNotExist(err) {
		os.Mkdir(Setup.Path, 0700)
	} else if err != nil {
		return
	}

	configFile := Setup.Path + Setup.File

	_, err = os.Stat(configFile)
	if err != nil {
		return
	}

	b, err := json.MarshalIndent(config, "", "\t")
	if err != nil {
		return
	}

	err = ioutil.WriteFile(configFile, b, 0644)
	if err != nil {
		return
	}
	return
}

func parseTags(s interface{}, superTag string) (err error) {

	st := reflect.TypeOf(s)

	if st.Kind() != reflect.Ptr {
		err = errors.New("Not a pointer")
		return
	}

	refField := st.Elem()
	if refField.Kind() != reflect.Struct {
		err = errors.New("Not a struct")
		return
	}

	//vt := reflect.ValueOf(s)
	refValue := reflect.ValueOf(s).Elem()
	for i := 0; i < refField.NumField(); i++ {
		field := refField.Field(i)
		value := refValue.Field(i)
		kind := field.Type.Kind()

		if field.PkgPath != "" {
			continue
		}

		t := updateTag(&field, superTag)
		if t == "" {
			continue
		}

		if f, ok := parseMap[kind]; ok {
			err = f(&field, &value, t)
			if err != nil {
				return
			}
		} else {
			err = errors.New("Type not supported " + kind.String())
			return
		}

		fmt.Println("name:", field.Name,
			"| cfg:", field.Tag.Get(Setup.Tag),
			"| cfgDefault:", field.Tag.Get(Setup.TagDefault),
			"| type:", field.Type)

	}
	return
}

func updateTag(field *reflect.StructField, superTag string) (ret string) {
	ret = field.Tag.Get(Setup.Tag)
	if ret == Setup.TagDisabled {
		return
	}

	if ret == "" {
		ret = strings.ToUpper(field.Name)
	}

	if superTag != "" {
		ret = superTag + Setup.EnvironmentVarSeparator + ret
	}
	return
}

func getNewValue(field *reflect.StructField, tag string) (ret string) {

	ret = os.Getenv(tag)
	if ret != "" {
		return
	}

	ret = field.Tag.Get(Setup.TagDefault)
	if ret != "" {
		return
	}

	return

}

func reflectStruct(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	err = parseTags(value.Addr().Interface(), tag)
	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	//value.SetInt(999)

	newValue := getNewValue(field, tag)

	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}
	value.SetInt(intNewValue)

	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	//value.SetString("TEST")
	newValue := getNewValue(field, tag)

	value.SetString(newValue)

	return
}
<commit_msg>bug fix<commit_after>package goConfig

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/pkg/errors"
)

// Settings default
type Settings struct {
	// Path sets default config path
	Path string
	// File name of default config file
	File string
	// FileRequired config file required
	FileRequired bool
	// Tag set the main tag
	Tag string
	// TagDefault set tag default
	TagDefault string
	// TagDisabled used to not process an input
	TagDisabled string
	// EnvironmentVarSeparator separe names on environment variables
	EnvironmentVarSeparator string
}

// Setup Pointer to internal variables
var Setup *Settings

// ReflectFunc type used to create funcrions to parse struct and tags
type ReflectFunc func(
	field *reflect.StructField,
	value *reflect.Value,
	tag string) (err error)

var parseMap map[reflect.Kind]ReflectFunc

func init() {
	Setup = &Settings{
		Path:                    "./",
		File:                    "config.json",
		Tag:                     "cfg",
		TagDefault:              "cfgDefault",
		TagDisabled:             "-",
		EnvironmentVarSeparator: "_",
		FileRequired:            false,
	}

	parseMap = make(map[reflect.Kind]ReflectFunc)

	parseMap[reflect.Struct] = reflectStruct
	parseMap[reflect.Int] = reflectInt
	parseMap[reflect.String] = reflectString

}

// LoadJSON config file
func LoadJSON(config interface{}) (err error) {
	configFile := Setup.Path + Setup.File
	file, err := os.Open(configFile)
	if os.IsNotExist(err) && !Setup.FileRequired {
		err = nil
		return
	} else if err != nil {
		return
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	err = decoder.Decode(&config)
	if err != nil {
		return
	}

	return
}

// Load config file
func Load(config interface{}) (err error) {

	err = LoadJSON(config)
	if err != nil {
		return
	}

	err = parseTags(config, "")
	if err != nil {
		return
	}

	return
}

// Save config file
func Save(config interface{}) (err error) {
	_, err = os.Stat(Setup.Path)
	if os.IsNotExist(err) {
		os.Mkdir(Setup.Path, 0700)
	} else if err != nil {
		return
	}

	configFile := Setup.Path + Setup.File

	_, err = os.Stat(configFile)
	if err != nil {
		return
	}

	b, err := json.MarshalIndent(config, "", "\t")
	if err != nil {
		return
	}

	err = ioutil.WriteFile(configFile, b, 0644)
	if err != nil {
		return
	}
	return
}

func parseTags(s interface{}, superTag string) (err error) {

	st := reflect.TypeOf(s)

	if st.Kind() != reflect.Ptr {
		err = errors.New("Not a pointer")
		return
	}

	refField := st.Elem()
	if refField.Kind() != reflect.Struct {
		err = errors.New("Not a struct")
		return
	}

	//vt := reflect.ValueOf(s)
	refValue := reflect.ValueOf(s).Elem()
	for i := 0; i < refField.NumField(); i++ {
		field := refField.Field(i)
		value := refValue.Field(i)
		kind := field.Type.Kind()

		if field.PkgPath != "" {
			continue
		}

		t := updateTag(&field, superTag)
		if t == "" {
			continue
		}

		if f, ok := parseMap[kind]; ok {
			err = f(&field, &value, t)
			if err != nil {
				return
			}
		} else {
			err = errors.New("Type not supported " + kind.String())
			return
		}

		fmt.Println("name:", field.Name,
			"| cfg:", field.Tag.Get(Setup.Tag),
			"| cfgDefault:", field.Tag.Get(Setup.TagDefault),
			"| type:", field.Type)

	}
	return
}

func updateTag(field *reflect.StructField, superTag string) (ret string) {
	ret = field.Tag.Get(Setup.Tag)
	if ret == Setup.TagDisabled {
		ret = ""
		return
	}

	if ret == "" {
		ret = strings.ToUpper(field.Name)
	}

	if superTag != "" {
		ret = superTag + Setup.EnvironmentVarSeparator + ret
	}
	return
}

func getNewValue(field *reflect.StructField, tag string) (ret string) {

	ret = os.Getenv(tag)
	if ret != "" {
		return
	}

	ret = field.Tag.Get(Setup.TagDefault)
	if ret != "" {
		return
	}

	return

}

func reflectStruct(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	err = parseTags(value.Addr().Interface(), tag)
	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	//value.SetInt(999)

	newValue := getNewValue(field, tag)

	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}
	value.SetInt(intNewValue)

	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	//value.SetString("TEST")
	newValue := getNewValue(field, tag)

	value.SetString(newValue)

	return
}
<|endoftext|>


<commit_before>package orm

import (
	"testing"
)

func TestDeleteByID(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//check if the object is stored in the table and if the ID is populated after insert
	ormTest.DropTable()
	ormTest.CreateTable()
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	err = ormTest.Save(&dslTest)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	id := dslTest.ID
	if id != 1 {
		t.Fatalf("\ndslTest.ID got:\t %v\nWant:\t\t\t 1\n", id)
	}

	n, err := ormTest.Delete().ByID(id)

	if n != 1 {
		t.Fatalf("\ndeleted got:\t %v\nWant:\t\t\t 1\n", n)
	}

	if err != nil {
		t.Fatalf("\nerr got:\t %v\nWant:\t\t\t nil\n", err)
	}

	dslTestFind, err := ormTest.Select().ByID(id)
	if dslTestFind != nil {
		t.Fatalf("\ndslTest got:\t %v\nWant:\t\t\t nil\n", dslTest)
	}

	if err.Error() != "sql: no rows in result set" {
		t.Fatalf("want: `sql: no rows in result set`, got: `%v`", err)
	}

	oldDeleteSQL := ormTest.deleteSQL
	ormTest.deleteSQL = "wrong-sql"
	n, err = ormTest.Delete().ByID(id)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.deleteSQL = oldDeleteSQL
}
<commit_msg>Add unit test for DeleteWhere<commit_after>package orm

import (
	"testing"
)

func TestDeleteByID(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//check if the object is stored in the table and if the ID is populated after insert
	ormTest.DropTable()
	ormTest.CreateTable()
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	err = ormTest.Save(&dslTest)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	id := dslTest.ID
	if id != 1 {
		t.Fatalf("\ndslTest.ID got:\t %v\nWant:\t\t\t 1\n", id)
	}

	n, err := ormTest.Delete().ByID(id)

	if n != 1 {
		t.Fatalf("\ndeleted got:\t %v\nWant:\t\t\t 1\n", n)
	}

	if err != nil {
		t.Fatalf("\nerr got:\t %v\nWant:\t\t\t nil\n", err)
	}

	dslTestFind, err := ormTest.Select().ByID(id)
	if dslTestFind != nil {
		t.Fatalf("\ndslTest got:\t %v\nWant:\t\t\t nil\n", dslTest)
	}

	if err.Error() != "sql: no rows in result set" {
		t.Fatalf("want: `sql: no rows in result set`, got: `%v`", err)
	}

	oldDeleteSQL := ormTest.deleteSQL
	ormTest.deleteSQL = "wrong-sql"
	n, err = ormTest.Delete().ByID(id)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.deleteSQL = oldDeleteSQL
}

func TestDeleteWhere(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//check if the object is stored in the table and if the ID is populated after insert
	ormTest.DropTable()
	ormTest.CreateTable()
	dslTest1 := DSLTest{FieldString: "teststring1", FieldInt: 111}
	err = ormTest.Save(&dslTest1)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	dslTest2 := DSLTest{FieldString: "teststring2", FieldInt: 222}
	err = ormTest.Save(&dslTest2)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	dslTestResults, err := ormTest.Select().Where("FieldString like 'teststring%'")
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	if len(dslTestResults) != 2 {
		t.Fatalf("want: 2, got: %v", len(dslTestResults))
	}

	n, err := ormTest.Delete().Where("FieldString like 'teststring%'")
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	if n != 2 {
		t.Fatalf("want: 2, got: %v", n)
	}

	oldDeleteSQL := ormTest.deleteSQL
	ormTest.deleteSQL = "wrong-sql"
	n, err = ormTest.Delete().Where("FieldString like 'teststring%'")
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.deleteSQL = oldDeleteSQL
}
<|endoftext|>


<commit_before>// Package osgridconverter contains utility functions to convert
// Ordnance Survey grid references to latitude/longitude coordinates.
package osgridconverter

import (
	"errors"
	"fmt"
	"math"
	"strconv"
)

const (
	a  = 6377563.396              // Airy 1830 major & minor semi-axes
	b  = 6356256.909              // Airy 1830 major & minor semi-axes
	f0 = 0.9996012717             // NatGrid scale factor on central meridian
	φ0 = 49 * math.Pi / 180       // NatGrid true origin
	λ0 = -2 * math.Pi / 180       // NatGrid true origin
	n0 = -100000                  // northing of true origin, metres
	e0 = 400000                   // easting of true origin, metres
	e2 = 1 - (b*b)/(a*a)          // eccentricity squared
	n  = (a - b) / (a + b)        // n
	n2 = 0.0000027996662693370183 // n²
	n3 = n * n * n                // n³
)

// Coordinates struct holds the latitude and longitude coordinates
type Coordinates struct {
	Lat float64
	Lon float64
}

// OsGrid struct holds the easting and northing grid points
type OsGrid struct {
	Easting  float64
	Northing float64
}

// ConvertToLatLon converts Ordnance Survey grid reference easting and northing
// coordinates to latitude and longitude according to the WGS-84 ellipsoidal model.
// Easting and Northing arguments should be fully numeric
// references in metres (eg 438700, 114800).
// It returns latitude and longitude coordinates as float64 type
func ConvertToLatLon(easting, northing float64) (Coordinates, error) {
	c := Coordinates{}

	// validate input
	if easting < 0 || northing < 0 {
		err := errors.New("Invalid arguments. Easting and Northing coordinates should be positive float64.")
		return c, err
	}

	φ := φ0
	M := float64(0)

	for northing-n0-M >= 0.00001 {
		φ = (northing-n0-M)/(a*f0) + φ
		Ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (φ - φ0)
		Mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(φ-φ0) * math.Cos(φ+φ0)
		Mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(φ-φ0)) * math.Cos(2*(φ+φ0))
		Md := (35 / 24) * n3 * math.Sin(3*(φ-φ0)) * math.Cos(3*(φ+φ0))
		M = b * f0 * (Ma - Mb + Mc - Md) // meridional arc
	}

	cosφ := math.Cos(φ)
	sinφ := math.Sin(φ)
	ν := a * f0 / math.Sqrt(1-e2*sinφ*sinφ)                // nu = transverse radius of curvature
	ρ := a * f0 * (1 - e2) / math.Pow(1-e2*sinφ*sinφ, 1.5) // rho = meridional radius of curvature
	η2 := ν/ρ - 1

	tanφ := math.Tan(φ)
	tan2φ := tanφ * tanφ
	tan4φ := tan2φ * tan2φ
	tan6φ := tan4φ * tan2φ
	secφ := 1 / cosφ
	ν3 := ν * ν * ν
	ν5 := ν3 * ν * ν
	ν7 := ν5 * ν * ν
	VII := tanφ / (2 * ρ * ν)
	VIII := tanφ / (24 * ρ * ν3) * (5 + 3*tan2φ + η2 - 9*tan2φ*η2)
	IX := tanφ / (720 * ρ * ν5) * (61 + 90*tan2φ + 45*tan4φ)
	X := secφ / ν
	XI := secφ / (6 * ν3) * (ν/ρ + 2*tan2φ)
	XII := secφ / (120 * ν5) * (5 + 28*tan2φ + 24*tan4φ)
	XIIA := secφ / (5040 * ν7) * (61 + 662*tan2φ + 1320*tan4φ + 720*tan6φ)

	dE := (easting - e0)
	dE2 := dE * dE
	dE3 := dE2 * dE
	dE4 := dE2 * dE2
	dE5 := dE3 * dE2
	dE6 := dE4 * dE2
	dE7 := dE5 * dE2
	φ = φ - VII*dE2 + VIII*dE4 - IX*dE6
	λ := λ0 + X*dE - XI*dE3 + XII*dE5 - XIIA*dE7

	c.Lat = toDegrees(φ)
	c.Lon = toDegrees(λ)

	return c, nil
}

// ConvertToNorthingEasting converts latitude and longitude to
// Ordnance Survey grid reference northing and easting.
// It returns northing and easting coordinates as float64 type
func ConvertToNorthingEasting(lat, lon float64) (OsGrid, error) {
	o := OsGrid{}

	// validate input
	if lat < -90 || lat > 90 {
		return o, errors.New("Latitude values must be between -90 and +90")
	}

	if lon < -180 || lon > 180 {
		return o, errors.New("Longitude values must be between -180 and +180")
	}

	φ := toRadians(lat)
	λ := toRadians(lon)

	cosφ := math.Cos(φ)
	sinφ := math.Sin(φ)
	ν := a * f0 / math.Sqrt(1-e2*sinφ*sinφ)
	ρ := a * f0 * (1 - e2) / math.Pow(1-e2*sinφ*sinφ, 1.5)
	η2 := ν/ρ - 1

	Ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (φ - φ0)
	Mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(φ-φ0) * math.Cos(φ+φ0)
	Mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(φ-φ0)) * math.Cos(2*(φ+φ0))
	Md := (35 / 24) * n3 * math.Sin(3*(φ-φ0)) * math.Cos(3*(φ+φ0))
	M := b * f0 * (Ma - Mb + Mc - Md)

	cos3φ := cosφ * cosφ * cosφ
	cos5φ := cos3φ * cosφ * cosφ
	tan2φ := math.Tan(φ) * math.Tan(φ)
	tan4φ := tan2φ * tan2φ

	I := M + n0
	II := (ν / 2) * sinφ * cosφ
	III := (ν / 24) * sinφ * cos3φ * (5 - tan2φ + 9*η2)
	IIIA := (ν / 720) * sinφ * cos5φ * (61 - 58*tan2φ + tan4φ)
	IV := ν * cosφ
	V := (ν / 6) * cos3φ * (ν/ρ - tan2φ)
	VI := (ν / 120) * cos5φ * (5 - 18*tan2φ + tan4φ + 14*η2 - 58*tan2φ*η2)

	Δλ := λ - λ0
	Δλ2 := Δλ * Δλ
	Δλ3 := Δλ2 * Δλ
	Δλ4 := Δλ3 * Δλ
	Δλ5 := Δλ4 * Δλ
	Δλ6 := Δλ5 * Δλ

	northingVal := I + II*Δλ2 + III*Δλ4 + IIIA*Δλ6
	northingVal, _ = strconv.ParseFloat(fmt.Sprintf("%.3f", northingVal), 64) // truncate after 3 decimal positions
	o.Northing = northingVal

	eastingVal := e0 + IV*Δλ + V*Δλ3 + VI*Δλ5
	eastingVal, _ = strconv.ParseFloat(fmt.Sprintf("%.3f", eastingVal), 64) // truncate after 3 decimal positions
	o.Easting = eastingVal

	return o, nil
}

// toDegrees converts radians to numeric degrees
func toDegrees(input float64) float64 {
	return input * 180 / math.Pi
}

// toRadians converts numeric degrees to radians
func toRadians(input float64) float64 {
	return input * math.Pi / 180
}
<commit_msg>return struct pointer<commit_after>// Package osgridconverter contains utility functions to convert
// Ordnance Survey grid references to latitude/longitude coordinates.
package osgridconverter

import (
	"errors"
	"fmt"
	"math"
	"strconv"
)

const (
	a  = 6377563.396              // Airy 1830 major & minor semi-axes
	b  = 6356256.909              // Airy 1830 major & minor semi-axes
	f0 = 0.9996012717             // NatGrid scale factor on central meridian
	φ0 = 49 * math.Pi / 180       // NatGrid true origin
	λ0 = -2 * math.Pi / 180       // NatGrid true origin
	n0 = -100000                  // northing of true origin, metres
	e0 = 400000                   // easting of true origin, metres
	e2 = 1 - (b*b)/(a*a)          // eccentricity squared
	n  = (a - b) / (a + b)        // n
	n2 = 0.0000027996662693370183 // n²
	n3 = n * n * n                // n³
)

// Coordinates struct holds the latitude and longitude coordinates
type Coordinates struct {
	Lat float64
	Lon float64
}

// OsGrid struct holds the easting and northing grid points
type OsGrid struct {
	Easting  float64
	Northing float64
}

// ConvertToLatLon converts Ordnance Survey grid reference easting and northing
// coordinates to latitude and longitude according to the WGS-84 ellipsoidal model.
// Easting and Northing arguments should be fully numeric
// references in metres (eg 438700, 114800).
// It returns a struct containing latitude and longitude coordinates as float64 type
// or an error if the arguments passed in are out of bounds
func ConvertToLatLon(easting, northing float64) (*Coordinates, error) {
	c := Coordinates{}

	// validate input
	if easting < 0 || northing < 0 {
		err := errors.New("Invalid arguments. Easting and Northing coordinates should be positive float64.")
		return &c, err
	}

	φ := φ0
	M := float64(0)

	for northing-n0-M >= 0.00001 {
		φ = (northing-n0-M)/(a*f0) + φ
		Ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (φ - φ0)
		Mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(φ-φ0) * math.Cos(φ+φ0)
		Mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(φ-φ0)) * math.Cos(2*(φ+φ0))
		Md := (35 / 24) * n3 * math.Sin(3*(φ-φ0)) * math.Cos(3*(φ+φ0))
		M = b * f0 * (Ma - Mb + Mc - Md) // meridional arc
	}

	cosφ := math.Cos(φ)
	sinφ := math.Sin(φ)
	ν := a * f0 / math.Sqrt(1-e2*sinφ*sinφ)                // nu = transverse radius of curvature
	ρ := a * f0 * (1 - e2) / math.Pow(1-e2*sinφ*sinφ, 1.5) // rho = meridional radius of curvature
	η2 := ν/ρ - 1

	tanφ := math.Tan(φ)
	tan2φ := tanφ * tanφ
	tan4φ := tan2φ * tan2φ
	tan6φ := tan4φ * tan2φ
	secφ := 1 / cosφ
	ν3 := ν * ν * ν
	ν5 := ν3 * ν * ν
	ν7 := ν5 * ν * ν
	VII := tanφ / (2 * ρ * ν)
	VIII := tanφ / (24 * ρ * ν3) * (5 + 3*tan2φ + η2 - 9*tan2φ*η2)
	IX := tanφ / (720 * ρ * ν5) * (61 + 90*tan2φ + 45*tan4φ)
	X := secφ / ν
	XI := secφ / (6 * ν3) * (ν/ρ + 2*tan2φ)
	XII := secφ / (120 * ν5) * (5 + 28*tan2φ + 24*tan4φ)
	XIIA := secφ / (5040 * ν7) * (61 + 662*tan2φ + 1320*tan4φ + 720*tan6φ)

	dE := (easting - e0)
	dE2 := dE * dE
	dE3 := dE2 * dE
	dE4 := dE2 * dE2
	dE5 := dE3 * dE2
	dE6 := dE4 * dE2
	dE7 := dE5 * dE2
	φ = φ - VII*dE2 + VIII*dE4 - IX*dE6
	λ := λ0 + X*dE - XI*dE3 + XII*dE5 - XIIA*dE7

	c.Lat = toDegrees(φ)
	c.Lon = toDegrees(λ)

	return &c, nil
}

// ConvertToNorthingEasting converts latitude and longitude to
// Ordnance Survey grid reference northing and easting.
// It returns a struct containing easting and northing coordinates as float64 type
// or an error if the arguments passed in are out of bounds
func ConvertToNorthingEasting(lat, lon float64) (*OsGrid, error) {
	o := OsGrid{}

	// validate input
	if lat < -90 || lat > 90 {
		return &o, errors.New("Latitude values must be between -90 and +90")
	}

	if lon < -180 || lon > 180 {
		return &o, errors.New("Longitude values must be between -180 and +180")
	}

	φ := toRadians(lat)
	λ := toRadians(lon)

	cosφ := math.Cos(φ)
	sinφ := math.Sin(φ)
	ν := a * f0 / math.Sqrt(1-e2*sinφ*sinφ)
	ρ := a * f0 * (1 - e2) / math.Pow(1-e2*sinφ*sinφ, 1.5)
	η2 := ν/ρ - 1

	Ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (φ - φ0)
	Mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(φ-φ0) * math.Cos(φ+φ0)
	Mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(φ-φ0)) * math.Cos(2*(φ+φ0))
	Md := (35 / 24) * n3 * math.Sin(3*(φ-φ0)) * math.Cos(3*(φ+φ0))
	M := b * f0 * (Ma - Mb + Mc - Md)

	cos3φ := cosφ * cosφ * cosφ
	cos5φ := cos3φ * cosφ * cosφ
	tan2φ := math.Tan(φ) * math.Tan(φ)
	tan4φ := tan2φ * tan2φ

	I := M + n0
	II := (ν / 2) * sinφ * cosφ
	III := (ν / 24) * sinφ * cos3φ * (5 - tan2φ + 9*η2)
	IIIA := (ν / 720) * sinφ * cos5φ * (61 - 58*tan2φ + tan4φ)
	IV := ν * cosφ
	V := (ν / 6) * cos3φ * (ν/ρ - tan2φ)
	VI := (ν / 120) * cos5φ * (5 - 18*tan2φ + tan4φ + 14*η2 - 58*tan2φ*η2)

	Δλ := λ - λ0
	Δλ2 := Δλ * Δλ
	Δλ3 := Δλ2 * Δλ
	Δλ4 := Δλ3 * Δλ
	Δλ5 := Δλ4 * Δλ
	Δλ6 := Δλ5 * Δλ

	northingVal := I + II*Δλ2 + III*Δλ4 + IIIA*Δλ6
	northingVal, _ = strconv.ParseFloat(fmt.Sprintf("%.3f", northingVal), 64) // truncate after 3 decimal positions
	o.Northing = northingVal

	eastingVal := e0 + IV*Δλ + V*Δλ3 + VI*Δλ5
	eastingVal, _ = strconv.ParseFloat(fmt.Sprintf("%.3f", eastingVal), 64) // truncate after 3 decimal positions
	o.Easting = eastingVal

	return &o, nil
}

// toDegrees converts radians to numeric degrees
func toDegrees(input float64) float64 {
	return input * 180 / math.Pi
}

// toRadians converts numeric degrees to radians
func toRadians(input float64) float64 {
	return input * math.Pi / 180
}
<|endoftext|>


<commit_before>package dorp

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"strings"

	"golang.org/x/crypto/nacl/secretbox"
)

// A SetMessage is the Go representation of the JSON message
// sent to set states
type SetMessage struct {
	DoorState  string
	LightState string
}

// A State is  a binary condition of the door or lights.
type State int

const (
	Open State = iota
	Closed
	On
	Off
)

// PADDING_SIZE is the amount of padding used before the auth
// token in the message. The padding is used so that the same
// token encrypted with the same key produces different results
const PADDING_SIZE = 6

const DELIMITER = "/"

// String implements Stringer on States.
func (s State) String() string {
	switch s {
	case Open:
		return "Open"
	case Closed:
		return "Closed"
	case On:
		return "On"
	case Off:
		return "Off"
	default:
		panic("BAD STATE")
	}
}

// Encrypt takes a message and converts it to a base64 encoding
// of the encrypted string, followed by a separator, followed
// by the nonce
func Encrypt(key [32]byte, text []byte) (string, error) {
	var box []byte
	var nonce [24]byte
	n, err := rand.Reader.Read(nonce[:])
	if n != 24 {
		return "", fmt.Errorf("encrypt: unable to read 24 random bytes for nonce")
	}
	if err != nil {
		return "", err
	}
	box = secretbox.Seal(box[:0], text, &nonce, &key)
	return strings.Join([]string{
		base64.StdEncoding.EncodeToString(box),
		base64.StdEncoding.EncodeToString(nonce[:]),
	}, DELIMITER), nil
}

// Decrypt takes the base64 encoded box and nonce separated by DELIMITER
// and returns the opened box or an error
func Decrypt(data string, key [32]byte) ([]byte, error) {
	var nonce [24]byte
	var opened []byte
	parts := strings.Split(data, DELIMITER)
	if len(parts) != 2 {
		return nil, fmt.Errorf("decrypt: data contains too many delimiters")
	}
	box, err := base64.StdEncoding.DecodeString(parts[0])
	if err != nil {
		return nil, fmt.Errorf("decrypt box: %s", err)
	}
	nonceS, err := base64.StdEncoding.DecodeString(parts[1])
	if err != nil {
		return nil, fmt.Errorf("decrypt nonce: %s", err)
	}
	if n := copy(nonce[:], nonceS); n != 24 {
		return nil, fmt.Errorf("decrypt: nonce has incorrect length")
	}
	opened, ok := secretbox.Open(opened, box, &nonce, &key)
	if !ok {
		return nil, fmt.Errorf("decrypt: failed to open box")
	}
	return opened, nil
}

// KeyToByteArray converts a key to the [32]bytes required by nacl.secretbox
func KeyToByteArray(key string) ([32]byte, error) {
	var k [32]byte
	if len(key) != 32 {
		return k, fmt.Errorf("Key must be 32 bytes (characters) long")
	}
	n := copy(k[:], []byte(key))
	if n != 32 {
		return k, fmt.Errorf("Copying key failed")
	}
	return k, nil
}
<commit_msg>Change delimiter in message to one not used in base64 encoding... oops :P<commit_after>package dorp

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"strings"

	"golang.org/x/crypto/nacl/secretbox"
)

// A SetMessage is the Go representation of the JSON message
// sent to set states
type SetMessage struct {
	DoorState  string
	LightState string
}

// A State is  a binary condition of the door or lights.
type State int

const (
	Open State = iota
	Closed
	On
	Off
)

// PADDING_SIZE is the amount of padding used before the auth
// token in the message. The padding is used so that the same
// token encrypted with the same key produces different results
const PADDING_SIZE = 6

const DELIMITER = ";"

// String implements Stringer on States.
func (s State) String() string {
	switch s {
	case Open:
		return "Open"
	case Closed:
		return "Closed"
	case On:
		return "On"
	case Off:
		return "Off"
	default:
		panic("BAD STATE")
	}
}

// Encrypt takes a message and converts it to a base64 encoding
// of the encrypted string, followed by a separator, followed
// by the nonce
func Encrypt(key [32]byte, text []byte) (string, error) {
	var box []byte
	var nonce [24]byte
	n, err := rand.Reader.Read(nonce[:])
	if n != 24 {
		return "", fmt.Errorf("encrypt: unable to read 24 random bytes for nonce")
	}
	if err != nil {
		return "", err
	}
	box = secretbox.Seal(box[:0], text, &nonce, &key)
	return strings.Join([]string{
		base64.StdEncoding.EncodeToString(box),
		base64.StdEncoding.EncodeToString(nonce[:]),
	}, DELIMITER), nil
}

// Decrypt takes the base64 encoded box and nonce separated by DELIMITER
// and returns the opened box or an error
func Decrypt(data string, key [32]byte) ([]byte, error) {
	var nonce [24]byte
	var opened []byte
	parts := strings.Split(data, DELIMITER)
	if len(parts) != 2 {
		return nil, fmt.Errorf("decrypt: data contains too many delimiters")
	}
	box, err := base64.StdEncoding.DecodeString(parts[0])
	if err != nil {
		return nil, fmt.Errorf("decrypt box: %s", err)
	}
	nonceS, err := base64.StdEncoding.DecodeString(parts[1])
	if err != nil {
		return nil, fmt.Errorf("decrypt nonce: %s", err)
	}
	if n := copy(nonce[:], nonceS); n != 24 {
		return nil, fmt.Errorf("decrypt: nonce has incorrect length")
	}
	opened, ok := secretbox.Open(opened, box, &nonce, &key)
	if !ok {
		return nil, fmt.Errorf("decrypt: failed to open box")
	}
	return opened, nil
}

// KeyToByteArray converts a key to the [32]bytes required by nacl.secretbox
func KeyToByteArray(key string) ([32]byte, error) {
	var k [32]byte
	if len(key) != 32 {
		return k, fmt.Errorf("Key must be 32 bytes (characters) long")
	}
	n := copy(k[:], []byte(key))
	if n != 32 {
		return k, fmt.Errorf("Copying key failed")
	}
	return k, nil
}
<|endoftext|>


<commit_before>package router

import (
	"bytes"
	"encoding/gob"
	"encoding/hex"
	"fmt"
	"io"
	"time"
)

const (
	Protocol           = "weave"
	ProtocolMinVersion = 1
	ProtocolMaxVersion = 2
)

var (
	ProtocolBytes = []byte(Protocol)

	HeaderTimeout = 10 * time.Second

	ProtocolV1Features = []string{
		"ConnID",
		"Name",
		"NickName",
		"PeerNameFlavour",
		"UID",
	}

	ErrExpectedCrypto   = fmt.Errorf("Password specified, but peer requested an unencrypted connection")
	ErrExpectedNoCrypto = fmt.Errorf("No password specificed, but peer requested an encrypted connection")
)

// We don't need the full net.TCPConn to do the protocol intro.  This
// interface contains just the parts we do need, to support testing
type ProtocolIntroConn interface {
	// io.Reader
	Read(b []byte) (n int, err error)

	// io.Writer
	Write(b []byte) (n int, err error)

	// net.Conn's deadline methods
	SetDeadline(t time.Time) error
	SetReadDeadline(t time.Time) error
	SetWriteDeadline(t time.Time) error
}

type ProtocolIntroParams struct {
	MinVersion byte
	MaxVersion byte
	Features   map[string]string
	Conn       ProtocolIntroConn
	Password   []byte
	Outbound   bool
}

type ProtocolIntroResults struct {
	Features   map[string]string
	Receiver   TCPReceiver
	Sender     TCPSender
	SessionKey *[32]byte
	Version    byte
}

func (params ProtocolIntroParams) DoIntro() (res ProtocolIntroResults, err error) {
	if err = params.Conn.SetDeadline(time.Now().Add(HeaderTimeout)); err != nil {
		return
	}

	if res.Version, err = params.exchangeProtocolHeader(); err != nil {
		return
	}

	var pubKey, privKey *[32]byte
	if params.Password != nil {
		if pubKey, privKey, err = GenerateKeyPair(); err != nil {
			return
		}
	}

	if err = params.Conn.SetWriteDeadline(time.Time{}); err != nil {
		return
	}
	if err = params.Conn.SetReadDeadline(time.Now().Add(TCPHeartbeat * 2)); err != nil {
		return
	}

	switch res.Version {
	case 1:
		err = res.doIntroV1(params, pubKey, privKey)
	case 2:
		err = res.doIntroV2(params, pubKey, privKey)
	default:
		panic("unhandled protocol version")
	}

	return
}

func (params ProtocolIntroParams) exchangeProtocolHeader() (byte, error) {
	// Write in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	sendHeader := append(ProtocolBytes, params.MinVersion, params.MaxVersion)
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(sendHeader)
		writeDone <- err
	}()

	header := make([]byte, len(ProtocolBytes)+2)
	if n, err := io.ReadFull(params.Conn, header); err != nil && n == 0 {
		return 0, fmt.Errorf("failed to receive remote protocol header: %s", err)
	} else if err != nil {
		return 0, fmt.Errorf("received incomplete remote protocol header (%d octets instead of %d): %v; error: %s",
			n, len(header), header[:n], err)
	}

	if !bytes.Equal(ProtocolBytes, header[:len(ProtocolBytes)]) {
		return 0, fmt.Errorf("remote protocol header not recognised: %v", header[:len(ProtocolBytes)])
	}

	theirMinVersion := header[len(ProtocolBytes)]
	minVersion := theirMinVersion
	if params.MinVersion > minVersion {
		minVersion = params.MinVersion
	}

	theirMaxVersion := header[len(ProtocolBytes)+1]
	maxVersion := theirMaxVersion
	if maxVersion > params.MaxVersion {
		maxVersion = params.MaxVersion
	}

	if minVersion > maxVersion {
		return 0, fmt.Errorf("remote version range [%d,%d] is incompatible with ours [%d,%d]",
			theirMinVersion, theirMaxVersion,
			params.MinVersion, params.MaxVersion)
	}

	if err := <-writeDone; err != nil {
		return 0, err
	}

	return maxVersion, nil
}

// The V1 procotol consists of the protocol identification/version
// header, followed by a stream of gobified values.  The first value
// is the encoded features map (never encrypted).  The subsequent
// values are the messages on the connection (encrypted for an
// encrypted connection).  For an encrypted connection, the public key
// is passed in the "PublicKey" feature as a string of hex digits.
func (res *ProtocolIntroResults) doIntroV1(params ProtocolIntroParams, pubKey, privKey *[32]byte) error {
	features := filterV1Features(params.Features)
	if pubKey != nil {
		features["PublicKey"] = hex.EncodeToString(pubKey[:])
	}

	enc := gob.NewEncoder(params.Conn)
	dec := gob.NewDecoder(params.Conn)

	// Encode in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	encodeDone := make(chan error, 1)
	go func() {
		encodeDone <- enc.Encode(features)
	}()

	if err := dec.Decode(&res.Features); err != nil {
		return err
	}

	if err := <-encodeDone; err != nil {
		return err
	}

	if pubKey == nil {
		if _, present := res.Features["PublicKey"]; present {
			return ErrExpectedNoCrypto
		}

		res.setupNoCrypto(enc, dec)
	} else {
		remotePubKeyStr, ok := res.Features["PublicKey"]
		if !ok {
			return ErrExpectedCrypto
		}

		remotePubKey, err := hex.DecodeString(remotePubKeyStr)
		if err != nil {
			return err
		}

		res.setupCrypto(params, enc, dec, remotePubKey, privKey)
	}

	res.Features = filterV1Features(res.Features)
	return nil
}

// In the V1 protocol, the intro fields are sent unencrypted.  So we
// restrict them to an established subset of fields that are assumed
// to be safe.
func filterV1Features(intro map[string]string) map[string]string {
	safe := make(map[string]string)
	for _, k := range ProtocolV1Features {
		if val, ok := intro[k]; ok {
			safe[k] = val
		}
	}

	return safe
}

// The V2 procotol consists of the protocol identification/version
// header, followed by:
//
// - A single "encryption flag" byte: 0 for no encryption, 1 for
// encryption.
//
// - When the connection is encrypted, 32 bytes follow containing the
// public key.
//
// - Then a stream of gobified values.
//
// The gobified values are the messages on the connection (encrypted
// for an encrypted connection).  The first message contains the
// encoded features map (so in contrast to V1, it will be encrypted on
// an encrypted connection).
func (res *ProtocolIntroResults) doIntroV2(params ProtocolIntroParams, pubKey, privKey *[32]byte) error {
	// Public key exchange
	var wbuf []byte
	if pubKey == nil {
		wbuf = []byte{0}
	} else {
		wbuf = make([]byte, 1+len(*pubKey))
		wbuf[0] = 1
		copy(wbuf[1:], (*pubKey)[:])
	}

	// Write in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(wbuf)
		writeDone <- err
	}()

	rbuf := make([]byte, 1)
	if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
		return err
	}

	switch rbuf[0] {
	case 0:
		if pubKey != nil {
			return ErrExpectedCrypto
		}

		res.setupNoCrypto(gob.NewEncoder(params.Conn),
			gob.NewDecoder(params.Conn))

	case 1:
		if pubKey == nil {
			return ErrExpectedNoCrypto
		}

		rbuf = make([]byte, len(pubKey))
		if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
			return err
		}

		res.setupCrypto(params, gob.NewEncoder(params.Conn),
			gob.NewDecoder(params.Conn), rbuf, privKey)

	default:
		return fmt.Errorf("Bad encryption flag %d", rbuf[0])
	}

	if err := <-writeDone; err != nil {
		return err
	}

	// Features exchange
	go func() {
		buf := new(bytes.Buffer)
		if err := gob.NewEncoder(buf).Encode(&params.Features); err != nil {
			writeDone <- err
			return
		}

		writeDone <- res.Sender.Send(buf.Bytes())
	}()

	rbuf, err := res.Receiver.Receive()
	if err != nil {
		return err
	}

	if err := gob.NewDecoder(bytes.NewReader(rbuf)).Decode(&res.Features); err != nil {
		return err
	}

	if err := <-writeDone; err != nil {
		return err
	}

	return nil
}

func (res *ProtocolIntroResults) setupNoCrypto(enc *gob.Encoder, dec *gob.Decoder) {
	res.Sender = NewSimpleTCPSender(enc)
	res.Receiver = NewSimpleTCPReceiver(dec)
}

func (res *ProtocolIntroResults) setupCrypto(params ProtocolIntroParams,
	enc *gob.Encoder, dec *gob.Decoder, remotePubKey []byte,
	privKey *[32]byte) {
	var remotePubKeyArr [32]byte
	copy(remotePubKeyArr[:], remotePubKey)
	res.SessionKey = FormSessionKey(&remotePubKeyArr, privKey, params.Password)
	res.Sender = NewEncryptedTCPSender(enc, res.SessionKey, params.Outbound)
	res.Receiver = NewEncryptedTCPReceiver(dec, res.SessionKey, params.Outbound)
}

type ProtocolTag byte

const (
	ProtocolHeartbeat ProtocolTag = iota
	ProtocolConnectionEstablished
	ProtocolFragmentationReceived
	ProtocolPMTUVerified
	ProtocolGossip
	ProtocolGossipUnicast
	ProtocolGossipBroadcast
)

type ProtocolMsg struct {
	tag ProtocolTag
	msg []byte
}

type ProtocolSender interface {
	SendProtocolMsg(m ProtocolMsg)
}
<commit_msg>cosmetic<commit_after>package router

import (
	"bytes"
	"encoding/gob"
	"encoding/hex"
	"fmt"
	"io"
	"time"
)

const (
	Protocol           = "weave"
	ProtocolMinVersion = 1
	ProtocolMaxVersion = 2
)

var (
	ProtocolBytes = []byte(Protocol)

	HeaderTimeout = 10 * time.Second

	ProtocolV1Features = []string{
		"ConnID",
		"Name",
		"NickName",
		"PeerNameFlavour",
		"UID",
	}

	ErrExpectedCrypto   = fmt.Errorf("Password specified, but peer requested an unencrypted connection")
	ErrExpectedNoCrypto = fmt.Errorf("No password specificed, but peer requested an encrypted connection")
)

// We don't need the full net.TCPConn to do the protocol intro.  This
// interface contains just the parts we do need, to support testing
type ProtocolIntroConn interface {
	// io.Reader
	Read(b []byte) (n int, err error)

	// io.Writer
	Write(b []byte) (n int, err error)

	// net.Conn's deadline methods
	SetDeadline(t time.Time) error
	SetReadDeadline(t time.Time) error
	SetWriteDeadline(t time.Time) error
}

type ProtocolIntroParams struct {
	MinVersion byte
	MaxVersion byte
	Features   map[string]string
	Conn       ProtocolIntroConn
	Password   []byte
	Outbound   bool
}

type ProtocolIntroResults struct {
	Features   map[string]string
	Receiver   TCPReceiver
	Sender     TCPSender
	SessionKey *[32]byte
	Version    byte
}

func (params ProtocolIntroParams) DoIntro() (res ProtocolIntroResults, err error) {
	if err = params.Conn.SetDeadline(time.Now().Add(HeaderTimeout)); err != nil {
		return
	}

	if res.Version, err = params.exchangeProtocolHeader(); err != nil {
		return
	}

	var pubKey, privKey *[32]byte
	if params.Password != nil {
		if pubKey, privKey, err = GenerateKeyPair(); err != nil {
			return
		}
	}

	if err = params.Conn.SetWriteDeadline(time.Time{}); err != nil {
		return
	}
	if err = params.Conn.SetReadDeadline(time.Now().Add(TCPHeartbeat * 2)); err != nil {
		return
	}

	switch res.Version {
	case 1:
		err = res.doIntroV1(params, pubKey, privKey)
	case 2:
		err = res.doIntroV2(params, pubKey, privKey)
	default:
		panic("unhandled protocol version")
	}

	return
}

func (params ProtocolIntroParams) exchangeProtocolHeader() (byte, error) {
	// Write in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	sendHeader := append(ProtocolBytes, params.MinVersion, params.MaxVersion)
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(sendHeader)
		writeDone <- err
	}()

	header := make([]byte, len(ProtocolBytes)+2)
	if n, err := io.ReadFull(params.Conn, header); err != nil && n == 0 {
		return 0, fmt.Errorf("failed to receive remote protocol header: %s", err)
	} else if err != nil {
		return 0, fmt.Errorf("received incomplete remote protocol header (%d octets instead of %d): %v; error: %s",
			n, len(header), header[:n], err)
	}

	if !bytes.Equal(ProtocolBytes, header[:len(ProtocolBytes)]) {
		return 0, fmt.Errorf("remote protocol header not recognised: %v", header[:len(ProtocolBytes)])
	}

	theirMinVersion := header[len(ProtocolBytes)]
	minVersion := theirMinVersion
	if params.MinVersion > minVersion {
		minVersion = params.MinVersion
	}

	theirMaxVersion := header[len(ProtocolBytes)+1]
	maxVersion := theirMaxVersion
	if maxVersion > params.MaxVersion {
		maxVersion = params.MaxVersion
	}

	if minVersion > maxVersion {
		return 0, fmt.Errorf("remote version range [%d,%d] is incompatible with ours [%d,%d]",
			theirMinVersion, theirMaxVersion,
			params.MinVersion, params.MaxVersion)
	}

	if err := <-writeDone; err != nil {
		return 0, err
	}

	return maxVersion, nil
}

// The V1 procotol consists of the protocol identification/version
// header, followed by a stream of gobified values.  The first value
// is the encoded features map (never encrypted).  The subsequent
// values are the messages on the connection (encrypted for an
// encrypted connection).  For an encrypted connection, the public key
// is passed in the "PublicKey" feature as a string of hex digits.
func (res *ProtocolIntroResults) doIntroV1(params ProtocolIntroParams, pubKey, privKey *[32]byte) error {
	features := filterV1Features(params.Features)
	if pubKey != nil {
		features["PublicKey"] = hex.EncodeToString(pubKey[:])
	}

	enc := gob.NewEncoder(params.Conn)
	dec := gob.NewDecoder(params.Conn)

	// Encode in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	encodeDone := make(chan error, 1)
	go func() {
		encodeDone <- enc.Encode(features)
	}()

	if err := dec.Decode(&res.Features); err != nil {
		return err
	}

	if err := <-encodeDone; err != nil {
		return err
	}

	if pubKey == nil {
		if _, present := res.Features["PublicKey"]; present {
			return ErrExpectedNoCrypto
		}

		res.setupNoCrypto(enc, dec)
	} else {
		remotePubKeyStr, ok := res.Features["PublicKey"]
		if !ok {
			return ErrExpectedCrypto
		}

		remotePubKey, err := hex.DecodeString(remotePubKeyStr)
		if err != nil {
			return err
		}

		res.setupCrypto(params, enc, dec, remotePubKey, privKey)
	}

	res.Features = filterV1Features(res.Features)
	return nil
}

// In the V1 protocol, the intro fields are sent unencrypted.  So we
// restrict them to an established subset of fields that are assumed
// to be safe.
func filterV1Features(intro map[string]string) map[string]string {
	safe := make(map[string]string)
	for _, k := range ProtocolV1Features {
		if val, ok := intro[k]; ok {
			safe[k] = val
		}
	}

	return safe
}

// The V2 procotol consists of the protocol identification/version
// header, followed by:
//
// - A single "encryption flag" byte: 0 for no encryption, 1 for
// encryption.
//
// - When the connection is encrypted, 32 bytes follow containing the
// public key.
//
// - Then a stream of gobified values.
//
// The gobified values are the messages on the connection (encrypted
// for an encrypted connection).  The first message contains the
// encoded features map (so in contrast to V1, it will be encrypted on
// an encrypted connection).
func (res *ProtocolIntroResults) doIntroV2(params ProtocolIntroParams, pubKey, privKey *[32]byte) error {
	// Public key exchange
	var wbuf []byte
	if pubKey == nil {
		wbuf = []byte{0}
	} else {
		wbuf = make([]byte, 1+len(*pubKey))
		wbuf[0] = 1
		copy(wbuf[1:], (*pubKey)[:])
	}

	// Write in a separate goroutine to avoid the possibility of
	// deadlock.  The result channel is of size 1 so that the
	// goroutine does not linger even if we encounter an error on
	// the read side.
	writeDone := make(chan error, 1)
	go func() {
		_, err := params.Conn.Write(wbuf)
		writeDone <- err
	}()

	rbuf := make([]byte, 1)
	if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
		return err
	}

	switch rbuf[0] {
	case 0:
		if pubKey != nil {
			return ErrExpectedCrypto
		}

		res.setupNoCrypto(gob.NewEncoder(params.Conn), gob.NewDecoder(params.Conn))

	case 1:
		if pubKey == nil {
			return ErrExpectedNoCrypto
		}

		rbuf = make([]byte, len(pubKey))
		if _, err := io.ReadFull(params.Conn, rbuf); err != nil {
			return err
		}

		res.setupCrypto(params, gob.NewEncoder(params.Conn), gob.NewDecoder(params.Conn), rbuf, privKey)

	default:
		return fmt.Errorf("Bad encryption flag %d", rbuf[0])
	}

	if err := <-writeDone; err != nil {
		return err
	}

	// Features exchange
	go func() {
		buf := new(bytes.Buffer)
		if err := gob.NewEncoder(buf).Encode(&params.Features); err != nil {
			writeDone <- err
			return
		}

		writeDone <- res.Sender.Send(buf.Bytes())
	}()

	rbuf, err := res.Receiver.Receive()
	if err != nil {
		return err
	}

	if err := gob.NewDecoder(bytes.NewReader(rbuf)).Decode(&res.Features); err != nil {
		return err
	}

	if err := <-writeDone; err != nil {
		return err
	}

	return nil
}

func (res *ProtocolIntroResults) setupNoCrypto(enc *gob.Encoder, dec *gob.Decoder) {
	res.Sender = NewSimpleTCPSender(enc)
	res.Receiver = NewSimpleTCPReceiver(dec)
}

func (res *ProtocolIntroResults) setupCrypto(params ProtocolIntroParams,
	enc *gob.Encoder, dec *gob.Decoder, remotePubKey []byte,
	privKey *[32]byte) {
	var remotePubKeyArr [32]byte
	copy(remotePubKeyArr[:], remotePubKey)
	res.SessionKey = FormSessionKey(&remotePubKeyArr, privKey, params.Password)
	res.Sender = NewEncryptedTCPSender(enc, res.SessionKey, params.Outbound)
	res.Receiver = NewEncryptedTCPReceiver(dec, res.SessionKey, params.Outbound)
}

type ProtocolTag byte

const (
	ProtocolHeartbeat ProtocolTag = iota
	ProtocolConnectionEstablished
	ProtocolFragmentationReceived
	ProtocolPMTUVerified
	ProtocolGossip
	ProtocolGossipUnicast
	ProtocolGossipBroadcast
)

type ProtocolMsg struct {
	tag ProtocolTag
	msg []byte
}

type ProtocolSender interface {
	SendProtocolMsg(m ProtocolMsg)
}
<|endoftext|>


<commit_before>package button

import "github.com/forestgiant/eff"

// Draw function that is called to draw a button at a particular state
type Draw func(*Button, eff.Canvas)

// Click function that is called when the button is clicked
type Click func(*Button)

// Button defines an eff.Drawable that maintains the state of a button
type Button struct {
	Rect         eff.Rect
	mouseDown    bool
	mouseOver    bool
	Text         string
	ClickHandler func(b *Button)
	DrawDefault  Draw
	DrawDown     Draw
	DrawOver     Draw
}

// Hitbox returns the hitbox rect of the button, this is the same as Button.Rect
func (b *Button) Hitbox() eff.Rect {
	return b.Rect
}

// MouseDown function that is called when any mouse button is pressed down while the cursor is inside the hitbox
func (b *Button) MouseDown(leftState bool, middleState bool, rightState bool) {
	b.mouseDown = true
}

// MouseUp function that is called when any mouse button is released while the cursor is inside the hitbox
func (b *Button) MouseUp(leftState bool, middleState bool, rightState bool) {
	if b.mouseDown {
		b.mouseDown = false
		b.ClickHandler(b)
	}
}

// MouseOver function that is called when the mouse moves into the hitbox
func (b *Button) MouseOver() {
	b.mouseOver = true
}

// MouseOut function that is called when the mouse moves out of the hitbox
func (b *Button) MouseOut() {
	b.mouseOver = false
	b.mouseDown = false
}

// IsMouseOver function that returns true if the mouse cursor is currently inside the hitbox
func (b *Button) IsMouseOver() bool { return b.mouseOver }

// Draw calls the appropriate draw function based on the button state
func (b *Button) Draw(c eff.Canvas) {
	var drawFunc Draw
	if b.mouseDown {
		drawFunc = b.DrawDown
	} else if b.mouseOver {
		drawFunc = b.DrawOver
	} else {
		drawFunc = b.DrawDefault
	}

	if drawFunc != nil {
		drawFunc(b, c)
	}
}

// NewButton function that creates an instance of the component button
func NewButton(text string, rect eff.Rect, drawDefault Draw, drawDown Draw, drawOver Draw, clickhandler Click) Button {
	return Button{
		Rect:         rect,
		Text:         text,
		ClickHandler: clickhandler,
		DrawDefault:  drawDefault,
		DrawDown:     drawDown,
		DrawOver:     drawOver,
	}
}
<commit_msg>Fixed issue with the button component, now it will use the default draw if no others are specified<commit_after>package button

import "github.com/forestgiant/eff"

// Draw function that is called to draw a button at a particular state
type Draw func(*Button, eff.Canvas)

// Click function that is called when the button is clicked
type Click func(*Button)

// Button defines an eff.Drawable that maintains the state of a button
type Button struct {
	Rect         eff.Rect
	mouseDown    bool
	mouseOver    bool
	Text         string
	ClickHandler func(b *Button)
	DrawDefault  Draw
	DrawDown     Draw
	DrawOver     Draw
}

// Hitbox returns the hitbox rect of the button, this is the same as Button.Rect
func (b *Button) Hitbox() eff.Rect {
	return b.Rect
}

// MouseDown function that is called when any mouse button is pressed down while the cursor is inside the hitbox
func (b *Button) MouseDown(leftState bool, middleState bool, rightState bool) {
	b.mouseDown = true
}

// MouseUp function that is called when any mouse button is released while the cursor is inside the hitbox
func (b *Button) MouseUp(leftState bool, middleState bool, rightState bool) {
	if b.mouseDown {
		b.mouseDown = false
		b.ClickHandler(b)
	}
}

// MouseOver function that is called when the mouse moves into the hitbox
func (b *Button) MouseOver() {
	b.mouseOver = true
}

// MouseOut function that is called when the mouse moves out of the hitbox
func (b *Button) MouseOut() {
	b.mouseOver = false
	b.mouseDown = false
}

// IsMouseOver function that returns true if the mouse cursor is currently inside the hitbox
func (b *Button) IsMouseOver() bool { return b.mouseOver }

// Draw calls the appropriate draw function based on the button state
func (b *Button) Draw(c eff.Canvas) {
	var drawFunc Draw
	if b.mouseDown {
		drawFunc = b.DrawDown
	} else if b.mouseOver {
		drawFunc = b.DrawOver
	} else {
		drawFunc = b.DrawDefault
	}

	if drawFunc == nil {
		drawFunc = b.DrawDefault
	}

	if drawFunc != nil {
		drawFunc(b, c)
	}
}

// NewButton function that creates an instance of the component button
func NewButton(text string, rect eff.Rect, drawDefault Draw, drawDown Draw, drawOver Draw, clickhandler Click) Button {
	return Button{
		Rect:         rect,
		Text:         text,
		ClickHandler: clickhandler,
		DrawDefault:  drawDefault,
		DrawDown:     drawDown,
		DrawOver:     drawOver,
	}
}
<|endoftext|>


<commit_before>package matchers_test

import (
	"github.com/cloudfoundry-incubator/lattice/ltc/test_helpers/matchers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type woohoo struct {
	Flag bool
}

type woomap map[woohoo]string

var _ = Describe("ContainExactlyMatcher", func() {
	It("matches if the array contains exactly the elements in the expected array, but is order independent.", func() {

		Expect([]string{"hi there", "ho there", "hallo"}).To(matchers.ContainExactly([]string{"hi there", "ho there", "hallo"}))
		Expect([]string{"hi there", "ho there", "hallo"}).To(matchers.ContainExactly([]string{"ho there", "hallo", "hi there"}))
		Expect([]woohoo{woohoo{Flag: true}}).To(matchers.ContainExactly([]woohoo{woohoo{Flag: true}}))
		Expect([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}).To(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))

		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"hi there", "bye bye"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"ho there", "hi there"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"buhbye"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{}))

		Expect([]woohoo{woohoo{Flag: false}}).ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}}))
		Expect([]woohoo{woohoo{Flag: false}, woohoo{Flag: false}}).ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))
	})

	It("handles map types", func() {
		Expect(woomap{woohoo{true}: "fun", woohoo{false}: "not fun"}).To(matchers.ContainExactly(woomap{woohoo{false}: "not fun", woohoo{true}: "fun"}))
	})

	It("handles duplicate elements", func() {
		Expect([]int{-7, -7, 9, 4}).To(matchers.ContainExactly([]int{4, 9, -7, -7}))
		Expect([]int{-7, -7, 9, 4}).ToNot(matchers.ContainExactly([]int{4, 9, -7, 44}))
		Expect([]int{4, -7, 9, 44}).ToNot(matchers.ContainExactly([]int{4, 9, -7, -7}))
	})

	It("fails for non-array or slices", func() {
		failures := InterceptGomegaFailures(func() {
			Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly(46))
			Expect(23).ToNot(matchers.ContainExactly([]string{"hi there", "ho there", "hallo"}))
			Expect("woo").ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))
		})
		Expect(failures[0]).To(Equal("Matcher can only take an array or slice"))
		Expect(failures[1]).To(Equal("Matcher can only take an array or slice"))
		Expect(failures[2]).To(Equal("Matcher can only take an array or slice"))
	})

})
<commit_msg>Adds assertion to ContainExactly custom matcher.<commit_after>package matchers_test

import (
	"github.com/cloudfoundry-incubator/lattice/ltc/test_helpers/matchers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type woohoo struct {
	Flag bool
}

type woomap map[woohoo]string

var _ = Describe("ContainExactlyMatcher", func() {
	It("matches if the array contains exactly the elements in the expected array, but is order independent.", func() {

		Expect([]string{"hi there", "ho there", "hallo"}).To(matchers.ContainExactly([]string{"hi there", "ho there", "hallo"}))
		Expect([]string{"hi there", "ho there", "hallo"}).To(matchers.ContainExactly([]string{"ho there", "hallo", "hi there"}))
		Expect([]woohoo{woohoo{Flag: true}}).To(matchers.ContainExactly([]woohoo{woohoo{Flag: true}}))
		Expect([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}).To(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))

		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"hi there", "bye bye"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"ho there", "hi there"}))
		Expect([]string{"ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"ho there", "hi there", "hallo"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{"buhbye"}))
		Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly([]string{}))

		Expect([]woohoo{woohoo{Flag: false}}).ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}}))
		Expect([]woohoo{woohoo{Flag: false}, woohoo{Flag: false}}).ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))
	})

	It("handles map types", func() {
		Expect(woomap{woohoo{true}: "fun", woohoo{false}: "not fun"}).To(matchers.ContainExactly(woomap{woohoo{false}: "not fun", woohoo{true}: "fun"}))
	})

	It("handles duplicate elements", func() {
		Expect([]int{-7, -7, 9, 4}).To(matchers.ContainExactly([]int{4, 9, -7, -7}))
		Expect([]int{-7, -7, 9, 4}).ToNot(matchers.ContainExactly([]int{4, 9, -7, 44}))
		Expect([]int{4, -7, 9, 44}).ToNot(matchers.ContainExactly([]int{4, 9, -7, -7}))
	})

	It("fails for non-array or slices", func() {
		failures := InterceptGomegaFailures(func() {
			Expect([]string{"hi there", "ho there", "hallo"}).ToNot(matchers.ContainExactly(46))
			Expect(23).ToNot(matchers.ContainExactly([]string{"hi there", "ho there", "hallo"}))
			Expect("woo").ToNot(matchers.ContainExactly([]woohoo{woohoo{Flag: true}, woohoo{Flag: false}}))
		})
		Expect(failures[0]).To(Equal("Matcher can only take an array or slice"))
		Expect(failures[1]).To(Equal("Matcher can only take an array or slice"))
		Expect(failures[2]).To(Equal("Matcher can only take an array or slice"))
	})

})
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type Any interface{}
type Json map[string]Any

func createResponseBody(r *http.Request) string {
	err := r.ParseForm()
	if err != nil {
		log.Println("form:", err)
	}

	form := Json{}
	for k, v := range r.Form {
		form[k] = v
	}

	headers := Json{}
	for k, v := range r.Header {
		headers[k] = strings.Join(v, ", ")
	}

	body, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		log.Println("body:", err)
	}

	j := Json{
		"method":  r.Method,
		"url":     r.Host + r.URL.String(),
		"version": r.Proto,
		"headers": headers,
		"body":    string(body),
		"form":    form,
	}

	b, err := json.MarshalIndent(j, "", "  ")
	if err != nil {
		log.Println("json:", err)
		return ""
	}

	return string(b) + "\n"
}

func main() {
	http.HandleFunc("/delay/", func(w http.ResponseWriter, r *http.Request) {
		ms, err := strconv.ParseInt(r.URL.Path[7:], 10, 64)
		if err != nil {
			log.Println(err)
			return
		}

		time.Sleep(time.Duration(ms) * time.Millisecond)
		fmt.Fprintf(w, createResponseBody(r))
	})

	http.HandleFunc("/code/", func(w http.ResponseWriter, r *http.Request) {
		code, err := strconv.ParseInt(r.URL.Path[6:], 10, 0)
		if err != nil {
			log.Println(err)
			return
		}

		w.WriteHeader(int(code))
		fmt.Fprint(w, createResponseBody(r))
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, createResponseBody(r))
	})

	port := flag.String("port", "8080", "")
	socket := flag.String("socket", "", "")

	flag.Parse()

	if *socket == "" {
		log.Println("serving on :" + *port)
		log.Fatal(http.ListenAndServe(":"+*port, nil))

	} else {
		l, err := net.Listen("unix", *socket)
		if err != nil {
			log.Fatal("%s\n", err)
		}

		err = http.Serve(l, nil)
		if err != nil {
			log.Fatal(err)
		}
	}
}
<commit_msg>Remove socket when stopped<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"time"
)

type Any interface{}
type Json map[string]Any

func createResponseBody(r *http.Request) string {
	err := r.ParseForm()
	if err != nil {
		log.Println("form:", err)
	}

	form := Json{}
	for k, v := range r.Form {
		form[k] = v
	}

	headers := Json{}
	for k, v := range r.Header {
		headers[k] = strings.Join(v, ", ")
	}

	body, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		log.Println("body:", err)
	}

	j := Json{
		"method":  r.Method,
		"url":     r.Host + r.URL.String(),
		"version": r.Proto,
		"headers": headers,
		"body":    string(body),
		"form":    form,
	}

	b, err := json.MarshalIndent(j, "", "  ")
	if err != nil {
		log.Println("json:", err)
		return ""
	}

	return string(b) + "\n"
}

func main() {
	http.HandleFunc("/delay/", func(w http.ResponseWriter, r *http.Request) {
		ms, err := strconv.ParseInt(r.URL.Path[7:], 10, 64)
		if err != nil {
			log.Println(err)
			return
		}

		time.Sleep(time.Duration(ms) * time.Millisecond)
		fmt.Fprintf(w, createResponseBody(r))
	})

	http.HandleFunc("/code/", func(w http.ResponseWriter, r *http.Request) {
		code, err := strconv.ParseInt(r.URL.Path[6:], 10, 0)
		if err != nil {
			log.Println(err)
			return
		}

		w.WriteHeader(int(code))
		fmt.Fprint(w, createResponseBody(r))
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, createResponseBody(r))
	})

	port := flag.String("port", "8080", "")
	socket := flag.String("socket", "", "")

	flag.Parse()

	if *socket == "" {
		go func() {
			log.Println("serving on :" + *port)
			log.Fatal(http.ListenAndServe(":"+*port, nil))
		}()

	} else {
		l, err := net.Listen("unix", *socket)
		if err != nil {
			log.Fatal(err)
		}

		defer l.Close()

		go func() {
			log.Println("serving on", *socket)
			log.Fatal(http.Serve(l, nil))
		}()
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	s := <-c
	log.Printf("caught %s: shutting down", s)
}
<|endoftext|>


<commit_before>package echo

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"runtime"
	"strings"
	"sync"

	"encoding/xml"

	"github.com/labstack/echo/engine"
	"github.com/labstack/gommon/log"
)

type (
	Echo struct {
		prefix           string
		middleware       []Middleware
		head             Handler
		maxParam         *int
		notFoundHandler  HandlerFunc
		httpErrorHandler HTTPErrorHandler
		binder           Binder
		renderer         Renderer
		pool             sync.Pool
		debug            bool
		router           *Router
		logger           *log.Logger
	}

	Route struct {
		Method  string
		Path    string
		Handler string
	}

	HTTPError struct {
		code    int
		message string
	}

	Middleware interface {
		Handle(Handler) Handler
	}

	MiddlewareFunc func(Handler) Handler

	Handler interface {
		Handle(Context) error
	}

	HandlerFunc func(Context) error

	// HTTPErrorHandler is a centralized HTTP error handler.
	HTTPErrorHandler func(error, Context)

	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
	}

	binder struct {
	}

	// Validator is the interface that wraps the Validate method.
	Validator interface {
		Validate() error
	}

	// Renderer is the interface that wraps the Render method.
	Renderer interface {
		Render(io.Writer, string, interface{}, Context) error
	}
)

const (
	// CONNECT HTTP method
	CONNECT = "CONNECT"
	// DELETE HTTP method
	DELETE = "DELETE"
	// GET HTTP method
	GET = "GET"
	// HEAD HTTP method
	HEAD = "HEAD"
	// OPTIONS HTTP method
	OPTIONS = "OPTIONS"
	// PATCH HTTP method
	PATCH = "PATCH"
	// POST HTTP method
	POST = "POST"
	// PUT HTTP method
	PUT = "PUT"
	// TRACE HTTP method
	TRACE = "TRACE"

	//-------------
	// Media types
	//-------------

	ApplicationJSON                  = "application/json"
	ApplicationJSONCharsetUTF8       = ApplicationJSON + "; " + CharsetUTF8
	ApplicationJavaScript            = "application/javascript"
	ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
	ApplicationXML                   = "application/xml"
	ApplicationXMLCharsetUTF8        = ApplicationXML + "; " + CharsetUTF8
	ApplicationForm                  = "application/x-www-form-urlencoded"
	ApplicationProtobuf              = "application/protobuf"
	ApplicationMsgpack               = "application/msgpack"
	TextHTML                         = "text/html"
	TextHTMLCharsetUTF8              = TextHTML + "; " + CharsetUTF8
	TextPlain                        = "text/plain"
	TextPlainCharsetUTF8             = TextPlain + "; " + CharsetUTF8
	MultipartForm                    = "multipart/form-data"
	OctetStream                      = "application/octet-stream"

	//---------
	// Charset
	//---------

	CharsetUTF8 = "charset=utf-8"

	//---------
	// Headers
	//---------

	AcceptEncoding     = "Accept-Encoding"
	Authorization      = "Authorization"
	ContentDisposition = "Content-Disposition"
	ContentEncoding    = "Content-Encoding"
	ContentLength      = "Content-Length"
	ContentType        = "Content-Type"
	Location           = "Location"
	Upgrade            = "Upgrade"
	Vary               = "Vary"
	WWWAuthenticate    = "WWW-Authenticate"
	XForwardedFor      = "X-Forwarded-For"
	XRealIP            = "X-Real-IP"

	//-----------
	// Protocols
	//-----------

	WebSocket = "websocket"
)

var (
	methods = [...]string{
		CONNECT,
		DELETE,
		GET,
		HEAD,
		OPTIONS,
		PATCH,
		POST,
		PUT,
		TRACE,
	}

	//--------
	// Errors
	//--------

	ErrUnsupportedMediaType  = NewHTTPError(http.StatusUnsupportedMediaType)
	ErrNotFound              = NewHTTPError(http.StatusNotFound)
	ErrRendererNotRegistered = errors.New("renderer not registered")
	ErrInvalidRedirectCode   = errors.New("invalid redirect status code")

	//----------------
	// Error handlers
	//----------------

	notFoundHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusNotFound)
	})

	methodNotAllowedHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusMethodNotAllowed)
	})
)

// New creates an instance of Echo.
func New() (e *Echo) {
	e = &Echo{maxParam: new(int)}
	e.pool.New = func() interface{} {
		// NOTE: v2
		return NewContext(nil, nil, e)
	}
	e.router = NewRouter(e)
	e.head = e.router.Handle(nil)

	//----------
	// Defaults
	//----------

	e.SetHTTPErrorHandler(e.DefaultHTTPErrorHandler)
	e.SetBinder(&binder{})

	// Logger
	e.logger = log.New("echo")
	e.logger.SetLevel(log.FATAL)

	return
}

func (m MiddlewareFunc) Handle(h Handler) Handler {
	return m(h)
}

func (h HandlerFunc) Handle(c Context) error {
	return h(c)
}

// Router returns router.
func (e *Echo) Router() *Router {
	return e.router
}

// SetLogPrefix sets the prefix for the logger. Default value is `echo`.
func (e *Echo) SetLogPrefix(prefix string) {
	e.logger.SetPrefix(prefix)
}

// SetLogOutput sets the output destination for the logger. Default value is `os.Std*`
func (e *Echo) SetLogOutput(w io.Writer) {
	e.logger.SetOutput(w)
}

// SetLogLevel sets the log level for the logger. Default value is `log.FATAL`.
func (e *Echo) SetLogLevel(l log.Level) {
	e.logger.SetLevel(l)
}

// Logger returns the logger instance.
func (e *Echo) Logger() *log.Logger {
	return e.logger
}

// DefaultHTTPErrorHandler invokes the default HTTP error handler.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if he, ok := err.(*HTTPError); ok {
		code = he.code
		msg = he.message
	}
	if e.debug {
		msg = err.Error()
	}
	if !c.Response().Committed() {
		c.String(code, msg)
	}
	e.logger.Debug(err)
}

// SetHTTPErrorHandler registers a custom Echo.HTTPErrorHandler.
func (e *Echo) SetHTTPErrorHandler(h HTTPErrorHandler) {
	e.httpErrorHandler = h
}

// SetBinder registers a custom binder. It's invoked by Context.Bind().
func (e *Echo) SetBinder(b Binder) {
	e.binder = b
}

// SetRenderer registers an HTML template renderer. It's invoked by Context.Render().
func (e *Echo) SetRenderer(r Renderer) {
	e.renderer = r
}

// SetDebug enable/disable debug mode.
func (e *Echo) SetDebug(on bool) {
	e.debug = on
	e.SetLogLevel(log.DEBUG)
}

// Debug returns debug mode (enabled or disabled).
func (e *Echo) Debug() bool {
	return e.debug
}

// Use adds handler to the middleware chain.
func (e *Echo) Use(middleware ...Middleware) {
	e.middleware = append(e.middleware, middleware...)
	m := append(e.middleware, e.router)

	// Chain middleware
	for i := len(m) - 1; i >= 0; i-- {
		e.head = m[i].Handle(e.head)
	}
}

// Connect adds a CONNECT route > handler to the router.
func (e *Echo) Connect(path string, h Handler, m ...Middleware) {
	e.add(CONNECT, path, h, m...)
}

// Delete adds a DELETE route > handler to the router.
func (e *Echo) Delete(path string, h Handler, m ...Middleware) {
	e.add(DELETE, path, h, m...)
}

// Get adds a GET route > handler to the router.
func (e *Echo) Get(path string, h Handler, m ...Middleware) {
	e.add(GET, path, h, m...)
}

// Head adds a HEAD route > handler to the router.
func (e *Echo) Head(path string, h Handler, m ...Middleware) {
	e.add(HEAD, path, h, m...)
}

// Options adds an OPTIONS route > handler to the router.
func (e *Echo) Options(path string, h Handler, m ...Middleware) {
	e.add(OPTIONS, path, h, m...)
}

// Patch adds a PATCH route > handler to the router.
func (e *Echo) Patch(path string, h Handler, m ...Middleware) {
	e.add(PATCH, path, h, m...)
}

// Post adds a POST route > handler to the router.
func (e *Echo) Post(path string, h Handler, m ...Middleware) {
	e.add(POST, path, h, m...)
}

// Put adds a PUT route > handler to the router.
func (e *Echo) Put(path string, h Handler, m ...Middleware) {
	e.add(PUT, path, h, m...)
}

// Trace adds a TRACE route > handler to the router.
func (e *Echo) Trace(path string, h Handler, m ...Middleware) {
	e.add(TRACE, path, h, m...)
}

// Any adds a route > handler to the router for all HTTP methods.
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

// Match adds a route > handler to the router for multiple HTTP methods provided.
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

func (e *Echo) add(method, path string, handler Handler, middleware ...Middleware) {
	name := handlerName(handler)
	e.router.Add(method, path, HandlerFunc(func(c Context) error {
		for _, m := range middleware {
			handler = m.Handle(handler)
		}
		return handler.Handle(c)
	}), e)
	r := Route{
		Method:  method,
		Path:    path,
		Handler: name,
	}
	e.router.routes = append(e.router.routes, r)
}

// Group creates a new sub-router with prefix.
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) {
	g = &Group{prefix: prefix, echo: e}
	g.Use(m...)
	return
}

// URI generates a URI from handler.
func (e *Echo) URI(handler Handler, params ...interface{}) string {
	uri := new(bytes.Buffer)
	ln := len(params)
	n := 0
	name := handlerName(handler)
	for _, r := range e.router.routes {
		if r.Handler == name {
			for i, l := 0, len(r.Path); i < l; i++ {
				if r.Path[i] == ':' && n < ln {
					for ; i < l && r.Path[i] != '/'; i++ {
					}
					uri.WriteString(fmt.Sprintf("%v", params[n]))
					n++
				}
				if i < l {
					uri.WriteByte(r.Path[i])
				}
			}
			break
		}
	}
	return uri.String()
}

// URL is an alias for `URI` function.
func (e *Echo) URL(h Handler, params ...interface{}) string {
	return e.URI(h, params...)
}

// Routes returns the registered routes.
func (e *Echo) Routes() []Route {
	return e.router.routes
}

func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
	c := e.pool.Get().(*context)
	c.reset(req, res)

	// Execute chain
	if err := e.head.Handle(c); err != nil {
		e.httpErrorHandler(err, c)
	}

	e.pool.Put(c)
}

// Run starts the HTTP engine.
func (e *Echo) Run(eng engine.Engine) {
	eng.SetHandler(e.ServeHTTP)
	eng.SetLogger(e.logger)
	eng.Start()
}

func NewHTTPError(code int, msg ...string) *HTTPError {
	he := &HTTPError{code: code, message: http.StatusText(code)}
	if len(msg) > 0 {
		m := msg[0]
		he.message = m
	}
	return he
}

// SetCode sets code.
func (e *HTTPError) SetCode(code int) {
	e.code = code
}

// Code returns code.
func (e *HTTPError) Code() int {
	return e.code
}

// Error returns message.
func (e *HTTPError) Error() string {
	return e.message
}

func (binder) Bind(i interface{}, c Context) (err error) {
	req := c.Request()
	ct := req.Header().Get(ContentType)
	err = ErrUnsupportedMediaType
	if strings.HasPrefix(ct, ApplicationJSON) {
		if err = json.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	} else if strings.HasPrefix(ct, ApplicationXML) {
		if err = xml.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	}
	return
}

func handlerName(h Handler) string {
	t := reflect.ValueOf(h).Type()
	if t.Kind() == reflect.Func {
		return runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
	}
	return t.String()
}
<commit_msg>WrapMiddleware for echo.Handler<commit_after>package echo

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"runtime"
	"strings"
	"sync"

	"encoding/xml"

	"github.com/labstack/echo/engine"
	"github.com/labstack/gommon/log"
)

type (
	Echo struct {
		prefix           string
		middleware       []Middleware
		head             Handler
		maxParam         *int
		notFoundHandler  HandlerFunc
		httpErrorHandler HTTPErrorHandler
		binder           Binder
		renderer         Renderer
		pool             sync.Pool
		debug            bool
		router           *Router
		logger           *log.Logger
	}

	Route struct {
		Method  string
		Path    string
		Handler string
	}

	HTTPError struct {
		code    int
		message string
	}

	Middleware interface {
		Handle(Handler) Handler
	}

	MiddlewareFunc func(Handler) Handler

	Handler interface {
		Handle(Context) error
	}

	HandlerFunc func(Context) error

	// HTTPErrorHandler is a centralized HTTP error handler.
	HTTPErrorHandler func(error, Context)

	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
	}

	binder struct {
	}

	// Validator is the interface that wraps the Validate method.
	Validator interface {
		Validate() error
	}

	// Renderer is the interface that wraps the Render method.
	Renderer interface {
		Render(io.Writer, string, interface{}, Context) error
	}
)

const (
	// CONNECT HTTP method
	CONNECT = "CONNECT"
	// DELETE HTTP method
	DELETE = "DELETE"
	// GET HTTP method
	GET = "GET"
	// HEAD HTTP method
	HEAD = "HEAD"
	// OPTIONS HTTP method
	OPTIONS = "OPTIONS"
	// PATCH HTTP method
	PATCH = "PATCH"
	// POST HTTP method
	POST = "POST"
	// PUT HTTP method
	PUT = "PUT"
	// TRACE HTTP method
	TRACE = "TRACE"

	//-------------
	// Media types
	//-------------

	ApplicationJSON                  = "application/json"
	ApplicationJSONCharsetUTF8       = ApplicationJSON + "; " + CharsetUTF8
	ApplicationJavaScript            = "application/javascript"
	ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
	ApplicationXML                   = "application/xml"
	ApplicationXMLCharsetUTF8        = ApplicationXML + "; " + CharsetUTF8
	ApplicationForm                  = "application/x-www-form-urlencoded"
	ApplicationProtobuf              = "application/protobuf"
	ApplicationMsgpack               = "application/msgpack"
	TextHTML                         = "text/html"
	TextHTMLCharsetUTF8              = TextHTML + "; " + CharsetUTF8
	TextPlain                        = "text/plain"
	TextPlainCharsetUTF8             = TextPlain + "; " + CharsetUTF8
	MultipartForm                    = "multipart/form-data"
	OctetStream                      = "application/octet-stream"

	//---------
	// Charset
	//---------

	CharsetUTF8 = "charset=utf-8"

	//---------
	// Headers
	//---------

	AcceptEncoding     = "Accept-Encoding"
	Authorization      = "Authorization"
	ContentDisposition = "Content-Disposition"
	ContentEncoding    = "Content-Encoding"
	ContentLength      = "Content-Length"
	ContentType        = "Content-Type"
	Location           = "Location"
	Upgrade            = "Upgrade"
	Vary               = "Vary"
	WWWAuthenticate    = "WWW-Authenticate"
	XForwardedFor      = "X-Forwarded-For"
	XRealIP            = "X-Real-IP"

	//-----------
	// Protocols
	//-----------

	WebSocket = "websocket"
)

var (
	methods = [...]string{
		CONNECT,
		DELETE,
		GET,
		HEAD,
		OPTIONS,
		PATCH,
		POST,
		PUT,
		TRACE,
	}

	//--------
	// Errors
	//--------

	ErrUnsupportedMediaType  = NewHTTPError(http.StatusUnsupportedMediaType)
	ErrNotFound              = NewHTTPError(http.StatusNotFound)
	ErrRendererNotRegistered = errors.New("renderer not registered")
	ErrInvalidRedirectCode   = errors.New("invalid redirect status code")

	//----------------
	// Error handlers
	//----------------

	notFoundHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusNotFound)
	})

	methodNotAllowedHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusMethodNotAllowed)
	})
)

// New creates an instance of Echo.
func New() (e *Echo) {
	e = &Echo{maxParam: new(int)}
	e.pool.New = func() interface{} {
		// NOTE: v2
		return NewContext(nil, nil, e)
	}
	e.router = NewRouter(e)
	e.head = e.router.Handle(nil)

	//----------
	// Defaults
	//----------

	e.SetHTTPErrorHandler(e.DefaultHTTPErrorHandler)
	e.SetBinder(&binder{})

	// Logger
	e.logger = log.New("echo")
	e.logger.SetLevel(log.FATAL)

	return
}

func (m MiddlewareFunc) Handle(h Handler) Handler {
	return m(h)
}

func (h HandlerFunc) Handle(c Context) error {
	return h(c)
}

// Router returns router.
func (e *Echo) Router() *Router {
	return e.router
}

// SetLogPrefix sets the prefix for the logger. Default value is `echo`.
func (e *Echo) SetLogPrefix(prefix string) {
	e.logger.SetPrefix(prefix)
}

// SetLogOutput sets the output destination for the logger. Default value is `os.Std*`
func (e *Echo) SetLogOutput(w io.Writer) {
	e.logger.SetOutput(w)
}

// SetLogLevel sets the log level for the logger. Default value is `log.FATAL`.
func (e *Echo) SetLogLevel(l log.Level) {
	e.logger.SetLevel(l)
}

// Logger returns the logger instance.
func (e *Echo) Logger() *log.Logger {
	return e.logger
}

// DefaultHTTPErrorHandler invokes the default HTTP error handler.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if he, ok := err.(*HTTPError); ok {
		code = he.code
		msg = he.message
	}
	if e.debug {
		msg = err.Error()
	}
	if !c.Response().Committed() {
		c.String(code, msg)
	}
	e.logger.Debug(err)
}

// SetHTTPErrorHandler registers a custom Echo.HTTPErrorHandler.
func (e *Echo) SetHTTPErrorHandler(h HTTPErrorHandler) {
	e.httpErrorHandler = h
}

// SetBinder registers a custom binder. It's invoked by Context.Bind().
func (e *Echo) SetBinder(b Binder) {
	e.binder = b
}

// SetRenderer registers an HTML template renderer. It's invoked by Context.Render().
func (e *Echo) SetRenderer(r Renderer) {
	e.renderer = r
}

// SetDebug enable/disable debug mode.
func (e *Echo) SetDebug(on bool) {
	e.debug = on
	e.SetLogLevel(log.DEBUG)
}

// Debug returns debug mode (enabled or disabled).
func (e *Echo) Debug() bool {
	return e.debug
}

// Use adds handler to the middleware chain.
func (e *Echo) Use(middleware ...Middleware) {
	e.middleware = append(e.middleware, middleware...)
	m := append(e.middleware, e.router)

	// Chain middleware
	for i := len(m) - 1; i >= 0; i-- {
		e.head = m[i].Handle(e.head)
	}
}

// Connect adds a CONNECT route > handler to the router.
func (e *Echo) Connect(path string, h Handler, m ...Middleware) {
	e.add(CONNECT, path, h, m...)
}

// Delete adds a DELETE route > handler to the router.
func (e *Echo) Delete(path string, h Handler, m ...Middleware) {
	e.add(DELETE, path, h, m...)
}

// Get adds a GET route > handler to the router.
func (e *Echo) Get(path string, h Handler, m ...Middleware) {
	e.add(GET, path, h, m...)
}

// Head adds a HEAD route > handler to the router.
func (e *Echo) Head(path string, h Handler, m ...Middleware) {
	e.add(HEAD, path, h, m...)
}

// Options adds an OPTIONS route > handler to the router.
func (e *Echo) Options(path string, h Handler, m ...Middleware) {
	e.add(OPTIONS, path, h, m...)
}

// Patch adds a PATCH route > handler to the router.
func (e *Echo) Patch(path string, h Handler, m ...Middleware) {
	e.add(PATCH, path, h, m...)
}

// Post adds a POST route > handler to the router.
func (e *Echo) Post(path string, h Handler, m ...Middleware) {
	e.add(POST, path, h, m...)
}

// Put adds a PUT route > handler to the router.
func (e *Echo) Put(path string, h Handler, m ...Middleware) {
	e.add(PUT, path, h, m...)
}

// Trace adds a TRACE route > handler to the router.
func (e *Echo) Trace(path string, h Handler, m ...Middleware) {
	e.add(TRACE, path, h, m...)
}

// Any adds a route > handler to the router for all HTTP methods.
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

// Match adds a route > handler to the router for multiple HTTP methods provided.
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

func (e *Echo) add(method, path string, handler Handler, middleware ...Middleware) {
	name := handlerName(handler)
	e.router.Add(method, path, HandlerFunc(func(c Context) error {
		for _, m := range middleware {
			handler = m.Handle(handler)
		}
		return handler.Handle(c)
	}), e)
	r := Route{
		Method:  method,
		Path:    path,
		Handler: name,
	}
	e.router.routes = append(e.router.routes, r)
}

// Group creates a new sub-router with prefix.
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) {
	g = &Group{prefix: prefix, echo: e}
	g.Use(m...)
	return
}

// URI generates a URI from handler.
func (e *Echo) URI(handler Handler, params ...interface{}) string {
	uri := new(bytes.Buffer)
	ln := len(params)
	n := 0
	name := handlerName(handler)
	for _, r := range e.router.routes {
		if r.Handler == name {
			for i, l := 0, len(r.Path); i < l; i++ {
				if r.Path[i] == ':' && n < ln {
					for ; i < l && r.Path[i] != '/'; i++ {
					}
					uri.WriteString(fmt.Sprintf("%v", params[n]))
					n++
				}
				if i < l {
					uri.WriteByte(r.Path[i])
				}
			}
			break
		}
	}
	return uri.String()
}

// URL is an alias for `URI` function.
func (e *Echo) URL(h Handler, params ...interface{}) string {
	return e.URI(h, params...)
}

// Routes returns the registered routes.
func (e *Echo) Routes() []Route {
	return e.router.routes
}

func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
	c := e.pool.Get().(*context)
	c.reset(req, res)

	// Execute chain
	if err := e.head.Handle(c); err != nil {
		e.httpErrorHandler(err, c)
	}

	e.pool.Put(c)
}

// Run starts the HTTP engine.
func (e *Echo) Run(eng engine.Engine) {
	eng.SetHandler(e.ServeHTTP)
	eng.SetLogger(e.logger)
	eng.Start()
}

func NewHTTPError(code int, msg ...string) *HTTPError {
	he := &HTTPError{code: code, message: http.StatusText(code)}
	if len(msg) > 0 {
		m := msg[0]
		he.message = m
	}
	return he
}

// SetCode sets code.
func (e *HTTPError) SetCode(code int) {
	e.code = code
}

// Code returns code.
func (e *HTTPError) Code() int {
	return e.code
}

// Error returns message.
func (e *HTTPError) Error() string {
	return e.message
}

func (binder) Bind(i interface{}, c Context) (err error) {
	req := c.Request()
	ct := req.Header().Get(ContentType)
	err = ErrUnsupportedMediaType
	if strings.HasPrefix(ct, ApplicationJSON) {
		if err = json.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	} else if strings.HasPrefix(ct, ApplicationXML) {
		if err = xml.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	}
	return
}

// WrapMiddleware wrap `echo.Handler` into `echo.MiddlewareFunc`.
func WrapMiddleware(h Handler) MiddlewareFunc {
	return func(next Handler) Handler {
		return HandlerFunc(func(c Context) error {
			if !c.Response().Committed() {
				h.Handle(c)
			}
			return next.Handle(c)
		})
	}
}

func handlerName(h Handler) string {
	t := reflect.ValueOf(h).Type()
	if t.Kind() == reflect.Func {
		return runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
	}
	return t.String()
}
<|endoftext|>


<commit_before>// Implements the RolesReader interface (roles.go) for the simplest case - a safe data structure
// for storing the AccessKey, Secret and Token. Identical to RolesMaster except this allows
// the token to be set. If in doubt or in need of the most flexibility and fewest surprises, use this.
//
package roles_simple

import (
	"errors"
	sdk_credentials "github.com/awslabs/aws-sdk-go/aws"
	roles "github.com/smugmug/goawsroles/roles"
	"sync"
)

const (
	ROLE_PROVIDER = "simple"
)

// RolesSimple is populated directly once from master credentials
type RolesSimple struct {
	roleFields *roles.RolesFields
	lock       sync.RWMutex
}

// NewRolesSimple returns a pointer to a RolesSimple instance.
func NewRolesSimple(accessKey, secret, token string) *RolesSimple {
	r := new(RolesSimple)
	r.roleFields = roles.NewRolesFields()
	r.roleFields.AccessKey = accessKey
	r.roleFields.Secret = secret
	r.roleFields.Token = token
	return r
}

// ProviderType is a descriptive string of the implementation.
func (rf *RolesSimple) ProviderType() string {
	return ROLE_PROVIDER
}

// UsingIAM tells us if the credentials provided by this role are temporary credentials which
// also have a Token component, or if they are durable key/secret-only credentials.
func (rf *RolesSimple) UsingIAM() bool {
	return false
}

// IsEmpty determines if a RolesSimple struct is uninitialized.
func (rf *RolesSimple) IsEmpty() bool {
	return rf.roleFields.IsEmpty()
}

// ZeroRoles recreate the RolesSimple as initialized by NewRolesSimple
func (rf *RolesSimple) ZeroRoles() {
	rf.lock.Lock()
	rf.roleFields.ZeroRoles()
	rf.lock.Unlock()
}

// RolesRead is a no-op here since RolesSimple is immutable after its initial setting.
func (rf *RolesSimple) RolesRead() error {
	return nil
}

// RolesWatch will panic on this implementation as master credentials are immutable.
func (rf *RolesSimple) RolesWatch(err_chan chan error, read_signal chan bool) {
	panic("RolesWatch not defined for RolesSimple as credentials are immutable")
}

// Get returns the (accessKey,secret,token), or an error.
func (rf *RolesSimple) Get() (string, string, string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	secret := ""
	if rf.roleFields.Secret == "" {
		return "", "", "", errors.New("roles_simple.Get: empty Secret")
	} else {
		secret = rf.roleFields.Secret
	}
	accessKey := ""
	if rf.roleFields.AccessKey == "" {
		return "", "", "", errors.New("roles_simple.Get: empty AccessKey")
	} else {
		accessKey = rf.roleFields.AccessKey
	}
	token := ""
	if rf.roleFields.Token == "" {
		return "", "", "", errors.New("roles_simple.Get: empty Token")
	} else {
		token = rf.roleFields.Token
	}
	return accessKey, secret, token, nil
}

// GetAccessKey returns the accessKey or an error.
func (rf *RolesSimple) GetAccessKey() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.AccessKey == "" {
		return "", errors.New("roles_simple.GetAccessKey: empty AccessKey")
	} else {
		return rf.roleFields.AccessKey, nil
	}
}

// GetSecret returns the secret or an error.
func (rf *RolesSimple) GetSecret() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.Secret == "" {
		return "", errors.New("roles_simple.GetSecret: empty Secret")
	} else {
		return rf.roleFields.Secret, nil
	}
}

// GetToken returns the token or an error.
func (rf *RolesSimple) GetToken() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.Token == "" {
		return "", errors.New("roles_simple.GetToken: empty Token")
	} else {
		return rf.roleFields.Token, nil
	}
}

// Credentials will expose the Role as a sdk Credential.
func (rf *RolesSimple) Credentials() (*sdk_credentials.Credentials, error) {
	accessKey, secret, token, get_err := rf.Get()
	if get_err != nil {
		return nil, get_err
	}
	return &sdk_credentials.Credentials{
		AccessKeyID:     accessKey,
		SecretAccessKey: secret,
		SessionToken:    token}, nil
}
<commit_msg>RolesSimple should be true for IAM<commit_after>// Implements the RolesReader interface (roles.go) for the simplest case - a safe data structure
// for storing the AccessKey, Secret and Token. Identical to RolesMaster except this allows
// the token to be set. If in doubt or in need of the most flexibility and fewest surprises, use this.
//
package roles_simple

import (
	"errors"
	sdk_credentials "github.com/awslabs/aws-sdk-go/aws"
	roles "github.com/smugmug/goawsroles/roles"
	"sync"
)

const (
	ROLE_PROVIDER = "simple"
)

// RolesSimple is populated directly once from master credentials
type RolesSimple struct {
	roleFields *roles.RolesFields
	lock       sync.RWMutex
}

// NewRolesSimple returns a pointer to a RolesSimple instance.
func NewRolesSimple(accessKey, secret, token string) *RolesSimple {
	r := new(RolesSimple)
	r.roleFields = roles.NewRolesFields()
	r.roleFields.AccessKey = accessKey
	r.roleFields.Secret = secret
	r.roleFields.Token = token
	return r
}

// ProviderType is a descriptive string of the implementation.
func (rf *RolesSimple) ProviderType() string {
	return ROLE_PROVIDER
}

// UsingIAM tells us if the credentials provided by this role are temporary credentials which
// also have a Token component, or if they are durable key/secret-only credentials. For this
// package, we allow a token to be set, so we can assume they are IAM-issued.
func (rf *RolesSimple) UsingIAM() bool {
	return true
}

// IsEmpty determines if a RolesSimple struct is uninitialized.
func (rf *RolesSimple) IsEmpty() bool {
	return rf.roleFields.IsEmpty()
}

// ZeroRoles recreate the RolesSimple as initialized by NewRolesSimple
func (rf *RolesSimple) ZeroRoles() {
	rf.lock.Lock()
	rf.roleFields.ZeroRoles()
	rf.lock.Unlock()
}

// RolesRead is a no-op here since RolesSimple is immutable after its initial setting.
func (rf *RolesSimple) RolesRead() error {
	return nil
}

// RolesWatch will panic on this implementation as master credentials are immutable.
func (rf *RolesSimple) RolesWatch(err_chan chan error, read_signal chan bool) {
	panic("RolesWatch not defined for RolesSimple as credentials are immutable")
}

// Get returns the (accessKey,secret,token), or an error.
func (rf *RolesSimple) Get() (string, string, string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	secret := ""
	if rf.roleFields.Secret == "" {
		return "", "", "", errors.New("roles_simple.Get: empty Secret")
	} else {
		secret = rf.roleFields.Secret
	}
	accessKey := ""
	if rf.roleFields.AccessKey == "" {
		return "", "", "", errors.New("roles_simple.Get: empty AccessKey")
	} else {
		accessKey = rf.roleFields.AccessKey
	}
	token := ""
	if rf.roleFields.Token == "" {
		return "", "", "", errors.New("roles_simple.Get: empty Token")
	} else {
		token = rf.roleFields.Token
	}
	return accessKey, secret, token, nil
}

// GetAccessKey returns the accessKey or an error.
func (rf *RolesSimple) GetAccessKey() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.AccessKey == "" {
		return "", errors.New("roles_simple.GetAccessKey: empty AccessKey")
	} else {
		return rf.roleFields.AccessKey, nil
	}
}

// GetSecret returns the secret or an error.
func (rf *RolesSimple) GetSecret() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.Secret == "" {
		return "", errors.New("roles_simple.GetSecret: empty Secret")
	} else {
		return rf.roleFields.Secret, nil
	}
}

// GetToken returns the token or an error.
func (rf *RolesSimple) GetToken() (string, error) {
	rf.lock.RLock()
	defer rf.lock.RUnlock()
	if rf.roleFields.Token == "" {
		return "", errors.New("roles_simple.GetToken: empty Token")
	} else {
		return rf.roleFields.Token, nil
	}
}

// Credentials will expose the Role as a sdk Credential.
func (rf *RolesSimple) Credentials() (*sdk_credentials.Credentials, error) {
	accessKey, secret, token, get_err := rf.Get()
	if get_err != nil {
		return nil, get_err
	}
	return &sdk_credentials.Credentials{
		AccessKeyID:     accessKey,
		SecretAccessKey: secret,
		SessionToken:    token}, nil
}
<|endoftext|>


<commit_before>package main

import "fmt"

type Message struct {
	Data map[string]string `json:"data,omitempty"`
}

func main() {
	a := &Message{}
	fmt.Println(a.Data)
	//add
	a.Data = make(map[string]string, 10)
	//panic: assignment to entry in nil map
	a.Data["test"] = "test1"
	fmt.Println(a)

	b := new(Message)
	fmt.Println(b.Data)
	//add
	b.Data = map[string]string{}
	//panic: assignment to entry in nil map
	b.Data["test"] = "test1"
	fmt.Println(b)
}
<commit_msg>inner struct slice map<commit_after>package main

import "fmt"

type istruct struct {
	A int
}

type Message struct {
	Data  map[string]string `json:"data,omitempty"`
	Data1 []int
	Data2 [2]int
	Data3 istruct
}

func main() {
	a := &Message{}
	fmt.Println(a.Data)
	//add
	a.Data = make(map[string]string, 10)
	//panic: assignment to entry in nil map
	a.Data["test"] = "test1"
	//panic: runtime error: index out of range
	//a.Data1[0] = 1
	//0,0
	fmt.Println(len(a.Data1), cap(a.Data1))
	a.Data1 = []int{}
	//0,0
	fmt.Println(len(a.Data1), cap(a.Data1))
	//ok 10 10
	a.Data1 = make([]int, 10, 10)
	a.Data1[0] = 1

	a.Data2[0] = 1

	a.Data3.A = 1
	fmt.Println(a)

	//panic: runtime error: index out of range
	//bb := []int{}
	//bb[0] = 1
	//fmt.Println(bb)

	b := new(Message)
	fmt.Println(b.Data)
	//add
	b.Data = map[string]string{}
	//panic: assignment to entry in nil map
	b.Data["test"] = "test1"
	fmt.Println(b)

}
<|endoftext|>