<commit_before>// +build !confonly

package kcp

import (
	"crypto/cipher"
	"fmt"

	"v2ray.com/core/common"
	"v2ray.com/core/transport/internet"
)

const protocolName = "mkcp"

// GetMTUValue returns the value of MTU settings.
func (c *Config) GetMTUValue() uint32 {
	if c == nil || c.Mtu == nil {
		return 1350
	}
	return c.Mtu.Value
}

// GetTTIValue returns the value of TTI settings.
func (c *Config) GetTTIValue() uint32 {
	if c == nil || c.Tti == nil {
		return 50
	}
	return c.Tti.Value
}

// GetUplinkCapacityValue returns the value of UplinkCapacity settings.
func (c *Config) GetUplinkCapacityValue() uint32 {
	if c == nil || c.UplinkCapacity == nil {
		return 5
	}
	return c.UplinkCapacity.Value
}

// GetDownlinkCapacityValue returns the value of DownlinkCapacity settings.
func (c *Config) GetDownlinkCapacityValue() uint32 {
	if c == nil || c.DownlinkCapacity == nil {
		return 20
	}
	return c.DownlinkCapacity.Value
}

// GetWriteBufferSize returns the size of WriterBuffer in bytes.
func (c *Config) GetWriteBufferSize() uint32 {
	if c == nil || c.WriteBuffer == nil {
		return 2 * 1024 * 1024
	}
	return c.WriteBuffer.Size
}

// GetReadBufferSize returns the size of ReadBuffer in bytes.
func (c *Config) GetReadBufferSize() uint32 {
	if c == nil || c.ReadBuffer == nil {
		return 2 * 1024 * 1024
	}
	return c.ReadBuffer.Size
}

// GetSecurity returns the security settings.
func (c *Config) GetSecurity() (cipher.AEAD, error) {
	if c.Seed != nil {
		fmt.Println("=========NewAEADAESGCMBasedOnSeed Used============")
		return NewAEADAESGCMBasedOnSeed(c.Seed.Seed), nil
	}
	return NewSimpleAuthenticator(), nil
}

func (c *Config) GetPackerHeader() (internet.PacketHeader, error) {
	if c.HeaderConfig != nil {
		rawConfig, err := c.HeaderConfig.GetInstance()
		if err != nil {
			return nil, err
		}

		return internet.CreatePacketHeader(rawConfig)
	}
	return nil, nil
}

func (c *Config) GetSendingInFlightSize() uint32 {
	size := c.GetUplinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
	if size < 8 {
		size = 8
	}
	return size
}

func (c *Config) GetSendingBufferSize() uint32 {
	return c.GetWriteBufferSize() / c.GetMTUValue()
}

func (c *Config) GetReceivingInFlightSize() uint32 {
	size := c.GetDownlinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
	if size < 8 {
		size = 8
	}
	return size
}

func (c *Config) GetReceivingBufferSize() uint32 {
	return c.GetReadBufferSize() / c.GetMTUValue()
}

func init() {
	common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
		return new(Config)
	}))
}
<commit_msg>kcp: removing annoying NewAEADAESGCMBasedOnSeed hint<commit_after>// +build !confonly

package kcp

import (
	"crypto/cipher"
	"v2ray.com/core/common"
	"v2ray.com/core/transport/internet"
)

const protocolName = "mkcp"

// GetMTUValue returns the value of MTU settings.
func (c *Config) GetMTUValue() uint32 {
	if c == nil || c.Mtu == nil {
		return 1350
	}
	return c.Mtu.Value
}

// GetTTIValue returns the value of TTI settings.
func (c *Config) GetTTIValue() uint32 {
	if c == nil || c.Tti == nil {
		return 50
	}
	return c.Tti.Value
}

// GetUplinkCapacityValue returns the value of UplinkCapacity settings.
func (c *Config) GetUplinkCapacityValue() uint32 {
	if c == nil || c.UplinkCapacity == nil {
		return 5
	}
	return c.UplinkCapacity.Value
}

// GetDownlinkCapacityValue returns the value of DownlinkCapacity settings.
func (c *Config) GetDownlinkCapacityValue() uint32 {
	if c == nil || c.DownlinkCapacity == nil {
		return 20
	}
	return c.DownlinkCapacity.Value
}

// GetWriteBufferSize returns the size of WriterBuffer in bytes.
func (c *Config) GetWriteBufferSize() uint32 {
	if c == nil || c.WriteBuffer == nil {
		return 2 * 1024 * 1024
	}
	return c.WriteBuffer.Size
}

// GetReadBufferSize returns the size of ReadBuffer in bytes.
func (c *Config) GetReadBufferSize() uint32 {
	if c == nil || c.ReadBuffer == nil {
		return 2 * 1024 * 1024
	}
	return c.ReadBuffer.Size
}

// GetSecurity returns the security settings.
func (c *Config) GetSecurity() (cipher.AEAD, error) {
	if c.Seed != nil {
		return NewAEADAESGCMBasedOnSeed(c.Seed.Seed), nil
	}
	return NewSimpleAuthenticator(), nil
}

func (c *Config) GetPackerHeader() (internet.PacketHeader, error) {
	if c.HeaderConfig != nil {
		rawConfig, err := c.HeaderConfig.GetInstance()
		if err != nil {
			return nil, err
		}

		return internet.CreatePacketHeader(rawConfig)
	}
	return nil, nil
}

func (c *Config) GetSendingInFlightSize() uint32 {
	size := c.GetUplinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
	if size < 8 {
		size = 8
	}
	return size
}

func (c *Config) GetSendingBufferSize() uint32 {
	return c.GetWriteBufferSize() / c.GetMTUValue()
}

func (c *Config) GetReceivingInFlightSize() uint32 {
	size := c.GetDownlinkCapacityValue() * 1024 * 1024 / c.GetMTUValue() / (1000 / c.GetTTIValue())
	if size < 8 {
		size = 8
	}
	return size
}

func (c *Config) GetReceivingBufferSize() uint32 {
	return c.GetReadBufferSize() / c.GetMTUValue()
}

func init() {
	common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
		return new(Config)
	}))
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package models

import (
	"github.com/bboozzoo/q3stats/store"
	"github.com/jinzhu/gorm"
)

const (
	NoUser = 0
)

// Alias is a nickname used during the match.
type Alias struct {
	gorm.Model

	// alias, ex. 'honeybunny', 'Klesk'
	Alias string

	// player claiming this alias
	PlayerID uint
}

func GetAliases(store store.DB, user int) []Alias {
	var aliases []Alias
	store.Conn().
		Where(&Alias{PlayerID: 0}).
		Find(&aliases)

	return aliases
}

func ClaimAliasesByPlayer(store store.DB, player uint, aliases []string) {
	// update aliases set player_id = `player` where aliases in
	// `aliases`?

	db := store.Conn()

	for _, a := range aliases {
		db.Model(&Alias{}).
			Where(&Alias{Alias: a}).
			Update("player_id", player)
	}
}
<commit_msg>models/alias: properly select unclaimed aliases<commit_after>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package models

import (
	"github.com/bboozzoo/q3stats/store"
	"github.com/jinzhu/gorm"
)

const (
	NoUser = 0
)

// Alias is a nickname used during the match.
type Alias struct {
	gorm.Model

	// alias, ex. 'honeybunny', 'Klesk'
	Alias string

	// player claiming this alias
	PlayerID uint
}

func GetAliases(store store.DB, user int) []Alias {
	var aliases []Alias
	store.Conn().
		Model(&Alias{}).
		Where("player_id = ?", user).
		Find(&aliases)

	return aliases
}

func ClaimAliasesByPlayer(store store.DB, player uint, aliases []string) {
	// update aliases set player_id = `player` where aliases in
	// `aliases`?

	db := store.Conn()

	for _, a := range aliases {
		db.Model(&Alias{}).
			Where(&Alias{Alias: a}).
			Update("player_id", player)
	}
}
<|endoftext|>


<commit_before>package dockermachine

import (
	"os"
	"os/exec"

	"github.com/andrewsmedina/yati/tsuru/iaas"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) createMachine() error {
	cmd := exec.Command("docker-machine", "create", "tsuru", "-d", "virtualbox")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (i *dmIaas) getIP() (string, error) {
	cmd := exec.Command("docker-machine", "ip", "tsuru")
	output, err := cmd.Output()
	return string(output), err
}

func (i *dmIaas) deleteMachine() error {
	cmd := exec.Command("docker-machine", "rm", "tsuru", "-y")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	err := i.createMachine()
	if err != nil {
		return nil, err
	}
	ip, err := i.getIP()
	if err != nil {
		return nil, err
	}
	config := map[string]string{}
	m := iaas.Machine{
		Address: ip,
		Iaas:    "docker-machine",
		Config:  config,
	}
	return &m, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	return i.deleteMachine()
}
<commit_msg>iaas/dm: get config from machine<commit_after>package dockermachine

import (
	"os"
	"os/exec"

	"github.com/andrewsmedina/yati/tsuru/iaas"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) createMachine() error {
	cmd := exec.Command("docker-machine", "create", "tsuru", "-d", "virtualbox")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (i *dmIaas) getIP() (string, error) {
	cmd := exec.Command("docker-machine", "ip", "tsuru")
	output, err := cmd.Output()
	return string(output), err
}

func (i *dmIaas) getConfig() (map[string]string, error) {
	cmd := exec.Command("docker-machine", "config", "tsuru")
	output, err := cmd.Output()
	return map[string]string{"config": string(output)}, err
}

func (i *dmIaas) deleteMachine() error {
	cmd := exec.Command("docker-machine", "rm", "tsuru", "-y")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	err := i.createMachine()
	if err != nil {
		return nil, err
	}
	ip, err := i.getIP()
	if err != nil {
		return nil, err
	}
	config, err := i.getConfig()
	if err != nil {
		return nil, err
	}
	m := iaas.Machine{
		Address: ip,
		Iaas:    "docker-machine",
		Config:  config,
	}
	return &m, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	return i.deleteMachine()
}
<|endoftext|>


<commit_before>package dockermachine

import (
	"os/exec"

	"github.com/andrewsmedina/yati/tsuru/iaas"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) createMachine() error {
	cmd := exec.Command("docker-machine", "create", "tsuru", "-d", "virtualbox")
	return cmd.Run()
}

func (i *dmIaas) getIP() (string, error) {
	cmd := exec.Command("docker-machine", "ip", "tsuru")
	output, err := cmd.Output()
	return string(output), err
}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	err := i.createMachine()
	if err != nil {
		return nil, err
	}
	ip, err := i.getIP()
	if err != nil {
		return nil, err
	}
	return &iaas.Machine{Address: ip}, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	return nil
}
<commit_msg>iaas/dm: remove machine<commit_after>package dockermachine

import (
	"os/exec"

	"github.com/andrewsmedina/yati/tsuru/iaas"
)

func init() {
	iaas.Register("docker-machine", &dmIaas{})
}

type dmIaas struct{}

func (i *dmIaas) createMachine() error {
	cmd := exec.Command("docker-machine", "create", "tsuru", "-d", "virtualbox")
	return cmd.Run()
}

func (i *dmIaas) getIP() (string, error) {
	cmd := exec.Command("docker-machine", "ip", "tsuru")
	output, err := cmd.Output()
	return string(output), err
}

func (i *dmIaas) deleteMachine() error {
	cmd := exec.Command("docker-machine", "rm", "tsuru")
	return cmd.Run()
}

func (i *dmIaas) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	err := i.createMachine()
	if err != nil {
		return nil, err
	}
	ip, err := i.getIP()
	if err != nil {
		return nil, err
	}
	return &iaas.Machine{Address: ip}, nil
}

func (i *dmIaas) DeleteMachine(m *iaas.Machine) error {
	return i.deleteMachine()
}
<|endoftext|>


<commit_before>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package installer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/docker/machine/drivers/amazonec2"
	"github.com/docker/machine/drivers/azure"
	"github.com/docker/machine/drivers/digitalocean"
	"github.com/docker/machine/drivers/exoscale"
	"github.com/docker/machine/drivers/generic"
	"github.com/docker/machine/drivers/google"
	"github.com/docker/machine/drivers/hyperv"
	"github.com/docker/machine/drivers/none"
	"github.com/docker/machine/drivers/openstack"
	"github.com/docker/machine/drivers/rackspace"
	"github.com/docker/machine/drivers/softlayer"
	"github.com/docker/machine/drivers/virtualbox"
	"github.com/docker/machine/drivers/vmwarefusion"
	"github.com/docker/machine/drivers/vmwarevcloudair"
	"github.com/docker/machine/drivers/vmwarevsphere"
	"github.com/docker/machine/libmachine"
	"github.com/docker/machine/libmachine/cert"
	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/drivers/plugin"
	"github.com/docker/machine/libmachine/drivers/rpc"
	"github.com/docker/machine/libmachine/host"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/fsouza/go-dockerclient"
	"github.com/tsuru/tsuru/cmd"
)

var (
	dockerHTTPSPort            = 2376
	storeBasePath              = cmd.JoinWithUserDir(".tsuru", "installs")
	defaultDockerMachineConfig = &DockerMachineConfig{
		DriverName: "virtualbox",
		Name:       "tsuru",
		DriverOpts: make(map[string]interface{}),
	}
)

type Machine struct {
	IP      string
	Config  map[string]string
	Address string
	CAPath  string
}

func (m *Machine) dockerClient() (*docker.Client, error) {
	return docker.NewTLSClient(
		m.Address,
		filepath.Join(m.CAPath, "cert.pem"),
		filepath.Join(m.CAPath, "key.pem"),
		filepath.Join(m.CAPath, "ca.pem"),
	)
}

type DockerMachine struct {
	driverOpts map[string]interface{}
	rawDriver  []byte
	driverName string
	storePath  string
	certsPath  string
	Name       string
}

type DockerMachineConfig struct {
	DriverName string
	DriverOpts map[string]interface{}
	CAPath     string
	Name       string
}

func NewDockerMachine(config *DockerMachineConfig) (*DockerMachine, error) {
	storePath := filepath.Join(storeBasePath, config.Name)
	certsPath := filepath.Join(storePath, "certs")
	err := os.MkdirAll(certsPath, 0700)
	if err != nil {
		return nil, fmt.Errorf("failed to create certs dir: %s", err)
	}
	if config.CAPath != "" {
		fmt.Printf("Copying CA file from %s to %s", filepath.Join(config.CAPath, "ca.pem"), filepath.Join(certsPath, "ca.pem"))
		err = copy(filepath.Join(config.CAPath, "ca.pem"), filepath.Join(certsPath, "ca.pem"))
		if err != nil {
			return nil, fmt.Errorf("failed to copy ca file: %s", err)
		}
		fmt.Printf("Copying CA key from %s to %s", filepath.Join(config.CAPath, "ca-key.pem"), filepath.Join(certsPath, "ca-key.pem"))
		err = copy(filepath.Join(config.CAPath, "ca-key.pem"), filepath.Join(certsPath, "ca-key.pem"))
		if err != nil {
			return nil, fmt.Errorf("failed to copy ca key file: %s", err)
		}
	}
	rawDriver, err := json.Marshal(&drivers.BaseDriver{
		MachineName: config.Name,
		StorePath:   storePath,
	})
	if err != nil {
		return nil, fmt.Errorf("Error creating docker-machine driver: %s", err)
	}
	return &DockerMachine{
		driverOpts: config.DriverOpts,
		rawDriver:  rawDriver,
		driverName: config.DriverName,
		storePath:  storePath,
		certsPath:  certsPath,
		Name:       config.Name,
	}, nil
}

func copy(src, dst string) error {
	fileSrc, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(dst, fileSrc, 0644)
	if err != nil {
		return err
	}
	return nil
}

func (d *DockerMachine) CreateMachine() (*Machine, error) {
	client := libmachine.NewClient(d.storePath, d.certsPath)
	defer client.Close()
	host, err := client.NewHost(d.driverName, d.rawDriver)
	if err != nil {
		return nil, err
	}
	configureDriver(host.Driver, d.driverOpts)
	err = client.Create(host)
	if err != nil {
		fmt.Printf("Ignoring error on machine creation: %s", err)
	}
	ip, err := host.Driver.GetIP()
	if err != nil {
		return nil, err
	}
	err = d.uploadRegistryCertificate(host)
	if err != nil {
		return nil, err
	}
	config := map[string]string{}
	m := Machine{
		IP:     ip,
		Config: config,
		CAPath: d.certsPath,
	}
	m.Address = fmt.Sprintf("https://%s:%d", m.IP, dockerHTTPSPort)
	return &m, nil
}

func (d *DockerMachine) uploadRegistryCertificate(host *host.Host) error {
	ip, err := host.Driver.GetIP()
	if err != nil {
		return err
	}
	if _, err = os.Stat(filepath.Join(d.certsPath, "registry-cert.pem")); os.IsNotExist(err) {
		errCreate := d.createRegistryCertificate(ip)
		if errCreate != nil {
			return errCreate
		}
	}
	fmt.Printf("Uploading registry certificate...\n")
	args := []string{
		"-o StrictHostKeyChecking=no",
		"-i",
		fmt.Sprintf("%s/machines/%s/id_rsa", d.storePath, d.Name),
		"-r",
		fmt.Sprintf("%s/", d.certsPath),
		fmt.Sprintf("%s@%s:/home/%s/", host.Driver.GetSSHUsername(), ip, host.Driver.GetSSHUsername()),
	}
	comm := exec.Command("scp", args...)
	stdout, err := comm.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Command: %s. Error:%s", string(stdout), err.Error())
	}
	certsBasePath := fmt.Sprintf("/home/%s/certs/%s:5000", host.Driver.GetSSHUsername(), ip)
	_, err = host.RunSSHCommand(fmt.Sprintf("mkdir -p %s", certsBasePath))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("cp /home/%s/certs/*.pem %s/", host.Driver.GetSSHUsername(), certsBasePath))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("sudo mkdir /etc/docker/certs.d && sudo cp -r /home/%s/certs/* /etc/docker/certs.d/", host.Driver.GetSSHUsername()))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("cat %s/ca.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt", certsBasePath))
	return err
}

func (d *DockerMachine) createRegistryCertificate(hosts ...string) error {
	fmt.Printf("Creating registry certificate...\n")
	caOrg := mcnutils.GetUsername()
	org := caOrg + ".<bootstrap>"
	generator := &cert.X509CertGenerator{}
	certOpts := &cert.Options{
		Hosts:       hosts,
		CertFile:    filepath.Join(d.certsPath, "registry-cert.pem"),
		KeyFile:     filepath.Join(d.certsPath, "registry-key.pem"),
		CAFile:      filepath.Join(d.certsPath, "ca.pem"),
		CAKeyFile:   filepath.Join(d.certsPath, "ca-key.pem"),
		Org:         org,
		Bits:        2048,
		SwarmMaster: false,
	}
	return generator.GenerateCert(certOpts)
}

func configureDriver(driver drivers.Driver, driverOpts map[string]interface{}) error {
	opts := &rpcdriver.RPCFlags{Values: driverOpts}
	for _, c := range driver.GetCreateFlags() {
		_, ok := opts.Values[c.String()]
		if !ok {
			opts.Values[c.String()] = c.Default()
			if c.Default() == nil {
				opts.Values[c.String()] = false
			}
		}
	}
	if err := driver.SetConfigFromFlags(opts); err != nil {
		return fmt.Errorf("Error setting driver configurations: %s", err)
	}
	return nil
}

func (d *DockerMachine) DeleteMachine(m *Machine) error {
	client := libmachine.NewClient(d.storePath, d.certsPath)
	defer client.Close()
	h, err := client.Load(d.Name)
	if err != nil {
		return err
	}
	err = h.Driver.Remove()
	if err != nil {
		return err
	}
	return client.Remove(d.Name)
}

func RunDriver(driverName string) error {
	switch driverName {
	case "amazonec2":
		plugin.RegisterDriver(amazonec2.NewDriver("", ""))
	case "azure":
		plugin.RegisterDriver(azure.NewDriver("", ""))
	case "digitalocean":
		plugin.RegisterDriver(digitalocean.NewDriver("", ""))
	case "exoscale":
		plugin.RegisterDriver(exoscale.NewDriver("", ""))
	case "generic":
		plugin.RegisterDriver(generic.NewDriver("", ""))
	case "google":
		plugin.RegisterDriver(google.NewDriver("", ""))
	case "hyperv":
		plugin.RegisterDriver(hyperv.NewDriver("", ""))
	case "none":
		plugin.RegisterDriver(none.NewDriver("", ""))
	case "openstack":
		plugin.RegisterDriver(openstack.NewDriver("", ""))
	case "rackspace":
		plugin.RegisterDriver(rackspace.NewDriver("", ""))
	case "softlayer":
		plugin.RegisterDriver(softlayer.NewDriver("", ""))
	case "virtualbox":
		plugin.RegisterDriver(virtualbox.NewDriver("", ""))
	case "vmwarefusion":
		plugin.RegisterDriver(vmwarefusion.NewDriver("", ""))
	case "vmwarevcloudair":
		plugin.RegisterDriver(vmwarevcloudair.NewDriver("", ""))
	case "vmwarevsphere":
		plugin.RegisterDriver(vmwarevsphere.NewDriver("", ""))
	default:
		return fmt.Errorf("Unsupported driver: %s\n", driverName)
	}
	return nil
}
<commit_msg>installer: refactor ssh and scp usage<commit_after>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package installer

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/docker/machine/drivers/amazonec2"
	"github.com/docker/machine/drivers/azure"
	"github.com/docker/machine/drivers/digitalocean"
	"github.com/docker/machine/drivers/exoscale"
	"github.com/docker/machine/drivers/generic"
	"github.com/docker/machine/drivers/google"
	"github.com/docker/machine/drivers/hyperv"
	"github.com/docker/machine/drivers/none"
	"github.com/docker/machine/drivers/openstack"
	"github.com/docker/machine/drivers/rackspace"
	"github.com/docker/machine/drivers/softlayer"
	"github.com/docker/machine/drivers/virtualbox"
	"github.com/docker/machine/drivers/vmwarefusion"
	"github.com/docker/machine/drivers/vmwarevcloudair"
	"github.com/docker/machine/drivers/vmwarevsphere"
	"github.com/docker/machine/libmachine"
	"github.com/docker/machine/libmachine/cert"
	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/drivers/plugin"
	"github.com/docker/machine/libmachine/drivers/rpc"
	"github.com/docker/machine/libmachine/host"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/fsouza/go-dockerclient"
	"github.com/tsuru/tsuru-client/tsuru/client"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/exec"
)

var (
	dockerHTTPSPort            = 2376
	storeBasePath              = cmd.JoinWithUserDir(".tsuru", "installs")
	defaultDockerMachineConfig = &DockerMachineConfig{
		DriverName: "virtualbox",
		Name:       "tsuru",
		DriverOpts: make(map[string]interface{}),
	}
)

type Machine struct {
	*host.Host
	IP      string
	Config  map[string]string
	Address string
	CAPath  string
}

func (m *Machine) dockerClient() (*docker.Client, error) {
	return docker.NewTLSClient(
		m.Address,
		filepath.Join(m.CAPath, "cert.pem"),
		filepath.Join(m.CAPath, "key.pem"),
		filepath.Join(m.CAPath, "ca.pem"),
	)
}

func (m Machine) Driver() drivers.Driver {
	return m.Host.Driver
}

type DockerMachine struct {
	driverOpts map[string]interface{}
	rawDriver  []byte
	driverName string
	storePath  string
	certsPath  string
	Name       string
}

type DockerMachineConfig struct {
	DriverName string
	DriverOpts map[string]interface{}
	CAPath     string
	Name       string
}

func NewDockerMachine(config *DockerMachineConfig) (*DockerMachine, error) {
	storePath := filepath.Join(storeBasePath, config.Name)
	certsPath := filepath.Join(storePath, "certs")
	err := os.MkdirAll(certsPath, 0700)
	if err != nil {
		return nil, fmt.Errorf("failed to create certs dir: %s", err)
	}
	if config.CAPath != "" {
		fmt.Printf("Copying CA file from %s to %s", filepath.Join(config.CAPath, "ca.pem"), filepath.Join(certsPath, "ca.pem"))
		err = copy(filepath.Join(config.CAPath, "ca.pem"), filepath.Join(certsPath, "ca.pem"))
		if err != nil {
			return nil, fmt.Errorf("failed to copy ca file: %s", err)
		}
		fmt.Printf("Copying CA key from %s to %s", filepath.Join(config.CAPath, "ca-key.pem"), filepath.Join(certsPath, "ca-key.pem"))
		err = copy(filepath.Join(config.CAPath, "ca-key.pem"), filepath.Join(certsPath, "ca-key.pem"))
		if err != nil {
			return nil, fmt.Errorf("failed to copy ca key file: %s", err)
		}
	}
	rawDriver, err := json.Marshal(&drivers.BaseDriver{
		MachineName: config.Name,
		StorePath:   storePath,
	})
	if err != nil {
		return nil, fmt.Errorf("Error creating docker-machine driver: %s", err)
	}
	return &DockerMachine{
		driverOpts: config.DriverOpts,
		rawDriver:  rawDriver,
		driverName: config.DriverName,
		storePath:  storePath,
		certsPath:  certsPath,
		Name:       config.Name,
	}, nil
}

func copy(src, dst string) error {
	fileSrc, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(dst, fileSrc, 0644)
	if err != nil {
		return err
	}
	return nil
}

func (d *DockerMachine) CreateMachine() (*Machine, error) {
	client := libmachine.NewClient(d.storePath, d.certsPath)
	defer client.Close()
	host, err := client.NewHost(d.driverName, d.rawDriver)
	if err != nil {
		return nil, err
	}
	configureDriver(host.Driver, d.driverOpts)
	err = client.Create(host)
	if err != nil {
		fmt.Printf("Ignoring error on machine creation: %s", err)
	}
	ip, err := host.Driver.GetIP()
	if err != nil {
		return nil, err
	}
	config := map[string]string{}
	m := Machine{
		IP:     ip,
		Config: config,
		CAPath: d.certsPath,
		Host:   host,
	}
	m.Address = fmt.Sprintf("https://%s:%d", m.IP, dockerHTTPSPort)
	err = d.uploadRegistryCertificate(m)
	if err != nil {
		return nil, err
	}
	return &m, nil
}

type sshTarget interface {
	RunSSHCommand(string) (string, error)
	Driver() drivers.Driver
}

func (d *DockerMachine) uploadRegistryCertificate(host sshTarget) error {
	driver := host.Driver()
	ip, err := driver.GetIP()
	if err != nil {
		return err
	}
	if _, err = os.Stat(filepath.Join(d.certsPath, "registry-cert.pem")); os.IsNotExist(err) {
		errCreate := d.createRegistryCertificate(ip)
		if errCreate != nil {
			return errCreate
		}
	}
	fmt.Printf("Uploading registry certificate...\n")
	args := []string{
		"-o StrictHostKeyChecking=no",
		"-i",
		fmt.Sprintf("%s/machines/%s/id_rsa", d.storePath, d.Name),
		"-r",
		fmt.Sprintf("%s/", d.certsPath),
		fmt.Sprintf("%s@%s:/home/%s/", driver.GetSSHUsername(), ip, driver.GetSSHUsername()),
	}
	stdout := bytes.NewBufferString("")
	opts := exec.ExecuteOptions{
		Cmd:    "scp",
		Args:   args,
		Stdout: stdout,
	}
	err = client.Executor().Execute(opts)
	if err != nil {
		return fmt.Errorf("Command: %s. Error:%s", stdout.String(), err.Error())
	}
	certsBasePath := fmt.Sprintf("/home/%s/certs/%s:5000", driver.GetSSHUsername(), ip)
	_, err = host.RunSSHCommand(fmt.Sprintf("mkdir -p %s", certsBasePath))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("cp /home/%s/certs/*.pem %s/", driver.GetSSHUsername(), certsBasePath))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("sudo mkdir /etc/docker/certs.d && sudo cp -r /home/%s/certs/* /etc/docker/certs.d/", driver.GetSSHUsername()))
	if err != nil {
		return err
	}
	_, err = host.RunSSHCommand(fmt.Sprintf("cat %s/ca.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt", certsBasePath))
	return err
}

func (d *DockerMachine) createRegistryCertificate(hosts ...string) error {
	fmt.Printf("Creating registry certificate...\n")
	caOrg := mcnutils.GetUsername()
	org := caOrg + ".<bootstrap>"
	generator := &cert.X509CertGenerator{}
	certOpts := &cert.Options{
		Hosts:       hosts,
		CertFile:    filepath.Join(d.certsPath, "registry-cert.pem"),
		KeyFile:     filepath.Join(d.certsPath, "registry-key.pem"),
		CAFile:      filepath.Join(d.certsPath, "ca.pem"),
		CAKeyFile:   filepath.Join(d.certsPath, "ca-key.pem"),
		Org:         org,
		Bits:        2048,
		SwarmMaster: false,
	}
	return generator.GenerateCert(certOpts)
}

func configureDriver(driver drivers.Driver, driverOpts map[string]interface{}) error {
	opts := &rpcdriver.RPCFlags{Values: driverOpts}
	for _, c := range driver.GetCreateFlags() {
		_, ok := opts.Values[c.String()]
		if !ok {
			opts.Values[c.String()] = c.Default()
			if c.Default() == nil {
				opts.Values[c.String()] = false
			}
		}
	}
	if err := driver.SetConfigFromFlags(opts); err != nil {
		return fmt.Errorf("Error setting driver configurations: %s", err)
	}
	return nil
}

func (d *DockerMachine) DeleteMachine(m *Machine) error {
	client := libmachine.NewClient(d.storePath, d.certsPath)
	defer client.Close()
	h, err := client.Load(d.Name)
	if err != nil {
		return err
	}
	err = h.Driver.Remove()
	if err != nil {
		return err
	}
	return client.Remove(d.Name)
}

func RunDriver(driverName string) error {
	switch driverName {
	case "amazonec2":
		plugin.RegisterDriver(amazonec2.NewDriver("", ""))
	case "azure":
		plugin.RegisterDriver(azure.NewDriver("", ""))
	case "digitalocean":
		plugin.RegisterDriver(digitalocean.NewDriver("", ""))
	case "exoscale":
		plugin.RegisterDriver(exoscale.NewDriver("", ""))
	case "generic":
		plugin.RegisterDriver(generic.NewDriver("", ""))
	case "google":
		plugin.RegisterDriver(google.NewDriver("", ""))
	case "hyperv":
		plugin.RegisterDriver(hyperv.NewDriver("", ""))
	case "none":
		plugin.RegisterDriver(none.NewDriver("", ""))
	case "openstack":
		plugin.RegisterDriver(openstack.NewDriver("", ""))
	case "rackspace":
		plugin.RegisterDriver(rackspace.NewDriver("", ""))
	case "softlayer":
		plugin.RegisterDriver(softlayer.NewDriver("", ""))
	case "virtualbox":
		plugin.RegisterDriver(virtualbox.NewDriver("", ""))
	case "vmwarefusion":
		plugin.RegisterDriver(vmwarefusion.NewDriver("", ""))
	case "vmwarevcloudair":
		plugin.RegisterDriver(vmwarevcloudair.NewDriver("", ""))
	case "vmwarevsphere":
		plugin.RegisterDriver(vmwarevsphere.NewDriver("", ""))
	default:
		return fmt.Errorf("Unsupported driver: %s\n", driverName)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Gary Burd. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"bytes"
	"go/scanner"

	"nvim-go/gb"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/garyburd/neovim-go/vim/vimutil"
	"golang.org/x/tools/imports"
)

func init() {
	plugin.HandleCommand("Gofmt", &plugin.CommandOptions{Range: "%", Eval: "expand('%:p')"}, Fmt)
}

var options = imports.Options{
	AllErrors: true,
	Comments:  true,
	TabIndent: true,
	TabWidth:  8,
}

func Fmt(v *vim.Vim, r [2]int, file string) error {
	defer gb.WithGoBuildForPath(file)()

	b, err := v.CurrentBuffer()
	if err != nil {
		return err
	}

	in, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}

	buf, err := imports.Process("", bytes.Join(in, []byte{'\n'}), &options)
	if err != nil {
		return reportErrors(v, b, err)
	}

	out := bytes.Split(bytes.TrimSuffix(buf, []byte{'\n'}), []byte{'\n'})

	return minUpdate(v, b, in, out)
}

func reportErrors(v *vim.Vim, b vim.Buffer, formatErr error) error {
	var qfl []*vimutil.QuickfixError
	if e, ok := formatErr.(scanner.Error); ok {
		qfl = append(qfl, &vimutil.QuickfixError{
			LNum: e.Pos.Line,
			Col:  e.Pos.Column,
			Text: e.Msg,
		})
	} else if el, ok := formatErr.(scanner.ErrorList); ok {
		for _, e := range el {
			qfl = append(qfl, &vimutil.QuickfixError{
				LNum: e.Pos.Line,
				Col:  e.Pos.Column,
				Text: e.Msg,
			})
		}
	}

	if len(qfl) == 0 {
		return formatErr
	}

	bufnr, err := v.BufferNumber(b)
	if err != nil {
		return err
	}
	for i := range qfl {
		qfl[i].Bufnr = bufnr
	}

	if err := v.Call("setqflist", nil, qfl); err != nil {
		return err
	}

	return v.Command("cc")
}

func minUpdate(v *vim.Vim, b vim.Buffer, in [][]byte, out [][]byte) error {

	// Find matching head lines.
	n := len(out)
	if len(in) < len(out) {
		n = len(in)
	}
	head := 0
	for ; head < n; head++ {
		if !bytes.Equal(in[head], out[head]) {
			break
		}
	}

	// Nothing to do?
	if head == len(in) && head == len(out) {
		return nil
	}

	// Find matching tail lines.
	n -= head
	tail := 0
	for ; tail < n; tail++ {
		if !bytes.Equal(in[len(in)-tail-1], out[len(out)-tail-1]) {
			break
		}
	}

	// Update the buffer.
	includeStart := true
	start := head
	end := len(in) - tail
	repl := out[head : len(out)-tail]

	if start == len(in) {
		start = -1
		includeStart = false
	}

	return v.SetBufferLineSlice(b, start, end, includeStart, false, repl)
}
<commit_msg>Support location list<commit_after>// Copyright 2015 Gary Burd. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"bytes"
	"go/scanner"

	"nvim-go/gb"
	"nvim-go/nvim"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/garyburd/neovim-go/vim/vimutil"
	"golang.org/x/tools/imports"
)

func init() {
	plugin.HandleCommand("Gofmt", &plugin.CommandOptions{Range: "%", Eval: "expand('%:p')"}, Fmt)
	plugin.HandleAutocmd("BufWritePre", &plugin.AutocmdOptions{Pattern: "*.go"}, onBufWritePre)
}

var options = imports.Options{
	AllErrors: true,
	Comments:  true,
	TabIndent: true,
	TabWidth:  8,
}

func Fmt(v *vim.Vim, r [2]int, file string) error {
	defer gb.WithGoBuildForPath(file)()

	b, err := v.CurrentBuffer()
	if err != nil {
		return err
	}

	in, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}

	buf, err := imports.Process("", bytes.Join(in, []byte{'\n'}), &options)
	if err != nil {
		return nvim.LoclistErrors(v, b, err)
	} else {
		nvim.LoclistClose(v)
	}

	out := bytes.Split(bytes.TrimSuffix(buf, []byte{'\n'}), []byte{'\n'})

	return minUpdate(v, b, in, out)
}

type BufWritePre struct {
	Name string `msgpack:",array"`
	Cwd  string
}

func onBufWritePre(v *vim.Vim, eval *BufWritePre) error {
	var (
		b vim.Buffer
		w vim.Window
	)
	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	p.Command("Gofmt")

	return p.Wait()
}

func reportErrors(v *vim.Vim, b vim.Buffer, formatErr error) error {
	var qfl []*vimutil.QuickfixError
	if e, ok := formatErr.(scanner.Error); ok {
		qfl = append(qfl, &vimutil.QuickfixError{
			LNum: e.Pos.Line,
			Col:  e.Pos.Column,
			Text: e.Msg,
		})
	} else if el, ok := formatErr.(scanner.ErrorList); ok {
		for _, e := range el {
			qfl = append(qfl, &vimutil.QuickfixError{
				LNum: e.Pos.Line,
				Col:  e.Pos.Column,
				Text: e.Msg,
			})
		}
	}

	if len(qfl) == 0 {
		return formatErr
	}

	bufnr, err := v.BufferNumber(b)
	if err != nil {
		return err
	}
	for i := range qfl {
		qfl[i].Bufnr = bufnr
	}

	if err := v.Call("setqflist", nil, qfl); err != nil {
		return err
	}

	return v.Command("cc")
}

func minUpdate(v *vim.Vim, b vim.Buffer, in [][]byte, out [][]byte) error {
	// Find matching head lines.
	n := len(out)
	if len(in) < len(out) {
		n = len(in)
	}
	head := 0
	for ; head < n; head++ {
		if !bytes.Equal(in[head], out[head]) {
			break
		}
	}

	// Nothing to do?
	if head == len(in) && head == len(out) {
		return nil
	}

	// Find matching tail lines.
	n -= head
	tail := 0
	for ; tail < n; tail++ {
		if !bytes.Equal(in[len(in)-tail-1], out[len(out)-tail-1]) {
			break
		}
	}

	// Update the buffer.
	includeStart := true
	start := head
	end := len(in) - tail
	repl := out[head : len(out)-tail]

	if start == len(in) {
		start = -1
		includeStart = false
	}

	return v.SetBufferLineSlice(b, start, end, includeStart, false, repl)
}
<|endoftext|>


<commit_before>package goca

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/kolo/xmlrpc"
)

var (
	client *oneClient
)

// OneConfig contains the information to communicate with OpenNebula
type OneConfig struct {
	// Token is the authentication string. In the format of <user>:<password>
	Token string

	// XmlrpcURL contains OpenNebula's XML-RPC API endpoint. Defaults to
	// http://localhost:2633/RPC2
	XmlrpcURL string
}

type oneClient struct {
	token             string
	xmlrpcClient      *xmlrpc.Client
	xmlrpcClientError error
}

type response struct {
	status  bool
	body    string
	bodyInt int
}

// Resource implements an OpenNebula Resource methods. *XMLResource implements
// all these methods
type Resource interface {
	Body() string
	XPath(string) (string, bool)
	XPathIter(string) *XMLIter
	GetIDFromName(string, string) (uint, error)
}

// Initializes the client variable, used as a singleton
func init() {
	err := SetClient(NewConfig("", "", ""))
	if err != nil {
		log.Fatal(err)
	}
}

// NewConfig returns a new OneConfig object with the specified user, password,
// and xmlrpcURL
func NewConfig(user string, password string, xmlrpcURL string) OneConfig {
	var authToken string
	var oneAuthPath string

	oneXmlrpc := xmlrpcURL

	if user == "" && password == "" {
		oneAuthPath = os.Getenv("ONE_AUTH")
		if oneAuthPath == "" {
			oneAuthPath = os.Getenv("HOME") + "/.one/one_auth"
		}

		token, err := ioutil.ReadFile(oneAuthPath)
		if err == nil {
			authToken = strings.TrimSpace(string(token))
		} else {
			authToken = ""
		}
	} else {
		authToken = user + ":" + password
	}

	if oneXmlrpc == "" {
		oneXmlrpc = os.Getenv("ONE_XMLRPC")
		if oneXmlrpc == "" {
			oneXmlrpc = "http://localhost:2633/RPC2"
		}
	}

	config := OneConfig{
		Token:     authToken,
		XmlrpcURL: oneXmlrpc,
	}

	return config
}

// SetClient assigns a value to the client variable
func SetClient(conf OneConfig) error {

	xmlrpcClient, xmlrpcClientError := xmlrpc.NewClient(conf.XmlrpcURL, nil)

	client = &oneClient{
		token:             conf.Token,
		xmlrpcClient:      xmlrpcClient,
		xmlrpcClientError: xmlrpcClientError,
	}

	return nil
}

// SystemVersion returns the current OpenNebula Version
func SystemVersion() (string, error) {
	response, err := client.Call("one.system.version")
	if err != nil {
		return "", err
	}

	return response.Body(), nil
}

// Call is an XML-RPC wrapper. It returns a pointer to response and an error.
func (c *oneClient) Call(method string, args ...interface{}) (*response, error) {
	var (
		ok bool

		status  bool
		body    string
		bodyInt int64
	)

	if c.xmlrpcClientError != nil {
		return nil, fmt.Errorf("Unitialized client. Token: '%s', xmlrpcClient: '%s'", c.token, c.xmlrpcClientError)
	}

	result := []interface{}{}

	xmlArgs := make([]interface{}, len(args)+1)

	xmlArgs[0] = c.token
	copy(xmlArgs[1:], args[:])

	err := c.xmlrpcClient.Call(method, xmlArgs, &result)
	if err != nil {
		log.Fatal(err)
	}

	status, ok = result[0].(bool)
	if ok == false {
		log.Fatal("Unexpected XML-RPC response. Expected: Index 0 Boolean")
	}

	body, ok = result[1].(string)
	if ok == false {
		bodyInt, ok = result[1].(int64)
		if ok == false {
			log.Fatal("Unexpected XML-RPC response. Expected: Index 0 Int or String")
		}
	}

	// TODO: errCode? result[2]

	r := &response{status, body, int(bodyInt)}

	if status == false {
		err = errors.New(body)
	}

	return r, err
}

// Body accesses the body of the response
func (r *response) Body() string {
	return r.body
}

// BodyInt accesses the body of the response, if it's an int.
func (r *response) BodyInt() int {
	return r.bodyInt
}
<commit_msg>Add support to Bool type in XMLRPC response<commit_after>package goca

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/kolo/xmlrpc"
)

var (
	client *oneClient
)

// OneConfig contains the information to communicate with OpenNebula
type OneConfig struct {
	// Token is the authentication string. In the format of <user>:<password>
	Token string

	// XmlrpcURL contains OpenNebula's XML-RPC API endpoint. Defaults to
	// http://localhost:2633/RPC2
	XmlrpcURL string
}

type oneClient struct {
	token             string
	xmlrpcClient      *xmlrpc.Client
	xmlrpcClientError error
}

type response struct {
	status   bool
	body     string
	bodyInt  int
	bodyBool bool
}

// Resource implements an OpenNebula Resource methods. *XMLResource implements
// all these methods
type Resource interface {
	Body() string
	XPath(string) (string, bool)
	XPathIter(string) *XMLIter
	GetIDFromName(string, string) (uint, error)
}

// Initializes the client variable, used as a singleton
func init() {
	err := SetClient(NewConfig("", "", ""))
	if err != nil {
		log.Fatal(err)
	}
}

// NewConfig returns a new OneConfig object with the specified user, password,
// and xmlrpcURL
func NewConfig(user string, password string, xmlrpcURL string) OneConfig {
	var authToken string
	var oneAuthPath string

	oneXmlrpc := xmlrpcURL

	if user == "" && password == "" {
		oneAuthPath = os.Getenv("ONE_AUTH")
		if oneAuthPath == "" {
			oneAuthPath = os.Getenv("HOME") + "/.one/one_auth"
		}

		token, err := ioutil.ReadFile(oneAuthPath)
		if err == nil {
			authToken = strings.TrimSpace(string(token))
		} else {
			authToken = ""
		}
	} else {
		authToken = user + ":" + password
	}

	if oneXmlrpc == "" {
		oneXmlrpc = os.Getenv("ONE_XMLRPC")
		if oneXmlrpc == "" {
			oneXmlrpc = "http://localhost:2633/RPC2"
		}
	}

	config := OneConfig{
		Token:     authToken,
		XmlrpcURL: oneXmlrpc,
	}

	return config
}

// SetClient assigns a value to the client variable
func SetClient(conf OneConfig) error {

	xmlrpcClient, xmlrpcClientError := xmlrpc.NewClient(conf.XmlrpcURL, nil)

	client = &oneClient{
		token:             conf.Token,
		xmlrpcClient:      xmlrpcClient,
		xmlrpcClientError: xmlrpcClientError,
	}

	return nil
}

// SystemVersion returns the current OpenNebula Version
func SystemVersion() (string, error) {
	response, err := client.Call("one.system.version")
	if err != nil {
		return "", err
	}

	return response.Body(), nil
}

// Call is an XML-RPC wrapper. It returns a pointer to response and an error.
func (c *oneClient) Call(method string, args ...interface{}) (*response, error) {
	var (
		ok bool

		status  bool
		body    string
		bodyInt int64
		bodyBool bool
	)

	if c.xmlrpcClientError != nil {
		return nil, fmt.Errorf("Unitialized client. Token: '%s', xmlrpcClient: '%s'", c.token, c.xmlrpcClientError)
	}

	result := []interface{}{}

	xmlArgs := make([]interface{}, len(args)+1)

	xmlArgs[0] = c.token
	copy(xmlArgs[1:], args[:])

	err := c.xmlrpcClient.Call(method, xmlArgs, &result)
	if err != nil {
		log.Fatal(err)
	}

	status, ok = result[0].(bool)
	if ok == false {
		log.Fatal("Unexpected XML-RPC response. Expected: Index 0 Boolean")
	}

	body, ok = result[1].(string)
	if ok == false {
		bodyInt, ok = result[1].(int64)
		if ok == false {
			bodyBool, ok = result[1].(bool)
			if ok == false {
				log.Fatal("Unexpected XML-RPC response. Expected: Index 0 Int or String")
			}
		}
	}

	// TODO: errCode? result[2]

	r := &response{status, body, int(bodyInt), bodyBool}

	if status == false {
		err = errors.New(body)
	}

	return r, err
}

// Body accesses the body of the response
func (r *response) Body() string {
	return r.body
}

// BodyInt accesses the body of the response, if it's an int.
func (r *response) BodyInt() int {
	return r.bodyInt
}
<|endoftext|>


<commit_before>package models

import (
	"database/sql"
	"github.com/asaskevich/govalidator"
	"golang.org/x/crypto/bcrypt"

	"github.com/techjanitor/pram-post/config"
	e "github.com/techjanitor/pram-post/errors"
	u "github.com/techjanitor/pram-post/utils"
)

// loginmodel contains user name and password
type LoginModel struct {
	Name      string
	Password  string
	Hash      []byte
	Id        uint
	Group     uint
	Confirmed bool
	Locked    bool
	Banned    bool
	Sid       string
}

// Validate will check the provided name and password
func (r *LoginModel) Validate() (err error) {

	// Validate name input
	name := u.Validate{Input: r.Name, Max: config.Settings.Limits.NameMaxLength, Min: config.Settings.Limits.NameMinLength}
	if name.IsEmpty() {
		return e.ErrNameEmpty
	} else if name.MinLength() {
		return e.ErrNameShort
	} else if name.MaxLength() {
		return e.ErrNameLong
	}

	// check if name is alphanumeric
	if !govalidator.IsAlphanumeric(r.Name) {
		return e.ErrNameAlphaNum
	}

	// Validate password input
	password := u.Validate{Input: r.Password, Max: config.Settings.Limits.NameMaxLength, Min: config.Settings.Limits.NameMinLength}
	if password.IsEmpty() {
		return e.ErrPasswordEmpty
	} else if password.MinLength() {
		return e.ErrPasswordShort
	} else if password.MaxLength() {
		return e.ErrPasswordLong
	}

	return

}

// log user in
func (r *LoginModel) Login() (err error) {

	// Get Database handle
	db, err := u.GetDb()
	if err != nil {
		return
	}

	// get hashed password from database
	err = db.QueryRow("select user_id, user_password, usergroup_id, user_confirmed, user_locked, user_banned from users where user_name = ?", r.Name).Scan(&r.Id, &r.Hash, &r.Group, &r.Confirmed, &r.Locked, &r.Banned)
	if err == sql.ErrNoRows {
		return e.ErrInvalidUser
	} else if err != nil {
		return
	}

	// compare provided password to stored hash
	bcrypt.CompareHashAndPassword(r.Hash, []byte(r.Password))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return e.ErrInvalidPassword
	} else if err != nil {
		return
	}

	// if account is not confirmed
	if !r.Confirmed {
		return e.ErrUserNotConfirmed
	}

	// if locked
	if r.Locked {
		return e.ErrUserLocked
	}

	// if banned
	if r.Banned {
		return e.ErrUserBanned
	}

	// make new session for user
	r.Sid, err = u.NewSession(r.Id)
	if err != nil {
		return
	}

	return

}
<commit_msg>debug login<commit_after>package models

import (
	"database/sql"
	"fmt"
	"github.com/asaskevich/govalidator"
	"golang.org/x/crypto/bcrypt"

	"github.com/techjanitor/pram-post/config"
	e "github.com/techjanitor/pram-post/errors"
	u "github.com/techjanitor/pram-post/utils"
)

// loginmodel contains user name and password
type LoginModel struct {
	Name      string
	Password  string
	Hash      []byte
	Id        uint
	Group     uint
	Confirmed bool
	Locked    bool
	Banned    bool
	Sid       string
}

// Validate will check the provided name and password
func (r *LoginModel) Validate() (err error) {

	// Validate name input
	name := u.Validate{Input: r.Name, Max: config.Settings.Limits.NameMaxLength, Min: config.Settings.Limits.NameMinLength}
	if name.IsEmpty() {
		return e.ErrNameEmpty
	} else if name.MinLength() {
		return e.ErrNameShort
	} else if name.MaxLength() {
		return e.ErrNameLong
	}

	// check if name is alphanumeric
	if !govalidator.IsAlphanumeric(r.Name) {
		return e.ErrNameAlphaNum
	}

	// Validate password input
	password := u.Validate{Input: r.Password, Max: config.Settings.Limits.NameMaxLength, Min: config.Settings.Limits.NameMinLength}
	if password.IsEmpty() {
		return e.ErrPasswordEmpty
	} else if password.MinLength() {
		return e.ErrPasswordShort
	} else if password.MaxLength() {
		return e.ErrPasswordLong
	}

	return

}

// log user in
func (r *LoginModel) Login() (err error) {

	// Get Database handle
	db, err := u.GetDb()
	if err != nil {
		return
	}

	// get hashed password from database
	err = db.QueryRow("select user_id, user_password, usergroup_id, user_confirmed, user_locked, user_banned from users where user_name = ?", r.Name).Scan(&r.Id, &r.Hash, &r.Group, &r.Confirmed, &r.Locked, &r.Banned)
	if err == sql.ErrNoRows {
		return e.ErrInvalidUser
	} else if err != nil {
		return
	}

	fmt.Printf("%s\n%s\n", r.Hash, r.Password)

	// compare provided password to stored hash
	bcrypt.CompareHashAndPassword(r.Hash, []byte(r.Password))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return e.ErrInvalidPassword
	} else if err != nil {
		return
	}

	// if account is not confirmed
	if !r.Confirmed {
		return e.ErrUserNotConfirmed
	}

	// if locked
	if r.Locked {
		return e.ErrUserLocked
	}

	// if banned
	if r.Banned {
		return e.ErrUserBanned
	}

	// make new session for user
	r.Sid, err = u.NewSession(r.Id)
	if err != nil {
		return
	}

	return

}
<|endoftext|>


<commit_before>package storage

type multiIterator struct {
	current int
	iters   []Iterator
}

// NewMultiIterator returns an iterator that iterates over the given iterators.
func NewMultiIterator(iters []Iterator) Iterator {
	if len(iters) == 0 {
		return &NullIter{}
	}

	return &multiIterator{current: 0, iters: iters}
}

func (m *multiIterator) Next() bool {
	for ; m.current < len(m.iters); m.current++ {
		if m.iters[m.current].Next() {
			return true
		}
	}
	return false
}

func (m *multiIterator) Key() []byte {
	return m.iters[m.current].Key()
}

func (m *multiIterator) Value() ([]byte, error) {
	return m.iters[m.current].Value()
}

func (m *multiIterator) Release() {
	for i := range m.iters {
		m.iters[i].Release()
	}
	m.current = 0
	m.iters = []Iterator{&NullIter{}}
}

func (m *multiIterator) Seek(key []byte) bool {
	m.current = 0
	iters := []Iterator{}
	ok := false
	for i := range m.iters {
		if m.iters[i].Seek(key) {
			iters = append(iters, m.iters[i])
			ok = true
		}
	}
	return ok
}
<commit_msg>#178 multi_iterator looks broken<commit_after>package storage

type multiIterator struct {
	current int
	// "current" iterators, that might be limited to iters that contain
	// some Seek'ed values
	iters []Iterator
	// original iters
	origIters []Iterator
}

// NewMultiIterator returns an iterator that iterates over the given iterators.
func NewMultiIterator(iters []Iterator) Iterator {
	if len(iters) == 0 {
		return &NullIter{}
	}

	return &multiIterator{
		current:   0,
		iters:     iters,
		origIters: iters,
	}
}

func (m *multiIterator) Next() bool {
	for ; m.current < len(m.iters); m.current++ {
		if m.iters[m.current].Next() {
			return true
		}
	}
	return false
}

func (m *multiIterator) Key() []byte {
	return m.iters[m.current].Key()
}

func (m *multiIterator) Value() ([]byte, error) {
	return m.iters[m.current].Value()
}

func (m *multiIterator) Release() {
	for i := range m.iters {
		m.iters[i].Release()
	}
	m.current = 0
	m.iters = nil
}

func (m *multiIterator) Seek(key []byte) bool {
	m.current = 0
	m.iters = nil

	// at least one iterator's seek was successful
	ok := false

	// iterate over all (original) iterators
	for _, iter := range m.origIters {
		// if it matches, apply it to the list of iters we'll be using for the next Next()
		if iter.Seek(key) {
			m.iters = append(m.iters, iter)
			ok = true
		}
	}

	return ok
}
<|endoftext|>


<commit_before>package cassandra

import (
	"flag"
	"time"

	"github.com/grafana/globalconf"
)

type StoreConfig struct {
	Enabled                  bool
	Addrs                    string
	Keyspace                 string
	Consistency              string
	HostSelectionPolicy      string
	Timeout                  string
	ReadConcurrency          int
	WriteConcurrency         int
	ReadQueueSize            int
	WriteQueueSize           int
	Retries                  int
	WindowFactor             int
	OmitReadTimeout          string
	CqlProtocolVersion       int
	CreateKeyspace           bool
	DisableInitialHostLookup bool
	SSL                      bool
	CaPath                   string
	HostVerification         bool
	Auth                     bool
	Username                 string
	Password                 string
	SchemaFile               string
	ConnectionCheckInterval  time.Duration
	ConnectionCheckTimeout   time.Duration
}

// return StoreConfig with default values set.
func NewStoreConfig() *StoreConfig {
	return &StoreConfig{
		Enabled:                  true,
		Addrs:                    "localhost",
		Keyspace:                 "metrictank",
		Consistency:              "one",
		HostSelectionPolicy:      "tokenaware,hostpool-epsilon-greedy",
		Timeout:                  "1s",
		ReadConcurrency:          20,
		WriteConcurrency:         10,
		ReadQueueSize:            200000,
		WriteQueueSize:           100000,
		Retries:                  0,
		WindowFactor:             20,
		OmitReadTimeout:          "60s",
		CqlProtocolVersion:       4,
		CreateKeyspace:           true,
		DisableInitialHostLookup: false,
		SSL:                      false,
		CaPath:                   "/etc/metrictank/ca.pem",
		HostVerification:         true,
		Auth:                     false,
		Username:                 "cassandra",
		Password:                 "cassandra",
		SchemaFile:               "/etc/metrictank/schema-store-cassandra.toml",
		ConnectionCheckInterval:  time.Second * 5,
		ConnectionCheckTimeout:   time.Second * 30,
	}
}

var CliConfig = NewStoreConfig()

func ConfigSetup() *flag.FlagSet {
	cas := flag.NewFlagSet("cassandra", flag.ExitOnError)
	cas.BoolVar(&CliConfig.Enabled, "enabled", CliConfig.Enabled, "enable the cassandra backend store plugin")
	cas.StringVar(&CliConfig.Addrs, "addrs", CliConfig.Addrs, "cassandra host (may be given multiple times as comma-separated list)")
	cas.StringVar(&CliConfig.Keyspace, "keyspace", CliConfig.Keyspace, "cassandra keyspace to use for storing the metric data table")
	cas.StringVar(&CliConfig.Consistency, "consistency", CliConfig.Consistency, "write consistency (any|one|two|three|quorum|all|local_quorum|each_quorum|local_one")
	cas.StringVar(&CliConfig.HostSelectionPolicy, "host-selection-policy", CliConfig.HostSelectionPolicy, "")
	cas.StringVar(&CliConfig.Timeout, "timeout", CliConfig.Timeout, "cassandra timeout")
	cas.IntVar(&CliConfig.ReadConcurrency, "read-concurrency", CliConfig.ReadConcurrency, "max number of concurrent reads to cassandra.")
	cas.IntVar(&CliConfig.WriteConcurrency, "write-concurrency", CliConfig.WriteConcurrency, "max number of concurrent writes to cassandra.")
	cas.IntVar(&CliConfig.ReadQueueSize, "read-queue-size", CliConfig.ReadQueueSize, "max number of outstanding reads before reads will be dropped. This is important if you run queries that result in many reads in parallel.")
	cas.IntVar(&CliConfig.WriteQueueSize, "write-queue-size", CliConfig.WriteQueueSize, "write queue size per cassandra worker. should be large engough to hold all at least the total number of series expected, divided by how many workers you have")
	cas.IntVar(&CliConfig.Retries, "retries", CliConfig.Retries, "how many times to retry a query before failing it")
	cas.IntVar(&CliConfig.WindowFactor, "window-factor", CliConfig.WindowFactor, "size of compaction window relative to TTL")
	cas.StringVar(&CliConfig.OmitReadTimeout, "omit-read-timeout", CliConfig.OmitReadTimeout, "if a read is older than this, it will be omitted,  not executed")
	cas.IntVar(&CliConfig.CqlProtocolVersion, "cql-protocol-version", CliConfig.CqlProtocolVersion, "cql protocol version to use")
	cas.BoolVar(&CliConfig.CreateKeyspace, "create-keyspace", CliConfig.CreateKeyspace, "enable the creation of the mdata keyspace and tables, only one node needs this")
	cas.BoolVar(&CliConfig.DisableInitialHostLookup, "disable-initial-host-lookup", CliConfig.DisableInitialHostLookup, "instruct the driver to not attempt to get host info from the system.peers table")
	cas.BoolVar(&CliConfig.SSL, "ssl", CliConfig.SSL, "enable SSL connection to cassandra")
	cas.StringVar(&CliConfig.CaPath, "ca-path", CliConfig.CaPath, "cassandra CA certificate path when using SSL")
	cas.BoolVar(&CliConfig.HostVerification, "host-verification", CliConfig.HostVerification, "host (hostname and server cert) verification when using SSL")
	cas.BoolVar(&CliConfig.Auth, "auth", CliConfig.Auth, "enable cassandra authentication")
	cas.StringVar(&CliConfig.Username, "username", CliConfig.Username, "username for authentication")
	cas.StringVar(&CliConfig.Password, "password", CliConfig.Password, "password for authentication")
	cas.StringVar(&CliConfig.SchemaFile, "schema-file", CliConfig.SchemaFile, "File containing the needed schemas in case database needs initializing")
	cas.DurationVar(&CliConfig.ConnectionCheckInterval, "connection-check-interval", CliConfig.ConnectionCheckInterval, "interval at which to perform a connection check to cassandra, set to 0 to disable.")
	cas.DurationVar(&CliConfig.ConnectionCheckTimeout, "connection-check-timeout", CliConfig.ConnectionCheckTimeout, "maximum total time to wait before considering a connection to cassandra invalid. This value should be higher than connection-check-interval.")
	globalconf.Register("cassandra", cas, flag.ExitOnError)
	return cas
}
<commit_msg>Support MaxChunkSpan config<commit_after>package cassandra

import (
	"errors"
	"flag"
	"fmt"
	"time"

	"github.com/grafana/globalconf"
)

type StoreConfig struct {
	Enabled                  bool
	Addrs                    string
	Keyspace                 string
	Consistency              string
	HostSelectionPolicy      string
	Timeout                  string
	ReadConcurrency          int
	WriteConcurrency         int
	ReadQueueSize            int
	WriteQueueSize           int
	Retries                  int
	WindowFactor             int
	OmitReadTimeout          string
	CqlProtocolVersion       int
	CreateKeyspace           bool
	DisableInitialHostLookup bool
	SSL                      bool
	CaPath                   string
	HostVerification         bool
	Auth                     bool
	Username                 string
	Password                 string
	SchemaFile               string
	ConnectionCheckInterval  time.Duration
	ConnectionCheckTimeout   time.Duration
	MaxChunkSpan             time.Duration
}

// Validate makes sure the StoreConfig settings are valid
func (cfg *StoreConfig) Validate(schemaMaxChunkSpan uint32) error {
	if CliConfig.MaxChunkSpan%time.Second != 0 {
		return errors.New("max-chunkspan must be a whole number of seconds")
	}
	if CliConfig.Enabled {
		if uint32(CliConfig.MaxChunkSpan.Seconds()) < schemaMaxChunkSpan {
			return fmt.Errorf("max-chunkspan must be at least as high as the max chunkspan used in your storage-schemas (which is %d)", schemaMaxChunkSpan)
		}
	}
	return nil
}

// return StoreConfig with default values set.
func NewStoreConfig() *StoreConfig {
	return &StoreConfig{
		Enabled:                  true,
		Addrs:                    "localhost",
		Keyspace:                 "metrictank",
		Consistency:              "one",
		HostSelectionPolicy:      "tokenaware,hostpool-epsilon-greedy",
		Timeout:                  "1s",
		ReadConcurrency:          20,
		WriteConcurrency:         10,
		ReadQueueSize:            200000,
		WriteQueueSize:           100000,
		Retries:                  0,
		WindowFactor:             20,
		OmitReadTimeout:          "60s",
		CqlProtocolVersion:       4,
		CreateKeyspace:           true,
		DisableInitialHostLookup: false,
		SSL:                      false,
		CaPath:                   "/etc/metrictank/ca.pem",
		HostVerification:         true,
		Auth:                     false,
		Username:                 "cassandra",
		Password:                 "cassandra",
		SchemaFile:               "/etc/metrictank/schema-store-cassandra.toml",
		ConnectionCheckInterval:  time.Second * 5,
		ConnectionCheckTimeout:   time.Second * 30,
		MaxChunkSpan:             time.Hour * 24,
	}
}

var CliConfig = NewStoreConfig()

func ConfigSetup() *flag.FlagSet {
	cas := flag.NewFlagSet("cassandra", flag.ExitOnError)
	cas.BoolVar(&CliConfig.Enabled, "enabled", CliConfig.Enabled, "enable the cassandra backend store plugin")
	cas.StringVar(&CliConfig.Addrs, "addrs", CliConfig.Addrs, "cassandra host (may be given multiple times as comma-separated list)")
	cas.StringVar(&CliConfig.Keyspace, "keyspace", CliConfig.Keyspace, "cassandra keyspace to use for storing the metric data table")
	cas.StringVar(&CliConfig.Consistency, "consistency", CliConfig.Consistency, "write consistency (any|one|two|three|quorum|all|local_quorum|each_quorum|local_one")
	cas.StringVar(&CliConfig.HostSelectionPolicy, "host-selection-policy", CliConfig.HostSelectionPolicy, "")
	cas.StringVar(&CliConfig.Timeout, "timeout", CliConfig.Timeout, "cassandra timeout")
	cas.IntVar(&CliConfig.ReadConcurrency, "read-concurrency", CliConfig.ReadConcurrency, "max number of concurrent reads to cassandra.")
	cas.IntVar(&CliConfig.WriteConcurrency, "write-concurrency", CliConfig.WriteConcurrency, "max number of concurrent writes to cassandra.")
	cas.IntVar(&CliConfig.ReadQueueSize, "read-queue-size", CliConfig.ReadQueueSize, "max number of outstanding reads before reads will be dropped. This is important if you run queries that result in many reads in parallel.")
	cas.IntVar(&CliConfig.WriteQueueSize, "write-queue-size", CliConfig.WriteQueueSize, "write queue size per cassandra worker. should be large engough to hold all at least the total number of series expected, divided by how many workers you have")
	cas.IntVar(&CliConfig.Retries, "retries", CliConfig.Retries, "how many times to retry a query before failing it")
	cas.IntVar(&CliConfig.WindowFactor, "window-factor", CliConfig.WindowFactor, "size of compaction window relative to TTL")
	cas.StringVar(&CliConfig.OmitReadTimeout, "omit-read-timeout", CliConfig.OmitReadTimeout, "if a read is older than this, it will be omitted,  not executed")
	cas.IntVar(&CliConfig.CqlProtocolVersion, "cql-protocol-version", CliConfig.CqlProtocolVersion, "cql protocol version to use")
	cas.BoolVar(&CliConfig.CreateKeyspace, "create-keyspace", CliConfig.CreateKeyspace, "enable the creation of the mdata keyspace and tables, only one node needs this")
	cas.BoolVar(&CliConfig.DisableInitialHostLookup, "disable-initial-host-lookup", CliConfig.DisableInitialHostLookup, "instruct the driver to not attempt to get host info from the system.peers table")
	cas.BoolVar(&CliConfig.SSL, "ssl", CliConfig.SSL, "enable SSL connection to cassandra")
	cas.StringVar(&CliConfig.CaPath, "ca-path", CliConfig.CaPath, "cassandra CA certificate path when using SSL")
	cas.BoolVar(&CliConfig.HostVerification, "host-verification", CliConfig.HostVerification, "host (hostname and server cert) verification when using SSL")
	cas.BoolVar(&CliConfig.Auth, "auth", CliConfig.Auth, "enable cassandra authentication")
	cas.StringVar(&CliConfig.Username, "username", CliConfig.Username, "username for authentication")
	cas.StringVar(&CliConfig.Password, "password", CliConfig.Password, "password for authentication")
	cas.StringVar(&CliConfig.SchemaFile, "schema-file", CliConfig.SchemaFile, "File containing the needed schemas in case database needs initializing")
	cas.DurationVar(&CliConfig.ConnectionCheckInterval, "connection-check-interval", CliConfig.ConnectionCheckInterval, "interval at which to perform a connection check to cassandra, set to 0 to disable.")
	cas.DurationVar(&CliConfig.ConnectionCheckTimeout, "connection-check-timeout", CliConfig.ConnectionCheckTimeout, "maximum total time to wait before considering a connection to cassandra invalid. This value should be higher than connection-check-interval.")
	cas.DurationVar(&CliConfig.MaxChunkSpan, "max-chunkspan", CliConfig.MaxChunkSpan, "Maximum chunkspan size used.")
	globalconf.Register("cassandra", cas, flag.ExitOnError)
	return cas
}
<|endoftext|>


<commit_before>// // This code is based on encoding/json and gorilla/schema

package encoding

import (

	// "errors"
	"errors"
	"reflect"
	"runtime"

	// "runtime"
	"strconv"
	"strings"
)

var byteSliceType = reflect.TypeOf([]byte(nil))

// Decode decodes map[string]interface{} into a struct. The first parameter
// must be a pointer.
func Decode(dst interface{}, src interface{}) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			if v, ok := r.(string); ok {
				err = errors.New(v)
			} else {
				err = r.(error)
			}
		}
	}()

	dv := reflect.ValueOf(dst)
	sv := reflect.ValueOf(src)
	if dv.Kind() != reflect.Ptr || dv.IsNil() {
		return &InvalidDecodeError{reflect.TypeOf(dst)}
	}

	decode(dv, sv)
	return nil
}

// decode decodes the source value into the destination value
func decode(dv, sv reflect.Value) {
	if dv.IsValid() {
		val := indirect(dv, false)
		val.Set(reflect.Zero(val.Type()))
	}

	if dv.IsValid() && sv.IsValid() {
		// Ensure that the source value has the correct type of parsing
		if sv.Kind() == reflect.Interface {
			sv = reflect.ValueOf(sv.Interface())
		}

		switch sv.Kind() {
		default:
			decodeLiteral(dv, sv)
		case reflect.Slice, reflect.Array:
			decodeArray(dv, sv)
		case reflect.Map:
			decodeObject(dv, sv)
		case reflect.Struct:
			dv = indirect(dv, false)
			dv.Set(sv)
		}
	}
}

// decodeLiteral decodes the source value into the destination value. This function
// is used to decode literal values.
func decodeLiteral(dv reflect.Value, sv reflect.Value) {
	dv = indirect(dv, true)

	// Special case for if sv is nil:
	switch sv.Kind() {
	case reflect.Invalid:
		dv.Set(reflect.Zero(dv.Type()))
		return
	}

	// Attempt to convert the value from the source type to the destination type
	switch value := sv.Interface().(type) {
	case nil:
		switch dv.Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
			dv.Set(reflect.Zero(dv.Type()))
		}
	case bool:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"bool", dv.Type()})
			return
		case reflect.Bool:
			dv.SetBool(value)
		case reflect.String:
			dv.SetString(strconv.FormatBool(value))
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(value))
			} else {
				panic(&DecodeTypeError{"bool", dv.Type()})
				return
			}
		}

	case string:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"string", dv.Type()})
			return
		case reflect.String:
			dv.SetString(value)
		case reflect.Bool:
			b, err := strconv.ParseBool(value)
			if err != nil {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetBool(b)
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.ParseInt(value, 10, 64)
			if err != nil || dv.OverflowInt(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetInt(n)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.ParseUint(value, 10, 64)
			if err != nil || dv.OverflowUint(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetUint(n)
		case reflect.Float32, reflect.Float64:
			n, err := strconv.ParseFloat(value, 64)
			if err != nil || dv.OverflowFloat(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetFloat(n)
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(string(value)))
			} else {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
		}

	case int, int8, int16, int32, int64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"int", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"int", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Int()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Int()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Int()))
		case reflect.String:
			dv.SetString(strconv.FormatInt(int64(reflect.ValueOf(value).Int()), 10))
		}
	case uint, uint8, uint16, uint32, uint64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"uint", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"uint", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Uint()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Uint()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Uint()))
		case reflect.String:
			dv.SetString(strconv.FormatUint(uint64(reflect.ValueOf(value).Uint()), 10))
		}
	case float32, float64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"float", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"float", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Float()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Float()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Float()))
		case reflect.String:
			dv.SetString(strconv.FormatFloat(float64(reflect.ValueOf(value).Float()), 'g', -1, 64))
		}
	default:
		panic(&DecodeTypeError{sv.Type().String(), dv.Type()})
		return
	}

	return
}

// decodeArray decodes the source value into the destination value. This function
// is used when the source value is a slice or array.
func decodeArray(dv reflect.Value, sv reflect.Value) {
	dv = indirect(dv, false)
	dt := dv.Type()

	// Ensure that the dest is also a slice or array
	switch dt.Kind() {
	case reflect.Interface:
		if dv.NumMethod() == 0 {
			// Decoding into nil interface?  Switch to non-reflect code.
			dv.Set(reflect.ValueOf(decodeArrayInterface(sv)))

			return
		}
		// Otherwise it's invalid.
		fallthrough
	default:
		panic(&DecodeTypeError{"array", dv.Type()})
		return
	case reflect.Array:
	case reflect.Slice:
		if sv.Type() == byteSliceType {
			dv.SetBytes(sv.Bytes())
			return
		}

		break
	}

	// Iterate through the slice/array and decode each element before adding it
	// to the dest slice/array
	i := 0
	for i < sv.Len() {
		if dv.Kind() == reflect.Slice {
			// Get element of array, growing if necessary.
			if i >= dv.Cap() {
				newcap := dv.Cap() + dv.Cap()/2
				if newcap < 4 {
					newcap = 4
				}
				newdv := reflect.MakeSlice(dv.Type(), dv.Len(), newcap)
				reflect.Copy(newdv, dv)
				dv.Set(newdv)
			}
			if i >= dv.Len() {
				dv.SetLen(i + 1)
			}
		}

		if i < dv.Len() {
			// Decode into element.
			decode(dv.Index(i), sv.Index(i))
		} else {
			// Ran out of fixed array: skip.
			decode(reflect.Value{}, sv.Index(i))
		}

		i++
	}

	// Ensure that the destination is the correct size
	if i < dv.Len() {
		if dv.Kind() == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(dv.Type().Elem())
			for ; i < dv.Len(); i++ {
				dv.Index(i).Set(z)
			}
		} else {
			dv.SetLen(i)
		}
	}
}

// decodeObject decodes the source value into the destination value. This function
// is used when the source value is a map or struct.
func decodeObject(dv reflect.Value, sv reflect.Value) (err error) {
	dv = indirect(dv, false)
	dt := dv.Type()

	// Decoding into nil interface?  Switch to non-reflect code.
	if dv.Kind() == reflect.Interface && dv.NumMethod() == 0 {
		dv.Set(reflect.ValueOf(decodeObjectInterface(sv)))
		return nil
	}

	// Check type of target: struct or map[string]T
	switch dv.Kind() {
	case reflect.Map:
		// map must have string kind
		if dt.Key().Kind() != reflect.String {
			panic(&DecodeTypeError{"object", dv.Type()})
			break
		}
		if dv.IsNil() {
			dv.Set(reflect.MakeMap(dt))
		}
	case reflect.Struct:
	default:
		panic(&DecodeTypeError{"object", dv.Type()})
		return
	}

	var mapElem reflect.Value

	for _, key := range sv.MapKeys() {
		var subdv reflect.Value
		var subsv reflect.Value = sv.MapIndex(key)

		skey := key.Interface().(string)

		if dv.Kind() == reflect.Map {
			elemType := dv.Type().Elem()
			if !mapElem.IsValid() {
				mapElem = reflect.New(elemType).Elem()
			} else {
				mapElem.Set(reflect.Zero(elemType))
			}
			subdv = mapElem
		} else {
			var f *field
			fields := cachedTypeFields(dv.Type())
			for i := range fields {
				ff := &fields[i]
				if ff.name == skey {
					f = ff
					break
				}
				if f == nil && strings.EqualFold(ff.name, skey) {
					f = ff
				}
			}
			if f != nil {
				subdv = dv
				for _, i := range f.index {
					if subdv.Kind() == reflect.Ptr {
						if subdv.IsNil() {
							subdv.Set(reflect.New(subdv.Type().Elem()))
						}
						subdv = subdv.Elem()
					}
					subdv = subdv.Field(i)
				}
			}
		}

		decode(subdv, subsv)

		if dv.Kind() == reflect.Map {
			kv := reflect.ValueOf(skey)
			dv.SetMapIndex(kv, subdv)
		}
	}

	return nil
}

// The following methods are simplified versions of those above designed to use
// less reflection

// decodeInterface decodes the source value into interface{}
func decodeInterface(sv reflect.Value) interface{} {
	// Ensure that the source value has the correct type of parsing
	if sv.Kind() == reflect.Interface {
		sv = reflect.ValueOf(sv.Interface())
	}

	switch sv.Kind() {
	case reflect.Slice, reflect.Array:
		return decodeArrayInterface(sv)
	case reflect.Map:
		return decodeObjectInterface(sv)
	default:
		return decodeLiteralInterface(sv)
	}
}

// decodeArrayInterface decodes the source value into []interface{}
func decodeArrayInterface(sv reflect.Value) interface{} {
	if sv.Type() == byteSliceType {
		return sv.Bytes()
	}

	arr := []interface{}{}
	for i := 0; i < sv.Len(); i++ {
		arr = append(arr, decodeInterface(sv.Index(i)))
	}
	return arr
}

// decodeObjectInterface decodes the source value into map[string]interface{}
func decodeObjectInterface(sv reflect.Value) interface{} {
	m := map[string]interface{}{}
	for _, key := range sv.MapKeys() {
		m[key.Interface().(string)] = decodeInterface(sv.MapIndex(key))
	}
	return m
}

// decodeLiteralInterface returns the interface of the source value
func decodeLiteralInterface(sv reflect.Value) interface{} {
	if !sv.IsValid() {
		return nil
	}

	return sv.Interface()
}

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
func indirect(v reflect.Value, decodeNull bool) reflect.Value {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodeNull || e.Elem().Kind() == reflect.Ptr) {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}
<commit_msg>Fixed empty slice decoding test<commit_after>// // This code is based on encoding/json and gorilla/schema

package encoding

import (

	// "errors"
	"errors"
	"reflect"
	"runtime"

	// "runtime"
	"strconv"
	"strings"
)

var byteSliceType = reflect.TypeOf([]byte(nil))

// Decode decodes map[string]interface{} into a struct. The first parameter
// must be a pointer.
func Decode(dst interface{}, src interface{}) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			if v, ok := r.(string); ok {
				err = errors.New(v)
			} else {
				err = r.(error)
			}
		}
	}()

	dv := reflect.ValueOf(dst)
	sv := reflect.ValueOf(src)
	if dv.Kind() != reflect.Ptr || dv.IsNil() {
		return &InvalidDecodeError{reflect.TypeOf(dst)}
	}

	decode(dv, sv)

	return nil
}

// decode decodes the source value into the destination value
func decode(dv, sv reflect.Value) {
	if dv.IsValid() {
		val := indirect(dv, false)
		val.Set(reflect.Zero(val.Type()))
	}

	if dv.IsValid() && sv.IsValid() {
		// Ensure that the source value has the correct type of parsing
		if sv.Kind() == reflect.Interface {
			sv = reflect.ValueOf(sv.Interface())
		}

		switch sv.Kind() {
		default:
			decodeLiteral(dv, sv)
		case reflect.Slice, reflect.Array:
			decodeArray(dv, sv)
		case reflect.Map:
			decodeObject(dv, sv)
		case reflect.Struct:
			dv = indirect(dv, false)
			dv.Set(sv)
		}
	}
}

// decodeLiteral decodes the source value into the destination value. This function
// is used to decode literal values.
func decodeLiteral(dv reflect.Value, sv reflect.Value) {
	dv = indirect(dv, true)

	// Special case for if sv is nil:
	switch sv.Kind() {
	case reflect.Invalid:
		dv.Set(reflect.Zero(dv.Type()))
		return
	}

	// Attempt to convert the value from the source type to the destination type
	switch value := sv.Interface().(type) {
	case nil:
		switch dv.Kind() {
		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
			dv.Set(reflect.Zero(dv.Type()))
		}
	case bool:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"bool", dv.Type()})
			return
		case reflect.Bool:
			dv.SetBool(value)
		case reflect.String:
			dv.SetString(strconv.FormatBool(value))
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(value))
			} else {
				panic(&DecodeTypeError{"bool", dv.Type()})
				return
			}
		}

	case string:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"string", dv.Type()})
			return
		case reflect.String:
			dv.SetString(value)
		case reflect.Bool:
			b, err := strconv.ParseBool(value)
			if err != nil {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetBool(b)
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			n, err := strconv.ParseInt(value, 10, 64)
			if err != nil || dv.OverflowInt(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetInt(n)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			n, err := strconv.ParseUint(value, 10, 64)
			if err != nil || dv.OverflowUint(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetUint(n)
		case reflect.Float32, reflect.Float64:
			n, err := strconv.ParseFloat(value, 64)
			if err != nil || dv.OverflowFloat(n) {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
			dv.SetFloat(n)
		case reflect.Interface:
			if dv.NumMethod() == 0 {
				dv.Set(reflect.ValueOf(string(value)))
			} else {
				panic(&DecodeTypeError{"string", dv.Type()})
				return
			}
		}

	case int, int8, int16, int32, int64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"int", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"int", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Int()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Int()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Int()))
		case reflect.String:
			dv.SetString(strconv.FormatInt(int64(reflect.ValueOf(value).Int()), 10))
		}
	case uint, uint8, uint16, uint32, uint64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"uint", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"uint", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Uint()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Uint()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Uint()))
		case reflect.String:
			dv.SetString(strconv.FormatUint(uint64(reflect.ValueOf(value).Uint()), 10))
		}
	case float32, float64:
		switch dv.Kind() {
		default:
			panic(&DecodeTypeError{"float", dv.Type()})
			return
		case reflect.Interface:
			if dv.NumMethod() != 0 {
				panic(&DecodeTypeError{"float", dv.Type()})
				return
			}
			dv.Set(reflect.ValueOf(value))

		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			dv.SetInt(int64(reflect.ValueOf(value).Float()))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			dv.SetUint(uint64(reflect.ValueOf(value).Float()))
		case reflect.Float32, reflect.Float64:
			dv.SetFloat(float64(reflect.ValueOf(value).Float()))
		case reflect.String:
			dv.SetString(strconv.FormatFloat(float64(reflect.ValueOf(value).Float()), 'g', -1, 64))
		}
	default:
		panic(&DecodeTypeError{sv.Type().String(), dv.Type()})
		return
	}

	return
}

// decodeArray decodes the source value into the destination value. This function
// is used when the source value is a slice or array.
func decodeArray(dv reflect.Value, sv reflect.Value) {
	dv = indirect(dv, false)
	dt := dv.Type()

	// Ensure that the dest is also a slice or array
	switch dt.Kind() {
	case reflect.Interface:
		if dv.NumMethod() == 0 {
			// Decoding into nil interface?  Switch to non-reflect code.
			dv.Set(reflect.ValueOf(decodeArrayInterface(sv)))

			return
		}
		// Otherwise it's invalid.
		fallthrough
	default:
		panic(&DecodeTypeError{"array", dv.Type()})
		return
	case reflect.Array:
	case reflect.Slice:
		if sv.Type() == byteSliceType {
			dv.SetBytes(sv.Bytes())
			return
		}

		newdv := reflect.MakeSlice(dv.Type(), dv.Len(), dv.Cap())
		dv.Set(newdv)

		break
	}

	// Iterate through the slice/array and decode each element before adding it
	// to the dest slice/array
	i := 0
	for i < sv.Len() {
		if dv.Kind() == reflect.Slice {
			// Get element of array, growing if necessary.
			if i >= dv.Cap() {
				newcap := dv.Cap() + dv.Cap()/2
				if newcap < 4 {
					newcap = 4
				}
				newdv := reflect.MakeSlice(dv.Type(), dv.Len(), newcap)
				reflect.Copy(newdv, dv)
				dv.Set(newdv)
			}
			if i >= dv.Len() {
				dv.SetLen(i + 1)
			}
		}

		if i < dv.Len() {
			// Decode into element.
			decode(dv.Index(i), sv.Index(i))
		} else {
			// Ran out of fixed array: skip.
			decode(reflect.Value{}, sv.Index(i))
		}

		i++
	}

	// Ensure that the destination is the correct size
	if i < dv.Len() {
		if dv.Kind() == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(dv.Type().Elem())
			for ; i < dv.Len(); i++ {
				dv.Index(i).Set(z)
			}
		} else {
			dv.SetLen(i)
		}
	}
}

// decodeObject decodes the source value into the destination value. This function
// is used when the source value is a map or struct.
func decodeObject(dv reflect.Value, sv reflect.Value) (err error) {
	dv = indirect(dv, false)
	dt := dv.Type()

	// Decoding into nil interface?  Switch to non-reflect code.
	if dv.Kind() == reflect.Interface && dv.NumMethod() == 0 {
		dv.Set(reflect.ValueOf(decodeObjectInterface(sv)))
		return nil
	}

	// Check type of target: struct or map[string]T
	switch dv.Kind() {
	case reflect.Map:
		// map must have string kind
		if dt.Key().Kind() != reflect.String {
			panic(&DecodeTypeError{"object", dv.Type()})
			break
		}
		if dv.IsNil() {
			dv.Set(reflect.MakeMap(dt))
		}
	case reflect.Struct:
	default:
		panic(&DecodeTypeError{"object", dv.Type()})
		return
	}

	var mapElem reflect.Value

	for _, key := range sv.MapKeys() {
		var subdv reflect.Value
		var subsv reflect.Value = sv.MapIndex(key)

		skey := key.Interface().(string)

		if dv.Kind() == reflect.Map {
			elemType := dv.Type().Elem()
			if !mapElem.IsValid() {
				mapElem = reflect.New(elemType).Elem()
			} else {
				mapElem.Set(reflect.Zero(elemType))
			}
			subdv = mapElem
		} else {
			var f *field
			fields := cachedTypeFields(dv.Type())
			for i := range fields {
				ff := &fields[i]
				if ff.name == skey {
					f = ff
					break
				}
				if f == nil && strings.EqualFold(ff.name, skey) {
					f = ff
				}
			}
			if f != nil {
				subdv = dv
				for _, i := range f.index {
					if subdv.Kind() == reflect.Ptr {
						if subdv.IsNil() {
							subdv.Set(reflect.New(subdv.Type().Elem()))
						}
						subdv = subdv.Elem()
					}
					subdv = subdv.Field(i)
				}
			}
		}

		decode(subdv, subsv)

		if dv.Kind() == reflect.Map {
			kv := reflect.ValueOf(skey)
			dv.SetMapIndex(kv, subdv)
		}
	}

	return nil
}

// The following methods are simplified versions of those above designed to use
// less reflection

// decodeInterface decodes the source value into interface{}
func decodeInterface(sv reflect.Value) interface{} {
	// Ensure that the source value has the correct type of parsing
	if sv.Kind() == reflect.Interface {
		sv = reflect.ValueOf(sv.Interface())
	}

	switch sv.Kind() {
	case reflect.Slice, reflect.Array:
		return decodeArrayInterface(sv)
	case reflect.Map:
		return decodeObjectInterface(sv)
	default:
		return decodeLiteralInterface(sv)
	}
}

// decodeArrayInterface decodes the source value into []interface{}
func decodeArrayInterface(sv reflect.Value) interface{} {
	if sv.Type() == byteSliceType {
		return sv.Bytes()
	}

	arr := []interface{}{}
	for i := 0; i < sv.Len(); i++ {
		arr = append(arr, decodeInterface(sv.Index(i)))
	}
	return arr
}

// decodeObjectInterface decodes the source value into map[string]interface{}
func decodeObjectInterface(sv reflect.Value) interface{} {
	m := map[string]interface{}{}
	for _, key := range sv.MapKeys() {
		m[key.Interface().(string)] = decodeInterface(sv.MapIndex(key))
	}
	return m
}

// decodeLiteralInterface returns the interface of the source value
func decodeLiteralInterface(sv reflect.Value) interface{} {
	if !sv.IsValid() {
		return nil
	}

	return sv.Interface()
}

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
func indirect(v reflect.Value, decodeNull bool) reflect.Value {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodeNull || e.Elem().Kind() == reflect.Ptr) {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}
<|endoftext|>


<commit_before>package encoding

import (
	"bytes"
	"io"
	"io/ioutil"
	"net/http"

	"golang.org/x/net/context"

	httptransport "github.com/go-kit/kit/transport/http"
)

// Encoder is anything that, given an interface, can store an encoding of the
// structure passed into Encode.
type Encoder interface {
	// Encode takes an interface, and should be able to translate it within the
	// given encoding, or it will fail with an error.
	Encode(interface{}) error
}

// GenerateEncoder is a function which takes an io.Writer, and returns an
// Encoder
type GenerateEncoder func(w io.Writer) Encoder

// MakeRequestEncoder takes a GenerateEncoder and returns an
// httptransport.EncodeRequestFunc
func MakeRequestEncoder(gen GenerateEncoder) httptransport.EncodeRequestFunc {
	return func(ctx context.Context, r *http.Request, request interface{}) error {
		var buf bytes.Buffer
		err := gen(&buf).Encode(request)
		r.Body = ioutil.NopCloser(&buf)
		return err
	}
}

// MakeResponseEncoder takes a GenerateEncoder and returns an
// httpstransport.EncodeResponseFunc
func MakeResponseEncoder(gen GenerateEncoder) httptransport.EncodeResponseFunc {
	return func(ctx context.Context, w http.ResponseWriter, response interface{}) error {
		if e, ok := response.(error); ok {
			// we have an error, we'll wrap it, to ensure it's transmission
			// encode-ability

			we := WrapError(e)
			return gen(w).Encode(we)
		}

		return gen(w).Encode(response)
	}
}
<commit_msg>add MakeErrorEncoder to easily wrap the Encoder specified<commit_after>package encoding

import (
	"bytes"
	"io"
	"io/ioutil"
	"net/http"

	"golang.org/x/net/context"

	httptransport "github.com/go-kit/kit/transport/http"
)

// Encoder is anything that, given an interface, can store an encoding of the
// structure passed into Encode.
type Encoder interface {
	// Encode takes an interface, and should be able to translate it within the
	// given encoding, or it will fail with an error.
	Encode(interface{}) error
}

// GenerateEncoder is a function which takes an io.Writer, and returns an
// Encoder
type GenerateEncoder func(w io.Writer) Encoder

// MakeRequestEncoder takes a GenerateEncoder and returns an
// httptransport.EncodeRequestFunc
func MakeRequestEncoder(gen GenerateEncoder) httptransport.EncodeRequestFunc {
	return func(ctx context.Context, r *http.Request, request interface{}) error {
		var buf bytes.Buffer
		err := gen(&buf).Encode(request)
		r.Body = ioutil.NopCloser(&buf)
		return err
	}
}

// MakeResponseEncoder takes a GenerateEncoder and returns an
// httpstransport.EncodeResponseFunc
func MakeResponseEncoder(gen GenerateEncoder) httptransport.EncodeResponseFunc {
	return func(ctx context.Context, w http.ResponseWriter, response interface{}) error {
		if e, ok := response.(error); ok {
			// we have an error, we'll wrap it, to ensure it's transmission
			// encode-ability

			we := WrapError(e)
			return gen(w).Encode(we)
		}

		return gen(w).Encode(response)
	}
}

// MakeErrorEncoder will take a generic GenerateEncoder function and will
// return an ErrorEncoder
func MakeErrorEncoder(gen RequestResponseEncoding) httptransport.ErrorEncoder {
	return func(ctx context.Context, err error, w http.ResponseWriter ) {
		gen.EncodeResponse()(ctx,w,err)
	}
}<|endoftext|>


<commit_before>package engine

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_NewArea_InvalidSize(t *testing.T) {
	var area *Area
	var err error

	area, err = NewArea(0, 0)
	require.NotNil(t, err)
	require.Nil(t, area)

	area, err = NewArea(1, 0)
	require.NotNil(t, err)
	require.Nil(t, area)

	area, err = NewArea(0, 1)
	require.NotNil(t, err)
	require.Nil(t, area)
}

func Test_NewArea_ValidSize(t *testing.T) {
	var area *Area
	var err error

	area, err = NewArea(1, 1)
	require.Nil(t, err)
	require.NotNil(t, area)

	area, err = NewArea(100, 100)
	require.Nil(t, err)
	require.NotNil(t, area)
}

func Test_Area_Navigate_SquareArea100x100(t *testing.T) {
	tests := []struct {
		inputDot    *Dot
		inputDir    Direction
		inputDis    uint8
		expectedDot *Dot
		expectedErr error
	}{
		{&Dot{0, 0}, DirectionWest, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionEast, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionNorth, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionSouth, 0, &Dot{0, 0}, nil},

		{&Dot{0, 0}, DirectionWest, 1, &Dot{99, 0}, nil},
		{&Dot{0, 0}, DirectionEast, 1, &Dot{1, 0}, nil},
		{&Dot{0, 0}, DirectionNorth, 1, &Dot{0, 99}, nil},
		{&Dot{0, 0}, DirectionSouth, 1, &Dot{0, 1}, nil},
	}

	area := Area{
		width:  100,
		height: 100,
	}

	for i, test := range tests {
		actualDot, actualErr := area.Navigate(test.inputDot, test.inputDir, test.inputDis)
		require.Equal(t, test.expectedDot, actualDot, i)
		require.Equal(t, test.expectedErr, actualErr, i)
	}
}
<commit_msg>Fix area test output<commit_after>package engine

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_NewArea_InvalidSize(t *testing.T) {
	var area *Area
	var err error

	area, err = NewArea(0, 0)
	require.NotNil(t, err)
	require.Nil(t, area)

	area, err = NewArea(1, 0)
	require.NotNil(t, err)
	require.Nil(t, area)

	area, err = NewArea(0, 1)
	require.NotNil(t, err)
	require.Nil(t, area)
}

func Test_NewArea_ValidSize(t *testing.T) {
	var area *Area
	var err error

	area, err = NewArea(1, 1)
	require.Nil(t, err)
	require.NotNil(t, area)

	area, err = NewArea(100, 100)
	require.Nil(t, err)
	require.NotNil(t, area)
}

func Test_Area_Navigate_SquareArea100x100(t *testing.T) {
	tests := []struct {
		inputDot    *Dot
		inputDir    Direction
		inputDis    uint8
		expectedDot *Dot
		expectedErr error
	}{
		{&Dot{0, 0}, DirectionWest, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionEast, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionNorth, 0, &Dot{0, 0}, nil},
		{&Dot{0, 0}, DirectionSouth, 0, &Dot{0, 0}, nil},

		{&Dot{0, 0}, DirectionWest, 1, &Dot{99, 0}, nil},
		{&Dot{0, 0}, DirectionEast, 1, &Dot{1, 0}, nil},
		{&Dot{0, 0}, DirectionNorth, 1, &Dot{0, 99}, nil},
		{&Dot{0, 0}, DirectionSouth, 1, &Dot{0, 1}, nil},
	}

	area := Area{
		width:  100,
		height: 100,
	}

	for i, test := range tests {
		actualDot, actualErr := area.Navigate(test.inputDot, test.inputDir, test.inputDis)
		require.Equal(t, test.expectedDot, actualDot, fmt.Sprintf("number %d", i))
		require.Equal(t, test.expectedErr, actualErr, fmt.Sprintf("number %d", i))
	}
}
<|endoftext|>