<commit_before>package job

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

var validCpdfOutput = `0 "Bookmark One" 1
0 "Bookmark Two" 2
1 "Nested under Two" 3
0 "Bad chars in title: \" 123" 4
`
var expectedParseOutput = []Bookmark{
	Bookmark{0, "Bookmark One", 1},
	Bookmark{0, "Bookmark Two", 2},
	Bookmark{1, "Nested under Two", 3},
	Bookmark{0, `Bad chars in title: \" 123`, 4},
}

// Set up serveral mock varities of the cpdf.InfoCmd type.
type validOutputter struct{}
type invalidOutputter struct{}
type erroringOutputter struct{}

func (o *invalidOutputter) PageCount() (int, error)  { return 0, nil }
func (o *validOutputter) PageCount() (int, error)    { return 0, nil }
func (o *erroringOutputter) PageCount() (int, error) { return 0, nil }

func (o *validOutputter) ListBookmarks() (out []byte, err error) {
	out = []byte(validCpdfOutput)
	return
}
func (o *invalidOutputter) ListBookmarks() (out []byte, err error) {
	out = []byte("some invalid output")
	return
}
func (o *erroringOutputter) ListBookmarks() (out []byte, err error) {
	err = fmt.Errorf("ListBookmarks() threw an error!")
	return
}

func TestParsesInvalidBookmarks(t *testing.T) {
	bookmarks, _ := ExtractBookmarks(&invalidOutputter{})
	assert.Equal(t, bookmarks.len(), 0)
}

func TestHandlesPdfErrors(t *testing.T) {
	bookmarks, err := ExtractBookmarks(&erroringOutputter{})
	assert.Error(t, err)
	assert.Equal(t, bookmarks.len(), 0)
}

func TestParsesValidBookmarks(t *testing.T) {
	bookmarks, err := ExtractBookmarks(&validOutputter{})
	assert.NoError(t, err)
	assert.Equal(t, len(expectedParseOutput), bookmarks.len())
	assert.Equal(t, bookmarks.list, expectedParseOutput)
}

func TestBookmarkStringification(t *testing.T) {
	var cases = []struct {
		in      Bookmark
		out     string
		message string
	}{
		{Bookmark{0, `Blah`, 1}, `0 "Blah" 1`, "Normal bookmark output"},
		{Bookmark{0, `Bl"ah`, 1}, `0 "Bl\"ah" 1`, "Quotes contained in bookmark titles are properly escaped"},
	}
	for _, c := range cases {
		assert.Equal(t, c.in.String(), c.out, c.message)
	}
}
<commit_msg>BUILDFIX implement new interface method in mocks<commit_after>package job

import (
	"errors"
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

var validCpdfOutput = `0 "Bookmark One" 1
0 "Bookmark Two" 2
1 "Nested under Two" 3
0 "Bad chars in title: \" 123" 4
`
var expectedParseOutput = []Bookmark{
	Bookmark{0, "Bookmark One", 1},
	Bookmark{0, "Bookmark Two", 2},
	Bookmark{1, "Nested under Two", 3},
	Bookmark{0, `Bad chars in title: \" 123`, 4},
}

// Set up serveral mock varities of the cpdf.InfoCmd type.
type validOutputter struct{}
type invalidOutputter struct{}
type erroringOutputter struct{}

func (o *invalidOutputter) PageCount() (int, error)  { return 0, nil }
func (o *validOutputter) PageCount() (int, error)    { return 0, nil }
func (o *erroringOutputter) PageCount() (int, error) { return 0, nil }

func (o *validOutputter) ListBookmarks() (out []byte, err error) {
	out = []byte(validCpdfOutput)
	return
}
func (o *invalidOutputter) ListBookmarks() (out []byte, err error) {
	out = []byte("some invalid output")
	return
}
func (o *erroringOutputter) ListBookmarks() (out []byte, err error) {
	err = fmt.Errorf("ListBookmarks() threw an error!")
	return
}

func (o *invalidOutputter) Validate() error  { return errors.New("") }
func (o *validOutputter) Validate() error    { return errors.New("") }
func (o *erroringOutputter) Validate() error { return errors.New("") }

func TestParsesInvalidBookmarks(t *testing.T) {
	bookmarks, _ := ExtractBookmarks(&invalidOutputter{})
	assert.Equal(t, bookmarks.len(), 0)
}

func TestHandlesPdfErrors(t *testing.T) {
	bookmarks, err := ExtractBookmarks(&erroringOutputter{})
	assert.Error(t, err)
	assert.Equal(t, bookmarks.len(), 0)
}

func TestParsesValidBookmarks(t *testing.T) {
	bookmarks, err := ExtractBookmarks(&validOutputter{})
	assert.NoError(t, err)
	assert.Equal(t, len(expectedParseOutput), bookmarks.len())
	assert.Equal(t, bookmarks.list, expectedParseOutput)
}

func TestBookmarkStringification(t *testing.T) {
	var cases = []struct {
		in      Bookmark
		out     string
		message string
	}{
		{Bookmark{0, `Blah`, 1}, `0 "Blah" 1`, "Normal bookmark output"},
		{Bookmark{0, `Bl"ah`, 1}, `0 "Bl\"ah" 1`, "Quotes contained in bookmark titles are properly escaped"},
	}
	for _, c := range cases {
		assert.Equal(t, c.in.String(), c.out, c.message)
	}
}
<|endoftext|>


<commit_before>package locks

import (
	"context"
	"fmt"
	"time"

	"github.com/hashicorp/consul/api"
)

type ConsulLockPool struct {
	client *api.Client
}

func NewConsulLockPool(consulAddress string) (ConsulLockPool, error) {
	api.DefaultConfig()
	client, err := api.NewClient(&api.Config{Address: consulAddress})
	if err != nil {
		return ConsulLockPool{}, err
	}

	if err != nil {
		return ConsulLockPool{}, fmt.Errorf("session create err: %v", err)
	}

	return ConsulLockPool{
		client: client,
	}, nil
}

func (p ConsulLockPool) NewLock(lockName string, expiry time.Duration) ConsulLock {
	return ConsulLock{
		client:   p.client,
		lockName: lockName,
		expiry:   expiry,
	}
}

type ConsulLock struct {
	client   *api.Client
	lockName string
	expiry   time.Duration
	done     chan struct{}
}

func (l *ConsulLock) Lock(ctx context.Context) (chan struct{}, error) {
	sEntry := &api.SessionEntry{
		TTL:      l.expiry.String(),
		Behavior: "delete",
	}
	options := &api.WriteOptions{}
	options = options.WithContext(ctx)
	sID, _, err := l.client.Session().Create(sEntry, options)
	if err != nil {
		return nil, err
	}

	acquireKv := &api.KVPair{
		Session: sID,
		Key:     l.lockName,
		Value:   []byte(sID),
	}
	acquired, _, err := l.client.KV().Acquire(acquireKv, options)
	if err != nil {
		return nil, err
	}

	if !acquired {
		l.client.Session().Destroy(sID, options)
		return nil, nil
	}

	// auto renew session
	l.done = make(chan struct{})
	go func() {
		err = l.client.Session().RenewPeriodic(sEntry.TTL, sID, options, l.done)
		if err != nil {
			close(l.done)
		}
	}()

	return l.done, nil
}

func (l ConsulLock) Unlock(ctx context.Context) error {
	close(l.done)
	options := &api.WriteOptions{}
	options = options.WithContext(ctx)
	_, err := l.client.KV().Delete(l.lockName, options)
	return err
}

func (l ConsulLock) WaitForUnlock(ctx context.Context) error {
	options := &api.QueryOptions{}
	options = options.WithContext(ctx)

	done := make(chan error, 1)
	heartbeat := l.expiry / 2

	go func() {
		ticker := time.NewTicker(heartbeat)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				kv, _, err := l.client.KV().Get(l.lockName, options)
				if err != nil {
					done <- err
					return
				}
				if kv == nil {
					done <- nil
					return
				}
			}
		}

	}()
	err := <-done

	return err
}
<commit_msg>consul lock pointer receiver<commit_after>package locks

import (
	"context"
	"fmt"
	"time"

	"github.com/hashicorp/consul/api"
)

type ConsulLockPool struct {
	client *api.Client
}

func NewConsulLockPool(consulAddress string) (ConsulLockPool, error) {
	api.DefaultConfig()
	client, err := api.NewClient(&api.Config{Address: consulAddress})
	if err != nil {
		return ConsulLockPool{}, err
	}

	if err != nil {
		return ConsulLockPool{}, fmt.Errorf("session create err: %v", err)
	}

	return ConsulLockPool{
		client: client,
	}, nil
}

func (p ConsulLockPool) NewLock(lockName string, expiry time.Duration) *ConsulLock {
	return &ConsulLock{
		client:   p.client,
		lockName: lockName,
		expiry:   expiry,
	}
}

type ConsulLock struct {
	client   *api.Client
	lockName string
	expiry   time.Duration
	done     chan struct{}
}

func (l *ConsulLock) Lock(ctx context.Context) (chan struct{}, error) {
	sEntry := &api.SessionEntry{
		TTL:      l.expiry.String(),
		Behavior: "delete",
	}
	options := &api.WriteOptions{}
	options = options.WithContext(ctx)
	sID, _, err := l.client.Session().Create(sEntry, options)
	if err != nil {
		return nil, err
	}

	acquireKv := &api.KVPair{
		Session: sID,
		Key:     l.lockName,
		Value:   []byte(sID),
	}
	acquired, _, err := l.client.KV().Acquire(acquireKv, options)
	if err != nil {
		return nil, err
	}

	if !acquired {
		l.client.Session().Destroy(sID, options)
		return nil, nil
	}

	// auto renew session
	l.done = make(chan struct{})
	go func() {
		err = l.client.Session().RenewPeriodic(sEntry.TTL, sID, options, l.done)
		if err != nil {
			close(l.done)
		}
	}()

	return l.done, nil
}

func (l ConsulLock) Unlock(ctx context.Context) error {
	close(l.done)
	options := &api.WriteOptions{}
	options = options.WithContext(ctx)
	_, err := l.client.KV().Delete(l.lockName, options)
	return err
}

func (l ConsulLock) WaitForUnlock(ctx context.Context) error {
	options := &api.QueryOptions{}
	options = options.WithContext(ctx)

	done := make(chan error, 1)
	heartbeat := l.expiry / 2

	go func() {
		ticker := time.NewTicker(heartbeat)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				kv, _, err := l.client.KV().Get(l.lockName, options)
				if err != nil {
					done <- err
					return
				}
				if kv == nil {
					done <- nil
					return
				}
			}
		}

	}()
	err := <-done

	return err
}
<|endoftext|>


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

// Package main is the main entry point for the app.
package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"

	"go.chromium.org/luci/common/data/rand/mathrand"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/proto/access"
	"go.chromium.org/luci/grpc/prpc"
	"go.chromium.org/luci/server"
	"go.chromium.org/luci/server/gaeemulation"
	"go.chromium.org/luci/server/module"
	"go.chromium.org/luci/server/router"
	"go.chromium.org/luci/server/tq"

	// Enable datastore transactional tasks support.
	_ "go.chromium.org/luci/server/tq/txn/datastore"

	"go.chromium.org/luci/buildbucket/appengine/rpc"
	pb "go.chromium.org/luci/buildbucket/proto"
)

// isBeefy returns whether the request was intended for the beefy service.
func isBeefy(req *http.Request) bool {
	return strings.Contains(req.Host, "beefy")
}

// isDev returns whether the request was intended for the dev instance.
func isDev(req *http.Request) bool {
	return strings.HasSuffix(req.Host, "-dev.appspot.com")
}

func main() {
	mods := []module.Module{
		gaeemulation.NewModuleFromFlags(),
		tq.NewModuleFromFlags(),
	}

	server.Main(nil, mods, func(srv *server.Server) error {
		// Proxy buildbucket.v2.Builds pRPC requests back to the Python
		// service in order to achieve a programmatic traffic split.
		// Because of the way dispatch routes work, requests are proxied
		// to a copy of the Python service hosted at a different path.
		// TODO(crbug/1042991): Remove the proxy once the go service handles all traffic.
		pythonURL, err := url.Parse(fmt.Sprintf("https://default-dot-%s.appspot.com/python", srv.Options.CloudProject))
		if err != nil {
			panic(err)
		}
		beefyURL, err := url.Parse(fmt.Sprintf("https://beefy-dot-%s.appspot.com/python", srv.Options.CloudProject))
		if err != nil {
			panic(err)
		}
		prx := httputil.NewSingleHostReverseProxy(pythonURL)
		prx.Director = func(req *http.Request) {
			target := pythonURL
			if isBeefy(req) {
				target = beefyURL
			}
			// According to net.Request documentation, setting Host is unnecessary
			// because URL.Host is supposed to be used for outbound requests.
			// However, on GAE, it seems that req.Host is incorrectly used.
			req.Host = target.Host
			req.URL.Scheme = target.Scheme
			req.URL.Host = target.Host
			req.URL.Path = fmt.Sprintf("%s%s", target.Path, req.URL.Path)
		}
		// makeOverride returns a prpc.Override which allows the given percentage of requests
		// through to this service, proxying the remainder to Python.
		makeOverride := func(prodPct, devPct int) func(*router.Context) bool {
			return func(ctx *router.Context) bool {
				// TODO(crbug/1090540): remove env k-v
				ctx.Context = context.WithValue(ctx.Context, "env", "Prod")
				pct := prodPct
				if isDev(ctx.Request) {
					pct = devPct
					// TODO(crbug/1090540): remove env k-v
					ctx.Context = context.WithValue(ctx.Context, "env", "Dev")
				}
				switch val := ctx.Request.Header.Get("Should-Proxy"); val {
				case "true":
					pct = 0
					logging.Debugf(ctx.Context, "request demanded to be proxied")
				case "false":
					pct = 100
					logging.Debugf(ctx.Context, "request demanded not to be proxied")
				}
				if mathrand.Intn(ctx.Context, 100) < pct {
					return false
				}
				target := pythonURL
				if isBeefy(ctx.Request) {
					target = beefyURL
				}
				logging.Debugf(ctx.Context, "proxying request to %s", target)
				prx.ServeHTTP(ctx.Writer, ctx.Request)
				return true
			}
		}

		srv.PRPC.AccessControl = prpc.AllowOriginAll
		access.RegisterAccessServer(srv.PRPC, &access.UnimplementedAccessServer{})
		pb.RegisterBuildsServer(srv.PRPC, rpc.NewBuilds())
		pb.RegisterBuildersServer(srv.PRPC, rpc.NewBuilders())
		// TODO(crbug/1082369): Remove this workaround once field masks can be decoded.
		srv.PRPC.HackFixFieldMasksForJSON = true

		// makeOverride(prod % -> Go, dev % -> Go).
		srv.PRPC.RegisterOverride("buildbucket.v2.Builds", "CancelBuild", makeOverride(0, 0))
		srv.PRPC.RegisterOverride("buildbucket.v2.Builds", "ScheduleBuild", makeOverride(0, 0))
		srv.PRPC.RegisterOverride("buildbucket.v2.Builds", "UpdateBuild", makeOverride(0, 100))
		return nil
	})
}
<commit_msg>Revert "[buildbucket] set 0% traffic for UpdateBuild() in default-go"<commit_after>// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main is the main entry point for the app.
package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"

	"go.chromium.org/luci/common/data/rand/mathrand"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/proto/access"
	"go.chromium.org/luci/grpc/prpc"
	"go.chromium.org/luci/server"
	"go.chromium.org/luci/server/gaeemulation"
	"go.chromium.org/luci/server/module"
	"go.chromium.org/luci/server/router"
	"go.chromium.org/luci/server/tq"

	// Enable datastore transactional tasks support.
	_ "go.chromium.org/luci/server/tq/txn/datastore"

	"go.chromium.org/luci/buildbucket/appengine/rpc"
	pb "go.chromium.org/luci/buildbucket/proto"
)

// isBeefy returns whether the request was intended for the beefy service.
func isBeefy(req *http.Request) bool {
	return strings.Contains(req.Host, "beefy")
}

// isDev returns whether the request was intended for the dev instance.
func isDev(req *http.Request) bool {
	return strings.HasSuffix(req.Host, "-dev.appspot.com")
}

func main() {
	mods := []module.Module{
		gaeemulation.NewModuleFromFlags(),
		tq.NewModuleFromFlags(),
	}

	server.Main(nil, mods, func(srv *server.Server) error {
		// Proxy buildbucket.v2.Builds pRPC requests back to the Python
		// service in order to achieve a programmatic traffic split.
		// Because of the way dispatch routes work, requests are proxied
		// to a copy of the Python service hosted at a different path.
		// TODO(crbug/1042991): Remove the proxy once the go service handles all traffic.
		pythonURL, err := url.Parse(fmt.Sprintf("https://default-dot-%s.appspot.com/python", srv.Options.CloudProject))
		if err != nil {
			panic(err)
		}
		beefyURL, err := url.Parse(fmt.Sprintf("https://beefy-dot-%s.appspot.com/python", srv.Options.CloudProject))
		if err != nil {
			panic(err)
		}
		prx := httputil.NewSingleHostReverseProxy(pythonURL)
		prx.Director = func(req *http.Request) {
			target := pythonURL
			if isBeefy(req) {
				target = beefyURL
			}
			// According to net.Request documentation, setting Host is unnecessary
			// because URL.Host is supposed to be used for outbound requests.
			// However, on GAE, it seems that req.Host is incorrectly used.
			req.Host = target.Host
			req.URL.Scheme = target.Scheme
			req.URL.Host = target.Host
			req.URL.Path = fmt.Sprintf("%s%s", target.Path, req.URL.Path)
		}
		// makeOverride returns a prpc.Override which allows the given percentage of requests
		// through to this service, proxying the remainder to Python.
		makeOverride := func(prodPct, devPct int) func(*router.Context) bool {
			return func(ctx *router.Context) bool {
				// TODO(crbug/1090540): remove env k-v
				ctx.Context = context.WithValue(ctx.Context, "env", "Prod")
				pct := prodPct
				if isDev(ctx.Request) {
					pct = devPct
					// TODO(crbug/1090540): remove env k-v
					ctx.Context = context.WithValue(ctx.Context, "env", "Dev")
				}
				switch val := ctx.Request.Header.Get("Should-Proxy"); val {
				case "true":
					pct = 0
					logging.Debugf(ctx.Context, "request demanded to be proxied")
				case "false":
					pct = 100
					logging.Debugf(ctx.Context, "request demanded not to be proxied")
				}
				if mathrand.Intn(ctx.Context, 100) < pct {
					return false
				}
				target := pythonURL
				if isBeefy(ctx.Request) {
					target = beefyURL
				}
				logging.Debugf(ctx.Context, "proxying request to %s", target)
				prx.ServeHTTP(ctx.Writer, ctx.Request)
				return true
			}
		}

		srv.PRPC.AccessControl = prpc.AllowOriginAll
		access.RegisterAccessServer(srv.PRPC, &access.UnimplementedAccessServer{})
		pb.RegisterBuildsServer(srv.PRPC, rpc.NewBuilds())
		pb.RegisterBuildersServer(srv.PRPC, rpc.NewBuilders())
		// TODO(crbug/1082369): Remove this workaround once field masks can be decoded.
		srv.PRPC.HackFixFieldMasksForJSON = true

		// makeOverride(prod % -> Go, dev % -> Go).
		srv.PRPC.RegisterOverride("buildbucket.v2.Builds", "CancelBuild", makeOverride(0, 0))
		srv.PRPC.RegisterOverride("buildbucket.v2.Builds", "ScheduleBuild", makeOverride(0, 0))
		return nil
	})
}
<|endoftext|>


<commit_before>package common

import (
	"cgl.tideland.biz/identifier"
	"encoding/hex"
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
	"os"
)

type StepKeyPair struct {
	Debug        bool
	DebugKeyPath string

	keyName string
}

func (s *StepKeyPair) Run(state map[string]interface{}) multistep.StepAction {
	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Creating temporary keypair for this instance...")
	keyName := fmt.Sprintf("packer %s", hex.EncodeToString(identifier.NewUUID().Raw()))
	log.Printf("temporary keypair name: %s", keyName)
	keyResp, err := ec2conn.CreateKeyPair(keyName)
	if err != nil {
		state["error"] = fmt.Errorf("Error creating temporary keypair: %s", err)
		return multistep.ActionHalt
	}

	// Set the keyname so we know to delete it later
	s.keyName = keyName

	// Set some state data for use in future steps
	state["keyPair"] = keyName
	state["privateKey"] = keyResp.KeyMaterial

	// If we're in debug mode, output the private key to the working
	// directory.
	if s.Debug {
		ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
		f, err := os.Create(s.DebugKeyPath)
		if err != nil {
			state["error"] = fmt.Errorf("Error saving debug key: %s", err)
			return multistep.ActionHalt
		}
		defer f.Close()

		if _, err := f.Write([]byte(keyResp.KeyMaterial)); err != nil {
			state["error"] = fmt.Errorf("Error saving debug key: %s", err)
			return multistep.ActionHalt
		}
	}

	return multistep.ActionContinue
}

func (s *StepKeyPair) Cleanup(state map[string]interface{}) {
	// If no key name is set, then we never created it, so just return
	if s.keyName == "" {
		return
	}

	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Deleting temporary keypair...")
	_, err := ec2conn.DeleteKeyPair(s.keyName)
	if err != nil {
		ui.Error(fmt.Sprintf(
			"Error cleaning up keypair. Please delete the key manually: %s", s.keyName))
	}
}
<commit_msg>builder/amazon: chmod debug key so it is ssh-ready<commit_after>package common

import (
	"cgl.tideland.biz/identifier"
	"encoding/hex"
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"log"
	"os"
)

type StepKeyPair struct {
	Debug        bool
	DebugKeyPath string

	keyName string
}

func (s *StepKeyPair) Run(state map[string]interface{}) multistep.StepAction {
	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Creating temporary keypair for this instance...")
	keyName := fmt.Sprintf("packer %s", hex.EncodeToString(identifier.NewUUID().Raw()))
	log.Printf("temporary keypair name: %s", keyName)
	keyResp, err := ec2conn.CreateKeyPair(keyName)
	if err != nil {
		state["error"] = fmt.Errorf("Error creating temporary keypair: %s", err)
		return multistep.ActionHalt
	}

	// Set the keyname so we know to delete it later
	s.keyName = keyName

	// Set some state data for use in future steps
	state["keyPair"] = keyName
	state["privateKey"] = keyResp.KeyMaterial

	// If we're in debug mode, output the private key to the working
	// directory.
	if s.Debug {
		ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
		f, err := os.Create(s.DebugKeyPath)
		if err != nil {
			state["error"] = fmt.Errorf("Error saving debug key: %s", err)
			return multistep.ActionHalt
		}
		defer f.Close()

		// Write the key out
		if _, err := f.Write([]byte(keyResp.KeyMaterial)); err != nil {
			state["error"] = fmt.Errorf("Error saving debug key: %s", err)
			return multistep.ActionHalt
		}

		// Chmod it so that it is SSH ready
		if err := f.Chmod(0600); err != nil {
			state["error"] = fmt.Errorf("Error setting permissions of debug key: %s", err)
			return multistep.ActionHalt
		}
	}

	return multistep.ActionContinue
}

func (s *StepKeyPair) Cleanup(state map[string]interface{}) {
	// If no key name is set, then we never created it, so just return
	if s.keyName == "" {
		return
	}

	ec2conn := state["ec2"].(*ec2.EC2)
	ui := state["ui"].(packer.Ui)

	ui.Say("Deleting temporary keypair...")
	_, err := ec2conn.DeleteKeyPair(s.keyName)
	if err != nil {
		ui.Error(fmt.Sprintf(
			"Error cleaning up keypair. Please delete the key manually: %s", s.keyName))
	}
}
<|endoftext|>


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

package sith

import (
	"sync"
	"time"

	"code.google.com/p/portaudio-go/portaudio"
	"github.com/op/go-libspotify/spotify"
)

var (
	// audioInputBufferSize is the number of delivered data from libspotify before
	// we start rejecting it to deliver any more.
	audioInputBufferSize = 16

	// audioOutputBufferSize is the maximum number of bytes to buffer before
	// passing it to PortAudio.
	audioOutputBufferSize = 8192

	// audioErrorDelay is the duration to delay between errors when setting up the
	// audio stream.
	audioErrorDelay = time.Second
)

// audio wraps the delivered Spotify data into a single struct.
type audio struct {
	format spotify.AudioFormat
	frames []byte
}

// audioWriter takes audio from libspotify and outputs it through PortAudio.
type audioWriter struct {
	input chan audio

	quit chan bool
	err  chan error
	wg   sync.WaitGroup
}

// newAudioWriter creates a new audioWriter handler.
func newAudioWriter() (audioWriter, error) {
	w := audioWriter{
		input: make(chan audio, audioInputBufferSize),
		quit:  make(chan bool, 1),
	}

	stream, err := newPortAudioStream()
	if err != nil {
		return w, err
	}

	w.wg.Add(1)
	go w.streamWriter(stream)
	return w, nil
}

// Close stops and closes the audio stream and terminates PortAudio.
func (w *audioWriter) Close() error {
	w.quit <- true
	w.wg.Wait()
	return nil
}

func (w *audioWriter) Error() <-chan error {
	return w.err
}

// WriteAudio implements the spotify.AudioWriter interface.
func (w *audioWriter) WriteAudio(format spotify.AudioFormat, frames []byte) int {
	select {
	case w.input <- audio{format, frames}:
		return len(frames)
	default:
		return 0
	}
}

// streamWriter reads data from the input buffer and writes it to the output
// portaudio buffer.
func (w *audioWriter) streamWriter(stream portAudioStream) {
	defer w.wg.Done()
	defer stream.Close()

	buffer := make([]int16, audioOutputBufferSize)
	output := buffer[:]

	for {
		// Wait for input data or signal to quit.
		var input audio
		select {
		case input = <-w.input:
		case <-w.quit:
			return
		}

		// Initialize the audio stream based on the specification of the input format.
		err := stream.Stream(&output, input.format.Channels, input.format.SampleRate)
		if err != nil {
			select {
			case w.err <- err:
			default:
				log.Error("Failed to prepare audio stream: %s", err)
				time.Sleep(audioErrorDelay)
			}
			continue
		}

		// Decode the incoming data which is expected to be 2 channels and
		// delivered as int16 in []byte, hence we need to convert it.
		i := 0
		for i < len(input.frames) {
			j := 0
			for j < len(buffer) && i < len(input.frames) {
				buffer[j] = int16(input.frames[i]) | int16(input.frames[i+1])<<8
				j += 1
				i += 2
			}

			output = buffer[:j]
			stream.Write()
		}
	}
}

// portAudioStream manages the output stream through PortAudio when requirement
// for number of channels or sample rate changes.
type portAudioStream struct {
	device *portaudio.DeviceInfo
	stream *portaudio.Stream

	channels   int
	sampleRate int
}

// newPortAudioStream creates a new portAudioStream using the default output
// device found on the system. It will also take care of automatically
// initialise the PortAudio API.
func newPortAudioStream() (portAudioStream, error) {
	var s portAudioStream
	if err := portaudio.Initialize(); err != nil {
		return s, err
	}
	out, err := portaudio.DefaultHostApi()
	if err != nil {
		portaudio.Terminate()
		return s, err
	}
	s.device = out.DefaultOutputDevice
	return s, nil
}

// Close closes any open audio stream and terminates the PortAudio API.
func (s *portAudioStream) Close() error {
	s.reset()
	return portaudio.Terminate()
}

func (s *portAudioStream) reset() error {
	if s.stream != nil {
		if err := s.stream.Stop(); err != nil {
			return err
		}
		if err := s.stream.Close(); err != nil {
			return err
		}
	}
	return nil
}

// Stream prepares the stream to go through the specified buffer, channels and
// sample rate, re-using any previously defined stream or setting up a new one.
func (s *portAudioStream) Stream(buffer *[]int16, channels int, sampleRate int) error {
	if s.stream == nil || s.channels != channels || s.sampleRate != sampleRate {
		s.reset()

		params := portaudio.HighLatencyParameters(nil, s.device)
		params.Output.Channels = channels
		params.SampleRate = float64(sampleRate)
		params.FramesPerBuffer = len(*buffer)

		stream, err := portaudio.OpenStream(params, buffer)
		if err != nil {
			return err
		}
		if err := stream.Start(); err != nil {
			stream.Close()
			return err
		}

		s.stream = stream
		s.channels = channels
		s.sampleRate = sampleRate
	}
	return nil
}

// Write pushes the data in the buffer through to PortAudio.
func (s *portAudioStream) Write() error {
	return s.stream.Write()
}
<commit_msg>Minimise thread switching during audio playback<commit_after>// Copyright 2013-2014 Örjan Persson
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sith

import (
	"runtime"
	"sync"
	"time"

	"code.google.com/p/portaudio-go/portaudio"
	"github.com/op/go-libspotify/spotify"
)

var (
	// audioInputBufferSize is the number of delivered data from libspotify before
	// we start rejecting it to deliver any more.
	audioInputBufferSize = 8

	// audioOutputBufferSize is the maximum number of bytes to buffer before
	// passing it to PortAudio.
	audioOutputBufferSize = 8192

	// audioErrorDelay is the duration to delay between errors when setting up the
	// audio stream.
	audioErrorDelay = time.Second
)

// audio wraps the delivered Spotify data into a single struct.
type audio struct {
	format spotify.AudioFormat
	frames []byte
}

// audioWriter takes audio from libspotify and outputs it through PortAudio.
type audioWriter struct {
	input chan audio

	quit chan bool
	err  chan error
	wg   sync.WaitGroup
}

// newAudioWriter creates a new audioWriter handler.
func newAudioWriter() (audioWriter, error) {
	w := audioWriter{
		input: make(chan audio, audioInputBufferSize),
		quit:  make(chan bool, 1),
	}

	stream, err := newPortAudioStream()
	if err != nil {
		return w, err
	}

	w.wg.Add(1)
	go w.streamWriter(stream)
	return w, nil
}

// Close stops and closes the audio stream and terminates PortAudio.
func (w *audioWriter) Close() error {
	w.quit <- true
	w.wg.Wait()
	return nil
}

func (w *audioWriter) Error() <-chan error {
	return w.err
}

// WriteAudio implements the spotify.AudioWriter interface.
func (w *audioWriter) WriteAudio(format spotify.AudioFormat, frames []byte) int {
	select {
	case w.input <- audio{format, frames}:
		return len(frames)
	default:
		return 0
	}
}

// streamWriter reads data from the input buffer and writes it to the output
// portaudio buffer.
func (w *audioWriter) streamWriter(stream portAudioStream) {
	defer w.wg.Done()
	defer stream.Close()

	runtime.LockOSThread()
	buffer := make([]int16, audioOutputBufferSize)
	output := buffer[:]

	for {
		// Wait for input data or signal to quit.
		var input audio
		select {
		case input = <-w.input:
		case <-w.quit:
			return
		}

		// Initialize the audio stream based on the specification of the input format.
		err := stream.Stream(&output, input.format.Channels, input.format.SampleRate)
		if err != nil {
			select {
			case w.err <- err:
			default:
				log.Error("Failed to prepare audio stream: %s", err)
				time.Sleep(audioErrorDelay)
			}
			continue
		}

		// Decode the incoming data which is expected to be 2 channels and
		// delivered as int16 in []byte, hence we need to convert it.
		i := 0
		for i < len(input.frames) {
			j := 0
			for j < len(buffer) && i < len(input.frames) {
				buffer[j] = int16(input.frames[i]) | int16(input.frames[i+1])<<8
				j += 1
				i += 2
			}

			output = buffer[:j]
			stream.Write()
		}
	}
}

// portAudioStream manages the output stream through PortAudio when requirement
// for number of channels or sample rate changes.
type portAudioStream struct {
	device *portaudio.DeviceInfo
	stream *portaudio.Stream

	channels   int
	sampleRate int
}

// newPortAudioStream creates a new portAudioStream using the default output
// device found on the system. It will also take care of automatically
// initialise the PortAudio API.
func newPortAudioStream() (portAudioStream, error) {
	var s portAudioStream
	if err := portaudio.Initialize(); err != nil {
		return s, err
	}
	out, err := portaudio.DefaultHostApi()
	if err != nil {
		portaudio.Terminate()
		return s, err
	}
	s.device = out.DefaultOutputDevice
	return s, nil
}

// Close closes any open audio stream and terminates the PortAudio API.
func (s *portAudioStream) Close() error {
	s.reset()
	return portaudio.Terminate()
}

func (s *portAudioStream) reset() error {
	if s.stream != nil {
		if err := s.stream.Stop(); err != nil {
			return err
		}
		if err := s.stream.Close(); err != nil {
			return err
		}
	}
	return nil
}

// Stream prepares the stream to go through the specified buffer, channels and
// sample rate, re-using any previously defined stream or setting up a new one.
func (s *portAudioStream) Stream(buffer *[]int16, channels int, sampleRate int) error {
	if s.stream == nil || s.channels != channels || s.sampleRate != sampleRate {
		s.reset()

		params := portaudio.HighLatencyParameters(nil, s.device)
		params.Output.Channels = channels
		params.SampleRate = float64(sampleRate)
		params.FramesPerBuffer = len(*buffer)

		stream, err := portaudio.OpenStream(params, buffer)
		if err != nil {
			return err
		}
		if err := stream.Start(); err != nil {
			stream.Close()
			return err
		}

		s.stream = stream
		s.channels = channels
		s.sampleRate = sampleRate
	}
	return nil
}

// Write pushes the data in the buffer through to PortAudio.
func (s *portAudioStream) Write() error {
	return s.stream.Write()
}
<|endoftext|>


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

import (
	"encoding/json"
	"fmt"
	"github.com/liangdas/mqant/log/beego"
)

func NewBeegoLogger(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) *logs.BeeLogger {
	log := logs.NewLogger()
	log.ProcessID = ProcessID
	log.EnableFuncCallDepth(true)
	log.Async(1024) //同步打印,可能影响性能
	log.SetLogFuncCallDepth(4)
	if debug {
		//控制台
		log.SetLogger(logs.AdapterConsole)
	}
	if contenttype, ok := settings["contenttype"]; ok {
		log.SetContentType(contenttype.(string))
	}
	if f, ok := settings["file"]; ok {
		ff := f.(map[string]interface{})
		Prefix := ""
		if prefix, ok := ff["prefix"]; ok {
			Prefix = prefix.(string)
		}
		Suffix := ".log"
		if suffix, ok := ff["suffix"]; ok {
			Suffix = suffix.(string)
		}
		ff["filename"] = fmt.Sprintf("%s/%v%s%s", Logdir, Prefix, ProcessID, Suffix)
		config, err := json.Marshal(ff)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterFile, string(config))
	}
	if f, ok := settings["multifile"]; ok {
		multifile := f.(map[string]interface{})
		Prefix := ""
		if prefix, ok := multifile["prefix"]; ok {
			Prefix = prefix.(string)
		}
		Suffix := ".log"
		if suffix, ok := multifile["suffix"]; ok {
			Suffix = suffix.(string)
		}
		multifile["filename"] = fmt.Sprintf("%s/%v%s%s", Logdir, Prefix, ProcessID, Suffix)
		config, err := json.Marshal(multifile)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterMultiFile, string(config))
	}
	if dingtalk, ok := settings["dingtalk"]; ok {
		config, err := json.Marshal(dingtalk)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterDingtalk, string(config))
	}
	if slack, ok := settings["slack"]; ok {
		config, err := json.Marshal(slack)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterSlack, string(config))
	}
	if jianliao, ok := settings["jianliao"]; ok {
		config, err := json.Marshal(jianliao)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterJianLiao, string(config))
	}
	if conn, ok := settings["conn"]; ok {
		config, err := json.Marshal(conn)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterConn, string(config))
	}
	if smtp, ok := settings["smtp"]; ok {
		config, err := json.Marshal(smtp)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterMail, string(config))
	}
	if es, ok := settings["es"]; ok {
		config, err := json.Marshal(es)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterEs, string(config))
	}
	return log
}
<commit_msg>=关闭日志缓存<commit_after>// Copyright 2014 mqant Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package log

import (
	"encoding/json"
	"fmt"
	"github.com/liangdas/mqant/log/beego"
)

func NewBeegoLogger(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) *logs.BeeLogger {
	log := logs.NewLogger()
	log.ProcessID = ProcessID
	log.EnableFuncCallDepth(true)
	//log.Async(1024) //同步打印,可能影响性能
	log.SetLogFuncCallDepth(4)
	if debug {
		//控制台
		log.SetLogger(logs.AdapterConsole)
	}
	if contenttype, ok := settings["contenttype"]; ok {
		log.SetContentType(contenttype.(string))
	}
	if f, ok := settings["file"]; ok {
		ff := f.(map[string]interface{})
		Prefix := ""
		if prefix, ok := ff["prefix"]; ok {
			Prefix = prefix.(string)
		}
		Suffix := ".log"
		if suffix, ok := ff["suffix"]; ok {
			Suffix = suffix.(string)
		}
		ff["filename"] = fmt.Sprintf("%s/%v%s%s", Logdir, Prefix, ProcessID, Suffix)
		config, err := json.Marshal(ff)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterFile, string(config))
	}
	if f, ok := settings["multifile"]; ok {
		multifile := f.(map[string]interface{})
		Prefix := ""
		if prefix, ok := multifile["prefix"]; ok {
			Prefix = prefix.(string)
		}
		Suffix := ".log"
		if suffix, ok := multifile["suffix"]; ok {
			Suffix = suffix.(string)
		}
		multifile["filename"] = fmt.Sprintf("%s/%v%s%s", Logdir, Prefix, ProcessID, Suffix)
		config, err := json.Marshal(multifile)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterMultiFile, string(config))
	}
	if dingtalk, ok := settings["dingtalk"]; ok {
		config, err := json.Marshal(dingtalk)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterDingtalk, string(config))
	}
	if slack, ok := settings["slack"]; ok {
		config, err := json.Marshal(slack)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterSlack, string(config))
	}
	if jianliao, ok := settings["jianliao"]; ok {
		config, err := json.Marshal(jianliao)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterJianLiao, string(config))
	}
	if conn, ok := settings["conn"]; ok {
		config, err := json.Marshal(conn)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterConn, string(config))
	}
	if smtp, ok := settings["smtp"]; ok {
		config, err := json.Marshal(smtp)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterMail, string(config))
	}
	if es, ok := settings["es"]; ok {
		config, err := json.Marshal(es)
		if err != nil {
			logs.Error(err)
		}
		log.SetLogger(logs.AdapterEs, string(config))
	}
	return log
}
<|endoftext|>


<commit_before>package logical

import (
	"errors"
	"fmt"
	"reflect"
	"time"

	"github.com/mitchellh/copystructure"
)

const (
	// HTTPContentType can be specified in the Data field of a Response
	// so that the HTTP front end can specify a custom Content-Type associated
	// with the HTTPRawBody. This can only be used for non-secrets, and should
	// be avoided unless absolutely necessary, such as implementing a specification.
	// The value must be a string.
	HTTPContentType = "http_content_type"

	// HTTPRawBody is the raw content of the HTTP body that goes with the HTTPContentType.
	// This can only be specified for non-secrets, and should should be similarly
	// avoided like the HTTPContentType. The value must be a byte slice.
	HTTPRawBody = "http_raw_body"

	// HTTPStatusCode is the response code of the HTTP body that goes with the HTTPContentType.
	// This can only be specified for non-secrets, and should should be similarly
	// avoided like the HTTPContentType. The value must be an integer.
	HTTPStatusCode = "http_status_code"
)

type ResponseWrapInfo struct {
	// Setting to non-zero specifies that the response should be wrapped.
	// Specifies the desired TTL of the wrapping token.
	TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"`

	// The token containing the wrapped response
	Token string `json:"token" structs:"token" mapstructure:"token"`

	// The creation time. This can be used with the TTL to figure out an
	// expected expiration.
	CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"cration_time"`

	// If the contained response is the output of a token creation call, the
	// created token's accessor will be accessible here
	WrappedAccessor string `json:"wrapped_accessor" structs:"wrapped_accessor" mapstructure:"wrapped_accessor"`

	// The format to use. This doesn't get returned, it's only internal.
	Format string `json:"format" structs:"format" mapstructure:"format"`
}

// Response is a struct that stores the response of a request.
// It is used to abstract the details of the higher level request protocol.
type Response struct {
	// Secret, if not nil, denotes that this response represents a secret.
	Secret *Secret `json:"secret" structs:"secret" mapstructure:"secret"`

	// Auth, if not nil, contains the authentication information for
	// this response. This is only checked and means something for
	// credential backends.
	Auth *Auth `json:"auth" structs:"auth" mapstructure:"auth"`

	// Response data is an opaque map that must have string keys. For
	// secrets, this data is sent down to the user as-is. To store internal
	// data that you don't want the user to see, store it in
	// Secret.InternalData.
	Data map[string]interface{} `json:"data" structs:"data" mapstructure:"data"`

	// Redirect is an HTTP URL to redirect to for further authentication.
	// This is only valid for credential backends. This will be blanked
	// for any logical backend and ignored.
	Redirect string `json:"redirect" structs:"redirect" mapstructure:"redirect"`

	// Warnings allow operations or backends to return warnings in response
	// to user actions without failing the action outright.
	// Making it private helps ensure that it is easy for various parts of
	// Vault (backend, core, etc.) to add warnings without accidentally
	// replacing what exists.
	warnings []string `json:"warnings" structs:"warnings" mapstructure:"warnings"`

	// Information for wrapping the response in a cubbyhole
	WrapInfo *ResponseWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"`
}

func init() {
	copystructure.Copiers[reflect.TypeOf(Response{})] = func(v interface{}) (interface{}, error) {
		input := v.(Response)
		ret := Response{
			Redirect: input.Redirect,
		}

		if input.Secret != nil {
			retSec, err := copystructure.Copy(input.Secret)
			if err != nil {
				return nil, fmt.Errorf("error copying Secret: %v", err)
			}
			ret.Secret = retSec.(*Secret)
		}

		if input.Auth != nil {
			retAuth, err := copystructure.Copy(input.Auth)
			if err != nil {
				return nil, fmt.Errorf("error copying Auth: %v", err)
			}
			ret.Auth = retAuth.(*Auth)
		}

		if input.Data != nil {
			retData, err := copystructure.Copy(&input.Data)
			if err != nil {
				return nil, fmt.Errorf("error copying Data: %v", err)
			}
			ret.Data = retData.(*map[string]interface{})
		}

		if input.Warnings() != nil {
			for _, warning := range input.Warnings() {
				ret.AddWarning(warning)
			}
		}

		if input.WrapInfo != nil {
			retWrapInfo, err := copystructure.Copy(input.WrapInfo)
			if err != nil {
				return nil, fmt.Errorf("error copying WrapInfo: %v", err)
			}
			ret.WrapInfo = retWrapInfo.(*ResponseWrapInfo)
		}

		return &ret, nil
	}
}

// AddWarning adds a warning into the response's warning list
func (r *Response) AddWarning(warning string) {
	if r.warnings == nil {
		r.warnings = make([]string, 0, 1)
	}
	r.warnings = append(r.warnings, warning)
}

// Warnings returns the list of warnings set on the response
func (r *Response) Warnings() []string {
	return r.warnings
}

// ClearWarnings clears the response's warning list
func (r *Response) ClearWarnings() {
	r.warnings = make([]string, 0, 1)
}

// Copies the warnings from the other response to this one
func (r *Response) CloneWarnings(other *Response) {
	r.warnings = other.warnings
}

// IsError returns true if this response seems to indicate an error.
func (r *Response) IsError() bool {
	return r != nil && r.Data != nil && len(r.Data) == 1 && r.Data["error"] != nil
}

func (r *Response) Error() error {
	if !r.IsError() {
		return nil
	}
	switch r.Data["error"].(type) {
	case string:
		return errors.New(r.Data["error"].(string))
	case error:
		return r.Data["error"].(error)
	}
	return nil
}

// HelpResponse is used to format a help response
func HelpResponse(text string, seeAlso []string) *Response {
	return &Response{
		Data: map[string]interface{}{
			"help":     text,
			"see_also": seeAlso,
		},
	}
}

// ErrorResponse is used to format an error response
func ErrorResponse(text string) *Response {
	return &Response{
		Data: map[string]interface{}{
			"error": text,
		},
	}
}

// ListResponse is used to format a response to a list operation.
func ListResponse(keys []string) *Response {
	resp := &Response{
		Data: map[string]interface{}{},
	}
	if len(keys) != 0 {
		resp.Data["keys"] = keys
	}
	return resp
}
<commit_msg>That's what you get for not building first.<commit_after>package logical

import (
	"errors"
	"fmt"
	"reflect"
	"time"

	"github.com/mitchellh/copystructure"
)

const (
	// HTTPContentType can be specified in the Data field of a Response
	// so that the HTTP front end can specify a custom Content-Type associated
	// with the HTTPRawBody. This can only be used for non-secrets, and should
	// be avoided unless absolutely necessary, such as implementing a specification.
	// The value must be a string.
	HTTPContentType = "http_content_type"

	// HTTPRawBody is the raw content of the HTTP body that goes with the HTTPContentType.
	// This can only be specified for non-secrets, and should should be similarly
	// avoided like the HTTPContentType. The value must be a byte slice.
	HTTPRawBody = "http_raw_body"

	// HTTPStatusCode is the response code of the HTTP body that goes with the HTTPContentType.
	// This can only be specified for non-secrets, and should should be similarly
	// avoided like the HTTPContentType. The value must be an integer.
	HTTPStatusCode = "http_status_code"
)

type ResponseWrapInfo struct {
	// Setting to non-zero specifies that the response should be wrapped.
	// Specifies the desired TTL of the wrapping token.
	TTL time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"`

	// The token containing the wrapped response
	Token string `json:"token" structs:"token" mapstructure:"token"`

	// The creation time. This can be used with the TTL to figure out an
	// expected expiration.
	CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"cration_time"`

	// If the contained response is the output of a token creation call, the
	// created token's accessor will be accessible here
	WrappedAccessor string `json:"wrapped_accessor" structs:"wrapped_accessor" mapstructure:"wrapped_accessor"`

	// The format to use. This doesn't get returned, it's only internal.
	Format string `json:"format" structs:"format" mapstructure:"format"`
}

// Response is a struct that stores the response of a request.
// It is used to abstract the details of the higher level request protocol.
type Response struct {
	// Secret, if not nil, denotes that this response represents a secret.
	Secret *Secret `json:"secret" structs:"secret" mapstructure:"secret"`

	// Auth, if not nil, contains the authentication information for
	// this response. This is only checked and means something for
	// credential backends.
	Auth *Auth `json:"auth" structs:"auth" mapstructure:"auth"`

	// Response data is an opaque map that must have string keys. For
	// secrets, this data is sent down to the user as-is. To store internal
	// data that you don't want the user to see, store it in
	// Secret.InternalData.
	Data map[string]interface{} `json:"data" structs:"data" mapstructure:"data"`

	// Redirect is an HTTP URL to redirect to for further authentication.
	// This is only valid for credential backends. This will be blanked
	// for any logical backend and ignored.
	Redirect string `json:"redirect" structs:"redirect" mapstructure:"redirect"`

	// Warnings allow operations or backends to return warnings in response
	// to user actions without failing the action outright.
	// Making it private helps ensure that it is easy for various parts of
	// Vault (backend, core, etc.) to add warnings without accidentally
	// replacing what exists.
	warnings []string `json:"warnings" structs:"warnings" mapstructure:"warnings"`

	// Information for wrapping the response in a cubbyhole
	WrapInfo *ResponseWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"`
}

func init() {
	copystructure.Copiers[reflect.TypeOf(Response{})] = func(v interface{}) (interface{}, error) {
		input := v.(Response)
		ret := Response{
			Redirect: input.Redirect,
		}

		if input.Secret != nil {
			retSec, err := copystructure.Copy(input.Secret)
			if err != nil {
				return nil, fmt.Errorf("error copying Secret: %v", err)
			}
			ret.Secret = retSec.(*Secret)
		}

		if input.Auth != nil {
			retAuth, err := copystructure.Copy(input.Auth)
			if err != nil {
				return nil, fmt.Errorf("error copying Auth: %v", err)
			}
			ret.Auth = retAuth.(*Auth)
		}

		if input.Data != nil {
			retData, err := copystructure.Copy(&input.Data)
			if err != nil {
				return nil, fmt.Errorf("error copying Data: %v", err)
			}
			ret.Data = *(retData.(*map[string]interface{}))
		}

		if input.Warnings() != nil {
			for _, warning := range input.Warnings() {
				ret.AddWarning(warning)
			}
		}

		if input.WrapInfo != nil {
			retWrapInfo, err := copystructure.Copy(input.WrapInfo)
			if err != nil {
				return nil, fmt.Errorf("error copying WrapInfo: %v", err)
			}
			ret.WrapInfo = retWrapInfo.(*ResponseWrapInfo)
		}

		return &ret, nil
	}
}

// AddWarning adds a warning into the response's warning list
func (r *Response) AddWarning(warning string) {
	if r.warnings == nil {
		r.warnings = make([]string, 0, 1)
	}
	r.warnings = append(r.warnings, warning)
}

// Warnings returns the list of warnings set on the response
func (r *Response) Warnings() []string {
	return r.warnings
}

// ClearWarnings clears the response's warning list
func (r *Response) ClearWarnings() {
	r.warnings = make([]string, 0, 1)
}

// Copies the warnings from the other response to this one
func (r *Response) CloneWarnings(other *Response) {
	r.warnings = other.warnings
}

// IsError returns true if this response seems to indicate an error.
func (r *Response) IsError() bool {
	return r != nil && r.Data != nil && len(r.Data) == 1 && r.Data["error"] != nil
}

func (r *Response) Error() error {
	if !r.IsError() {
		return nil
	}
	switch r.Data["error"].(type) {
	case string:
		return errors.New(r.Data["error"].(string))
	case error:
		return r.Data["error"].(error)
	}
	return nil
}

// HelpResponse is used to format a help response
func HelpResponse(text string, seeAlso []string) *Response {
	return &Response{
		Data: map[string]interface{}{
			"help":     text,
			"see_also": seeAlso,
		},
	}
}

// ErrorResponse is used to format an error response
func ErrorResponse(text string) *Response {
	return &Response{
		Data: map[string]interface{}{
			"error": text,
		},
	}
}

// ListResponse is used to format a response to a list operation.
func ListResponse(keys []string) *Response {
	resp := &Response{
		Data: map[string]interface{}{},
	}
	if len(keys) != 0 {
		resp.Data["keys"] = keys
	}
	return resp
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/joeshaw/gengen/genlib"
)

func main() {
	var outdir = flag.String("o", ".", "output directory")
	flag.Parse()

	if flag.NArg() < 2 {
		cmd := os.Args[0]
		fmt.Fprintf(os.Stderr, "usage: %s [-o <output_dir>] <package> <replacement types...>\n", cmd)
		fmt.Fprintf(os.Stderr, "example: %s -o ./btree github.com/joeshaw/gengen/examples/btree string string\n", cmd)
		os.Exit(1)
	}

	types := make([]string, flag.NArg()-1)
	for i := 1; i < flag.NArg(); i++ {
		types[i-1] = flag.Arg(i)
	}

	// run a "go get <pkg>"
	err := exec.Command("go", "get", flag.Arg(0)).Run()
	if err != nil {
		die(err)
	}

	// resolve the path into which we (might have) just installed it
	pkgpath := findPkgPath(flag.Arg(0))
	if pkgpath == "" {
		die(fmt.Errorf("couldn't find %s", flag.Arg(0)))
	}

	// list the source files
	sourcefiles, err := filepath.Glob(path.Join(pkgpath, "*.go"))
	if err != nil {
		die(err)
	}

	// create a temporary directory
	tdir, err := ioutil.TempDir("", "")
	if err != nil {
		die(err)
	}

	// convert all source files into the tmp dir
	for _, source_path := range sourcefiles {
		dest_path := path.Join(tdir, path.Base(source_path))
		err := convertFile(dest_path, source_path, types...)
		if err != nil {
			die(err)
		}
	}

	// move the converted files into our output dir
	replaceFiles(tdir, *outdir)

	// remove the temporary directory
	os.RemoveAll(tdir)
}

func convertFile(dest_path, source_path string, types ...string) error {
	buf, err := genlib.Generate(source_path, types...)
	if err != nil {
		return err
	}

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

	_, err = io.Copy(f, bytes.NewBuffer(buf))
	if err != nil {
		return err
	}

	return nil
}

func replaceFiles(source_dir, dest_dir string) {
	sources, err := filepath.Glob(path.Join(source_dir, "*.go"))
	if err != nil {
		die(err)
	}

	if !exists(dest_dir) {
		os.MkdirAll(dest_dir, 0755)
	}

	for _, source := range sources {
		dest := path.Join(dest_dir, path.Base(source))
		if err := os.Rename(source, dest); err != nil {
			if patherr, ok := err.(*os.LinkError); ok {
				if errno, ok := patherr.Err.(syscall.Errno); ok {
					if errno == syscall.EXDEV {
						if err = copyBytes(source, dest); err == nil {
							continue
						}
					}
				}
			}
			die(err)
		}
	}
}

func copyBytes(source, dest string) error {
	sfile, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sfile.Close()

	dfile, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer dfile.Close()

	_, err = io.Copy(dfile, sfile)
	return err
}

func findPkgPath(name string) string {
	for _, dir := range strings.Split(os.Getenv("GOPATH"), ";") {
		fullpath := path.Join(dir, "src", name)
		if exists(fullpath) {
			return fullpath
		}
	}
	return ""
}

func exists(fpath string) bool {
	_, err := os.Stat(fpath)
	return !os.IsNotExist(err)
}

func die(err error) {
	fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
	os.Exit(1)
}
<commit_msg>dedent/cleanup some logic<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/joeshaw/gengen/genlib"
)

func main() {
	var outdir = flag.String("o", ".", "output directory")
	flag.Parse()

	if flag.NArg() < 2 {
		cmd := os.Args[0]
		fmt.Fprintf(os.Stderr, "usage: %s [-o <output_dir>] <package> <replacement types...>\n", cmd)
		fmt.Fprintf(os.Stderr, "example: %s -o ./btree github.com/joeshaw/gengen/examples/btree string string\n", cmd)
		os.Exit(1)
	}

	types := make([]string, flag.NArg()-1)
	for i := 1; i < flag.NArg(); i++ {
		types[i-1] = flag.Arg(i)
	}

	// run a "go get <pkg>"
	err := exec.Command("go", "get", flag.Arg(0)).Run()
	if err != nil {
		die(err)
	}

	// resolve the path into which we (might have) just installed it
	pkgpath := findPkgPath(flag.Arg(0))
	if pkgpath == "" {
		die(fmt.Errorf("couldn't find %s", flag.Arg(0)))
	}

	// list the source files
	sourcefiles, err := filepath.Glob(path.Join(pkgpath, "*.go"))
	if err != nil {
		die(err)
	}

	// create a temporary directory
	tdir, err := ioutil.TempDir("", "")
	if err != nil {
		die(err)
	}

	// convert all source files into the tmp dir
	for _, source_path := range sourcefiles {
		dest_path := path.Join(tdir, path.Base(source_path))
		err := convertFile(dest_path, source_path, types...)
		if err != nil {
			die(err)
		}
	}

	// move the converted files into our output dir
	replaceFiles(tdir, *outdir)

	// remove the temporary directory
	os.RemoveAll(tdir)
}

func convertFile(dest_path, source_path string, types ...string) error {
	buf, err := genlib.Generate(source_path, types...)
	if err != nil {
		return err
	}

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

	_, err = io.Copy(f, bytes.NewBuffer(buf))
	if err != nil {
		return err
	}

	return nil
}

func replaceFiles(source_dir, dest_dir string) {
	sources, err := filepath.Glob(path.Join(source_dir, "*.go"))
	if err != nil {
		die(err)
	}

	if !exists(dest_dir) {
		os.MkdirAll(dest_dir, 0755)
	}

	for _, source := range sources {
		dest := path.Join(dest_dir, path.Base(source))

		// attempt a simple rename
		err := os.Rename(source, dest)
		if err == nil {
			continue
		}

		// /tmp is often a ramdisk so check for EXDEV
		linkerr, ok := err.(*os.LinkError)
		if !ok {
			die(err)
		}
		errno, ok := linkerr.Err.(syscall.Errno)
		if !ok {
			die(err)
		}
		if errno != syscall.EXDEV {
			die(err)
		}

		// have to copy the bytes explicitly
		if err = copyBytes(source, dest); err != nil {
			die(err)
		}
	}
}

func copyBytes(source, dest string) error {
	sfile, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sfile.Close()

	dfile, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer dfile.Close()

	_, err = io.Copy(dfile, sfile)
	return err
}

func findPkgPath(name string) string {
	for _, dir := range strings.Split(os.Getenv("GOPATH"), ";") {
		fullpath := path.Join(dir, "src", name)
		if exists(fullpath) {
			return fullpath
		}
	}
	return ""
}

func exists(fpath string) bool {
	_, err := os.Stat(fpath)
	return !os.IsNotExist(err)
}

func die(err error) {
	fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package golibbuttplug

import (
	"errors"
	"fmt"

	"github.com/funjack/golibbuttplug/message"
)

const (
	// CommandStopDevice ...
	CommandStopDevice = "StopDeviceCmd"
	// CommandRaw ...
	CommandRaw = "RawCmd"
	// CommandSingleMotorVibrate ...
	CommandSingleMotorVibrate = "SingleMotorVibrateCmd"
	// CommandKiiroo ...
	CommandKiiroo = "KiirooCmd"
	// CommandFleshlightLaunchFW12 ...
	CommandFleshlightLaunchFW12 = "FleshlightLaunchFW12Cmd"
	// CommandLovense ...
	CommandLovense = "LovenseCmd"
)

var (
	// ErrUnsupported is the error returned when the command executed is
	// not supported by the device.
	ErrUnsupported = errors.New("unsupported command")
	// ErrInvalidSpeed is the error retured when the speed is not supported
	// by the device.
	ErrInvalidSpeed = errors.New("invalid speed")
	// ErrInvalidPosition is the error retured when the position is not
	// supported by the device.
	ErrInvalidPosition = errors.New("invalid position")
	// ErrInvalidCmd is the error retured when the command is not
	// supported by the device.
	ErrInvalidCmd = errors.New("invalid command")
)

// Device structs represents a connected device and can be used to execute
// commands.
type Device struct {
	client *Client
	device message.Device
	done   chan struct{}
}

func (d *Device) String() string {
	return fmt.Sprintf("%s(%d)", d.device.DeviceName, d.device.DeviceIndex)
}

// Name returns the device name.
func (d *Device) Name() string {
	return d.device.DeviceName
}

// IsSupported returns true if the message type is supported.
func (d *Device) IsSupported(msgtype string) bool {
	for _, dm := range d.device.DeviceMessages {
		if dm == msgtype {
			return true
		}
	}
	return false
}

// Supported returns a list of all supported message types for this device.
func (d *Device) Supported() []string {
	return d.device.DeviceMessages
}

// StopDeviceCmd stops a device from whatever actions it may be taking.
func (d *Device) StopDeviceCmd() error {
	if !d.IsSupported(CommandStopDevice) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		StopDeviceCmd: &message.Device{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
		},
	})
}

// RawCmd sends a raw byte string to a device.
func (d *Device) RawCmd(cmd []byte) error {
	if !d.IsSupported(CommandRaw) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		RawCmd: &message.RawCmd{
			ID:      id,
			Command: cmd,
		},
	})
}

// SingleMotorVibrateCmd causes a toy that supports vibration to run at a
// certain speed. In order to abstract the dynamic range of different toys, the
// value sent is a float with a range of [0.0-1.0].
func (d *Device) SingleMotorVibrateCmd(spd float64) error {
	if !d.IsSupported(CommandSingleMotorVibrate) {
		return ErrUnsupported
	}
	if spd < 0 || spd > 1 {
		return ErrInvalidSpeed
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		SingleMotorVibrateCmd: &message.SingleMotorVibrateCmd{
			ID:    id,
			Speed: spd,
		},
	})
}

// KiirooCmd causes a toy that supports Kiiroo style commands to run whatever
// event may be related.
func (d *Device) KiirooCmd(cmd int) error {
	if !d.IsSupported(CommandKiiroo) {
		return ErrUnsupported
	}
	if cmd < 0 || cmd > 4 {
		return ErrInvalidCmd
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		KiirooCmd: &message.KiirooCmd{
			ID:      id,
			Command: cmd,
		},
	})
}

// FleshlightLaunchFW12Cmd causes a toy that supports Fleshlight Launch
// (Firmware Version 1.2) style commands to run whatever event may be related.
func (d *Device) FleshlightLaunchFW12Cmd(pos, spd int) error {
	if !d.IsSupported(CommandFleshlightLaunchFW12) {
		return ErrUnsupported
	}
	if pos < 0 || pos > 99 {
		return ErrInvalidPosition
	}
	if spd < 0 || spd > 99 {
		return ErrInvalidSpeed
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		FleshlightLaunchFW12Cmd: &message.FleshlightLaunchFW12Cmd{
			ID:       id,
			Position: pos,
			Speed:    spd,
		},
	})
}

// LovenseCmd causes a toy that supports Lovense style commands to run whatever
// event may be related.
func (d *Device) LovenseCmd(cmd string) error {
	if !d.IsSupported(CommandLovense) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		LovenseCmd: &message.LovenseCmd{
			ID:      id,
			Command: cmd,
		},
	})
}

// Disconnected returns a receiving channel, that is closed when the device is
// removed.
func (d *Device) Disconnected() <-chan struct{} {
	return d.done
}
<commit_msg>Bugfix send DeviceIndex for commands<commit_after>package golibbuttplug

import (
	"errors"
	"fmt"

	"github.com/funjack/golibbuttplug/message"
)

const (
	// CommandStopDevice ...
	CommandStopDevice = "StopDeviceCmd"
	// CommandRaw ...
	CommandRaw = "RawCmd"
	// CommandSingleMotorVibrate ...
	CommandSingleMotorVibrate = "SingleMotorVibrateCmd"
	// CommandKiiroo ...
	CommandKiiroo = "KiirooCmd"
	// CommandFleshlightLaunchFW12 ...
	CommandFleshlightLaunchFW12 = "FleshlightLaunchFW12Cmd"
	// CommandLovense ...
	CommandLovense = "LovenseCmd"
)

var (
	// ErrUnsupported is the error returned when the command executed is
	// not supported by the device.
	ErrUnsupported = errors.New("unsupported command")
	// ErrInvalidSpeed is the error retured when the speed is not supported
	// by the device.
	ErrInvalidSpeed = errors.New("invalid speed")
	// ErrInvalidPosition is the error retured when the position is not
	// supported by the device.
	ErrInvalidPosition = errors.New("invalid position")
	// ErrInvalidCmd is the error retured when the command is not
	// supported by the device.
	ErrInvalidCmd = errors.New("invalid command")
)

// Device structs represents a connected device and can be used to execute
// commands.
type Device struct {
	client *Client
	device message.Device
	done   chan struct{}
}

func (d *Device) String() string {
	return fmt.Sprintf("%s(%d)", d.device.DeviceName, d.device.DeviceIndex)
}

// Name returns the device name.
func (d *Device) Name() string {
	return d.device.DeviceName
}

// IsSupported returns true if the message type is supported.
func (d *Device) IsSupported(msgtype string) bool {
	for _, dm := range d.device.DeviceMessages {
		if dm == msgtype {
			return true
		}
	}
	return false
}

// Supported returns a list of all supported message types for this device.
func (d *Device) Supported() []string {
	return d.device.DeviceMessages
}

// StopDeviceCmd stops a device from whatever actions it may be taking.
func (d *Device) StopDeviceCmd() error {
	if !d.IsSupported(CommandStopDevice) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		StopDeviceCmd: &message.Device{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
		},
	})
}

// RawCmd sends a raw byte string to a device.
func (d *Device) RawCmd(cmd []byte) error {
	if !d.IsSupported(CommandRaw) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		RawCmd: &message.RawCmd{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
			Command:     cmd,
		},
	})
}

// SingleMotorVibrateCmd causes a toy that supports vibration to run at a
// certain speed. In order to abstract the dynamic range of different toys, the
// value sent is a float with a range of [0.0-1.0].
func (d *Device) SingleMotorVibrateCmd(spd float64) error {
	if !d.IsSupported(CommandSingleMotorVibrate) {
		return ErrUnsupported
	}
	if spd < 0 || spd > 1 {
		return ErrInvalidSpeed
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		SingleMotorVibrateCmd: &message.SingleMotorVibrateCmd{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
			Speed:       spd,
		},
	})
}

// KiirooCmd causes a toy that supports Kiiroo style commands to run whatever
// event may be related.
func (d *Device) KiirooCmd(cmd int) error {
	if !d.IsSupported(CommandKiiroo) {
		return ErrUnsupported
	}
	if cmd < 0 || cmd > 4 {
		return ErrInvalidCmd
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		KiirooCmd: &message.KiirooCmd{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
			Command:     cmd,
		},
	})
}

// FleshlightLaunchFW12Cmd causes a toy that supports Fleshlight Launch
// (Firmware Version 1.2) style commands to run whatever event may be related.
func (d *Device) FleshlightLaunchFW12Cmd(pos, spd int) error {
	if !d.IsSupported(CommandFleshlightLaunchFW12) {
		return ErrUnsupported
	}
	if pos < 0 || pos > 99 {
		return ErrInvalidPosition
	}
	if spd < 0 || spd > 99 {
		return ErrInvalidSpeed
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		FleshlightLaunchFW12Cmd: &message.FleshlightLaunchFW12Cmd{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
			Position:    pos,
			Speed:       spd,
		},
	})
}

// LovenseCmd causes a toy that supports Lovense style commands to run whatever
// event may be related.
func (d *Device) LovenseCmd(cmd string) error {
	if !d.IsSupported(CommandLovense) {
		return ErrUnsupported
	}
	id := d.client.counter.Generate()
	return d.client.sendMessage(id, message.OutgoingMessage{
		LovenseCmd: &message.LovenseCmd{
			ID:          id,
			DeviceIndex: d.device.DeviceIndex,
			Command:     cmd,
		},
	})
}

// Disconnected returns a receiving channel, that is closed when the device is
// removed.
func (d *Device) Disconnected() <-chan struct{} {
	return d.done
}
<|endoftext|>


<commit_before>package clw11

/*
#cgo windows linux LDFLAGS: -lOpenCL
#cgo darwin LDFLAGS: -framework OpenCL

#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import (
	"unsafe"
)

type (
	DeviceID               C.cl_device_id
	DeviceInfo             C.cl_device_info
	DeviceExecCapabilities C.cl_device_exec_capabilities
	DeviceFPConfig         C.cl_device_fp_config
	DeviceLocalMemType     C.cl_device_local_mem_type
	DeviceMemCacheType     C.cl_device_mem_cache_type
	DeviceType             C.cl_device_type
)

// Bitfield.
const (
	DeviceTypeDefault     DeviceType = C.CL_DEVICE_TYPE_DEFAULT
	DeviceTypeCpu         DeviceType = C.CL_DEVICE_TYPE_CPU
	DeviceTypeGpu         DeviceType = C.CL_DEVICE_TYPE_GPU
	DeviceTypeAccelerator DeviceType = C.CL_DEVICE_TYPE_ACCELERATOR
	DeviceTypeAll         DeviceType = C.CL_DEVICE_TYPE_ALL
)

const (
	DeviceTypeInfo                   DeviceInfo = C.CL_DEVICE_TYPE // Appended "Info" due to conflict with type.
	DeviceVendorId                   DeviceInfo = C.CL_DEVICE_VENDOR_ID
	DeviceMaxComputeUnits            DeviceInfo = C.CL_DEVICE_MAX_COMPUTE_UNITS
	DeviceMaxWorkItemDimensions      DeviceInfo = C.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
	DeviceMaxWorkGroupSize           DeviceInfo = C.CL_DEVICE_MAX_WORK_GROUP_SIZE
	DeviceMaxWorkItemSizes           DeviceInfo = C.CL_DEVICE_MAX_WORK_ITEM_SIZES
	DevicePreferredVectorWidthChar   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
	DevicePreferredVectorWidthShort  DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
	DevicePreferredVectorWidthInt    DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
	DevicePreferredVectorWidthLong   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
	DevicePreferredVectorWidthFloat  DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
	DevicePreferredVectorWidthDouble DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
	DeviceMaxClockFrequency          DeviceInfo = C.CL_DEVICE_MAX_CLOCK_FREQUENCY
	DeviceAddressBits                DeviceInfo = C.CL_DEVICE_ADDRESS_BITS
	DeviceMaxReadImageArgs           DeviceInfo = C.CL_DEVICE_MAX_READ_IMAGE_ARGS
	DeviceMaxWriteImageArgs          DeviceInfo = C.CL_DEVICE_MAX_WRITE_IMAGE_ARGS
	DeviceMaxMemAllocSize            DeviceInfo = C.CL_DEVICE_MAX_MEM_ALLOC_SIZE
	DeviceImage2dMaxWidth            DeviceInfo = C.CL_DEVICE_IMAGE2D_MAX_WIDTH
	DeviceImage2dMaxHeight           DeviceInfo = C.CL_DEVICE_IMAGE2D_MAX_HEIGHT
	DeviceImage3dMaxWidth            DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_WIDTH
	DeviceImage3dMaxHeight           DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_HEIGHT
	DeviceImage3dMaxDepth            DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_DEPTH
	DeviceImageSupport               DeviceInfo = C.CL_DEVICE_IMAGE_SUPPORT
	DeviceMaxParameterSize           DeviceInfo = C.CL_DEVICE_MAX_PARAMETER_SIZE
	DeviceMaxSamplers                DeviceInfo = C.CL_DEVICE_MAX_SAMPLERS
	DeviceMemBaseAddrAlign           DeviceInfo = C.CL_DEVICE_MEM_BASE_ADDR_ALIGN
	DeviceMinDataTypeAlignSize       DeviceInfo = C.CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
	DeviceSingleFpConfig             DeviceInfo = C.CL_DEVICE_SINGLE_FP_CONFIG
	DeviceGlobalMemCacheType         DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHE_TYPE
	DeviceGlobalMemCachelineSize     DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
	DeviceGlobalMemCacheSize         DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
	DeviceGlobalMemSize              DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_SIZE
	DeviceMaxConstantBufferSize      DeviceInfo = C.CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
	DeviceMaxConstantArgs            DeviceInfo = C.CL_DEVICE_MAX_CONSTANT_ARGS
	DeviceLocalMemTypeInfo           DeviceInfo = C.CL_DEVICE_LOCAL_MEM_TYPE // Appended "Info" due to conflict with type.
	DeviceLocalMemSize               DeviceInfo = C.CL_DEVICE_LOCAL_MEM_SIZE
	DeviceErrorCorrectionSupport     DeviceInfo = C.CL_DEVICE_ERROR_CORRECTION_SUPPORT
	DeviceProfilingTimerResolution   DeviceInfo = C.CL_DEVICE_PROFILING_TIMER_RESOLUTION
	DeviceEndianLittle               DeviceInfo = C.CL_DEVICE_ENDIAN_LITTLE
	DeviceAvailable                  DeviceInfo = C.CL_DEVICE_AVAILABLE
	DeviceCompilerAvailable          DeviceInfo = C.CL_DEVICE_COMPILER_AVAILABLE
	DeviceExecutionCapabilities      DeviceInfo = C.CL_DEVICE_EXECUTION_CAPABILITIES
	DeviceQueueProperties            DeviceInfo = C.CL_DEVICE_QUEUE_PROPERTIES
	DeviceName                       DeviceInfo = C.CL_DEVICE_NAME
	DeviceVendor                     DeviceInfo = C.CL_DEVICE_VENDOR
	DriverVersion                    DeviceInfo = C.CL_DRIVER_VERSION
	DeviceProfile                    DeviceInfo = C.CL_DEVICE_PROFILE
	DeviceVersion                    DeviceInfo = C.CL_DEVICE_VERSION
	DeviceExtensions                 DeviceInfo = C.CL_DEVICE_EXTENSIONS
	DevicePlatform                   DeviceInfo = C.CL_DEVICE_PLATFORM
	DevicePreferredVectorWidthHalf   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF
	DeviceHostUnifiedMemory          DeviceInfo = C.CL_DEVICE_HOST_UNIFIED_MEMORY
	DeviceNativeVectorWidthChar      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR
	DeviceNativeVectorWidthShort     DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT
	DeviceNativeVectorWidthInt       DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_INT
	DeviceNativeVectorWidthLong      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG
	DeviceNativeVectorWidthFloat     DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT
	DeviceNativeVectorWidthDouble    DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE
	DeviceNativeVectorWidthHalf      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF
	DeviceOpenclCVersion             DeviceInfo = C.CL_DEVICE_OPENCL_C_VERSION
)

// Bitfield.
const (
	FPDenorm         DeviceFPConfig = C.CL_FP_DENORM
	FPFma            DeviceFPConfig = C.CL_FP_FMA
	FPInfNan         DeviceFPConfig = C.CL_FP_INF_NAN
	FPRoundToInf     DeviceFPConfig = C.CL_FP_ROUND_TO_INF
	FPRoundToNearest DeviceFPConfig = C.CL_FP_ROUND_TO_NEAREST
	FPRoundToZero    DeviceFPConfig = C.CL_FP_ROUND_TO_ZERO
)

const (
	None           DeviceMemCacheType = C.CL_NONE
	ReadOnlyCache  DeviceMemCacheType = C.CL_READ_ONLY_CACHE
	ReadWriteCache DeviceMemCacheType = C.CL_READ_WRITE_CACHE
)

const (
	Global DeviceLocalMemType = C.CL_GLOBAL
	Local  DeviceLocalMemType = C.CL_LOCAL
)

// Bitfield
const (
	ExecKernel       DeviceExecCapabilities = C.CL_EXEC_KERNEL
	ExecNativeKernel DeviceExecCapabilities = C.CL_EXEC_NATIVE_KERNEL
)

func GetDeviceIDs(platform PlatformID, deviceType DeviceType, numEntries Uint, devices *DeviceID,
	numDevices *Uint) error {

	return NewError(C.clGetDeviceIDs(C.cl_platform_id(platform), C.cl_device_type(deviceType), C.cl_uint(numEntries),
		(*C.cl_device_id)(devices), (*C.cl_uint)(numDevices)))
}

func GetDeviceInfo(device DeviceID, paramName DeviceInfo, paramValueSize Size, paramValue unsafe.Pointer,
	paramValueSizeRet *Size) error {

	return NewError(C.clGetDeviceInfo(C.cl_device_id(device), C.cl_device_info(paramName), C.size_t(paramValueSize),
		paramValue, (*C.size_t)(paramValueSizeRet)))
}
<commit_msg>Keeping ID capitalization consistent.<commit_after>package clw11

/*
#cgo windows linux LDFLAGS: -lOpenCL
#cgo darwin LDFLAGS: -framework OpenCL

#ifdef __APPLE__
#include "OpenCL/opencl.h"
#else
#include "CL/opencl.h"
#endif
*/
import "C"
import (
	"unsafe"
)

type (
	DeviceID               C.cl_device_id
	DeviceInfo             C.cl_device_info
	DeviceExecCapabilities C.cl_device_exec_capabilities
	DeviceFPConfig         C.cl_device_fp_config
	DeviceLocalMemType     C.cl_device_local_mem_type
	DeviceMemCacheType     C.cl_device_mem_cache_type
	DeviceType             C.cl_device_type
)

// Bitfield.
const (
	DeviceTypeDefault     DeviceType = C.CL_DEVICE_TYPE_DEFAULT
	DeviceTypeCpu         DeviceType = C.CL_DEVICE_TYPE_CPU
	DeviceTypeGpu         DeviceType = C.CL_DEVICE_TYPE_GPU
	DeviceTypeAccelerator DeviceType = C.CL_DEVICE_TYPE_ACCELERATOR
	DeviceTypeAll         DeviceType = C.CL_DEVICE_TYPE_ALL
)

const (
	DeviceTypeInfo                   DeviceInfo = C.CL_DEVICE_TYPE // Appended "Info" due to conflict with type.
	DeviceVendorID                   DeviceInfo = C.CL_DEVICE_VENDOR_ID
	DeviceMaxComputeUnits            DeviceInfo = C.CL_DEVICE_MAX_COMPUTE_UNITS
	DeviceMaxWorkItemDimensions      DeviceInfo = C.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
	DeviceMaxWorkGroupSize           DeviceInfo = C.CL_DEVICE_MAX_WORK_GROUP_SIZE
	DeviceMaxWorkItemSizes           DeviceInfo = C.CL_DEVICE_MAX_WORK_ITEM_SIZES
	DevicePreferredVectorWidthChar   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
	DevicePreferredVectorWidthShort  DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
	DevicePreferredVectorWidthInt    DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
	DevicePreferredVectorWidthLong   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
	DevicePreferredVectorWidthFloat  DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
	DevicePreferredVectorWidthDouble DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
	DeviceMaxClockFrequency          DeviceInfo = C.CL_DEVICE_MAX_CLOCK_FREQUENCY
	DeviceAddressBits                DeviceInfo = C.CL_DEVICE_ADDRESS_BITS
	DeviceMaxReadImageArgs           DeviceInfo = C.CL_DEVICE_MAX_READ_IMAGE_ARGS
	DeviceMaxWriteImageArgs          DeviceInfo = C.CL_DEVICE_MAX_WRITE_IMAGE_ARGS
	DeviceMaxMemAllocSize            DeviceInfo = C.CL_DEVICE_MAX_MEM_ALLOC_SIZE
	DeviceImage2dMaxWidth            DeviceInfo = C.CL_DEVICE_IMAGE2D_MAX_WIDTH
	DeviceImage2dMaxHeight           DeviceInfo = C.CL_DEVICE_IMAGE2D_MAX_HEIGHT
	DeviceImage3dMaxWidth            DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_WIDTH
	DeviceImage3dMaxHeight           DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_HEIGHT
	DeviceImage3dMaxDepth            DeviceInfo = C.CL_DEVICE_IMAGE3D_MAX_DEPTH
	DeviceImageSupport               DeviceInfo = C.CL_DEVICE_IMAGE_SUPPORT
	DeviceMaxParameterSize           DeviceInfo = C.CL_DEVICE_MAX_PARAMETER_SIZE
	DeviceMaxSamplers                DeviceInfo = C.CL_DEVICE_MAX_SAMPLERS
	DeviceMemBaseAddrAlign           DeviceInfo = C.CL_DEVICE_MEM_BASE_ADDR_ALIGN
	DeviceMinDataTypeAlignSize       DeviceInfo = C.CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
	DeviceSingleFpConfig             DeviceInfo = C.CL_DEVICE_SINGLE_FP_CONFIG
	DeviceGlobalMemCacheType         DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHE_TYPE
	DeviceGlobalMemCachelineSize     DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
	DeviceGlobalMemCacheSize         DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
	DeviceGlobalMemSize              DeviceInfo = C.CL_DEVICE_GLOBAL_MEM_SIZE
	DeviceMaxConstantBufferSize      DeviceInfo = C.CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
	DeviceMaxConstantArgs            DeviceInfo = C.CL_DEVICE_MAX_CONSTANT_ARGS
	DeviceLocalMemTypeInfo           DeviceInfo = C.CL_DEVICE_LOCAL_MEM_TYPE // Appended "Info" due to conflict with type.
	DeviceLocalMemSize               DeviceInfo = C.CL_DEVICE_LOCAL_MEM_SIZE
	DeviceErrorCorrectionSupport     DeviceInfo = C.CL_DEVICE_ERROR_CORRECTION_SUPPORT
	DeviceProfilingTimerResolution   DeviceInfo = C.CL_DEVICE_PROFILING_TIMER_RESOLUTION
	DeviceEndianLittle               DeviceInfo = C.CL_DEVICE_ENDIAN_LITTLE
	DeviceAvailable                  DeviceInfo = C.CL_DEVICE_AVAILABLE
	DeviceCompilerAvailable          DeviceInfo = C.CL_DEVICE_COMPILER_AVAILABLE
	DeviceExecutionCapabilities      DeviceInfo = C.CL_DEVICE_EXECUTION_CAPABILITIES
	DeviceQueueProperties            DeviceInfo = C.CL_DEVICE_QUEUE_PROPERTIES
	DeviceName                       DeviceInfo = C.CL_DEVICE_NAME
	DeviceVendor                     DeviceInfo = C.CL_DEVICE_VENDOR
	DriverVersion                    DeviceInfo = C.CL_DRIVER_VERSION
	DeviceProfile                    DeviceInfo = C.CL_DEVICE_PROFILE
	DeviceVersion                    DeviceInfo = C.CL_DEVICE_VERSION
	DeviceExtensions                 DeviceInfo = C.CL_DEVICE_EXTENSIONS
	DevicePlatform                   DeviceInfo = C.CL_DEVICE_PLATFORM
	DevicePreferredVectorWidthHalf   DeviceInfo = C.CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF
	DeviceHostUnifiedMemory          DeviceInfo = C.CL_DEVICE_HOST_UNIFIED_MEMORY
	DeviceNativeVectorWidthChar      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR
	DeviceNativeVectorWidthShort     DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT
	DeviceNativeVectorWidthInt       DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_INT
	DeviceNativeVectorWidthLong      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG
	DeviceNativeVectorWidthFloat     DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT
	DeviceNativeVectorWidthDouble    DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE
	DeviceNativeVectorWidthHalf      DeviceInfo = C.CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF
	DeviceOpenclCVersion             DeviceInfo = C.CL_DEVICE_OPENCL_C_VERSION
)

// Bitfield.
const (
	FPDenorm         DeviceFPConfig = C.CL_FP_DENORM
	FPFma            DeviceFPConfig = C.CL_FP_FMA
	FPInfNan         DeviceFPConfig = C.CL_FP_INF_NAN
	FPRoundToInf     DeviceFPConfig = C.CL_FP_ROUND_TO_INF
	FPRoundToNearest DeviceFPConfig = C.CL_FP_ROUND_TO_NEAREST
	FPRoundToZero    DeviceFPConfig = C.CL_FP_ROUND_TO_ZERO
)

const (
	None           DeviceMemCacheType = C.CL_NONE
	ReadOnlyCache  DeviceMemCacheType = C.CL_READ_ONLY_CACHE
	ReadWriteCache DeviceMemCacheType = C.CL_READ_WRITE_CACHE
)

const (
	Global DeviceLocalMemType = C.CL_GLOBAL
	Local  DeviceLocalMemType = C.CL_LOCAL
)

// Bitfield
const (
	ExecKernel       DeviceExecCapabilities = C.CL_EXEC_KERNEL
	ExecNativeKernel DeviceExecCapabilities = C.CL_EXEC_NATIVE_KERNEL
)

func GetDeviceIDs(platform PlatformID, deviceType DeviceType, numEntries Uint, devices *DeviceID,
	numDevices *Uint) error {

	return NewError(C.clGetDeviceIDs(C.cl_platform_id(platform), C.cl_device_type(deviceType), C.cl_uint(numEntries),
		(*C.cl_device_id)(devices), (*C.cl_uint)(numDevices)))
}

func GetDeviceInfo(device DeviceID, paramName DeviceInfo, paramValueSize Size, paramValue unsafe.Pointer,
	paramValueSizeRet *Size) error {

	return NewError(C.clGetDeviceInfo(C.cl_device_id(device), C.cl_device_info(paramName), C.size_t(paramValueSize),
		paramValue, (*C.size_t)(paramValueSizeRet)))
}
<|endoftext|>


<commit_before>// Copyright 2010 The Walk 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 walk

import (
	"syscall"
	"unsafe"
)

import . "github.com/lxn/go-winapi"

const (
	DlgCmdOK       = IDOK
	DlgCmdCancel   = IDCANCEL
	DlgCmdAbort    = IDABORT
	DlgCmdRetry    = IDRETRY
	DlgCmdIgnore   = IDIGNORE
	DlgCmdYes      = IDYES
	DlgCmdNo       = IDNO
	DlgCmdClose    = IDCLOSE
	DlgCmdHelp     = IDHELP
	DlgCmdTryAgain = IDTRYAGAIN
	DlgCmdContinue = IDCONTINUE
	DlgCmdTimeout  = IDTIMEOUT
)

const dialogWindowClass = `\o/ Walk_Dialog_Class \o/`

func init() {
	MustRegisterWindowClass(dialogWindowClass)
}

type dialogish interface {
	DefaultButton() *PushButton
	CancelButton() *PushButton
}

type Dialog struct {
	TopLevelWindow
	result               int
	defaultButton        *PushButton
	cancelButton         *PushButton
	centerInOwnerWhenRun bool
}

func NewDialog(owner RootWidget) (*Dialog, error) {
	dlg := &Dialog{
		TopLevelWindow: TopLevelWindow{
			owner: owner,
		},
	}

	if err := InitWidget(
		dlg,
		owner,
		dialogWindowClass,
		WS_CAPTION|WS_SYSMENU|WS_THICKFRAME,
		WS_EX_DLGMODALFRAME); err != nil {
		return nil, err
	}

	dlg.centerInOwnerWhenRun = owner != nil

	dlg.children = newWidgetList(dlg)

	// This forces display of focus rectangles, as soon as the user starts to type.
	dlg.SendMessage(WM_CHANGEUISTATE, UIS_INITIALIZE, 0)

	dlg.result = DlgCmdClose

	return dlg, nil
}

func (dlg *Dialog) DefaultButton() *PushButton {
	return dlg.defaultButton
}

func (dlg *Dialog) SetDefaultButton(button *PushButton) error {
	if button != nil && !IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	succeeded := false
	if dlg.defaultButton != nil {
		if err := dlg.defaultButton.setAndClearStyleBits(BS_PUSHBUTTON, BS_DEFPUSHBUTTON); err != nil {
			return err
		}
		defer func() {
			if !succeeded {
				dlg.defaultButton.setAndClearStyleBits(BS_DEFPUSHBUTTON, BS_PUSHBUTTON)
			}
		}()
	}

	if button != nil {
		if err := button.setAndClearStyleBits(BS_DEFPUSHBUTTON, BS_PUSHBUTTON); err != nil {
			return err
		}
	}

	dlg.defaultButton = button

	succeeded = true

	return nil
}

func (dlg *Dialog) CancelButton() *PushButton {
	return dlg.cancelButton
}

func (dlg *Dialog) SetCancelButton(button *PushButton) error {
	if button != nil && !IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	dlg.cancelButton = button

	return nil
}

func (dlg *Dialog) Accept() {
	dlg.Close(DlgCmdOK)
}

func (dlg *Dialog) Cancel() {
	dlg.Close(DlgCmdCancel)
}

func (dlg *Dialog) Close(result int) {
	dlg.result = result

	dlg.TopLevelWindow.Close()
}

func firstFocusableDescendantCallback(hwnd HWND, lParam uintptr) uintptr {
	widget := widgetFromHWND(hwnd)

	if widget == nil || !widget.Visible() || !widget.Enabled() {
		return 1
	}

	style := uint(GetWindowLong(hwnd, GWL_STYLE))
	// FIXME: Ugly workaround for NumberEdit
	_, isTextSelectable := widget.(textSelectable)
	if style&WS_TABSTOP > 0 || isTextSelectable {
		hwndPtr := (*HWND)(unsafe.Pointer(lParam))
		*hwndPtr = hwnd
		return 0
	}

	return 1
}

var firstFocusableDescendantCallbackPtr = syscall.NewCallback(firstFocusableDescendantCallback)

func firstFocusableDescendant(container Container) Widget {
	var hwnd HWND

	EnumChildWindows(container.BaseWidget().hWnd, firstFocusableDescendantCallbackPtr, uintptr(unsafe.Pointer(&hwnd)))

	return widgetFromHWND(hwnd)
}

type textSelectable interface {
	SetTextSelection(start, end int)
}

func (dlg *Dialog) focusFirstCandidateDescendant() {
	widget := firstFocusableDescendant(dlg)
	if widget == nil {
		return
	}

	if err := widget.SetFocus(); err != nil {
		return
	}

	if textSel, ok := widget.(textSelectable); ok {
		textSel.SetTextSelection(0, -1)
	}
}

func (dlg *Dialog) Show() {
	if dlg.owner != nil {
		ob := dlg.owner.Bounds()
		b := dlg.Bounds()
		if dlg.centerInOwnerWhenRun {
			dlg.SetBounds(Rectangle{
				ob.X + (ob.Width-b.Width)/2,
				ob.Y + (ob.Height-b.Height)/2,
				b.Width,
				b.Height,
			})
		}
	} else {
		dlg.SetBounds(dlg.Bounds())
	}

	dlg.TopLevelWindow.Show()

	dlg.focusFirstCandidateDescendant()
}

func (dlg *Dialog) Run() int {
	dlg.Show()

	if dlg.owner != nil {
		dlg.owner.SetEnabled(false)
	}

	dlg.TopLevelWindow.Run()

	return dlg.result
}
<commit_msg>Dialog: Add Result method, default to DlgCmdNone<commit_after>// Copyright 2010 The Walk 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 walk

import (
	"syscall"
	"unsafe"
)

import . "github.com/lxn/go-winapi"

const (
	DlgCmdNone     = 0
	DlgCmdOK       = IDOK
	DlgCmdCancel   = IDCANCEL
	DlgCmdAbort    = IDABORT
	DlgCmdRetry    = IDRETRY
	DlgCmdIgnore   = IDIGNORE
	DlgCmdYes      = IDYES
	DlgCmdNo       = IDNO
	DlgCmdClose    = IDCLOSE
	DlgCmdHelp     = IDHELP
	DlgCmdTryAgain = IDTRYAGAIN
	DlgCmdContinue = IDCONTINUE
	DlgCmdTimeout  = IDTIMEOUT
)

const dialogWindowClass = `\o/ Walk_Dialog_Class \o/`

func init() {
	MustRegisterWindowClass(dialogWindowClass)
}

type dialogish interface {
	DefaultButton() *PushButton
	CancelButton() *PushButton
}

type Dialog struct {
	TopLevelWindow
	result               int
	defaultButton        *PushButton
	cancelButton         *PushButton
	centerInOwnerWhenRun bool
}

func NewDialog(owner RootWidget) (*Dialog, error) {
	dlg := &Dialog{
		TopLevelWindow: TopLevelWindow{
			owner: owner,
		},
	}

	if err := InitWidget(
		dlg,
		owner,
		dialogWindowClass,
		WS_CAPTION|WS_SYSMENU|WS_THICKFRAME,
		WS_EX_DLGMODALFRAME); err != nil {
		return nil, err
	}

	dlg.centerInOwnerWhenRun = owner != nil

	dlg.children = newWidgetList(dlg)

	// This forces display of focus rectangles, as soon as the user starts to type.
	dlg.SendMessage(WM_CHANGEUISTATE, UIS_INITIALIZE, 0)

	dlg.result = DlgCmdNone

	return dlg, nil
}

func (dlg *Dialog) DefaultButton() *PushButton {
	return dlg.defaultButton
}

func (dlg *Dialog) SetDefaultButton(button *PushButton) error {
	if button != nil && !IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	succeeded := false
	if dlg.defaultButton != nil {
		if err := dlg.defaultButton.setAndClearStyleBits(BS_PUSHBUTTON, BS_DEFPUSHBUTTON); err != nil {
			return err
		}
		defer func() {
			if !succeeded {
				dlg.defaultButton.setAndClearStyleBits(BS_DEFPUSHBUTTON, BS_PUSHBUTTON)
			}
		}()
	}

	if button != nil {
		if err := button.setAndClearStyleBits(BS_DEFPUSHBUTTON, BS_PUSHBUTTON); err != nil {
			return err
		}
	}

	dlg.defaultButton = button

	succeeded = true

	return nil
}

func (dlg *Dialog) CancelButton() *PushButton {
	return dlg.cancelButton
}

func (dlg *Dialog) SetCancelButton(button *PushButton) error {
	if button != nil && !IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	dlg.cancelButton = button

	return nil
}

func (dlg *Dialog) Result() int {
	return dlg.result
}

func (dlg *Dialog) Accept() {
	dlg.Close(DlgCmdOK)
}

func (dlg *Dialog) Cancel() {
	dlg.Close(DlgCmdCancel)
}

func (dlg *Dialog) Close(result int) {
	dlg.result = result

	dlg.TopLevelWindow.Close()
}

func firstFocusableDescendantCallback(hwnd HWND, lParam uintptr) uintptr {
	widget := widgetFromHWND(hwnd)

	if widget == nil || !widget.Visible() || !widget.Enabled() {
		return 1
	}

	style := uint(GetWindowLong(hwnd, GWL_STYLE))
	// FIXME: Ugly workaround for NumberEdit
	_, isTextSelectable := widget.(textSelectable)
	if style&WS_TABSTOP > 0 || isTextSelectable {
		hwndPtr := (*HWND)(unsafe.Pointer(lParam))
		*hwndPtr = hwnd
		return 0
	}

	return 1
}

var firstFocusableDescendantCallbackPtr = syscall.NewCallback(firstFocusableDescendantCallback)

func firstFocusableDescendant(container Container) Widget {
	var hwnd HWND

	EnumChildWindows(container.BaseWidget().hWnd, firstFocusableDescendantCallbackPtr, uintptr(unsafe.Pointer(&hwnd)))

	return widgetFromHWND(hwnd)
}

type textSelectable interface {
	SetTextSelection(start, end int)
}

func (dlg *Dialog) focusFirstCandidateDescendant() {
	widget := firstFocusableDescendant(dlg)
	if widget == nil {
		return
	}

	if err := widget.SetFocus(); err != nil {
		return
	}

	if textSel, ok := widget.(textSelectable); ok {
		textSel.SetTextSelection(0, -1)
	}
}

func (dlg *Dialog) Show() {
	if dlg.owner != nil {
		ob := dlg.owner.Bounds()
		b := dlg.Bounds()
		if dlg.centerInOwnerWhenRun {
			dlg.SetBounds(Rectangle{
				ob.X + (ob.Width-b.Width)/2,
				ob.Y + (ob.Height-b.Height)/2,
				b.Width,
				b.Height,
			})
		}
	} else {
		dlg.SetBounds(dlg.Bounds())
	}

	dlg.TopLevelWindow.Show()

	dlg.focusFirstCandidateDescendant()
}

func (dlg *Dialog) Run() int {
	dlg.Show()

	if dlg.owner != nil {
		dlg.owner.SetEnabled(false)
	}

	dlg.TopLevelWindow.Run()

	return dlg.result
}
<|endoftext|>