<commit_before>package goa

import (
	"bufio"
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"io"
	"mime"
	"net/http"
	"sync"

	"github.com/golang/gddo/httputil"
)

type (
	// A DecoderFactory generates custom decoders
	DecoderFactory interface {
		NewDecoder(r io.Reader) Decoder
	}

	// A Decoder unmarshals an io.Reader into an interface
	Decoder interface {
		Decode(v interface{}) error
	}

	// The ResettableDecoder is used to determine whether or not a Decoder can be reset and
	// thus safely reused in a sync.Pool
	ResettableDecoder interface {
		Decoder
		Reset(r io.Reader)
	}

	// decoderPool smartly determines whether to instantiate a new Decoder or reuse
	// one from a sync.Pool
	decoderPool struct {
		factory DecoderFactory
		pool    *sync.Pool
	}

	// A EncoderFactory generates custom encoders
	EncoderFactory interface {
		NewEncoder(w io.Writer) Encoder
	}

	// An Encoder marshals from an interface into an io.Writer
	Encoder interface {
		Encode(v interface{}) error
	}

	// The ResettableEncoder is used to determine whether or not a Encoder can be reset and
	// thus safely reused in a sync.Pool
	ResettableEncoder interface {
		Encoder
		Reset(w io.Writer)
	}

	// encoderPool smartly determines whether to instantiate a new Encoder or reuse
	// one from a sync.Pool
	encoderPool struct {
		factory EncoderFactory
		pool    *sync.Pool
	}

	// jsonFactory uses encoding/json to act as an DecoderFactory and EncoderFactory
	jsonFactory struct{}

	// xmlFactory uses encoding/xml to act as an DecoderFactory and EncoderFactory
	xmlFactory struct{}

	// gobFactory uses encoding/gob to act as an DecoderFactory and EncoderFactory
	gobFactory struct{}

	// // Unmarshaler is the interface implemented by objects that can unmarshal themselves.
	// // The input can be assumed to be a valid encoding that matches the Content-Type request header.
	// // Unmarshal must copy the data if it wishes to retain the data after returning.
	// Unmarshaler interface {
	// 	Unmarshal(v interface{}, shouldUnmarshal bool) error
	// }
)

var (
	// JSONContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/json to unmarshal unless overwritten using SetDecoder
	JSONContentTypes = []string{"application/json", "application/text+json"}

	// XMLContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/xml to unmarshal unless overwritten using SetDecoder
	XMLContentTypes = []string{"application/xml"}

	// GobContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/gob to unmarshal unless overwritten using SetDecoder
	GobContentTypes = []string{"application/gob"}
)

// initEncoding initializes all the decoder/encoder pools with the Content-Types found
// in JSONContentTypes and GobContentTypes. JSON is set as the default decoder.
func (app *Application) initEncoding() {
	// initialize maps
	contentTypeCount := len(JSONContentTypes) + len(XMLContentTypes) + len(GobContentTypes)
	app.decoderPools = make(map[string]*decoderPool, contentTypeCount)
	app.encoderPools = make(map[string]*encoderPool, contentTypeCount)

	// Add json support
	jf := &jsonFactory{}
	app.SetDecoder(jf, true, JSONContentTypes...)
	app.SetEncoder(jf, true, JSONContentTypes...)

	// Add xml support
	xf := &xmlFactory{}
	app.SetDecoder(xf, false, XMLContentTypes...)
	app.SetEncoder(xf, false, XMLContentTypes...)

	// Add gob support
	gf := &gobFactory{}
	app.SetDecoder(gf, false, GobContentTypes...)
	app.SetEncoder(gf, false, GobContentTypes...)
}

// DecodeRequest uses registered Decoders to unmarshal the request body based on
// the request `Content-Type` header
func (app *Application) DecodeRequest(ctx *Context, v interface{}) error {
	body := ctx.Request().Body
	contentType := ctx.Request().Header.Get("Content-Type")
	defer body.Close()

	var p *decoderPool
	if contentType == "" {
		// Default to JSON
		contentType = "application/json"
	} else {
		if mediaType, _, err := mime.ParseMediaType(contentType); err == nil {
			contentType = mediaType
		}
	}
	p = app.decoderPools[contentType]

	// Do not attempt to decode request bodies for which no decoder has been setup.
	// These may be handled differently by the service.
	if p != nil {
		// the decoderPool will handle whether or not a pool is actually in use
		decoder := p.Get(body)
		if err := decoder.Decode(v); err != nil {
			ctx.Error(err.Error(), "ContentType", contentType)
			return err
		}
		p.Put(decoder)
	}

	return nil
}

func detectContentType(ctx *Context, body io.Reader) string {
	bodyBuf := bufio.NewReader(body)
	// http.DetectContentType uses a max of 512 bytes
	peekSize := 512
	if bodyBuf.Buffered() < peekSize {
		peekSize = bodyBuf.Buffered()
	}
	b, err := bodyBuf.Peek(peekSize)
	if err != nil {
		return "*/*"
	}

	return http.DetectContentType(b)
}

// SetDecoder sets a specific decoder to be used for the specified content types. If
// a decoder is already registered, it will be overwritten.
func (app *Application) SetDecoder(f DecoderFactory, version string, makeDefault bool, contentTypes ...string) {
	p := newDecodePool(f)

	for _, contentType := range contentTypes {
		mediaType, _, err := mime.ParseMediaType(contentType)
		if err != nil {
			mediaType = contentType
		}
		app.decoderPools[mediaType] = p
	}

	if makeDefault {
		app.decoderPools["*/*"] = p
	}
}

// newDecodePool checks to see if the DecoderFactory returns reusable decoders
// and if so, creates a pool
func newDecodePool(f DecoderFactory) *decoderPool {
	// get a new decoder and type assert to see if it can be reset
	decoder := f.NewDecoder(nil)
	rd, ok := decoder.(ResettableDecoder)

	p := &decoderPool{
		factory: f,
	}

	// if the decoder can be reset, create a pool and put the typed decoder in
	if ok {
		p.pool = &sync.Pool{
			New: func() interface{} { return f.NewDecoder(nil) },
		}
		p.pool.Put(rd)
	}

	return p
}

// Get returns an already reset Decoder from the pool if possible
// or creates a new one if necessary
func (p *decoderPool) Get(r io.Reader) Decoder {
	if p.pool == nil {
		return p.factory.NewDecoder(r)
	}

	decoder := p.pool.Get().(ResettableDecoder)
	decoder.Reset(r)
	return decoder
}

// Put returns a Decoder into the pool if possible
func (p *decoderPool) Put(d Decoder) {
	if p.pool == nil {
		return
	}
	p.pool.Put(d)
}

// EncodeResponse uses registered Encoders to marshal the response body based on the request
// `Accept` header and writes it to the http.ResponseWriter
func (app *Application) EncodeResponse(ctx *Context, v interface{}) error {
	contentType := httputil.NegotiateContentType(ctx.Request(), app.encodableContentTypes, "*/*")
	p := app.encoderPools[contentType]

	// the encoderPool will handle whether or not a pool is actually in use
	encoder := p.Get(ctx)
	if err := encoder.Encode(v); err != nil {
		// TODO: log out error details
		return err
	}
	p.Put(encoder)

	return nil
}

// SetEncoder sets a specific encoder to be used for the specified content types. If
// a encoder is already registered, it will be overwritten.
func (app *Application) SetEncoder(f EncoderFactory, version string, makeDefault bool, contentTypes ...string) {
	p := newEncodePool(f)
	for _, contentType := range contentTypes {
		mediaType, _, err := mime.ParseMediaType(contentType)
		if err != nil {
			mediaType = contentType
		}
		app.encoderPools[mediaType] = p
	}

	if makeDefault {
		app.encoderPools["*/*"] = p
	}

	// Rebuild a unique index of registered content encoders to be used in EncodeResponse
	app.encodableContentTypes = make([]string, 0, len(app.encoderPools))
	for contentType := range app.encoderPools {
		app.encodableContentTypes = append(app.encodableContentTypes, contentType)
	}

}

// newEncodePool checks to see if the EncoderFactory returns reusable encoders
// and if so, creates a pool
func newEncodePool(f EncoderFactory) *encoderPool {
	// get a new encoder and type assert to see if it can be reset
	encoder := f.NewEncoder(nil)
	re, ok := encoder.(ResettableEncoder)

	p := &encoderPool{
		factory: f,
	}

	// if the encoder can be reset, create a pool and put the typed encoder in
	if ok {
		p.pool = &sync.Pool{
			New: func() interface{} { return f.NewEncoder(nil) },
		}
		p.pool.Put(re)
	}

	return p
}

// Get returns an already reset Encoder from the pool if possible
// or creates a new one if necessary
func (p *encoderPool) Get(w io.Writer) Encoder {
	if p.pool == nil {
		return p.factory.NewEncoder(w)
	}

	encoder := p.pool.Get().(ResettableEncoder)
	encoder.Reset(w)
	return encoder
}

// Put returns a Decoder into the pool if possible
func (p *encoderPool) Put(e Encoder) {
	if p.pool == nil {
		return
	}
	p.pool.Put(e)
}

// NewDecoder returns a new json.Decoder
func (f *jsonFactory) NewDecoder(r io.Reader) Decoder {
	return json.NewDecoder(r)
}

// NewEncoder returns a new json.Encoder
func (f *jsonFactory) NewEncoder(w io.Writer) Encoder {
	return json.NewEncoder(w)
}

// NewDecoder returns a new xml.Decoder
func (f *xmlFactory) NewDecoder(r io.Reader) Decoder {
	return xml.NewDecoder(r)
}

// NewEncoder returns a new xml.Encoder
func (f *xmlFactory) NewEncoder(w io.Writer) Encoder {
	return xml.NewEncoder(w)
}

// NewDecoder returns a new gob.Decoder
func (f *gobFactory) NewDecoder(r io.Reader) Decoder {
	return gob.NewDecoder(r)
}

// NewEncoder returns a new gob.Encoder
func (f *gobFactory) NewEncoder(w io.Writer) Encoder {
	return gob.NewEncoder(w)
}
<commit_msg>Change a encoder to an encoder<commit_after>package goa

import (
	"bufio"
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"io"
	"mime"
	"net/http"
	"sync"

	"github.com/golang/gddo/httputil"
)

type (
	// A DecoderFactory generates custom decoders
	DecoderFactory interface {
		NewDecoder(r io.Reader) Decoder
	}

	// A Decoder unmarshals an io.Reader into an interface
	Decoder interface {
		Decode(v interface{}) error
	}

	// The ResettableDecoder is used to determine whether or not a Decoder can be reset and
	// thus safely reused in a sync.Pool
	ResettableDecoder interface {
		Decoder
		Reset(r io.Reader)
	}

	// decoderPool smartly determines whether to instantiate a new Decoder or reuse
	// one from a sync.Pool
	decoderPool struct {
		factory DecoderFactory
		pool    *sync.Pool
	}

	// A EncoderFactory generates custom encoders
	EncoderFactory interface {
		NewEncoder(w io.Writer) Encoder
	}

	// An Encoder marshals from an interface into an io.Writer
	Encoder interface {
		Encode(v interface{}) error
	}

	// The ResettableEncoder is used to determine whether or not a Encoder can be reset and
	// thus safely reused in a sync.Pool
	ResettableEncoder interface {
		Encoder
		Reset(w io.Writer)
	}

	// encoderPool smartly determines whether to instantiate a new Encoder or reuse
	// one from a sync.Pool
	encoderPool struct {
		factory EncoderFactory
		pool    *sync.Pool
	}

	// jsonFactory uses encoding/json to act as an DecoderFactory and EncoderFactory
	jsonFactory struct{}

	// xmlFactory uses encoding/xml to act as an DecoderFactory and EncoderFactory
	xmlFactory struct{}

	// gobFactory uses encoding/gob to act as an DecoderFactory and EncoderFactory
	gobFactory struct{}

	// // Unmarshaler is the interface implemented by objects that can unmarshal themselves.
	// // The input can be assumed to be a valid encoding that matches the Content-Type request header.
	// // Unmarshal must copy the data if it wishes to retain the data after returning.
	// Unmarshaler interface {
	// 	Unmarshal(v interface{}, shouldUnmarshal bool) error
	// }
)

var (
	// JSONContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/json to unmarshal unless overwritten using SetDecoder
	JSONContentTypes = []string{"application/json", "application/text+json"}

	// XMLContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/xml to unmarshal unless overwritten using SetDecoder
	XMLContentTypes = []string{"application/xml"}

	// GobContentTypes is a slice of default Content-Type headers that will use stdlib
	// encoding/gob to unmarshal unless overwritten using SetDecoder
	GobContentTypes = []string{"application/gob"}
)

// initEncoding initializes all the decoder/encoder pools with the Content-Types found
// in JSONContentTypes and GobContentTypes. JSON is set as the default decoder.
func (app *Application) initEncoding() {
	// initialize maps
	contentTypeCount := len(JSONContentTypes) + len(XMLContentTypes) + len(GobContentTypes)
	app.decoderPools = make(map[string]*decoderPool, contentTypeCount)
	app.encoderPools = make(map[string]*encoderPool, contentTypeCount)

	// Add json support
	jf := &jsonFactory{}
	app.SetDecoder(jf, true, JSONContentTypes...)
	app.SetEncoder(jf, true, JSONContentTypes...)

	// Add xml support
	xf := &xmlFactory{}
	app.SetDecoder(xf, false, XMLContentTypes...)
	app.SetEncoder(xf, false, XMLContentTypes...)

	// Add gob support
	gf := &gobFactory{}
	app.SetDecoder(gf, false, GobContentTypes...)
	app.SetEncoder(gf, false, GobContentTypes...)
}

// DecodeRequest uses registered Decoders to unmarshal the request body based on
// the request `Content-Type` header
func (app *Application) DecodeRequest(ctx *Context, v interface{}) error {
	body := ctx.Request().Body
	contentType := ctx.Request().Header.Get("Content-Type")
	defer body.Close()

	var p *decoderPool
	if contentType == "" {
		// Default to JSON
		contentType = "application/json"
	} else {
		if mediaType, _, err := mime.ParseMediaType(contentType); err == nil {
			contentType = mediaType
		}
	}
	p = app.decoderPools[contentType]

	// Do not attempt to decode request bodies for which no decoder has been setup.
	// These may be handled differently by the service.
	if p != nil {
		// the decoderPool will handle whether or not a pool is actually in use
		decoder := p.Get(body)
		if err := decoder.Decode(v); err != nil {
			ctx.Error(err.Error(), "ContentType", contentType)
			return err
		}
		p.Put(decoder)
	}

	return nil
}

func detectContentType(ctx *Context, body io.Reader) string {
	bodyBuf := bufio.NewReader(body)
	// http.DetectContentType uses a max of 512 bytes
	peekSize := 512
	if bodyBuf.Buffered() < peekSize {
		peekSize = bodyBuf.Buffered()
	}
	b, err := bodyBuf.Peek(peekSize)
	if err != nil {
		return "*/*"
	}

	return http.DetectContentType(b)
}

// SetDecoder sets a specific decoder to be used for the specified content types. If
// a decoder is already registered, it will be overwritten.
func (app *Application) SetDecoder(f DecoderFactory, version string, makeDefault bool, contentTypes ...string) {
	p := newDecodePool(f)

	for _, contentType := range contentTypes {
		mediaType, _, err := mime.ParseMediaType(contentType)
		if err != nil {
			mediaType = contentType
		}
		app.decoderPools[mediaType] = p
	}

	if makeDefault {
		app.decoderPools["*/*"] = p
	}
}

// newDecodePool checks to see if the DecoderFactory returns reusable decoders
// and if so, creates a pool
func newDecodePool(f DecoderFactory) *decoderPool {
	// get a new decoder and type assert to see if it can be reset
	decoder := f.NewDecoder(nil)
	rd, ok := decoder.(ResettableDecoder)

	p := &decoderPool{
		factory: f,
	}

	// if the decoder can be reset, create a pool and put the typed decoder in
	if ok {
		p.pool = &sync.Pool{
			New: func() interface{} { return f.NewDecoder(nil) },
		}
		p.pool.Put(rd)
	}

	return p
}

// Get returns an already reset Decoder from the pool if possible
// or creates a new one if necessary
func (p *decoderPool) Get(r io.Reader) Decoder {
	if p.pool == nil {
		return p.factory.NewDecoder(r)
	}

	decoder := p.pool.Get().(ResettableDecoder)
	decoder.Reset(r)
	return decoder
}

// Put returns a Decoder into the pool if possible
func (p *decoderPool) Put(d Decoder) {
	if p.pool == nil {
		return
	}
	p.pool.Put(d)
}

// EncodeResponse uses registered Encoders to marshal the response body based on the request
// `Accept` header and writes it to the http.ResponseWriter
func (app *Application) EncodeResponse(ctx *Context, v interface{}) error {
	contentType := httputil.NegotiateContentType(ctx.Request(), app.encodableContentTypes, "*/*")
	p := app.encoderPools[contentType]

	// the encoderPool will handle whether or not a pool is actually in use
	encoder := p.Get(ctx)
	if err := encoder.Encode(v); err != nil {
		// TODO: log out error details
		return err
	}
	p.Put(encoder)

	return nil
}

// SetEncoder sets a specific encoder to be used for the specified content types. If
// an encoder is already registered, it will be overwritten.
func (app *Application) SetEncoder(f EncoderFactory, version string, makeDefault bool, contentTypes ...string) {
	p := newEncodePool(f)
	for _, contentType := range contentTypes {
		mediaType, _, err := mime.ParseMediaType(contentType)
		if err != nil {
			mediaType = contentType
		}
		app.encoderPools[mediaType] = p
	}

	if makeDefault {
		app.encoderPools["*/*"] = p
	}

	// Rebuild a unique index of registered content encoders to be used in EncodeResponse
	app.encodableContentTypes = make([]string, 0, len(app.encoderPools))
	for contentType := range app.encoderPools {
		app.encodableContentTypes = append(app.encodableContentTypes, contentType)
	}

}

// newEncodePool checks to see if the EncoderFactory returns reusable encoders
// and if so, creates a pool
func newEncodePool(f EncoderFactory) *encoderPool {
	// get a new encoder and type assert to see if it can be reset
	encoder := f.NewEncoder(nil)
	re, ok := encoder.(ResettableEncoder)

	p := &encoderPool{
		factory: f,
	}

	// if the encoder can be reset, create a pool and put the typed encoder in
	if ok {
		p.pool = &sync.Pool{
			New: func() interface{} { return f.NewEncoder(nil) },
		}
		p.pool.Put(re)
	}

	return p
}

// Get returns an already reset Encoder from the pool if possible
// or creates a new one if necessary
func (p *encoderPool) Get(w io.Writer) Encoder {
	if p.pool == nil {
		return p.factory.NewEncoder(w)
	}

	encoder := p.pool.Get().(ResettableEncoder)
	encoder.Reset(w)
	return encoder
}

// Put returns a Decoder into the pool if possible
func (p *encoderPool) Put(e Encoder) {
	if p.pool == nil {
		return
	}
	p.pool.Put(e)
}

// NewDecoder returns a new json.Decoder
func (f *jsonFactory) NewDecoder(r io.Reader) Decoder {
	return json.NewDecoder(r)
}

// NewEncoder returns a new json.Encoder
func (f *jsonFactory) NewEncoder(w io.Writer) Encoder {
	return json.NewEncoder(w)
}

// NewDecoder returns a new xml.Decoder
func (f *xmlFactory) NewDecoder(r io.Reader) Decoder {
	return xml.NewDecoder(r)
}

// NewEncoder returns a new xml.Encoder
func (f *xmlFactory) NewEncoder(w io.Writer) Encoder {
	return xml.NewEncoder(w)
}

// NewDecoder returns a new gob.Decoder
func (f *gobFactory) NewDecoder(r io.Reader) Decoder {
	return gob.NewDecoder(r)
}

// NewEncoder returns a new gob.Encoder
func (f *gobFactory) NewEncoder(w io.Writer) Encoder {
	return gob.NewEncoder(w)
}
<|endoftext|>


<commit_before>package ecs

import (
	"encoding/base64"
	"encoding/json"
	"strconv"
	"time"

	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/util"
)

// InstanceStatus represents instance status
type InstanceStatus string

// Constants of InstanceStatus
const (
	Creating = InstanceStatus("Creating")
	Running  = InstanceStatus("Running")
	Starting = InstanceStatus("Starting")

	Stopped  = InstanceStatus("Stopped")
	Stopping = InstanceStatus("Stopping")
)

type LockReason string

const (
	LockReasonFinancial = LockReason("financial")
	LockReasonSecurity  = LockReason("security")
)

type LockReasonType struct {
	LockReason LockReason
}

type DescribeInstanceStatusArgs struct {
	RegionId common.Region
	ZoneId   string
	common.Pagination
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancestatusitemtype
type InstanceStatusItemType struct {
	InstanceId string
	Status     InstanceStatus
}

type DescribeInstanceStatusResponse struct {
	common.Response
	common.PaginationResult
	InstanceStatuses struct {
		InstanceStatus []InstanceStatusItemType
	}
}

// DescribeInstanceStatus describes instance status
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancestatus
func (client *Client) DescribeInstanceStatus(args *DescribeInstanceStatusArgs) (instanceStatuses []InstanceStatusItemType, pagination *common.PaginationResult, err error) {
	args.Validate()
	response := DescribeInstanceStatusResponse{}

	err = client.Invoke("DescribeInstanceStatus", args, &response)

	if err == nil {
		return response.InstanceStatuses.InstanceStatus, &response.PaginationResult, nil
	}

	return nil, nil, err
}

type StopInstanceArgs struct {
	InstanceId string
	ForceStop  bool
}

type StopInstanceResponse struct {
	common.Response
}

// StopInstance stops instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&stopinstance
func (client *Client) StopInstance(instanceId string, forceStop bool) error {
	args := StopInstanceArgs{
		InstanceId: instanceId,
		ForceStop:  forceStop,
	}
	response := StopInstanceResponse{}
	err := client.Invoke("StopInstance", &args, &response)
	return err
}

type StartInstanceArgs struct {
	InstanceId string
}

type StartInstanceResponse struct {
	common.Response
}

// StartInstance starts instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&startinstance
func (client *Client) StartInstance(instanceId string) error {
	args := StartInstanceArgs{InstanceId: instanceId}
	response := StartInstanceResponse{}
	err := client.Invoke("StartInstance", &args, &response)
	return err
}

type RebootInstanceArgs struct {
	InstanceId string
	ForceStop  bool
}

type RebootInstanceResponse struct {
	common.Response
}

// RebootInstance reboot instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&rebootinstance
func (client *Client) RebootInstance(instanceId string, forceStop bool) error {
	request := RebootInstanceArgs{
		InstanceId: instanceId,
		ForceStop:  forceStop,
	}
	response := RebootInstanceResponse{}
	err := client.Invoke("RebootInstance", &request, &response)
	return err
}

type DescribeInstanceAttributeArgs struct {
	InstanceId string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&operationlockstype
type OperationLocksType struct {
	LockReason []LockReasonType //enum for financial, security
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&securitygroupidsettype
type SecurityGroupIdSetType struct {
	SecurityGroupId string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&ipaddresssettype
type IpAddressSetType struct {
	IpAddress []string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vpcattributestype
type VpcAttributesType struct {
	VpcId            string
	VSwitchId        string
	PrivateIpAddress IpAddressSetType
	NatIpAddress     string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&eipaddressassociatetype
type EipAddressAssociateType struct {
	AllocationId       string
	IpAddress          string
	Bandwidth          int
	InternetChargeType common.InternetChargeType
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instanceattributestype
type InstanceAttributesType struct {
	InstanceId         string
	InstanceName       string
	Description        string
	ImageId            string
	RegionId           common.Region
	ZoneId             string
	CPU                int
	Memory             int
	ClusterId          string
	InstanceType       string
	InstanceTypeFamily string
	HostName           string
	SerialNumber       string
	Status             InstanceStatus
	OperationLocks     OperationLocksType
	SecurityGroupIds   struct {
		SecurityGroupId []string
	}
	PublicIpAddress         IpAddressSetType
	InnerIpAddress          IpAddressSetType
	InstanceNetworkType     string //enum Classic | Vpc
	InternetMaxBandwidthIn  int
	InternetMaxBandwidthOut int
	InternetChargeType      common.InternetChargeType
	CreationTime            util.ISO6801Time //time.Time
	VpcAttributes           VpcAttributesType
	EipAddress              EipAddressAssociateType
	IoOptimized             StringOrBool
	InstanceChargeType      common.InstanceChargeType
	ExpiredTime             util.ISO6801Time
}

type DescribeInstanceAttributeResponse struct {
	common.Response
	InstanceAttributesType
}

// DescribeInstanceAttribute describes instance attribute
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstanceattribute
func (client *Client) DescribeInstanceAttribute(instanceId string) (instance *InstanceAttributesType, err error) {
	args := DescribeInstanceAttributeArgs{InstanceId: instanceId}

	response := DescribeInstanceAttributeResponse{}
	err = client.Invoke("DescribeInstanceAttribute", &args, &response)
	if err != nil {
		return nil, err
	}
	return &response.InstanceAttributesType, err
}

type ModifyInstanceAttributeArgs struct {
	InstanceId   string
	InstanceName string
	Description  string
	Password     string
	HostName     string
}

type ModifyInstanceAttributeResponse struct {
	common.Response
}

//ModifyInstanceAttribute  modify instance attrbute
//
// You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/modifyinstanceattribute.html
func (client *Client) ModifyInstanceAttribute(args *ModifyInstanceAttributeArgs) error {
	response := ModifyInstanceAttributeResponse{}
	err := client.Invoke("ModifyInstanceAttribute", args, &response)
	return err
}

// Default timeout value for WaitForInstance method
const InstanceDefaultTimeout = 120

// WaitForInstance waits for instance to given status
func (client *Client) WaitForInstance(instanceId string, status InstanceStatus, timeout int) error {
	if timeout <= 0 {
		timeout = InstanceDefaultTimeout
	}
	for {
		instance, err := client.DescribeInstanceAttribute(instanceId)
		if err != nil {
			return err
		}
		if instance.Status == status {
			//TODO
			//Sleep one more time for timing issues
			time.Sleep(DefaultWaitForInterval * time.Second)
			break
		}
		timeout = timeout - DefaultWaitForInterval
		if timeout <= 0 {
			return common.GetClientErrorFromString("Timeout")
		}
		time.Sleep(DefaultWaitForInterval * time.Second)

	}
	return nil
}

type DescribeInstanceVncUrlArgs struct {
	RegionId   common.Region
	InstanceId string
}

type DescribeInstanceVncUrlResponse struct {
	common.Response
	VncUrl string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancevncurl
func (client *Client) DescribeInstanceVncUrl(args *DescribeInstanceVncUrlArgs) (string, error) {
	response := DescribeInstanceVncUrlResponse{}

	err := client.Invoke("DescribeInstanceVncUrl", args, &response)

	if err == nil {
		return response.VncUrl, nil
	}

	return "", err
}

type DescribeInstancesArgs struct {
	RegionId            common.Region
	VpcId               string
	VSwitchId           string
	ZoneId              string
	InstanceIds         string
	InstanceNetworkType string
	InstanceName        string
	Status              InstanceStatus
	PrivateIpAddresses  string
	InnerIpAddresses    string
	PublicIpAddresses   string
	SecurityGroupId     string
	Tag                 map[string]string
	common.Pagination
}

type DescribeInstancesResponse struct {
	common.Response
	common.PaginationResult
	Instances struct {
		Instance []InstanceAttributesType
	}
}

// DescribeInstances describes instances
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstances
func (client *Client) DescribeInstances(args *DescribeInstancesArgs) (instances []InstanceAttributesType, pagination *common.PaginationResult, err error) {
	args.Validate()
	response := DescribeInstancesResponse{}

	err = client.Invoke("DescribeInstances", args, &response)

	if err == nil {
		return response.Instances.Instance, &response.PaginationResult, nil
	}

	return nil, nil, err
}

type DeleteInstanceArgs struct {
	InstanceId string
}

type DeleteInstanceResponse struct {
	common.Response
}

// DeleteInstance deletes instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&deleteinstance
func (client *Client) DeleteInstance(instanceId string) error {
	args := DeleteInstanceArgs{InstanceId: instanceId}
	response := DeleteInstanceResponse{}
	err := client.Invoke("DeleteInstance", &args, &response)
	return err
}

type DataDiskType struct {
	Size               int
	Category           DiskCategory //Enum cloud, ephemeral, ephemeral_ssd
	SnapshotId         string
	DiskName           string
	Description        string
	Device             string
	DeleteWithInstance bool
}

type SystemDiskType struct {
	Size        int
	Category    DiskCategory //Enum cloud, ephemeral, ephemeral_ssd
	DiskName    string
	Description string
}

type IoOptimized string

type StringOrBool struct {
	Value bool
}

// UnmarshalJSON implements the json.Unmarshaller interface.
func (io *StringOrBool) UnmarshalJSON(value []byte) error {
	if value[0] == '"' {
		var str string
		err := json.Unmarshal(value, &str)
		if err == nil {
			io.Value = (str == "true" || str == "optimized")
		}
		return err
	}
	var boolVal bool
	err := json.Unmarshal(value, &boolVal)
	if err == nil {
		io.Value = boolVal
	}
	return err
}

func (io StringOrBool) Bool() bool {
	return io.Value
}

func (io StringOrBool) String() string {
	return strconv.FormatBool(io.Value)
}

var (
	IoOptimizedNone      = IoOptimized("none")
	IoOptimizedOptimized = IoOptimized("optimized")
)

type CreateInstanceArgs struct {
	RegionId                common.Region
	ZoneId                  string
	ImageId                 string
	InstanceType            string
	SecurityGroupId         string
	InstanceName            string
	Description             string
	InternetChargeType      common.InternetChargeType
	InternetMaxBandwidthIn  int
	InternetMaxBandwidthOut int
	HostName                string
	Password                string
	IoOptimized             IoOptimized
	SystemDisk              SystemDiskType
	DataDisk                []DataDiskType
	VSwitchId               string
	PrivateIpAddress        string
	ClientToken             string
	InstanceChargeType      common.InstanceChargeType
	Period                  int
	UserData                string
}

type CreateInstanceResponse struct {
	common.Response
	InstanceId string
}

// CreateInstance creates instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance
func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId string, err error) {
	if args.UserData != "" {
		// Encode to base64 string
		args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData))
	}
	response := CreateInstanceResponse{}
	err = client.Invoke("CreateInstance", args, &response)
	if err != nil {
		return "", err
	}
	return response.InstanceId, err
}

type SecurityGroupArgs struct {
	InstanceId      string
	SecurityGroupId string
}

type SecurityGroupResponse struct {
	common.Response
}

//JoinSecurityGroup
//
//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/joinsecuritygroup.html
func (client *Client) JoinSecurityGroup(instanceId string, securityGroupId string) error {
	args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId}
	response := SecurityGroupResponse{}
	err := client.Invoke("JoinSecurityGroup", &args, &response)
	return err
}

//LeaveSecurityGroup
//
//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/leavesecuritygroup.html
func (client *Client) LeaveSecurityGroup(instanceId string, securityGroupId string) error {
	args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId}
	response := SecurityGroupResponse{}
	err := client.Invoke("LeaveSecurityGroup", &args, &response)
	return err
}
<commit_msg>Add tags for InstanceAttributesType<commit_after>package ecs

import (
	"encoding/base64"
	"encoding/json"
	"strconv"
	"time"

	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/util"
)

// InstanceStatus represents instance status
type InstanceStatus string

// Constants of InstanceStatus
const (
	Creating = InstanceStatus("Creating")
	Running  = InstanceStatus("Running")
	Starting = InstanceStatus("Starting")

	Stopped  = InstanceStatus("Stopped")
	Stopping = InstanceStatus("Stopping")
)

type LockReason string

const (
	LockReasonFinancial = LockReason("financial")
	LockReasonSecurity  = LockReason("security")
)

type LockReasonType struct {
	LockReason LockReason
}

type DescribeInstanceStatusArgs struct {
	RegionId common.Region
	ZoneId   string
	common.Pagination
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancestatusitemtype
type InstanceStatusItemType struct {
	InstanceId string
	Status     InstanceStatus
}

type DescribeInstanceStatusResponse struct {
	common.Response
	common.PaginationResult
	InstanceStatuses struct {
		InstanceStatus []InstanceStatusItemType
	}
}

// DescribeInstanceStatus describes instance status
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancestatus
func (client *Client) DescribeInstanceStatus(args *DescribeInstanceStatusArgs) (instanceStatuses []InstanceStatusItemType, pagination *common.PaginationResult, err error) {
	args.Validate()
	response := DescribeInstanceStatusResponse{}

	err = client.Invoke("DescribeInstanceStatus", args, &response)

	if err == nil {
		return response.InstanceStatuses.InstanceStatus, &response.PaginationResult, nil
	}

	return nil, nil, err
}

type StopInstanceArgs struct {
	InstanceId string
	ForceStop  bool
}

type StopInstanceResponse struct {
	common.Response
}

// StopInstance stops instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&stopinstance
func (client *Client) StopInstance(instanceId string, forceStop bool) error {
	args := StopInstanceArgs{
		InstanceId: instanceId,
		ForceStop:  forceStop,
	}
	response := StopInstanceResponse{}
	err := client.Invoke("StopInstance", &args, &response)
	return err
}

type StartInstanceArgs struct {
	InstanceId string
}

type StartInstanceResponse struct {
	common.Response
}

// StartInstance starts instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&startinstance
func (client *Client) StartInstance(instanceId string) error {
	args := StartInstanceArgs{InstanceId: instanceId}
	response := StartInstanceResponse{}
	err := client.Invoke("StartInstance", &args, &response)
	return err
}

type RebootInstanceArgs struct {
	InstanceId string
	ForceStop  bool
}

type RebootInstanceResponse struct {
	common.Response
}

// RebootInstance reboot instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&rebootinstance
func (client *Client) RebootInstance(instanceId string, forceStop bool) error {
	request := RebootInstanceArgs{
		InstanceId: instanceId,
		ForceStop:  forceStop,
	}
	response := RebootInstanceResponse{}
	err := client.Invoke("RebootInstance", &request, &response)
	return err
}

type DescribeInstanceAttributeArgs struct {
	InstanceId string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&operationlockstype
type OperationLocksType struct {
	LockReason []LockReasonType //enum for financial, security
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&securitygroupidsettype
type SecurityGroupIdSetType struct {
	SecurityGroupId string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&ipaddresssettype
type IpAddressSetType struct {
	IpAddress []string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vpcattributestype
type VpcAttributesType struct {
	VpcId            string
	VSwitchId        string
	PrivateIpAddress IpAddressSetType
	NatIpAddress     string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&eipaddressassociatetype
type EipAddressAssociateType struct {
	AllocationId       string
	IpAddress          string
	Bandwidth          int
	InternetChargeType common.InternetChargeType
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instanceattributestype
type InstanceAttributesType struct {
	InstanceId         string
	InstanceName       string
	Description        string
	ImageId            string
	RegionId           common.Region
	ZoneId             string
	CPU                int
	Memory             int
	ClusterId          string
	InstanceType       string
	InstanceTypeFamily string
	HostName           string
	SerialNumber       string
	Status             InstanceStatus
	OperationLocks     OperationLocksType
	SecurityGroupIds   struct {
		SecurityGroupId []string
	}
	PublicIpAddress         IpAddressSetType
	InnerIpAddress          IpAddressSetType
	InstanceNetworkType     string //enum Classic | Vpc
	InternetMaxBandwidthIn  int
	InternetMaxBandwidthOut int
	InternetChargeType      common.InternetChargeType
	CreationTime            util.ISO6801Time //time.Time
	VpcAttributes           VpcAttributesType
	EipAddress              EipAddressAssociateType
	IoOptimized             StringOrBool
	InstanceChargeType      common.InstanceChargeType
	ExpiredTime             util.ISO6801Time
	Tags                    struct {
		Tag []TagItemType
	}
}

type DescribeInstanceAttributeResponse struct {
	common.Response
	InstanceAttributesType
}

// DescribeInstanceAttribute describes instance attribute
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstanceattribute
func (client *Client) DescribeInstanceAttribute(instanceId string) (instance *InstanceAttributesType, err error) {
	args := DescribeInstanceAttributeArgs{InstanceId: instanceId}

	response := DescribeInstanceAttributeResponse{}
	err = client.Invoke("DescribeInstanceAttribute", &args, &response)
	if err != nil {
		return nil, err
	}
	return &response.InstanceAttributesType, err
}

type ModifyInstanceAttributeArgs struct {
	InstanceId   string
	InstanceName string
	Description  string
	Password     string
	HostName     string
}

type ModifyInstanceAttributeResponse struct {
	common.Response
}

//ModifyInstanceAttribute  modify instance attrbute
//
// You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/modifyinstanceattribute.html
func (client *Client) ModifyInstanceAttribute(args *ModifyInstanceAttributeArgs) error {
	response := ModifyInstanceAttributeResponse{}
	err := client.Invoke("ModifyInstanceAttribute", args, &response)
	return err
}

// Default timeout value for WaitForInstance method
const InstanceDefaultTimeout = 120

// WaitForInstance waits for instance to given status
func (client *Client) WaitForInstance(instanceId string, status InstanceStatus, timeout int) error {
	if timeout <= 0 {
		timeout = InstanceDefaultTimeout
	}
	for {
		instance, err := client.DescribeInstanceAttribute(instanceId)
		if err != nil {
			return err
		}
		if instance.Status == status {
			//TODO
			//Sleep one more time for timing issues
			time.Sleep(DefaultWaitForInterval * time.Second)
			break
		}
		timeout = timeout - DefaultWaitForInterval
		if timeout <= 0 {
			return common.GetClientErrorFromString("Timeout")
		}
		time.Sleep(DefaultWaitForInterval * time.Second)

	}
	return nil
}

type DescribeInstanceVncUrlArgs struct {
	RegionId   common.Region
	InstanceId string
}

type DescribeInstanceVncUrlResponse struct {
	common.Response
	VncUrl string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancevncurl
func (client *Client) DescribeInstanceVncUrl(args *DescribeInstanceVncUrlArgs) (string, error) {
	response := DescribeInstanceVncUrlResponse{}

	err := client.Invoke("DescribeInstanceVncUrl", args, &response)

	if err == nil {
		return response.VncUrl, nil
	}

	return "", err
}

type DescribeInstancesArgs struct {
	RegionId            common.Region
	VpcId               string
	VSwitchId           string
	ZoneId              string
	InstanceIds         string
	InstanceNetworkType string
	InstanceName        string
	Status              InstanceStatus
	PrivateIpAddresses  string
	InnerIpAddresses    string
	PublicIpAddresses   string
	SecurityGroupId     string
	Tag                 map[string]string
	common.Pagination
}

type DescribeInstancesResponse struct {
	common.Response
	common.PaginationResult
	Instances struct {
		Instance []InstanceAttributesType
	}
}

// DescribeInstances describes instances
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstances
func (client *Client) DescribeInstances(args *DescribeInstancesArgs) (instances []InstanceAttributesType, pagination *common.PaginationResult, err error) {
	args.Validate()
	response := DescribeInstancesResponse{}

	err = client.Invoke("DescribeInstances", args, &response)

	if err == nil {
		return response.Instances.Instance, &response.PaginationResult, nil
	}

	return nil, nil, err
}

type DeleteInstanceArgs struct {
	InstanceId string
}

type DeleteInstanceResponse struct {
	common.Response
}

// DeleteInstance deletes instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&deleteinstance
func (client *Client) DeleteInstance(instanceId string) error {
	args := DeleteInstanceArgs{InstanceId: instanceId}
	response := DeleteInstanceResponse{}
	err := client.Invoke("DeleteInstance", &args, &response)
	return err
}

type DataDiskType struct {
	Size               int
	Category           DiskCategory //Enum cloud, ephemeral, ephemeral_ssd
	SnapshotId         string
	DiskName           string
	Description        string
	Device             string
	DeleteWithInstance bool
}

type SystemDiskType struct {
	Size        int
	Category    DiskCategory //Enum cloud, ephemeral, ephemeral_ssd
	DiskName    string
	Description string
}

type IoOptimized string

type StringOrBool struct {
	Value bool
}

// UnmarshalJSON implements the json.Unmarshaller interface.
func (io *StringOrBool) UnmarshalJSON(value []byte) error {
	if value[0] == '"' {
		var str string
		err := json.Unmarshal(value, &str)
		if err == nil {
			io.Value = (str == "true" || str == "optimized")
		}
		return err
	}
	var boolVal bool
	err := json.Unmarshal(value, &boolVal)
	if err == nil {
		io.Value = boolVal
	}
	return err
}

func (io StringOrBool) Bool() bool {
	return io.Value
}

func (io StringOrBool) String() string {
	return strconv.FormatBool(io.Value)
}

var (
	IoOptimizedNone      = IoOptimized("none")
	IoOptimizedOptimized = IoOptimized("optimized")
)

type CreateInstanceArgs struct {
	RegionId                common.Region
	ZoneId                  string
	ImageId                 string
	InstanceType            string
	SecurityGroupId         string
	InstanceName            string
	Description             string
	InternetChargeType      common.InternetChargeType
	InternetMaxBandwidthIn  int
	InternetMaxBandwidthOut int
	HostName                string
	Password                string
	IoOptimized             IoOptimized
	SystemDisk              SystemDiskType
	DataDisk                []DataDiskType
	VSwitchId               string
	PrivateIpAddress        string
	ClientToken             string
	InstanceChargeType      common.InstanceChargeType
	Period                  int
	UserData                string
}

type CreateInstanceResponse struct {
	common.Response
	InstanceId string
}

// CreateInstance creates instance
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance
func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId string, err error) {
	if args.UserData != "" {
		// Encode to base64 string
		args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData))
	}
	response := CreateInstanceResponse{}
	err = client.Invoke("CreateInstance", args, &response)
	if err != nil {
		return "", err
	}
	return response.InstanceId, err
}

type SecurityGroupArgs struct {
	InstanceId      string
	SecurityGroupId string
}

type SecurityGroupResponse struct {
	common.Response
}

//JoinSecurityGroup
//
//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/joinsecuritygroup.html
func (client *Client) JoinSecurityGroup(instanceId string, securityGroupId string) error {
	args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId}
	response := SecurityGroupResponse{}
	err := client.Invoke("JoinSecurityGroup", &args, &response)
	return err
}

//LeaveSecurityGroup
//
//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/leavesecuritygroup.html
func (client *Client) LeaveSecurityGroup(instanceId string, securityGroupId string) error {
	args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId}
	response := SecurityGroupResponse{}
	err := client.Invoke("LeaveSecurityGroup", &args, &response)
	return err
}
<|endoftext|>


<commit_before>package tplight

import (
	"bufio"
	"encoding/json"
	"net"
	"strconv"
)

type Bulb interface {
	SetHSB(hue int, saturation int, brightness int)
	On()
	Off()
	Info() *map[string]int
}

type ldata struct {
	address string
}

func NewBulb(host string) Bulb {
	return &ldata{address: host}
}

func (b ldata) SetHSB(hue, saturation, brightness int) {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1," +
		"\"transition_period\": 0," +
		"\"hue\":" + strconv.Itoa(hue) + "," +
		"\"saturation\":" + strconv.Itoa(saturation) + "," +
		"\"brightness\":" + strconv.Itoa(brightness) + "," +
		"\"color_temp\" : 0" +
		"}}}")
	send(b.address, message)
}

func (b ldata) SetHSBT(hue, saturation, brightness, transition_period int) {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1," +
		"\"transition_period\":" + strconv.Itoa(transition_period) + "," +
		"\"hue\":" + strconv.Itoa(hue) + "," +
		"\"saturation\":" + strconv.Itoa(saturation) + "," +
		"\"brightness\":" + strconv.Itoa(brightness) + "," +
		"\"color_temp\" : 0" +
		"}}}")
	send(b.address, message)
}

func (b ldata) On() {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1" +
		"}}}")
	send(b.address, message)
}

func (b ldata) Off() {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":0," +
		"\"transition_period\":2" +
		"}}}")
	send(b.address, message)
}

func (b ldata) Info() *map[string]int {
	info := make(map[string]int)
	parsed := send(b.address, []byte("{\"system\" : {\"get_sysinfo\": {}}}")[:])
	data := parsed["system"].(map[string]interface{})["get_sysinfo"].(map[string]interface{})["light_state"].(map[string]interface{})
	info["onOff"] = int(data["on_off"].(float64))

	if info["onOff"] != 1 {
		info["hue"] = int(data["dft_on_state"].(map[string]interface{})["hue"].(float64))
		info["saturation"] = int(data["dft_on_state"].(map[string]interface{})["saturation"].(float64))
		info["brightness"] = int(data["dft_on_state"].(map[string]interface{})["brightness"].(float64))
	} else {
		info["hue"] = int(data["hue"].(float64))
		info["saturation"] = int(data["saturation"].(float64))
		info["brightness"] = int(data["brightness"].(float64))
	}

	return &info

}

func encrypt(data []byte) (output []byte) {
	key := byte(0xAB)
	for i := 0; i < len(data); i++ {
		c := data[i]
		output = append(output, c^key)
		key = output[i]
	}
	return output
}

func decrypt(data []byte) (output []byte) {
	key := byte(0xAB)
	for i := 0; i < len(data); i++ {
		c := data[i]
		output = append(output, c^key)
		key = c
	}
	return output
}

func send(hostname string, message []byte) (parsed map[string]interface{}) {
	data := encrypt(message)
	port := 9999
	conn, err := net.Dial("udp4", hostname+":"+strconv.Itoa(port))
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	_, err = conn.Write(data)
	if err != nil {
		panic(err)
	}
	rData := make([]byte, 1500)
	rLen, err := bufio.NewReader(conn).Read(rData)
	if err != nil {
		panic(err)
	}
	dData := decrypt(rData[:rLen])
	err = json.Unmarshal(dData, &parsed)
	if err != nil {
		panic(err)
	}
	return parsed
}
<commit_msg>Add missed method signature to interface<commit_after>package tplight

import (
	"bufio"
	"encoding/json"
	"net"
	"strconv"
)

type Bulb interface {
	SetHSB(hue int, saturation int, brightness int)
	SetHSBT(hue int, saturation int, brightness int, transition_period int)
	On()
	Off()
	Info() *map[string]int
}

type ldata struct {
	address string
}

func NewBulb(host string) Bulb {
	return &ldata{address: host}
}

func (b ldata) SetHSB(hue, saturation, brightness int) {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1," +
		"\"transition_period\": 0," +
		"\"hue\":" + strconv.Itoa(hue) + "," +
		"\"saturation\":" + strconv.Itoa(saturation) + "," +
		"\"brightness\":" + strconv.Itoa(brightness) + "," +
		"\"color_temp\" : 0" +
		"}}}")
	send(b.address, message)
}

func (b ldata) SetHSBT(hue, saturation, brightness, transition_period int) {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1," +
		"\"transition_period\":" + strconv.Itoa(transition_period) + "," +
		"\"hue\":" + strconv.Itoa(hue) + "," +
		"\"saturation\":" + strconv.Itoa(saturation) + "," +
		"\"brightness\":" + strconv.Itoa(brightness) + "," +
		"\"color_temp\" : 0" +
		"}}}")
	send(b.address, message)
}

func (b ldata) On() {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":1" +
		"}}}")
	send(b.address, message)
}

func (b ldata) Off() {
	message := []byte("{\"smartlife.iot.smartbulb.lightingservice\":" +
		"{\"transition_light_state\":" +
		"{\"ignore_default\":1," +
		"\"on_off\":0," +
		"\"transition_period\":2" +
		"}}}")
	send(b.address, message)
}

func (b ldata) Info() *map[string]int {
	info := make(map[string]int)
	parsed := send(b.address, []byte("{\"system\" : {\"get_sysinfo\": {}}}")[:])
	data := parsed["system"].(map[string]interface{})["get_sysinfo"].(map[string]interface{})["light_state"].(map[string]interface{})
	info["onOff"] = int(data["on_off"].(float64))

	if info["onOff"] != 1 {
		info["hue"] = int(data["dft_on_state"].(map[string]interface{})["hue"].(float64))
		info["saturation"] = int(data["dft_on_state"].(map[string]interface{})["saturation"].(float64))
		info["brightness"] = int(data["dft_on_state"].(map[string]interface{})["brightness"].(float64))
	} else {
		info["hue"] = int(data["hue"].(float64))
		info["saturation"] = int(data["saturation"].(float64))
		info["brightness"] = int(data["brightness"].(float64))
	}

	return &info

}

func encrypt(data []byte) (output []byte) {
	key := byte(0xAB)
	for i := 0; i < len(data); i++ {
		c := data[i]
		output = append(output, c^key)
		key = output[i]
	}
	return output
}

func decrypt(data []byte) (output []byte) {
	key := byte(0xAB)
	for i := 0; i < len(data); i++ {
		c := data[i]
		output = append(output, c^key)
		key = c
	}
	return output
}

func send(hostname string, message []byte) (parsed map[string]interface{}) {
	data := encrypt(message)
	port := 9999
	conn, err := net.Dial("udp4", hostname+":"+strconv.Itoa(port))
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	_, err = conn.Write(data)
	if err != nil {
		panic(err)
	}
	rData := make([]byte, 1500)
	rLen, err := bufio.NewReader(conn).Read(rData)
	if err != nil {
		panic(err)
	}
	dData := decrypt(rData[:rLen])
	err = json.Unmarshal(dData, &parsed)
	if err != nil {
		panic(err)
	}
	return parsed
}
<|endoftext|>


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

// package editor implements buffers representing views into a piece of text.
package editor

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/nsf/termbox-go"
)

type Buffer interface {
	GetLine(lineno int) (*Line, error)
	Lines() int
	Save(name string) error
}

type Drawer interface {
	DrawAt(x int, y int, w int, h int)
	Scroll(by int)
}

type Line struct {
	prev     *Line
	next     *Line
	Contents []byte
}

func (a *Line) InsertAt(offset int, toInsert []byte) {
	// do this the naive, allocating way
	// TODO: faster? less memory intensive way?

	a.Contents = append(
		a.Contents[:offset],
		append(toInsert, a.Contents[offset:]...)...)
}

func (l *Line) DeleteNAt(n int, offset int) {
	defer func() {
		if r := recover(); r != nil {
			LogItAll.Printf("DeleteNAt(%d, %d): %v\n", n, offset, r)
		}
	}()

	l.Contents = append(
		l.Contents[:offset],
		l.Contents[offset+n:]...,
	)
}

type SmallFileBuffer struct {
	Filename    string
	FirstLine   *Line
	CurrentLine *Line
	LastLine    *Line
}

func BufferizeFile(filename string) (Buffer, error) {
	a := new(SmallFileBuffer)
	a.Filename = filename
	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	startOfTokenIndex := 0
	currentLine := new(Line)
	a.FirstLine = currentLine
	a.CurrentLine = currentLine
	for i, c := range contents {
		if c == '\n' {
			currentLine.Contents = make([]byte, i+1-startOfTokenIndex)
			copy(currentLine.Contents, contents[startOfTokenIndex:i+1])
			startOfTokenIndex = i + 1
			nextLine := new(Line)
			currentLine.next = nextLine
			nextLine.prev = currentLine
			currentLine = nextLine
		}
	}
	a.LastLine = currentLine
	return a, nil
}

// expensive
func (b *SmallFileBuffer) Lines() int {
	i := 0
	for l := b.FirstLine; l != b.LastLine; i++ {
		l = l.next
	}
	return i + 1
}

func ClearBox(x int, y int, w int, h int) {
	for yi := 0; yi < h; yi++ {
		for xi := 0; xi < w; xi++ {
			termbox.SetCell(x+xi, y+yi, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
	}
}

func (a *SmallFileBuffer) GetLine(x int) (*Line, error) {
	currentLine := a.FirstLine
	i := 1
	for {
		if x == i {
			return currentLine, nil
		}
		currentLine = currentLine.next
		i += 1
		if currentLine == nil {
			return nil, fmt.Errorf("line %d does not exist", x)
		}
	}
}

func (a *SmallFileBuffer) Save(name string) error {
	if name == "" {
		name = a.Filename
	}

	f, err := os.Create(name)
	if err != nil {
		return err
	}

	for l := a.FirstLine; l.next != nil; l = l.next {
		written := 0
		for written != len(l.Contents) {
			n, err := f.Write(l.Contents[written:])
			if err != nil {
				LogItAll.Println(err)
			}
			written += n
		}
	}

	return nil
}
<commit_msg>Remove unused Drawer interface<commit_after>// Copyright 2015 Ethan Miller. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// package editor implements buffers representing views into a piece of text.
package editor

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/nsf/termbox-go"
)

type Buffer interface {
	GetLine(lineno int) (*Line, error)
	Lines() int
	Save(name string) error
}

type Line struct {
	prev     *Line
	next     *Line
	Contents []byte
}

func (a *Line) InsertAt(offset int, toInsert []byte) {
	// do this the naive, allocating way
	// TODO: faster? less memory intensive way?

	a.Contents = append(
		a.Contents[:offset],
		append(toInsert, a.Contents[offset:]...)...)
}

func (l *Line) DeleteNAt(n int, offset int) {
	defer func() {
		if r := recover(); r != nil {
			LogItAll.Printf("DeleteNAt(%d, %d): %v\n", n, offset, r)
		}
	}()

	l.Contents = append(
		l.Contents[:offset],
		l.Contents[offset+n:]...,
	)
}

type SmallFileBuffer struct {
	Filename    string
	FirstLine   *Line
	CurrentLine *Line
	LastLine    *Line
}

func BufferizeFile(filename string) (Buffer, error) {
	a := new(SmallFileBuffer)
	a.Filename = filename
	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	startOfTokenIndex := 0
	currentLine := new(Line)
	a.FirstLine = currentLine
	a.CurrentLine = currentLine
	for i, c := range contents {
		if c == '\n' {
			currentLine.Contents = make([]byte, i+1-startOfTokenIndex)
			copy(currentLine.Contents, contents[startOfTokenIndex:i+1])
			startOfTokenIndex = i + 1
			nextLine := new(Line)
			currentLine.next = nextLine
			nextLine.prev = currentLine
			currentLine = nextLine
		}
	}
	a.LastLine = currentLine
	return a, nil
}

// expensive
func (b *SmallFileBuffer) Lines() int {
	i := 0
	for l := b.FirstLine; l != b.LastLine; i++ {
		l = l.next
	}
	return i + 1
}

func ClearBox(x int, y int, w int, h int) {
	for yi := 0; yi < h; yi++ {
		for xi := 0; xi < w; xi++ {
			termbox.SetCell(x+xi, y+yi, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
	}
}

func (a *SmallFileBuffer) GetLine(x int) (*Line, error) {
	currentLine := a.FirstLine
	i := 1
	for {
		if x == i {
			return currentLine, nil
		}
		currentLine = currentLine.next
		i += 1
		if currentLine == nil {
			return nil, fmt.Errorf("line %d does not exist", x)
		}
	}
}

func (a *SmallFileBuffer) Save(name string) error {
	if name == "" {
		name = a.Filename
	}

	f, err := os.Create(name)
	if err != nil {
		return err
	}

	for l := a.FirstLine; l.next != nil; l = l.next {
		written := 0
		for written != len(l.Contents) {
			n, err := f.Write(l.Contents[written:])
			if err != nil {
				LogItAll.Println(err)
			}
			written += n
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package geoloader

// The AnnWrapper struct controls concurrent operations on Annotator objects.
// It is designed for minimal contention on GetAnnotator(), and safe loading and unloading.
// TODO - pull this out to an internal package, since it is only used by the directory.

import (
	"log"
	"sync"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/m-lab/annotation-service/api"
	"github.com/m-lab/annotation-service/metrics"
)

type AnnWrapper struct {
	lock sync.RWMutex // Should be held when reading or modifying the annotator pointer or err fields
	// The lock must be held when accessing either of these.
	ann api.Annotator // Updated only while holding write lock.
	err error         // Non-nil if annotator is unloaded or loading, OR there was a non-recoverable load error.

	// This field is accessed using atomics.
	// In an empty wrapper, this should point to time.Time{} zero value.
	lastUsed unsafe.Pointer // pointer to the lastUsed time.Time.
}

// UpdateLastUsed updates the last used time to the current time.
func (ae *AnnWrapper) UpdateLastUsed() {
	newTime := time.Now()
	atomic.StorePointer(&ae.lastUsed, unsafe.Pointer(&newTime))
}

// GetLastUsed returns the time that the annotator was last successfully fetched with GetAnnotator.
func (ae *AnnWrapper) GetLastUsed() time.Time {
	ptr := atomic.LoadPointer(&ae.lastUsed)
	if ptr == nil {
		log.Println("Error in getLastUsed for", ae)
		return time.Time{}
	}
	return *(*time.Time)(ptr)
}

// ReserveForLoad attempts to set the state to loading, indicated by the `err` field
// containing ErrAnnotatorLoading.
// Returns true IFF the reservation was obtained.
func (ae *AnnWrapper) ReserveForLoad() bool {
	ae.lock.Lock()
	defer ae.lock.Unlock()
	if ae.err == nil {
		return false
	}
	if ae.err == ErrAnnotatorLoading { // This is the public error
		return false
	}
	// This takes ownership of the slot
	ae.err = ErrAnnotatorLoading
	return true
}

// SetAnnotator attempts to store `ann`, and update the error state.
// It may fail if the state has changed, e.g. because of an unload.
func (ae *AnnWrapper) SetAnnotator(ann api.Annotator, err error) error {
	ae.lock.Lock()
	defer ae.lock.Unlock()

	if ae.err != ErrAnnotatorLoading {
		log.Println("This should never happen", ErrGoroutineNotOwner)
		return ErrGoroutineNotOwner
	}
	if ae.ann != nil {
		log.Println("This should never happen", ErrMapEntryAlreadySet)
		return ErrMapEntryAlreadySet
	}
	ae.ann = ann
	ae.err = err
	ae.UpdateLastUsed()

	metrics.LoadCount.Inc()
	metrics.PendingLoads.Dec()
	metrics.DatasetCount.Inc()

	return nil
}

// GetAnnotator gets the current annotator, if there is one, and the error state.
func (ae *AnnWrapper) GetAnnotator() (ann api.Annotator, err error) {
	ae.UpdateLastUsed()

	ae.lock.RLock()
	defer ae.lock.RUnlock()

	return ae.ann, ae.err
}

// Unload unloads the annotator and resets the state to the empty state.
// If another goroutine is concurrently trying to load this, we don't
// really care.  The other goroutine will fail when it attempts to SetAnnotator()
func (ae *AnnWrapper) Unload() {
	ae.lock.Lock()
	defer ae.lock.Unlock()

	if ae.ann != nil {
		ae.ann.Unload()
	}

	ae.ann = nil
	ae.err = ErrNilEntry
	atomic.StorePointer(&ae.lastUsed, unsafe.Pointer(&time.Time{}))
}

func NewAnnWrapper() AnnWrapper {
	return AnnWrapper{err: ErrNilEntry, lastUsed: unsafe.Pointer(&time.Time{})}
}
<commit_msg>more comments somehow left out<commit_after>package geoloader

// The AnnWrapper struct controls concurrent operations on Annotator objects.
// It is designed for minimal contention on GetAnnotator(), and safe loading and unloading.
// TODO - pull this out to an internal package, since it is only used by the directory.

import (
	"log"
	"sync"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/m-lab/annotation-service/api"
	"github.com/m-lab/annotation-service/metrics"
)

type AnnWrapper struct {
	// The lock must be held when accessing ann or err fields.
	lock sync.RWMutex

	// Updated only while holding write lock.
	ann api.Annotator

	// err field is used to indicate the wrapper status.
	// nil error means that the annotator is populated and ready for use.
	// An empty wrapper will have a non-nil error, indicating whether a previous load failed,
	// or annotator is currently loading, or annotator is nil and wrapper is idle.
	err error

	// This field is accessed using atomics.
	// In an empty wrapper, this should point to time.Time{} zero value.
	lastUsed unsafe.Pointer // pointer to the lastUsed time.Time.
}

// UpdateLastUsed updates the last used time to the current time.
func (ae *AnnWrapper) UpdateLastUsed() {
	newTime := time.Now()
	atomic.StorePointer(&ae.lastUsed, unsafe.Pointer(&newTime))
}

// GetLastUsed returns the time that the annotator was last successfully fetched with GetAnnotator.
func (ae *AnnWrapper) GetLastUsed() time.Time {
	ptr := atomic.LoadPointer(&ae.lastUsed)
	if ptr == nil {
		log.Println("Error in getLastUsed for", ae)
		return time.Time{}
	}
	return *(*time.Time)(ptr)
}

// ReserveForLoad attempts to set the state to loading, indicated by the `err` field
// containing ErrAnnotatorLoading.
// Returns true IFF the reservation was obtained.
func (ae *AnnWrapper) ReserveForLoad() bool {
	ae.lock.Lock()
	defer ae.lock.Unlock()
	if ae.err == nil {
		return false
	}
	if ae.err == ErrAnnotatorLoading { // This is the public error
		return false
	}
	// This takes ownership of the slot
	ae.err = ErrAnnotatorLoading
	return true
}

// SetAnnotator attempts to store `ann`, and update the error state.
// It may fail if the state has changed, e.g. because of an unload.
func (ae *AnnWrapper) SetAnnotator(ann api.Annotator, err error) error {
	ae.lock.Lock()
	defer ae.lock.Unlock()

	if ae.err != ErrAnnotatorLoading {
		log.Println("This should never happen", ErrGoroutineNotOwner)
		return ErrGoroutineNotOwner
	}
	if ae.ann != nil {
		log.Println("This should never happen", ErrMapEntryAlreadySet)
		return ErrMapEntryAlreadySet
	}
	ae.ann = ann
	ae.err = err
	ae.UpdateLastUsed()

	metrics.LoadCount.Inc()
	metrics.PendingLoads.Dec()
	metrics.DatasetCount.Inc()

	return nil
}

// GetAnnotator gets the current annotator, if there is one, and the error state.
func (ae *AnnWrapper) GetAnnotator() (ann api.Annotator, err error) {
	ae.UpdateLastUsed()

	ae.lock.RLock()
	defer ae.lock.RUnlock()

	return ae.ann, ae.err
}

// Unload unloads the annotator and resets the state to the empty state.
// If another goroutine is concurrently trying to load this, we don't
// really care.  The other goroutine will fail when it attempts to SetAnnotator()
func (ae *AnnWrapper) Unload() {
	ae.lock.Lock()
	defer ae.lock.Unlock()

	if ae.ann != nil {
		ae.ann.Unload()
	}

	ae.ann = nil
	ae.err = ErrNilEntry
	atomic.StorePointer(&ae.lastUsed, unsafe.Pointer(&time.Time{}))
}

func NewAnnWrapper() AnnWrapper {
	return AnnWrapper{err: ErrNilEntry, lastUsed: unsafe.Pointer(&time.Time{})}
}
<|endoftext|>


<commit_before>package envplate

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

const (
	NoDefaultDefined = ""
	NoKeyDefined     = ""
)

var exp = regexp.MustCompile(`\$\{(.+?)(?:\:\-(.+?))?\}`)

func Apply(globs []string) {

	matches := false

	for _, pattern := range globs {

		files, err := filepath.Glob(pattern)

		if err != nil {
			Log(ERROR, err.Error())
		}

		for _, name := range files {

			if info, _ := os.Stat(name); info.IsDir() {
				continue
			}

			matches = true

			if err := parse(name); err != nil {
				Log(ERROR, "Error while parsing '%s': %v", name, err)
			}

		}

	}

	if !matches {
		Log(ERROR, "Zero files matched passed globs '%v'", globs)
	}

}

func createBackup(file string) error {

	source, err := os.Open(file)

	if err != nil {
		return err
	}

	defer source.Close()

	target, err := os.Create(fmt.Sprintf("%s.bak", file))

	if err != nil {
		return err
	}

	defer target.Close()

	if _, err := io.Copy(target, source); err != nil {
		return err
	}

	if err := os.Chmod(target.Name(), filemode(source.Name())); err != nil {
		return err
	}

	return nil

}

func parse(file string) error {

	content, err := ioutil.ReadFile(file)

	if err != nil {
		return fmt.Errorf("Cannot open %s: %v", file, err)
	}

	Log(DEBUG, "Parsing environment references in '%s'", file)

	parsed := exp.ReplaceAllStringFunc(string(content), func(match string) string {

		var (
			key, def = capture(match)
			value    = os.Getenv(key)
		)

		if value == NoKeyDefined {

			if def == NoDefaultDefined {
				Log(ERROR, "'%s' requires undeclared environment variable '%s', no default is given", file, key)
			} else {

				if Config.Strict {
					Log(ERROR, "'%s' requires undeclared environment variable '%s', but cannot use default '%s' (strict-mode)", file, key, def)
				} else {
					Log(DEBUG, "'%s' requires undeclared environment variable '%s', using default '%s'", file, key, def)
					value = def
				}

			}

		} else {
			Log(DEBUG, "Expanding reference to '%s' to value '%s'", key, value)
		}

		return value

	})

	if Config.DryRun {
		Log(INFO, "Expanding all references in '%s' would look like this:\n%s", file, parsed)
	} else {

		if Config.Backup {

			Log(DEBUG, "Creating backup of '%s'", file)

			if err := createBackup(file); err != nil {
				return err
			}

		}

		return ioutil.WriteFile(file, []byte(parsed), filemode(file))

	}

	return nil

}

func capture(s string) (key, def string) {

	matches := exp.FindStringSubmatch(s)

	key = matches[1]
	def = matches[2]

	return key, def

}

func filemode(file string) os.FileMode {

	fileinfo, err := os.Stat(file)

	if err != nil {
		Log(ERROR, "Cannot stat '%s': %v", file, err)
	}

	return fileinfo.Mode()

}
<commit_msg>Add backslash as escape character<commit_after>package envplate

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

const (
	NoDefaultDefined = ""
	NoKeyDefined     = ""
)

var exp = regexp.MustCompile(`(.?)\$\{(.+?)(?:\:\-(.+?))?\}`)

func Apply(globs []string) {

	matches := false

	for _, pattern := range globs {

		files, err := filepath.Glob(pattern)

		if err != nil {
			Log(ERROR, err.Error())
		}

		for _, name := range files {

			if info, _ := os.Stat(name); info.IsDir() {
				continue
			}

			matches = true

			if err := parse(name); err != nil {
				Log(ERROR, "Error while parsing '%s': %v", name, err)
			}

		}

	}

	if !matches {
		Log(ERROR, "Zero files matched passed globs '%v'", globs)
	}

}

func createBackup(file string) error {

	source, err := os.Open(file)

	if err != nil {
		return err
	}

	defer source.Close()

	target, err := os.Create(fmt.Sprintf("%s.bak", file))

	if err != nil {
		return err
	}

	defer target.Close()

	if _, err := io.Copy(target, source); err != nil {
		return err
	}

	if err := os.Chmod(target.Name(), filemode(source.Name())); err != nil {
		return err
	}

	return nil

}

func parse(file string) error {

	content, err := ioutil.ReadFile(file)

	if err != nil {
		return fmt.Errorf("Cannot open %s: %v", file, err)
	}

	Log(DEBUG, "Parsing environment references in '%s'", file)

	parsed := exp.ReplaceAllStringFunc(string(content), func(match string) string {

		var (
			pre, key, def = capture(match)
			value    = os.Getenv(key)
		)

                if pre == `\` {

                  return match[1:len(match)]

                }

		if value == NoKeyDefined {

			if def == NoDefaultDefined {
				Log(ERROR, "'%s' requires undeclared environment variable '%s', no default is given", file, key)
			} else {

				if Config.Strict {
					Log(ERROR, "'%s' requires undeclared environment variable '%s', but cannot use default '%s' (strict-mode)", file, key, def)
				} else {
					Log(DEBUG, "'%s' requires undeclared environment variable '%s', using default '%s'", file, key, def)
					value = def
				}

			}

		} else {
			Log(DEBUG, "Expanding reference to '%s' to value '%s'", key, value)
		}

		return pre + value

	})

	if Config.DryRun {
		Log(INFO, "Expanding all references in '%s' would look like this:\n%s", file, parsed)
	} else {

		if Config.Backup {

			Log(DEBUG, "Creating backup of '%s'", file)

			if err := createBackup(file); err != nil {
				return err
			}

		}

		return ioutil.WriteFile(file, []byte(parsed), filemode(file))

	}

	return nil

}

func capture(s string) (pre, key, def string) {

	matches := exp.FindStringSubmatch(s)

        pre = matches[1]
	key = matches[2]
	def = matches[3]

	return pre, key, def

}

func filemode(file string) os.FileMode {

	fileinfo, err := os.Stat(file)

	if err != nil {
		Log(ERROR, "Cannot stat '%s': %v", file, err)
	}

	return fileinfo.Mode()

}
<|endoftext|>


<commit_before>package main

import (
	"github.com/BurntSushi/toml"
	"github.com/codegangsta/negroni"
	"github.com/emilevauge/traefik/middlewares"
	"github.com/gorilla/mux"
	"github.com/mailgun/oxy/forward"
	"github.com/mailgun/oxy/roundrobin"
	"github.com/op/go-logging"
	"github.com/thoas/stats"
	"github.com/tylerb/graceful"
	"github.com/unrolled/render"
	"gopkg.in/alecthomas/kingpin.v2"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"reflect"
	"syscall"
	"time"
	fmtlog "log"
	"github.com/mailgun/oxy/cbreaker"
)

var (
	globalConfigFile     = kingpin.Arg("conf", "Main configration file.").Default("traefik.toml").String()
	currentConfiguration = new(Configuration)
	metrics              = stats.New()
	log                  = logging.MustGetLogger("traefik")
	oxyLogger			 = &OxyLogger{}
	templatesRenderer    = render.New(render.Options{
		Directory:  "templates",
		Asset:      Asset,
		AssetNames: AssetNames,
	})
)

func main() {
	kingpin.Parse()
	fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
	var srv *graceful.Server
	var configurationRouter *mux.Router
	var configurationChan = make(chan *Configuration)
	defer close(configurationChan)
	var providers = []Provider{}
	var format = logging.MustStringFormatter("%{color}%{time:15:04:05.000} %{shortfile:20.20s} %{level:8.8s} %{id:03x} ▶%{color:reset} %{message}")
	var sigs = make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// load global configuration
	gloablConfiguration := LoadFileConfig(*globalConfigFile)

	loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile)
	defer loggerMiddleware.Close()

	// logging
	backends := []logging.Backend{}
	level, err := logging.LogLevel(gloablConfiguration.LogLevel)
	if err != nil {
		log.Fatal("Error getting level", err)
	}

	if len(gloablConfiguration.TraefikLogsFile) > 0 {
		fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		defer fi.Close()
		if err != nil {
			log.Fatal("Error opening file", err)
		} else {
			logBackend := logging.NewLogBackend(fi, "", 0)
			logBackendFormatter := logging.NewBackendFormatter(logBackend, logging.GlogFormatter)
			logBackendLeveled := logging.AddModuleLevel(logBackend)
			logBackendLeveled.SetLevel(level, "")
			backends = append(backends, logBackendFormatter)
		}
	}
	if gloablConfiguration.TraefikLogsStdout {
		logBackend := logging.NewLogBackend(os.Stdout, "", 0)
		logBackendFormatter := logging.NewBackendFormatter(logBackend, format)
		logBackendLeveled := logging.AddModuleLevel(logBackend)
		logBackendLeveled.SetLevel(level, "")
		backends = append(backends, logBackendFormatter)
	}
	logging.SetBackend(backends...)

	configurationRouter = LoadDefaultConfig(gloablConfiguration)

	// listen new configurations from providers
	go func() {
		for {
			configuration := <-configurationChan
			log.Info("Configuration receveived %+v", configuration)
			if configuration == nil {
				log.Info("Skipping empty configuration")
			} else if reflect.DeepEqual(currentConfiguration, configuration) {
				log.Info("Skipping same configuration")
			} else {
				newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration)
				if (err == nil ){
					currentConfiguration = configuration
					configurationRouter = newConfigurationRouter
					srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
					time.Sleep(3 * time.Second)
				}else{
					log.Error("Error loading new configuration, aborted ", err)
				}
			}
		}
	}()

	// configure providers
	if gloablConfiguration.Docker != nil {
		providers = append(providers, gloablConfiguration.Docker)
	}
	if gloablConfiguration.Marathon != nil {
		providers = append(providers, gloablConfiguration.Marathon)
	}
	if gloablConfiguration.File != nil {
		if len(gloablConfiguration.File.Filename) == 0 {
			// no filename, setting to global config file
			gloablConfiguration.File.Filename = *globalConfigFile
		}
		providers = append(providers, gloablConfiguration.File)
	}
	if gloablConfiguration.Web != nil {
		providers = append(providers, gloablConfiguration.Web)
	}
	// providers = append(providers, NewConsulProvider())

	// start providers
	for _, provider := range providers {
		log.Notice("Starting provider %v %+v", reflect.TypeOf(provider), provider)
		currentProvider := provider
		go func() {
			currentProvider.Provide(configurationChan)
		}()
	}

	goAway := false
	go func() {
		sig := <-sigs
		log.Notice("I have to go... %+v", sig)
		goAway = true
		srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
	}()

	for {
		if goAway {
			break
		}

		// middlewares
		var negroni = negroni.New()
		negroni.Use(metrics)
		negroni.Use(loggerMiddleware)
		//negroni.Use(middlewares.NewCircuitBreaker(oxyLogger))
		//negroni.Use(middlewares.NewRoutes(configurationRouter))
		negroni.UseHandler(configurationRouter)

		srv = &graceful.Server{
			Timeout:          time.Duration(gloablConfiguration.GraceTimeOut) * time.Second,
			NoSignalHandling: true,

			Server: &http.Server{
				Addr:    gloablConfiguration.Port,
				Handler: negroni,
			},
		}

		go func() {
			if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 {
				srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile)
			} else {
				srv.ListenAndServe()
			}
		}()
		log.Notice("Started")
		<-srv.StopChan()
		log.Notice("Stopped")
	}
}

func LoadConfig(configuration *Configuration, gloablConfiguration *GlobalConfiguration) (*mux.Router, error) {
	router := mux.NewRouter()
	router.NotFoundHandler = http.HandlerFunc(notFoundHandler)
	backends := map[string]http.Handler{}
	for frontendName, frontend := range configuration.Frontends {
		log.Debug("Creating frontend %s", frontendName)
		fwd, _ := forward.New(forward.Logger(oxyLogger))
		newRoute := router.NewRoute().Name(frontendName)
		for routeName, route := range frontend.Routes {
			log.Debug("Creating route %s %s:%s", routeName, route.Rule, route.Value)
			newRouteReflect := Invoke(newRoute, route.Rule, route.Value)
			newRoute = newRouteReflect[0].Interface().(*mux.Route)
		}
		if backends[frontend.Backend] == nil {
			log.Debug("Creating backend %s", frontend.Backend)
			lb, _ := roundrobin.New(fwd)
			rb, _ := roundrobin.NewRebalancer(lb, roundrobin.RebalancerLogger(oxyLogger))
			for serverName, server := range configuration.Backends[frontend.Backend].Servers {
				if url, err := url.Parse(server.Url); err != nil{
					return nil, err
				}else{
					log.Debug("Creating server %s %s", serverName, url.String())
					rb.UpsertServer(url, roundrobin.Weight(server.Weight))
				}
			}
			backends[frontend.Backend] = rb
		} else {
			log.Debug("Reusing backend %s", frontend.Backend)
		}
//		stream.New(backends[frontend.Backend], stream.Retry("IsNetworkError() && Attempts() <= " + strconv.Itoa(gloablConfiguration.Replay)), stream.Logger(oxyLogger))
		var negroni = negroni.New()
		negroni.Use(middlewares.NewCircuitBreaker(backends[frontend.Backend], cbreaker.Logger(oxyLogger)))
		newRoute.Handler(negroni)
		err := newRoute.GetError()
		if err != nil {
			log.Error("Error building route ", err)
		}
	}
	return router, nil
}

func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
	inputs := make([]reflect.Value, len(args))
	for i := range args {
		inputs[i] = reflect.ValueOf(args[i])
	}
	return reflect.ValueOf(any).MethodByName(name).Call(inputs)
}

func LoadFileConfig(file string) *GlobalConfiguration {
	configuration := NewGlobalConfiguration()
	if _, err := toml.DecodeFile(file, configuration); err != nil {
		log.Fatal("Error reading file ", err)
	}
	log.Debug("Global configuration loaded %+v", configuration)
	return configuration
}<commit_msg>Corrects log level<commit_after>package main

import (
	"github.com/BurntSushi/toml"
	"github.com/codegangsta/negroni"
	"github.com/emilevauge/traefik/middlewares"
	"github.com/gorilla/mux"
	"github.com/mailgun/oxy/forward"
	"github.com/mailgun/oxy/roundrobin"
	"github.com/op/go-logging"
	"github.com/thoas/stats"
	"github.com/tylerb/graceful"
	"github.com/unrolled/render"
	"gopkg.in/alecthomas/kingpin.v2"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"reflect"
	"syscall"
	"time"
	fmtlog "log"
	"github.com/mailgun/oxy/cbreaker"
)

var (
	globalConfigFile     = kingpin.Arg("conf", "Main configration file.").Default("traefik.toml").String()
	currentConfiguration = new(Configuration)
	metrics              = stats.New()
	log                  = logging.MustGetLogger("traefik")
	oxyLogger			 = &OxyLogger{}
	templatesRenderer    = render.New(render.Options{
		Directory:  "templates",
		Asset:      Asset,
		AssetNames: AssetNames,
	})
)

func main() {
	kingpin.Parse()
	fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
	var srv *graceful.Server
	var configurationRouter *mux.Router
	var configurationChan = make(chan *Configuration)
	defer close(configurationChan)
	var providers = []Provider{}
	var format = logging.MustStringFormatter("%{color}%{time:15:04:05.000} %{shortfile:20.20s} %{level:8.8s} %{id:03x} ▶%{color:reset} %{message}")
	var sigs = make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// load global configuration
	gloablConfiguration := LoadFileConfig(*globalConfigFile)

	loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile)
	defer loggerMiddleware.Close()

	// logging
	backends := []logging.Backend{}
	level, err := logging.LogLevel(gloablConfiguration.LogLevel)
	if err != nil {
		log.Fatal("Error getting level", err)
	}

	if len(gloablConfiguration.TraefikLogsFile) > 0 {
		fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		defer fi.Close()
		if err != nil {
			log.Fatal("Error opening file", err)
		} else {
			logBackend := logging.NewLogBackend(fi, "", 0)
			logBackendFormatter := logging.NewBackendFormatter(logBackend, logging.GlogFormatter)
			backends = append(backends, logBackendFormatter)
		}
	}
	if gloablConfiguration.TraefikLogsStdout {
		logBackend := logging.NewLogBackend(os.Stdout, "", 0)
		logBackendFormatter := logging.NewBackendFormatter(logBackend, format)
		backends = append(backends, logBackendFormatter)
	}
	logging.SetBackend(backends...)
	logging.SetLevel(level, "traefik")

	configurationRouter = LoadDefaultConfig(gloablConfiguration)

	// listen new configurations from providers
	go func() {
		for {
			configuration := <-configurationChan
			log.Info("Configuration receveived %+v", configuration)
			if configuration == nil {
				log.Info("Skipping empty configuration")
			} else if reflect.DeepEqual(currentConfiguration, configuration) {
				log.Info("Skipping same configuration")
			} else {
				newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration)
				if (err == nil ){
					currentConfiguration = configuration
					configurationRouter = newConfigurationRouter
					srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
					time.Sleep(3 * time.Second)
				}else{
					log.Error("Error loading new configuration, aborted ", err)
				}
			}
		}
	}()

	// configure providers
	if gloablConfiguration.Docker != nil {
		providers = append(providers, gloablConfiguration.Docker)
	}
	if gloablConfiguration.Marathon != nil {
		providers = append(providers, gloablConfiguration.Marathon)
	}
	if gloablConfiguration.File != nil {
		if len(gloablConfiguration.File.Filename) == 0 {
			// no filename, setting to global config file
			gloablConfiguration.File.Filename = *globalConfigFile
		}
		providers = append(providers, gloablConfiguration.File)
	}
	if gloablConfiguration.Web != nil {
		providers = append(providers, gloablConfiguration.Web)
	}
	// providers = append(providers, NewConsulProvider())

	// start providers
	for _, provider := range providers {
		log.Notice("Starting provider %v %+v", reflect.TypeOf(provider), provider)
		currentProvider := provider
		go func() {
			currentProvider.Provide(configurationChan)
		}()
	}

	goAway := false
	go func() {
		sig := <-sigs
		log.Notice("I have to go... %+v", sig)
		goAway = true
		srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
	}()

	for {
		if goAway {
			break
		}

		// middlewares
		var negroni = negroni.New()
		negroni.Use(metrics)
		negroni.Use(loggerMiddleware)
		//negroni.Use(middlewares.NewCircuitBreaker(oxyLogger))
		//negroni.Use(middlewares.NewRoutes(configurationRouter))
		negroni.UseHandler(configurationRouter)

		srv = &graceful.Server{
			Timeout:          time.Duration(gloablConfiguration.GraceTimeOut) * time.Second,
			NoSignalHandling: true,

			Server: &http.Server{
				Addr:    gloablConfiguration.Port,
				Handler: negroni,
			},
		}

		go func() {
			if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 {
				srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile)
			} else {
				srv.ListenAndServe()
			}
		}()
		log.Notice("Started")
		<-srv.StopChan()
		log.Notice("Stopped")
	}
}

func LoadConfig(configuration *Configuration, gloablConfiguration *GlobalConfiguration) (*mux.Router, error) {
	router := mux.NewRouter()
	router.NotFoundHandler = http.HandlerFunc(notFoundHandler)
	backends := map[string]http.Handler{}
	for frontendName, frontend := range configuration.Frontends {
		log.Debug("Creating frontend %s", frontendName)
		fwd, _ := forward.New(forward.Logger(oxyLogger))
		newRoute := router.NewRoute().Name(frontendName)
		for routeName, route := range frontend.Routes {
			log.Debug("Creating route %s %s:%s", routeName, route.Rule, route.Value)
			newRouteReflect := Invoke(newRoute, route.Rule, route.Value)
			newRoute = newRouteReflect[0].Interface().(*mux.Route)
		}
		if backends[frontend.Backend] == nil {
			log.Debug("Creating backend %s", frontend.Backend)
			lb, _ := roundrobin.New(fwd)
			rb, _ := roundrobin.NewRebalancer(lb, roundrobin.RebalancerLogger(oxyLogger))
			for serverName, server := range configuration.Backends[frontend.Backend].Servers {
				if url, err := url.Parse(server.Url); err != nil{
					return nil, err
				}else{
					log.Debug("Creating server %s %s", serverName, url.String())
					rb.UpsertServer(url, roundrobin.Weight(server.Weight))
				}
			}
			backends[frontend.Backend] = rb
		} else {
			log.Debug("Reusing backend %s", frontend.Backend)
		}
//		stream.New(backends[frontend.Backend], stream.Retry("IsNetworkError() && Attempts() <= " + strconv.Itoa(gloablConfiguration.Replay)), stream.Logger(oxyLogger))
		var negroni = negroni.New()
		negroni.Use(middlewares.NewCircuitBreaker(backends[frontend.Backend], cbreaker.Logger(oxyLogger)))
		newRoute.Handler(negroni)
		err := newRoute.GetError()
		if err != nil {
			log.Error("Error building route ", err)
		}
	}
	return router, nil
}

func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
	inputs := make([]reflect.Value, len(args))
	for i := range args {
		inputs[i] = reflect.ValueOf(args[i])
	}
	return reflect.ValueOf(any).MethodByName(name).Call(inputs)
}

func LoadFileConfig(file string) *GlobalConfiguration {
	configuration := NewGlobalConfiguration()
	if _, err := toml.DecodeFile(file, configuration); err != nil {
		log.Fatal("Error reading file ", err)
	}
	log.Debug("Global configuration loaded %+v", configuration)
	return configuration
}<|endoftext|>


<commit_before>package neurgo

type TrainingSample struct {

	// for each sensor in the network, provide a sample input vector
	sampleInputs [][]float64

	// for each actuator in the network, provide an expected output vector
	expectedOutputs [][]float64

}

type StochasticHillClimber struct {
	currentCandidate *NeuralNetwork
	currentOptimal *NeuralNetwork
}

type Trainer interface {
	train(neuralNet *NeuralNetwork, examples []*TrainingSample) *NeuralNetwork
}

func (shc *StochasticHillClimber) train(examples []*TrainingSample) *NeuralNetwork {
	return &NeuralNetwork{}
}
<commit_msg>pseudocode for trainer implementation<commit_after>package neurgo

type TrainingSample struct {

	// for each sensor in the network, provide a sample input vector
	sampleInputs [][]float64

	// for each actuator in the network, provide an expected output vector
	expectedOutputs [][]float64

}

type StochasticHillClimber struct {
	currentCandidate *NeuralNetwork
	currentOptimal *NeuralNetwork
}

type Trainer interface {
	train(neuralNet *NeuralNetwork, examples []*TrainingSample) *NeuralNetwork
}

func (shc *StochasticHillClimber) train(neuralNet *NeuralNetwork, examples []*TrainingSample) *NeuralNetwork {

	/*
	// Repeat

	// Apply NN to problem and save fitness
	fitness = neuralNet.FitnessScore(examples)

	// Save the genotype
	currentWinner := neuralNet.Copy()

	// Perturb synaptic weights and biases
	shc.PerturbParameters(neuralNet)

	// Re-Apply NN to problem
	newFitness := neuralNet.FitnessScore(examples)

	// If the fitness of the perturbed NN is higher, discard original NN and keep
	// the new.  If the fitness of original is higher, discard perturbed and keep
	// the old.
	if newFitness < fitness {
		neuralNet.RestoreFrom(currentWinner)
	}

	// Until - acceptable solution is found, or stopping condition reached

	// Return - genotype with the fittest combination of weights
        */

	return &NeuralNetwork{}
}
<|endoftext|>


<commit_before>// Package aws provides core functionality for making requests to AWS services.
package aws

// SDKName is the name of this AWS SDK
const SDKName = "aws-sdk-go"

// SDKVersion is the version of this SDK
const SDKVersion = "1.4.9"
<commit_msg>Tag release v1.4.10<commit_after>// Package aws provides core functionality for making requests to AWS services.
package aws

// SDKName is the name of this AWS SDK
const SDKName = "aws-sdk-go"

// SDKVersion is the version of this SDK
const SDKVersion = "1.4.10"
<|endoftext|>


<commit_before>package editor

import "github.com/elpinal/coco3/screen"

type visual struct {
	nvCommon

	start int
}

func newVisual(s streamSet, e *editor) *visual {
	return &visual{
		nvCommon: nvCommon{
			streamSet: s,
			editor:    e,
		},

		start: e.pos,
	}
}

func (v *visual) Mode() mode {
	return modeVisual
}

func (v *visual) Runes() []rune {
	return v.buf
}

func (v *visual) Position() int {
	return v.pos
}

func (v *visual) Message() []rune {
	return []rune("-- VISUAL --")
}

func (v *visual) Highlight() *screen.Hi {
	return &screen.Hi{
		Left:  min(v.start, v.pos),
		Right: constrain(max(v.start, v.pos)+1, 0, len(v.buf)),
	}
}

func (v *visual) Run() (end continuity, next mode, err error) {
	next = modeVisual
	r, _, err := v.in.ReadRune()
	if err != nil {
		return end, next, err
	}
	for ('1' <= r && r <= '9') || (v.count != 0 && r == '0') {
		v.count = v.count*10 + int(r-'0')
		r1, _, err := v.streamSet.in.ReadRune()
		if err != nil {
			return end, next, err
		}
		r = r1
	}
	if v.count == 0 {
		v.count = 1
	}
	cmd, ok := visualCommands[r]
	if !ok {
		return
	}
	if m := cmd(v, r); m != 0 {
		next = m
	}
	if next != modeInsert && v.pos == len(v.buf) {
		v.move(v.pos - 1)
	}
	v.count = 0
	return
}

type visualCommand = func(*visual, rune) mode

var visualCommands = map[rune]visualCommand{
	CharEscape: (*visual).escape,
	'$':        (*visual).endline,
	'0':        (*visual).beginline,
	'B':        (*visual).wordBack,
	'F':        (*visual).searchBackward,
	'b':        (*visual).wordBack,
	'd':        (*visual).delete,
	'f':        (*visual).search,
	'h':        (*visual).left,
	'l':        (*visual).right,
}

func (v *visual) escape(_ rune) mode {
	return modeNormal
}

func (v *visual) delete(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.delete(hi.Left, hi.Right)
	return modeNormal
}
<commit_msg>Support v_c command<commit_after>package editor

import "github.com/elpinal/coco3/screen"

type visual struct {
	nvCommon

	start int
}

func newVisual(s streamSet, e *editor) *visual {
	return &visual{
		nvCommon: nvCommon{
			streamSet: s,
			editor:    e,
		},

		start: e.pos,
	}
}

func (v *visual) Mode() mode {
	return modeVisual
}

func (v *visual) Runes() []rune {
	return v.buf
}

func (v *visual) Position() int {
	return v.pos
}

func (v *visual) Message() []rune {
	return []rune("-- VISUAL --")
}

func (v *visual) Highlight() *screen.Hi {
	return &screen.Hi{
		Left:  min(v.start, v.pos),
		Right: constrain(max(v.start, v.pos)+1, 0, len(v.buf)),
	}
}

func (v *visual) Run() (end continuity, next mode, err error) {
	next = modeVisual
	r, _, err := v.in.ReadRune()
	if err != nil {
		return end, next, err
	}
	for ('1' <= r && r <= '9') || (v.count != 0 && r == '0') {
		v.count = v.count*10 + int(r-'0')
		r1, _, err := v.streamSet.in.ReadRune()
		if err != nil {
			return end, next, err
		}
		r = r1
	}
	if v.count == 0 {
		v.count = 1
	}
	cmd, ok := visualCommands[r]
	if !ok {
		return
	}
	if m := cmd(v, r); m != 0 {
		next = m
	}
	if next != modeInsert && v.pos == len(v.buf) {
		v.move(v.pos - 1)
	}
	v.count = 0
	return
}

type visualCommand = func(*visual, rune) mode

var visualCommands = map[rune]visualCommand{
	CharEscape: (*visual).escape,
	'$':        (*visual).endline,
	'0':        (*visual).beginline,
	'B':        (*visual).wordBack,
	'F':        (*visual).searchBackward,
	'b':        (*visual).wordBack,
	'c':        (*visual).change,
	'd':        (*visual).delete,
	'f':        (*visual).search,
	'h':        (*visual).left,
	'l':        (*visual).right,
}

func (v *visual) escape(_ rune) mode {
	return modeNormal
}

func (v *visual) delete(_ rune) mode {
	hi := v.Highlight()
	v.nvCommon.delete(hi.Left, hi.Right)
	return modeNormal
}

func (v *visual) change(r rune) mode {
	_ = v.delete(r)
	return modeInsert
}
<|endoftext|>