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

// Bytes objects

package py

import (
	"bytes"
	"fmt"
	"strings"
)

var BytesType = ObjectType.NewType("bytes",
	`bytes(iterable_of_ints) -> bytes
bytes(string, encoding[, errors]) -> bytes
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
bytes(int) -> bytes object of size given by the parameter initialized with null bytes
bytes() -> empty bytes object

Construct an immutable array of bytes from:
  - an iterable yielding integers in range(256)
  - a text string encoded using the specified encoding
  - any object implementing the buffer API.
  - an integer`, BytesNew, nil)

type Bytes []byte

// Type of this Bytes object
func (o Bytes) Type() *Type {
	return BytesType
}

// BytesNew
func BytesNew(metatype *Type, args Tuple, kwargs StringDict) (res Object, err error) {
	var x Object
	var encoding Object
	var errors Object
	var New Object
	kwlist := []string{"source", "encoding", "errors"}

	err = ParseTupleAndKeywords(args, kwargs, "|Oss:bytes", kwlist, &x, &encoding, &errors)
	if err != nil {
		return nil, err
	}
	if x == nil {
		if encoding != nil || errors != nil {
			return nil, ExceptionNewf(TypeError, "encoding or errors without sequence argument")
		}
		return Bytes{}, nil
	}

	if s, ok := x.(String); ok {
		// Encode via the codec registry
		if encoding == nil {
			return nil, ExceptionNewf(TypeError, "string argument without an encoding")
		}
		encodingStr := strings.ToLower(string(encoding.(String)))
		if encodingStr == "utf-8" || encodingStr == "utf8" {
			return Bytes([]byte(s)), nil
		}
		// FIXME
		// New = PyUnicode_AsEncodedString(x, encoding, errors)
		// assert(PyBytes_Check(New))
		// return New
		return nil, ExceptionNewf(NotImplementedError, "String decode for %q not implemented", encodingStr)
	}

	// We'd like to call PyObject_Bytes here, but we need to check for an
	// integer argument before deferring to PyBytes_FromObject, something
	// PyObject_Bytes doesn't do.
	var ok bool
	if I, ok := x.(I__bytes__); ok {
		New, err = I.M__bytes__()
		if err != nil {
			return nil, err
		}
	} else if New, ok, err = TypeCall0(x, "__bytes__"); ok {
		if err != nil {
			return nil, err
		}
	} else {
		goto no_bytes_method
	}
	if _, ok = New.(Bytes); !ok {
		return nil, ExceptionNewf(TypeError, "__bytes__ returned non-bytes (type %s)", New.Type().Name)
	}
no_bytes_method:

	// Is it an integer?
	_, isInt := x.(Int)
	_, isBigInt := x.(*BigInt)
	if isInt || isBigInt {
		size, err := MakeGoInt(x)
		if err != nil {
			return nil, err
		}
		if size < 0 {
			return nil, ExceptionNewf(ValueError, "negative count")
		}
		return make(Bytes, size), nil
	}

	// If it's not unicode, there can't be encoding or errors
	if encoding != nil || errors != nil {
		return nil, ExceptionNewf(TypeError, "encoding or errors without a string argument")
	}

	return BytesFromObject(x)
}

// Converts an object into bytes
func BytesFromObject(x Object) (Bytes, error) {
	// Look for special cases
	// FIXME implement converting from any object implementing the buffer API.
	switch z := x.(type) {
	case Bytes:
		// Immutable type so just return what was passed in
		return z, nil
	case String:
		return nil, ExceptionNewf(TypeError, "cannot convert unicode object to bytes")
	}
	// Otherwise iterate through the whatever converting it into ints
	b := Bytes{}
	var loopErr error
	iterErr := Iterate(x, func(item Object) bool {
		var value int
		value, loopErr = IndexInt(item)
		if loopErr != nil {
			return true
		}
		if value < 0 || value >= 256 {
			loopErr = ExceptionNewf(ValueError, "bytes must be in range(0, 256)")
			return true
		}
		b = append(b, byte(value))
		return false
	})
	if iterErr != nil {
		return nil, iterErr
	}
	if loopErr != nil {
		return nil, loopErr
	}
	return b, nil
}

func (a Bytes) M__str__() (Object, error) {
	return a.M__repr__()
}

func (a Bytes) M__repr__() (Object, error) {
	// FIXME combine this with parser/stringescape.go into file in py?
	var out bytes.Buffer
	quote := '\''
	if bytes.IndexByte(a, byte('\'')) >= 0 && !(bytes.IndexByte(a, byte('"')) >= 0) {
		quote = '"'
	}
	out.WriteRune('b')
	out.WriteRune(quote)
	for _, c := range a {
		switch {
		case c < 0x20:
			switch c {
			case '\t':
				out.WriteString(`\t`)
			case '\n':
				out.WriteString(`\n`)
			case '\r':
				out.WriteString(`\r`)
			default:
				fmt.Fprintf(&out, `\x%02x`, c)
			}
		case c < 0x7F:
			if c == '\\' || (quote == '\'' && c == '\'') || (quote == '"' && c == '"') {
				out.WriteRune('\\')
			}
			out.WriteByte(c)
		default:
			fmt.Fprintf(&out, "\\x%02x", c)
		}
	}
	out.WriteRune(quote)
	return String(out.String()), nil
}

// Convert an Object to an Bytes
//
// Retrurns ok as to whether the conversion worked or not
func convertToBytes(other Object) (Bytes, bool) {
	switch b := other.(type) {
	case Bytes:
		return b, true
	}
	return []byte(nil), false
}

// Rich comparison

func (a Bytes) M__lt__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) < 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__le__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) <= 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__eq__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Equal(a, b)), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__ne__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(!bytes.Equal(a, b)), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__gt__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) > 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__ge__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) >= 0), nil
	}
	return NotImplemented, nil
}

// Check interface is satisfied
var _ richComparison = (Bytes)(nil)
<commit_msg>py: make bytes implement __{i,}add__<commit_after>// Copyright 2018 The go-python Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Bytes objects

package py

import (
	"bytes"
	"fmt"
	"strings"
)

var BytesType = ObjectType.NewType("bytes",
	`bytes(iterable_of_ints) -> bytes
bytes(string, encoding[, errors]) -> bytes
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
bytes(int) -> bytes object of size given by the parameter initialized with null bytes
bytes() -> empty bytes object

Construct an immutable array of bytes from:
  - an iterable yielding integers in range(256)
  - a text string encoded using the specified encoding
  - any object implementing the buffer API.
  - an integer`, BytesNew, nil)

type Bytes []byte

// Type of this Bytes object
func (o Bytes) Type() *Type {
	return BytesType
}

// BytesNew
func BytesNew(metatype *Type, args Tuple, kwargs StringDict) (res Object, err error) {
	var x Object
	var encoding Object
	var errors Object
	var New Object
	kwlist := []string{"source", "encoding", "errors"}

	err = ParseTupleAndKeywords(args, kwargs, "|Oss:bytes", kwlist, &x, &encoding, &errors)
	if err != nil {
		return nil, err
	}
	if x == nil {
		if encoding != nil || errors != nil {
			return nil, ExceptionNewf(TypeError, "encoding or errors without sequence argument")
		}
		return Bytes{}, nil
	}

	if s, ok := x.(String); ok {
		// Encode via the codec registry
		if encoding == nil {
			return nil, ExceptionNewf(TypeError, "string argument without an encoding")
		}
		encodingStr := strings.ToLower(string(encoding.(String)))
		if encodingStr == "utf-8" || encodingStr == "utf8" {
			return Bytes([]byte(s)), nil
		}
		// FIXME
		// New = PyUnicode_AsEncodedString(x, encoding, errors)
		// assert(PyBytes_Check(New))
		// return New
		return nil, ExceptionNewf(NotImplementedError, "String decode for %q not implemented", encodingStr)
	}

	// We'd like to call PyObject_Bytes here, but we need to check for an
	// integer argument before deferring to PyBytes_FromObject, something
	// PyObject_Bytes doesn't do.
	var ok bool
	if I, ok := x.(I__bytes__); ok {
		New, err = I.M__bytes__()
		if err != nil {
			return nil, err
		}
	} else if New, ok, err = TypeCall0(x, "__bytes__"); ok {
		if err != nil {
			return nil, err
		}
	} else {
		goto no_bytes_method
	}
	if _, ok = New.(Bytes); !ok {
		return nil, ExceptionNewf(TypeError, "__bytes__ returned non-bytes (type %s)", New.Type().Name)
	}
no_bytes_method:

	// Is it an integer?
	_, isInt := x.(Int)
	_, isBigInt := x.(*BigInt)
	if isInt || isBigInt {
		size, err := MakeGoInt(x)
		if err != nil {
			return nil, err
		}
		if size < 0 {
			return nil, ExceptionNewf(ValueError, "negative count")
		}
		return make(Bytes, size), nil
	}

	// If it's not unicode, there can't be encoding or errors
	if encoding != nil || errors != nil {
		return nil, ExceptionNewf(TypeError, "encoding or errors without a string argument")
	}

	return BytesFromObject(x)
}

// Converts an object into bytes
func BytesFromObject(x Object) (Bytes, error) {
	// Look for special cases
	// FIXME implement converting from any object implementing the buffer API.
	switch z := x.(type) {
	case Bytes:
		// Immutable type so just return what was passed in
		return z, nil
	case String:
		return nil, ExceptionNewf(TypeError, "cannot convert unicode object to bytes")
	}
	// Otherwise iterate through the whatever converting it into ints
	b := Bytes{}
	var loopErr error
	iterErr := Iterate(x, func(item Object) bool {
		var value int
		value, loopErr = IndexInt(item)
		if loopErr != nil {
			return true
		}
		if value < 0 || value >= 256 {
			loopErr = ExceptionNewf(ValueError, "bytes must be in range(0, 256)")
			return true
		}
		b = append(b, byte(value))
		return false
	})
	if iterErr != nil {
		return nil, iterErr
	}
	if loopErr != nil {
		return nil, loopErr
	}
	return b, nil
}

func (a Bytes) M__str__() (Object, error) {
	return a.M__repr__()
}

func (a Bytes) M__repr__() (Object, error) {
	// FIXME combine this with parser/stringescape.go into file in py?
	var out bytes.Buffer
	quote := '\''
	if bytes.IndexByte(a, byte('\'')) >= 0 && !(bytes.IndexByte(a, byte('"')) >= 0) {
		quote = '"'
	}
	out.WriteRune('b')
	out.WriteRune(quote)
	for _, c := range a {
		switch {
		case c < 0x20:
			switch c {
			case '\t':
				out.WriteString(`\t`)
			case '\n':
				out.WriteString(`\n`)
			case '\r':
				out.WriteString(`\r`)
			default:
				fmt.Fprintf(&out, `\x%02x`, c)
			}
		case c < 0x7F:
			if c == '\\' || (quote == '\'' && c == '\'') || (quote == '"' && c == '"') {
				out.WriteRune('\\')
			}
			out.WriteByte(c)
		default:
			fmt.Fprintf(&out, "\\x%02x", c)
		}
	}
	out.WriteRune(quote)
	return String(out.String()), nil
}

// Convert an Object to an Bytes
//
// Retrurns ok as to whether the conversion worked or not
func convertToBytes(other Object) (Bytes, bool) {
	switch b := other.(type) {
	case Bytes:
		return b, true
	}
	return []byte(nil), false
}

// Rich comparison

func (a Bytes) M__lt__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) < 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__le__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) <= 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__eq__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Equal(a, b)), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__ne__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(!bytes.Equal(a, b)), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__gt__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) > 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__ge__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		return NewBool(bytes.Compare(a, b) >= 0), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__add__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		o := make([]byte, len(a)+len(b))
		copy(o[:len(a)], a)
		copy(o[len(a):], b)
		return Bytes(o), nil
	}
	return NotImplemented, nil
}

func (a Bytes) M__iadd__(other Object) (Object, error) {
	if b, ok := convertToBytes(other); ok {
		a = append(a, b...)
		return a, nil
	}
	return NotImplemented, nil
}

// Check interface is satisfied
var (
	_ richComparison = (Bytes)(nil)
	_ I__add__       = (Bytes)(nil)
	_ I__iadd__      = (Bytes)(nil)
)
<|endoftext|>


<commit_before>/*
 *
 * pig is a very simple game involving dice rolls.
 *
 */
package pig

import (
	"github.com/jkomoros/boardgame"
	"math/rand"
)

//go:generate autoreader

type gameDelegate struct {
	boardgame.DefaultGameDelegate
}

func (g *gameDelegate) Name() string {
	return "pig"
}

func (g *gameDelegate) DisplayName() string {
	return "Pig"
}

func (g *gameDelegate) LegalNumPlayers(numPlayers int) bool {
	return numPlayers > 0 && numPlayers < 6
}

func (g *gameDelegate) DefaultNumPlayers() int {
	return 2
}

func (g *gameDelegate) DistributeComponentToStarterStack(state boardgame.State, c *boardgame.Component) (boardgame.Stack, error) {
	game, _ := concreteStates(state)
	return game.Die, nil
}

func (g *gameDelegate) FinishSetUp(state boardgame.MutableState) {

	game, _ := concreteStates(state)

	//Pick a player to start randomly.
	startingPlayer := boardgame.PlayerIndex(rand.Intn(len(state.Players())))

	game.CurrentPlayer = startingPlayer

}

func (g *gameDelegate) EmptyGameState() boardgame.MutableSubState {
	dice := g.Manager().Chest().Deck(diceDeckName)

	if dice == nil {
		return nil
	}

	return &gameState{
		CurrentPlayer: 0,
		Die:           boardgame.NewSizedStack(dice, 1),
	}
}

func (g *gameDelegate) EmptyPlayerState(index boardgame.PlayerIndex) boardgame.MutablePlayerState {
	return &playerState{
		playerIndex: index,
		TotalScore:  0,
		RoundScore:  0,
		DieCounted:  true,
		Done:        false,
		Busted:      false,
	}
}

func (g *gameDelegate) EmptyDynamicComponentValues(deck *boardgame.Deck) boardgame.MutableSubState {
	if deck.Name() == diceDeckName {
		return &dieDynamicValue{
			Value: 1,
		}
	}
	return nil
}

func NewManager(storage boardgame.StorageManager) *boardgame.GameManager {
	chest := boardgame.NewComponentChest()

	dice := boardgame.NewDeck()

	dice.AddComponent(DefaultDie())

	chest.AddDeck(diceDeckName, dice)

	manager := boardgame.NewGameManager(&gameDelegate{}, chest, storage)

	if manager == nil {
		panic("No manager returned")
	}

	manager.AddPlayerMoveFactory(MoveRollDiceFactory)
	manager.AddPlayerMoveFactory(MoveDoneTurnFactory)

	manager.AddFixUpMoveFactory(MoveCountDieFactory)
	manager.AddFixUpMoveFactory(MoveAdvanceNextPlayerFactory)

	manager.SetUp()

	return manager
}
<commit_msg>Define a CheckGameFinished. Part of #372.<commit_after>/*
 *
 * pig is a very simple game involving dice rolls.
 *
 */
package pig

import (
	"github.com/jkomoros/boardgame"
	"math/rand"
)

//go:generate autoreader

//TODO: this should be configurable, and thus in the gameState.
const TargetScore = 100

type gameDelegate struct {
	boardgame.DefaultGameDelegate
}

func (g *gameDelegate) Name() string {
	return "pig"
}

func (g *gameDelegate) DisplayName() string {
	return "Pig"
}

func (g *gameDelegate) LegalNumPlayers(numPlayers int) bool {
	return numPlayers > 0 && numPlayers < 6
}

func (g *gameDelegate) DefaultNumPlayers() int {
	return 2
}

func (g *gameDelegate) DistributeComponentToStarterStack(state boardgame.State, c *boardgame.Component) (boardgame.Stack, error) {
	game, _ := concreteStates(state)
	return game.Die, nil
}

func (g *gameDelegate) FinishSetUp(state boardgame.MutableState) {

	game, _ := concreteStates(state)

	//Pick a player to start randomly.
	startingPlayer := boardgame.PlayerIndex(rand.Intn(len(state.Players())))

	game.CurrentPlayer = startingPlayer

}

func (g *gameDelegate) CheckGameFinished(state boardgame.State) (finished bool, winners []boardgame.PlayerIndex) {
	_, players := concreteStates(state)

	for i, player := range players {
		if player.TotalScore >= TargetScore {
			winners = append(winners, boardgame.PlayerIndex(i))
		}
	}

	if len(winners) > 0 {
		return true, winners
	}

	return false, nil
}

func (g *gameDelegate) EmptyGameState() boardgame.MutableSubState {
	dice := g.Manager().Chest().Deck(diceDeckName)

	if dice == nil {
		return nil
	}

	return &gameState{
		CurrentPlayer: 0,
		Die:           boardgame.NewSizedStack(dice, 1),
	}
}

func (g *gameDelegate) EmptyPlayerState(index boardgame.PlayerIndex) boardgame.MutablePlayerState {
	return &playerState{
		playerIndex: index,
		TotalScore:  0,
		RoundScore:  0,
		DieCounted:  true,
		Done:        false,
		Busted:      false,
	}
}

func (g *gameDelegate) EmptyDynamicComponentValues(deck *boardgame.Deck) boardgame.MutableSubState {
	if deck.Name() == diceDeckName {
		return &dieDynamicValue{
			Value: 1,
		}
	}
	return nil
}

func NewManager(storage boardgame.StorageManager) *boardgame.GameManager {
	chest := boardgame.NewComponentChest()

	dice := boardgame.NewDeck()

	dice.AddComponent(DefaultDie())

	chest.AddDeck(diceDeckName, dice)

	manager := boardgame.NewGameManager(&gameDelegate{}, chest, storage)

	if manager == nil {
		panic("No manager returned")
	}

	manager.AddPlayerMoveFactory(MoveRollDiceFactory)
	manager.AddPlayerMoveFactory(MoveDoneTurnFactory)

	manager.AddFixUpMoveFactory(MoveCountDieFactory)
	manager.AddFixUpMoveFactory(MoveAdvanceNextPlayerFactory)

	manager.SetUp()

	return manager
}
<|endoftext|>


<commit_before>// Copyright 2019 The Ebiten 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.

// +build example jsgo

package main

import (
	"fmt"
	"image/color"
	"log"
	"math/rand"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var offscreen *ebiten.Image

func init() {
	offscreen, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterDefault)
}

func update(screen *ebiten.Image) error {
	w, h := offscreen.Size()
	x := rand.Intn(w)
	y := rand.Intn(h)
	c := color.RGBA{
		byte(rand.Intn(256)),
		byte(rand.Intn(256)),
		byte(rand.Intn(256)),
		byte(0xff),
	}
	offscreen.Set(x, y, c)

	if ebiten.IsDrawingSkipped() {
		return nil
	}

	screen.DrawImage(offscreen, nil)
	ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.CurrentTPS()))
	return nil
}

func main() {
	if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Test"); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>examples/set: Add FPS to see the performance<commit_after>// Copyright 2019 The Ebiten 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.

// +build example jsgo

package main

import (
	"fmt"
	"image/color"
	"log"
	"math/rand"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var offscreen *ebiten.Image

func init() {
	offscreen, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterDefault)
}

func update(screen *ebiten.Image) error {
	w, h := offscreen.Size()
	x := rand.Intn(w)
	y := rand.Intn(h)
	c := color.RGBA{
		byte(rand.Intn(256)),
		byte(rand.Intn(256)),
		byte(rand.Intn(256)),
		byte(0xff),
	}
	offscreen.Set(x, y, c)

	if ebiten.IsDrawingSkipped() {
		return nil
	}

	screen.DrawImage(offscreen, nil)
	ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
	return nil
}

func main() {
	if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Test"); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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 firestore

import (
	"context"
	"errors"
	"fmt"
	"sort"

	"google.golang.org/api/iterator"
	firestorepb "google.golang.org/genproto/googleapis/firestore/v1"
)

// A CollectionGroupRef is a reference to a group of collections sharing the
// same ID.
type CollectionGroupRef struct {
	c *Client

	// Use the methods of Query on a CollectionGroupRef to create and run queries.
	Query
}

func newCollectionGroupRef(c *Client, dbPath, collectionID string) *CollectionGroupRef {
	return &CollectionGroupRef{
		c: c,

		Query: Query{
			c:              c,
			collectionID:   collectionID,
			path:           dbPath,
			parentPath:     dbPath + "/documents",
			allDescendants: true,
		},
	}
}

// GetPartitionedQueries returns a slice of Query objects, each containing a
// partition of a collection group. partitionCount must be a positive value and
// the number of returned partitions may be less than the requested number if
// providing the desired number would result in partitions with very few documents.
//
// If a Collection Group Query would return a large number of documents, this
// can help to subdivide the query to smaller working units that can be distributed.
func (cgr CollectionGroupRef) GetPartitionedQueries(ctx context.Context, partitionCount int) ([]Query, error) {
	qp, err := cgr.getPartitions(ctx, partitionCount)
	if err != nil {
		return nil, err
	}
	queries := make([]Query, len(qp))
	for _, part := range qp {
		queries = append(queries, part.toQuery())
	}
	return queries, nil
}

// getPartitions returns a slice of queryPartition objects, describing a start
// and end range to query a subsection of the collection group. partitionCount
// must be a positive value and the number of returned partitions may be less
// than the requested number if providing the desired number would result in
// partitions with very few documents.
func (cgr CollectionGroupRef) getPartitions(ctx context.Context, partitionCount int) ([]queryPartition, error) {
	orderedQuery := cgr.query().OrderBy(DocumentID, Asc)

	if partitionCount <= 0 {
		return nil, errors.New("a positive partitionCount must be provided")
	} else if partitionCount == 1 {
		return []queryPartition{{CollectionGroupQuery: orderedQuery}}, nil
	}

	db := cgr.c.path()
	ctx = withResourceHeader(ctx, db)

	// CollectionGroup Queries need to be ordered by __name__ ASC.
	query, err := orderedQuery.toProto()
	if err != nil {
		return nil, err
	}
	structuredQuery := &firestorepb.PartitionQueryRequest_StructuredQuery{
		StructuredQuery: query,
	}

	// Uses default PageSize
	pbr := &firestorepb.PartitionQueryRequest{
		Parent:         db + "/documents",
		PartitionCount: int64(partitionCount),
		QueryType:      structuredQuery,
	}
	cursorReferences := make([]*firestorepb.Value, 0, partitionCount)
	iter := cgr.c.c.PartitionQuery(ctx, pbr)
	for {
		cursor, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("GetPartitions: %v", err)
		}
		cursorReferences = append(cursorReferences, cursor.GetValues()...)
	}

	// From Proto documentation:
	// To obtain a complete result set ordered with respect to the results of the
	// query supplied to PartitionQuery, the results sets should be merged:
	// cursor A, cursor B, cursor M, cursor Q, cursor U, cursor W
	// Once we have exhausted the pages, the cursor values need to be sorted in
	// lexicographical order by segment (areas between '/').
	sort.Sort(byFirestoreValue(cursorReferences))

	queryPartitions := make([]queryPartition, 0, len(cursorReferences))
	previousCursor := ""

	for _, cursor := range cursorReferences {
		cursorRef := cursor.GetReferenceValue()

		// remove the root path from the reference, as queries take cursors
		// relative to a collection
		cursorRef = cursorRef[len(orderedQuery.path)+1:]

		qp := queryPartition{
			CollectionGroupQuery: orderedQuery,
			StartAt:              previousCursor,
			EndBefore:            cursorRef,
		}
		queryPartitions = append(queryPartitions, qp)
		previousCursor = cursorRef
	}

	// In the case there were no partitions, we still add a single partition to
	// the result, that covers the complete range.
	lastPart := queryPartition{CollectionGroupQuery: orderedQuery}
	if len(cursorReferences) > 0 {
		cursorRef := cursorReferences[len(cursorReferences)-1].GetReferenceValue()
		lastPart.StartAt = cursorRef[len(orderedQuery.path)+1:]
	}
	queryPartitions = append(queryPartitions, lastPart)

	return queryPartitions, nil
}

// queryPartition provides a Collection Group Reference and start and end split
// points allowing for a section of a collection group to be queried. This is
// used by GetPartitions which, given a CollectionGroupReference returns smaller
// sub-queries or partitions
type queryPartition struct {
	// CollectionGroupQuery is an ordered query on a CollectionGroupReference.
	// This query must be ordered Asc on __name__.
	// Example: client.CollectionGroup("collectionID").query().OrderBy(DocumentID, Asc)
	CollectionGroupQuery Query

	// StartAt is a document reference value, relative to the collection, not
	// a complete parent path.
	// Example: "documents/collectionName/documentName"
	StartAt string

	// EndBefore is a document reference value, relative to the collection, not
	// a complete parent path.
	// Example: "documents/collectionName/documentName"
	EndBefore string
}

// toQuery converts a queryPartition object to a Query object
func (qp queryPartition) toQuery() Query {
	q := *qp.CollectionGroupQuery.query()

	// Remove the leading path before calling StartAt, EndBefore
	if qp.StartAt != "" {
		q = q.StartAt(qp.StartAt)
	}
	if qp.EndBefore != "" {
		q = q.EndBefore(qp.EndBefore)
	}
	return q
}
<commit_msg>fix(firestore): correct an issue with returning empty paritions from GetPartionedQueries (#4346)<commit_after>// Copyright 2019 Google LLC
//
// 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 firestore

import (
	"context"
	"errors"
	"fmt"
	"sort"

	"google.golang.org/api/iterator"
	firestorepb "google.golang.org/genproto/googleapis/firestore/v1"
)

// A CollectionGroupRef is a reference to a group of collections sharing the
// same ID.
type CollectionGroupRef struct {
	c *Client

	// Use the methods of Query on a CollectionGroupRef to create and run queries.
	Query
}

func newCollectionGroupRef(c *Client, dbPath, collectionID string) *CollectionGroupRef {
	return &CollectionGroupRef{
		c: c,

		Query: Query{
			c:              c,
			collectionID:   collectionID,
			path:           dbPath,
			parentPath:     dbPath + "/documents",
			allDescendants: true,
		},
	}
}

// GetPartitionedQueries returns a slice of Query objects, each containing a
// partition of a collection group. partitionCount must be a positive value and
// the number of returned partitions may be less than the requested number if
// providing the desired number would result in partitions with very few documents.
//
// If a Collection Group Query would return a large number of documents, this
// can help to subdivide the query to smaller working units that can be distributed.
func (cgr CollectionGroupRef) GetPartitionedQueries(ctx context.Context, partitionCount int) ([]Query, error) {
	qp, err := cgr.getPartitions(ctx, partitionCount)
	if err != nil {
		return nil, err
	}
	queries := make([]Query, len(qp))
	for i, part := range qp {
		queries[i] = part.toQuery()
	}
	return queries, nil
}

// getPartitions returns a slice of queryPartition objects, describing a start
// and end range to query a subsection of the collection group. partitionCount
// must be a positive value and the number of returned partitions may be less
// than the requested number if providing the desired number would result in
// partitions with very few documents.
func (cgr CollectionGroupRef) getPartitions(ctx context.Context, partitionCount int) ([]queryPartition, error) {
	orderedQuery := cgr.query().OrderBy(DocumentID, Asc)

	if partitionCount <= 0 {
		return nil, errors.New("a positive partitionCount must be provided")
	} else if partitionCount == 1 {
		return []queryPartition{{CollectionGroupQuery: orderedQuery}}, nil
	}

	db := cgr.c.path()
	ctx = withResourceHeader(ctx, db)

	// CollectionGroup Queries need to be ordered by __name__ ASC.
	query, err := orderedQuery.toProto()
	if err != nil {
		return nil, err
	}
	structuredQuery := &firestorepb.PartitionQueryRequest_StructuredQuery{
		StructuredQuery: query,
	}

	// Uses default PageSize
	pbr := &firestorepb.PartitionQueryRequest{
		Parent:         db + "/documents",
		PartitionCount: int64(partitionCount),
		QueryType:      structuredQuery,
	}
	cursorReferences := make([]*firestorepb.Value, 0, partitionCount)
	iter := cgr.c.c.PartitionQuery(ctx, pbr)
	for {
		cursor, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("GetPartitions: %v", err)
		}
		cursorReferences = append(cursorReferences, cursor.GetValues()...)
	}

	// From Proto documentation:
	// To obtain a complete result set ordered with respect to the results of the
	// query supplied to PartitionQuery, the results sets should be merged:
	// cursor A, cursor B, cursor M, cursor Q, cursor U, cursor W
	// Once we have exhausted the pages, the cursor values need to be sorted in
	// lexicographical order by segment (areas between '/').
	sort.Sort(byFirestoreValue(cursorReferences))

	queryPartitions := make([]queryPartition, 0, len(cursorReferences))
	previousCursor := ""

	for _, cursor := range cursorReferences {
		cursorRef := cursor.GetReferenceValue()

		// remove the root path from the reference, as queries take cursors
		// relative to a collection
		cursorRef = cursorRef[len(orderedQuery.path)+1:]

		qp := queryPartition{
			CollectionGroupQuery: orderedQuery,
			StartAt:              previousCursor,
			EndBefore:            cursorRef,
		}
		queryPartitions = append(queryPartitions, qp)
		previousCursor = cursorRef
	}

	// In the case there were no partitions, we still add a single partition to
	// the result, that covers the complete range.
	lastPart := queryPartition{CollectionGroupQuery: orderedQuery}
	if len(cursorReferences) > 0 {
		cursorRef := cursorReferences[len(cursorReferences)-1].GetReferenceValue()
		lastPart.StartAt = cursorRef[len(orderedQuery.path)+1:]
	}
	queryPartitions = append(queryPartitions, lastPart)

	return queryPartitions, nil
}

// queryPartition provides a Collection Group Reference and start and end split
// points allowing for a section of a collection group to be queried. This is
// used by GetPartitions which, given a CollectionGroupReference returns smaller
// sub-queries or partitions
type queryPartition struct {
	// CollectionGroupQuery is an ordered query on a CollectionGroupReference.
	// This query must be ordered Asc on __name__.
	// Example: client.CollectionGroup("collectionID").query().OrderBy(DocumentID, Asc)
	CollectionGroupQuery Query

	// StartAt is a document reference value, relative to the collection, not
	// a complete parent path.
	// Example: "documents/collectionName/documentName"
	StartAt string

	// EndBefore is a document reference value, relative to the collection, not
	// a complete parent path.
	// Example: "documents/collectionName/documentName"
	EndBefore string
}

// toQuery converts a queryPartition object to a Query object
func (qp queryPartition) toQuery() Query {
	q := *qp.CollectionGroupQuery.query()

	// Remove the leading path before calling StartAt, EndBefore
	if qp.StartAt != "" {
		q = q.StartAt(qp.StartAt)
	}
	if qp.EndBefore != "" {
		q = q.EndBefore(qp.EndBefore)
	}
	return q
}
<|endoftext|>


<commit_before>package htm

import (
	//"math"
	"bytes"
)

//Entries are positions of non-zero values
type SparseEntry struct {
	Row int
	Col int
}

//Sparse binary matrix stores indexes of non-zero entries in matrix
//to conserve space
type SparseBinaryMatrix struct {
	Width             int
	Height            int
	TotalNonZeroCount int
	Entries           []SparseEntry
}

//Create new sparse binary matrix of specified size
func NewSparseBinaryMatrix(height, width int) *SparseBinaryMatrix {
	m := &SparseBinaryMatrix{}
	m.Height = height
	m.Width = width
	//Intialize with 70% sparsity
	//m.Entries = make([]SparseEntry, int(math.Ceil(width*height*0.3)))
	return m
}

//Create sparse binary matrix from specified dense matrix
func NewSparseBinaryMatrixFromDense(values [][]bool) *SparseBinaryMatrix {
	if len(values) < 1 {
		panic("No values specified.")
	}
	m := &SparseBinaryMatrix{}
	m.Height = len(values)
	m.Width = len(values[0])

	for r := 0; r < m.Height; r++ {
		m.SetRowFromDense(r, values[r])
	}

	return m
}

// func NewRandSparseBinaryMatrix() *SparseBinaryMatrix {
// }

// func (sm *SparseBinaryMatrix) Resize(width int, height int) {
// }

//Get value at col,row position
func (sm *SparseBinaryMatrix) Get(row int, col int) bool {
	for _, val := range sm.Entries {
		if val.Row == row && val.Col == col {
			return true
		}
	}
	return false
}

func (sm *SparseBinaryMatrix) delete(row int, col int) {
	for idx, val := range sm.Entries {
		if val.Row == row && val.Col == col {
			sm.Entries = append(sm.Entries[:idx], sm.Entries[idx+1:]...)
			break
		}
	}

}

//Set value at row,col position
func (sm *SparseBinaryMatrix) Set(row int, col int, value bool) {
	if !value {
		sm.delete(row, col)
		return
	}

	if sm.Get(row, col) {
		return
	}

	newEntry := SparseEntry{}
	newEntry.Col = col
	newEntry.Row = row
	sm.Entries = append(sm.Entries, newEntry)

}

//Replaces specified row with values, assumes values is ordered
//correctly
func (sm *SparseBinaryMatrix) ReplaceRow(row int, values []bool) {
	sm.validateRowCol(row, len(values))

	for i := 0; i < sm.Width; i++ {
		sm.Set(row, i, values[i])
	}
}

//Replaces row with true values at specified indices
func (sm *SparseBinaryMatrix) ReplaceRowByIndices(row int, indices []int) {
	sm.validateRow(row)

	for i := 0; i < sm.Width; i++ {
		val := false
		for x := 0; x < len(indices); x++ {
			if i == indices[x] {
				val = true
				break
			}
		}
		sm.Set(row, i, val)
	}
}

//Returns dense row
func (sm *SparseBinaryMatrix) GetDenseRow(row int) []bool {
	sm.validateRow(row)
	result := make([]bool, sm.Width)

	for i := 0; i < len(sm.Entries); i++ {
		if sm.Entries[i].Row == row {
			result[sm.Entries[i].Col] = true
		}
	}

	return result
}

//Returns a rows "on" indices
func (sm *SparseBinaryMatrix) GetRowIndices(row int) []int {
	result := []int{}
	for i := 0; i < len(sm.Entries); i++ {
		if sm.Entries[i].Row == row {
			result = append(result, sm.Entries[i].Col)
		}
	}
	return result
}

//Sets a sparse row from dense representation
func (sm *SparseBinaryMatrix) SetRowFromDense(row int, denseRow []bool) {
	sm.validateRowCol(row, len(denseRow))
	for i := 0; i < sm.Width; i++ {
		sm.Set(row, i, denseRow[i])
	}
}

//In a normal matrix this would be multiplication in binary terms
//we just and then sum the true entries
func (sm *SparseBinaryMatrix) RowAndSum(row []bool) []int {
	sm.validateCol(len(row))
	result := make([]int, sm.Height)

	for _, val := range sm.Entries {
		if row[val.Col] {
			result[val.Row]++
		}
	}

	return result
}

func (sm *SparseBinaryMatrix) ToString() string {
	var buffer bytes.Buffer

	for r := 0; r < sm.Height; r++ {
		for c := 0; c < sm.Width; c++ {
			if sm.Get(r, c) {
				buffer.WriteByte('1')
			} else {
				buffer.WriteByte('0')
			}
		}
		buffer.WriteByte('\n')
	}

	return buffer.String()
}

func (sm *SparseBinaryMatrix) validateCol(col int) {
	if col > sm.Width {
		panic("Specified row is wider than matrix.")
	}
}

func (sm *SparseBinaryMatrix) validateRow(row int) {
	if row > sm.Height {
		panic("Specified row is out of bounds.")
	}
}

func (sm *SparseBinaryMatrix) validateRowCol(row int, col int) {
	sm.validateCol(col)
	sm.validateRow(row)
}
<commit_msg>Added int constructor and flatten function<commit_after>package htm

import (
	//"math"
	"bytes"
)

//Entries are positions of non-zero values
type SparseEntry struct {
	Row int
	Col int
}

//Sparse binary matrix stores indexes of non-zero entries in matrix
//to conserve space
type SparseBinaryMatrix struct {
	Width             int
	Height            int
	TotalNonZeroCount int
	Entries           []SparseEntry
}

//Create new sparse binary matrix of specified size
func NewSparseBinaryMatrix(height, width int) *SparseBinaryMatrix {
	m := &SparseBinaryMatrix{}
	m.Height = height
	m.Width = width
	//Intialize with 70% sparsity
	//m.Entries = make([]SparseEntry, int(math.Ceil(width*height*0.3)))
	return m
}

//Create sparse binary matrix from specified dense matrix
func NewSparseBinaryMatrixFromDense(values [][]bool) *SparseBinaryMatrix {
	if len(values) < 1 {
		panic("No values specified.")
	}
	m := &SparseBinaryMatrix{}
	m.Height = len(values)
	m.Width = len(values[0])

	for r := 0; r < m.Height; r++ {
		m.SetRowFromDense(r, values[r])
	}

	return m
}

// Creates a sparse binary matrix from specified integer array
// (any values greater than 0 are true)
func NewSparseBinaryMatrixFromInts(values [][]int) *SparseBinaryMatrix {
	if len(values) < 1 {
		panic("No values specified.")
	}

	m := &SparseBinaryMatrix{}
	m.Height = len(values)
	m.Width = len(values[0])

	for r := 0; r < m.Height; r++ {
		for c := 0; c < m.Width; c++ {
			if values[r][c] > 0 {
				m.Set(r, c, true)
			}
		}
	}

	return m
}

// func NewRandSparseBinaryMatrix() *SparseBinaryMatrix {
// }

// func (sm *SparseBinaryMatrix) Resize(width int, height int) {
// }

//Returns flattend dense represenation
func (sm *SparseBinaryMatrix) Flatten() []bool {
	result := make([]bool, sm.Height*sm.Width)
	for _, val := range sm.Entries {
		result[(val.Row*sm.Width)+val.Col] = true
	}
	return result
}

//Get value at col,row position
func (sm *SparseBinaryMatrix) Get(row int, col int) bool {
	for _, val := range sm.Entries {
		if val.Row == row && val.Col == col {
			return true
		}
	}
	return false
}

func (sm *SparseBinaryMatrix) delete(row int, col int) {
	for idx, val := range sm.Entries {
		if val.Row == row && val.Col == col {
			sm.Entries = append(sm.Entries[:idx], sm.Entries[idx+1:]...)
			break
		}
	}

}

//Set value at row,col position
func (sm *SparseBinaryMatrix) Set(row int, col int, value bool) {
	if !value {
		sm.delete(row, col)
		return
	}

	if sm.Get(row, col) {
		return
	}

	newEntry := SparseEntry{}
	newEntry.Col = col
	newEntry.Row = row
	sm.Entries = append(sm.Entries, newEntry)

}

//Replaces specified row with values, assumes values is ordered
//correctly
func (sm *SparseBinaryMatrix) ReplaceRow(row int, values []bool) {
	sm.validateRowCol(row, len(values))

	for i := 0; i < sm.Width; i++ {
		sm.Set(row, i, values[i])
	}
}

//Replaces row with true values at specified indices
func (sm *SparseBinaryMatrix) ReplaceRowByIndices(row int, indices []int) {
	sm.validateRow(row)

	for i := 0; i < sm.Width; i++ {
		val := false
		for x := 0; x < len(indices); x++ {
			if i == indices[x] {
				val = true
				break
			}
		}
		sm.Set(row, i, val)
	}
}

//Returns dense row
func (sm *SparseBinaryMatrix) GetDenseRow(row int) []bool {
	sm.validateRow(row)
	result := make([]bool, sm.Width)

	for i := 0; i < len(sm.Entries); i++ {
		if sm.Entries[i].Row == row {
			result[sm.Entries[i].Col] = true
		}
	}

	return result
}

//Returns a rows "on" indices
func (sm *SparseBinaryMatrix) GetRowIndices(row int) []int {
	result := []int{}
	for i := 0; i < len(sm.Entries); i++ {
		if sm.Entries[i].Row == row {
			result = append(result, sm.Entries[i].Col)
		}
	}
	return result
}

//Sets a sparse row from dense representation
func (sm *SparseBinaryMatrix) SetRowFromDense(row int, denseRow []bool) {
	sm.validateRowCol(row, len(denseRow))
	for i := 0; i < sm.Width; i++ {
		sm.Set(row, i, denseRow[i])
	}
}

//In a normal matrix this would be multiplication in binary terms
//we just and then sum the true entries
func (sm *SparseBinaryMatrix) RowAndSum(row []bool) []int {
	sm.validateCol(len(row))
	result := make([]int, sm.Height)

	for _, val := range sm.Entries {
		if row[val.Col] {
			result[val.Row]++
		}
	}

	return result
}

func (sm *SparseBinaryMatrix) ToString() string {
	var buffer bytes.Buffer

	for r := 0; r < sm.Height; r++ {
		for c := 0; c < sm.Width; c++ {
			if sm.Get(r, c) {
				buffer.WriteByte('1')
			} else {
				buffer.WriteByte('0')
			}
		}
		buffer.WriteByte('\n')
	}

	return buffer.String()
}

func (sm *SparseBinaryMatrix) validateCol(col int) {
	if col > sm.Width {
		panic("Specified row is wider than matrix.")
	}
}

func (sm *SparseBinaryMatrix) validateRow(row int) {
	if row > sm.Height {
		panic("Specified row is out of bounds.")
	}
}

func (sm *SparseBinaryMatrix) validateRowCol(row int, col int) {
	sm.validateCol(col)
	sm.validateRow(row)
}
<|endoftext|>


<commit_before>package bind

import (
	"bufio"
	"fmt"
	"github.com/devigned/veil/cgo"
	"github.com/devigned/veil/core"
	"go/types"
	"log"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
	"text/template"
	"unicode"
)

const (
	RETURN_VAR_NAME  = "cret"
	CFFI_HELPER_NAME = "_CffiHelper"
	HEADER_FILE_NAME = "output.h"
	PYTHON_FILE_NAME = "generated.py"
	PYTHON_TEMPLATE  = `import os
import sys
import cffi as _cffi_backend

_PY3 = sys.version_info[0] == 3

ffi = _cffi_backend.FFI()
ffi.cdef("""{{.CDef}}""")

{{ $cret := .ReturnVarName -}}
{{ $cffiHelperName := .CffiHelperName -}}

class _CffiHelper(object):

    here = os.path.dirname(os.path.abspath(__file__))
    lib = ffi.dlopen(os.path.join(here, "output"))

    @staticmethod
    def error_string(ptr):
        return _CffiHelper.c2py_string(_CffiHelper.lib.cgo_error_to_string(ptr))

    @staticmethod
    def cgo_free(ptr):
        return _CffiHelper.lib.cgo_cfree(ptr)

    @staticmethod
    def cgo_decref(ptr):
        return _CffiHelper.lib.cgo_decref(ptr)

    @staticmethod
    def handle_error(err):
        ptr = ffi.cast("void *", err)
        if not _CffiHelper.lib.cgo_is_error_nil(ptr):
            raise Exception(_CffiHelper.error_string(ptr))

    @staticmethod
    def c2py_string(s):
        pystr = ffi.string(s)
        _CffiHelper.lib.cgo_cfree(s)
        if _PY3:
            pystr = pystr.decode('utf-8')
        return pystr

class VeilObject(object):
    def __init__(self, uuid_ptr):
        self.uuid_ptr = uuid_ptr

    def __del__(self):
        _CffiHelper.cgo_decref(self.uuid_ptr)

class VeilError(Exception):
    def __init__(self, uuid_ptr):
        self.veil_obj = VeilObject(uuid_ptr=uuid_ptr)
        message = _CffiHelper.error_string(uuid_ptr)
        super(VeilError, self).__init__(message)

    @staticmethod
    def is_nil(uuid_ptr):
        return _CffiHelper.lib.cgo_is_error_nil(uuid_ptr)

# Globally defined functions
{{range $_, $func := .Funcs}}
def {{$func.Name}}({{$func.PrintArgs}}):
    {{ range $_, $inTrx := $func.InputTransforms -}}
      {{ $inTrx }}
    {{ end -}}
    {{$cret}} = _CffiHelper.lib.{{$func.Call -}}
    {{ range $idx, $result := $func.Results -}}
		{{if $result.IsError -}}
			if not VeilError.is_nil(cret.r1):
				{{ printf "raise VeilError(%s.r%d)" $cret $idx -}}
		{{end}}
    {{ end -}}
    return {{$func.PrintReturns}}

{{end}}

`
)

var (
	startCGoDefine  = regexp.MustCompile(`^typedef`)
	sizeOfRemove    = regexp.MustCompile(`_check_for_64_bit_pointer_matching_GoInt`)
	complexRemove   = regexp.MustCompile(`_Complex`)
	endif           = regexp.MustCompile(`^#endif`)
	endOfCGoDefine  = regexp.MustCompile(`^#ifdef __cplusplus`)
	extern          = regexp.MustCompile(`^extern \w`)
	sizeTypeReplace = regexp.MustCompile(`__SIZE_TYPE__`)
	removeFilters   = []*regexp.Regexp{sizeOfRemove, complexRemove}
	replaceFilters  = map[string]*regexp.Regexp{"size_t": sizeTypeReplace}
)

var pythonTemplate *template.Template

func init() {
	replacedTabsTemplate := removeTabs(PYTHON_TEMPLATE)
	if tmpl, err := template.New("codeTemplate").Parse(replacedTabsTemplate); err != nil {
		panic(err)

	} else {
		pythonTemplate = tmpl
	}
}

func removeTabs(src string) string {
	return strings.Replace(src, "\t", "  ", -1)
}

// Py3Binder contains the data for generating a python 3 binding
type Py3Binder struct {
	pkg *cgo.Package
}

type PyTemplateData struct {
	CDef           string
	Funcs          []*PyFunc
	CffiHelperName string
	ReturnVarName  string
}

type PyParam struct {
	underlying     *types.Var
	InputTransform string
}

func NewPyParam(v *types.Var) *PyParam {
	return &PyParam{underlying: v}
}

func (p PyParam) HasInputTransform() bool {
	return p.InputTransform != ""
}

func (p PyParam) Name() string {
	return ToSnake(p.underlying.Name())
}

func (p PyParam) IsError() bool {
	return cgo.ImplementsError(p.underlying.Type())
}

type PyFunc struct {
	fun     cgo.Func
	Name    string
	Params  []*PyParam
	Results []*PyParam
}

func (f PyFunc) InputTransforms() []string {
	// TODO: add input transformations
	return []string{}
}

func (f PyFunc) Call() string {
	return f.fun.CGoName() + "(" + f.PrintArgs() + ")"
}

func (f PyFunc) PrintArgs() string {
	names := make([]string, len(f.Params))
	for i := 0; i < len(names); i++ {
		names[i] = f.Params[i].Name()
	}
	return strings.Join(names, ", ")
}

func (f PyFunc) PrintReturns() string {
	if len(f.Results) > 1 {
		names := []string{}
		for i := 0; i < len(f.Results); i++ {
			if !cgo.ImplementsError(f.Results[i].underlying.Type()) {
				names = append(names, fmt.Sprintf(RETURN_VAR_NAME+".r%d", i))
			}
		}
		return strings.Join(names, ", ")
	} else {
		return RETURN_VAR_NAME
	}
}

// NewPy3Binder creates a new Binder for Python 3
func NewPy3Binder(pkg *cgo.Package) Bindable {
	return &Py3Binder{
		pkg: pkg,
	}
}

// Bind is the Python 3 implementation of Bind
func (p Py3Binder) Bind(outDir string) error {
	headerPath := path.Join(outDir, HEADER_FILE_NAME)
	cdefText, err := p.cDefText(headerPath)
	if err != nil {
		return core.NewSystemErrorF("Failed to generate Python CDefs: %v", err)
	}

	data := PyTemplateData{
		CDef:           strings.Join(cdefText, "\n"),
		Funcs:          p.Funcs(),
		CffiHelperName: CFFI_HELPER_NAME,
		ReturnVarName:  RETURN_VAR_NAME,
	}

	pythonFilePath := path.Join(outDir, PYTHON_FILE_NAME)
	f, err := os.Create(pythonFilePath)
	if err != nil {
		return core.NewSystemErrorF("Unable to create %s", path.Join(outDir, PYTHON_FILE_NAME))
	}

	w := bufio.NewWriter(f)
	pythonTemplate.Execute(w, data)
	w.Flush()
	f.Close()

	PyFormat(pythonFilePath)

	return nil
}

func (p Py3Binder) Funcs() []*PyFunc {
	funcs := make([]*PyFunc, len(p.pkg.Funcs()))

	for idx, f := range p.pkg.Funcs() {

		pyParams := make([]*PyParam, f.Signature().Params().Len())
		for i := 0; i < f.Signature().Params().Len(); i++ {
			param := f.Signature().Params().At(i)
			pyParams[i] = NewPyParam(param)
		}

		pyResults := make([]*PyParam, f.Signature().Results().Len())
		for i := 0; i < f.Signature().Results().Len(); i++ {
			param := f.Signature().Results().At(i)
			pyResults[i] = NewPyParam(param)
		}

		funcs[idx] = &PyFunc{
			fun:     f,
			Name:    ToSnake(f.Name()),
			Params:  pyParams,
			Results: pyResults,
		}
	}
	return funcs
}

func (p Py3Binder) cDefText(headerPath string) ([]string, error) {
	if file, err := os.Open(headerPath); err == nil {
		defer file.Close()

		filteredHeaders := []string{}
		recording := false

		// create a new scanner and read the file line by line
		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			text := scanner.Text()

			if !recording && (startCGoDefine.MatchString(text) || extern.MatchString(text)) {
				recording = true
			}

			if recording {
				if endif.MatchString(text) || endOfCGoDefine.MatchString(text) {
					recording = false
					continue
				}

				matched := false
				for _, filter := range removeFilters {
					if filter.MatchString(text) {
						matched = true
						break
					}
				}

				if !matched {
					for key, value := range replaceFilters {
						if value.MatchString(text) {
							text = value.ReplaceAllString(text, key)
						}
					}
					text = removeTabs(text)
					filteredHeaders = append(filteredHeaders, text)
				}
			}
		}

		// check for errors
		if err = scanner.Err(); err != nil {
			return nil, core.NewSystemError(err)
		}

		return filteredHeaders, nil

	} else {
		return nil, core.NewSystemError(err)
	}
}

// ToSnake convert the given string to snake case following the Golang format:
// acronyms are converted to lower-case and preceded by an underscore.
// via: https://gist.github.com/elwinar/14e1e897fdbe4d3432e1
func ToSnake(in string) string {
	runes := []rune(in)
	length := len(runes)

	var out []rune
	for i := 0; i < length; i++ {
		if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
			out = append(out, '_')
		}
		out = append(out, unicode.ToLower(runes[i]))
	}

	return string(out)
}

func PyFormat(path string) {
	which := exec.Command("which", "yapf")
	if err := which.Run(); err == nil {
		cmd := exec.Command("yapf", "-i", "--style={based_on_style: pep8, column_limit: 100}", path)
		err = cmd.Run()
	} else {
		log.Println("To format your Python code run `pip install yapf`")
	}
}
<commit_msg>handle strings via input transform and return format<commit_after>package bind

import (
	"bufio"
	"fmt"
	"github.com/devigned/veil/cgo"
	"github.com/devigned/veil/core"
	"go/types"
	"log"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
	"text/template"
	"unicode"
)

const (
	RETURN_VAR_NAME  = "cret"
	CFFI_HELPER_NAME = "_CffiHelper"
	HEADER_FILE_NAME = "output.h"
	PYTHON_FILE_NAME = "generated.py"
	PYTHON_TEMPLATE  = `import os
import sys
import cffi as _cffi_backend

_PY3 = sys.version_info[0] == 3

ffi = _cffi_backend.FFI()
ffi.cdef("""{{.CDef}}""")

{{ $cret := .ReturnVarName -}}
{{ $cffiHelperName := .CffiHelperName -}}

class _CffiHelper(object):

    here = os.path.dirname(os.path.abspath(__file__))
    lib = ffi.dlopen(os.path.join(here, "output"))

    @staticmethod
    def error_string(ptr):
        return _CffiHelper.c2py_string(_CffiHelper.lib.cgo_error_to_string(ptr))

    @staticmethod
    def cgo_free(ptr):
        return _CffiHelper.lib.cgo_cfree(ptr)

    @staticmethod
    def cgo_decref(ptr):
        return _CffiHelper.lib.cgo_decref(ptr)

    @staticmethod
    def handle_error(err):
        ptr = ffi.cast("void *", err)
        if not _CffiHelper.lib.cgo_is_error_nil(ptr):
            raise Exception(_CffiHelper.error_string(ptr))

    @staticmethod
    def c2py_string(s):
        pystr = ffi.string(s)
        _CffiHelper.lib.cgo_cfree(s)
        if _PY3:
            pystr = pystr.decode('utf-8')
        return pystr

class VeilObject(object):
    def __init__(self, uuid_ptr):
        self.uuid_ptr = uuid_ptr

    def __del__(self):
        _CffiHelper.cgo_decref(self.uuid_ptr)

class VeilError(Exception):
    def __init__(self, uuid_ptr):
        self.veil_obj = VeilObject(uuid_ptr=uuid_ptr)
        message = _CffiHelper.error_string(uuid_ptr)
        super(VeilError, self).__init__(message)

    @staticmethod
    def is_nil(uuid_ptr):
        return _CffiHelper.lib.cgo_is_error_nil(uuid_ptr)

# Globally defined functions
{{range $_, $func := .Funcs}}
def {{$func.Name}}({{$func.PrintArgs}}):
    {{ range $_, $inTrx := $func.InputTransforms -}}
      {{ $inTrx }}
    {{ end -}}
    {{$cret}} = _CffiHelper.lib.{{$func.Call -}}
    {{ range $idx, $result := $func.Results -}}
		{{if $result.IsError -}}
			if not VeilError.is_nil(cret.r1):
				{{ printf "raise VeilError(%s.r%d)" $cret $idx -}}
		{{end}}
    {{ end -}}
    return {{$func.PrintReturns}}

{{end}}

`
	STRING_INPUT_TRANSFORM = "%s = ffi.new(\"char[]\", %s.encode(\"utf-8\"))"

	STRING_OUTPUT_TRANSFORM = "_CffiHelper.c2py_string(%s)"
)

var (
	startCGoDefine  = regexp.MustCompile(`^typedef`)
	sizeOfRemove    = regexp.MustCompile(`_check_for_64_bit_pointer_matching_GoInt`)
	complexRemove   = regexp.MustCompile(`_Complex`)
	endif           = regexp.MustCompile(`^#endif`)
	endOfCGoDefine  = regexp.MustCompile(`^#ifdef __cplusplus`)
	extern          = regexp.MustCompile(`^extern \w`)
	sizeTypeReplace = regexp.MustCompile(`__SIZE_TYPE__`)
	removeFilters   = []*regexp.Regexp{sizeOfRemove, complexRemove}
	replaceFilters  = map[string]*regexp.Regexp{"size_t": sizeTypeReplace}
)

var pythonTemplate *template.Template

func init() {
	replacedTabsTemplate := removeTabs(PYTHON_TEMPLATE)
	if tmpl, err := template.New("codeTemplate").Parse(replacedTabsTemplate); err != nil {
		panic(err)

	} else {
		pythonTemplate = tmpl
	}
}

func removeTabs(src string) string {
	return strings.Replace(src, "\t", "  ", -1)
}

// Py3Binder contains the data for generating a python 3 binding
type Py3Binder struct {
	pkg *cgo.Package
}

type PyTemplateData struct {
	CDef           string
	Funcs          []*PyFunc
	CffiHelperName string
	ReturnVarName  string
}

type PyParam struct {
	underlying     *types.Var
	InputTransform string
}

func NewPyParam(v *types.Var) *PyParam {
	return &PyParam{underlying: v}
}

func (p PyParam) HasInputTransform() bool {
	return p.InputTransform != ""
}

func (p PyParam) Name() string {
	return ToSnake(p.underlying.Name())
}

func (p PyParam) IsError() bool {
	return cgo.ImplementsError(p.underlying.Type())
}

func (p PyParam) ReturnFormat(varName string) string {
	switch t := p.underlying.Type().(type) {
	case *types.Basic:
		if t.Kind() == types.String {
			return fmt.Sprintf(STRING_OUTPUT_TRANSFORM, varName)
		}
	}
	return varName
}

type PyFunc struct {
	fun     cgo.Func
	Name    string
	Params  []*PyParam
	Results []*PyParam
}

func (f PyFunc) InputTransforms() []string {
	inputTranforms := []string{}
	for _, param := range f.Params {
		switch t := param.underlying.Type().(type) {
		case *types.Basic:
			if t.Kind() == types.String {
				varName := param.Name()
				inputTranforms = append(inputTranforms,
					fmt.Sprintf(STRING_INPUT_TRANSFORM, varName, varName))
			}
		}
	}
	return inputTranforms
}

func (f PyFunc) Call() string {
	return f.fun.CGoName() + "(" + f.PrintArgs() + ")"
}

func (f PyFunc) PrintArgs() string {
	names := make([]string, len(f.Params))
	for i := 0; i < len(names); i++ {
		names[i] = f.Params[i].Name()
	}
	return strings.Join(names, ", ")
}

func (f PyFunc) PrintReturns() string {
	if len(f.Results) > 1 {
		names := []string{}
		for i := 0; i < len(f.Results); i++ {
			result := f.Results[i]
			if !cgo.ImplementsError(result.underlying.Type()) {
				names = append(names,
					result.ReturnFormat(fmt.Sprintf(RETURN_VAR_NAME+".r%d", i)))
			}
		}
		return strings.Join(names, ", ")
	} else {
		result := f.Results[0]
		return result.ReturnFormat(RETURN_VAR_NAME)
	}
}

// NewPy3Binder creates a new Binder for Python 3
func NewPy3Binder(pkg *cgo.Package) Bindable {
	return &Py3Binder{
		pkg: pkg,
	}
}

// Bind is the Python 3 implementation of Bind
func (p Py3Binder) Bind(outDir string) error {
	headerPath := path.Join(outDir, HEADER_FILE_NAME)
	cdefText, err := p.cDefText(headerPath)
	if err != nil {
		return core.NewSystemErrorF("Failed to generate Python CDefs: %v", err)
	}

	data := PyTemplateData{
		CDef:           strings.Join(cdefText, "\n"),
		Funcs:          p.Funcs(),
		CffiHelperName: CFFI_HELPER_NAME,
		ReturnVarName:  RETURN_VAR_NAME,
	}

	pythonFilePath := path.Join(outDir, PYTHON_FILE_NAME)
	f, err := os.Create(pythonFilePath)
	if err != nil {
		return core.NewSystemErrorF("Unable to create %s", path.Join(outDir, PYTHON_FILE_NAME))
	}

	w := bufio.NewWriter(f)
	pythonTemplate.Execute(w, data)
	w.Flush()
	f.Close()

	PyFormat(pythonFilePath)

	return nil
}

func (p Py3Binder) Funcs() []*PyFunc {
	funcs := make([]*PyFunc, len(p.pkg.Funcs()))

	for idx, f := range p.pkg.Funcs() {

		pyParams := make([]*PyParam, f.Signature().Params().Len())
		for i := 0; i < f.Signature().Params().Len(); i++ {
			param := f.Signature().Params().At(i)
			pyParams[i] = NewPyParam(param)
		}

		pyResults := make([]*PyParam, f.Signature().Results().Len())
		for i := 0; i < f.Signature().Results().Len(); i++ {
			param := f.Signature().Results().At(i)
			pyResults[i] = NewPyParam(param)
		}

		funcs[idx] = &PyFunc{
			fun:     f,
			Name:    ToSnake(f.Name()),
			Params:  pyParams,
			Results: pyResults,
		}
	}
	return funcs
}

func (p Py3Binder) cDefText(headerPath string) ([]string, error) {
	if file, err := os.Open(headerPath); err == nil {
		defer file.Close()

		filteredHeaders := []string{}
		recording := false

		// create a new scanner and read the file line by line
		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			text := scanner.Text()

			if !recording && (startCGoDefine.MatchString(text) || extern.MatchString(text)) {
				recording = true
			}

			if recording {
				if endif.MatchString(text) || endOfCGoDefine.MatchString(text) {
					recording = false
					continue
				}

				matched := false
				for _, filter := range removeFilters {
					if filter.MatchString(text) {
						matched = true
						break
					}
				}

				if !matched {
					for key, value := range replaceFilters {
						if value.MatchString(text) {
							text = value.ReplaceAllString(text, key)
						}
					}
					text = removeTabs(text)
					filteredHeaders = append(filteredHeaders, text)
				}
			}
		}

		// check for errors
		if err = scanner.Err(); err != nil {
			return nil, core.NewSystemError(err)
		}

		return filteredHeaders, nil

	} else {
		return nil, core.NewSystemError(err)
	}
}

// ToSnake convert the given string to snake case following the Golang format:
// acronyms are converted to lower-case and preceded by an underscore.
// via: https://gist.github.com/elwinar/14e1e897fdbe4d3432e1
func ToSnake(in string) string {
	runes := []rune(in)
	length := len(runes)

	var out []rune
	for i := 0; i < length; i++ {
		if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
			out = append(out, '_')
		}
		out = append(out, unicode.ToLower(runes[i]))
	}

	return string(out)
}

func PyFormat(path string) {
	which := exec.Command("which", "yapf")
	if err := which.Run(); err == nil {
		cmd := exec.Command("yapf", "-i", "--style={based_on_style: pep8, column_limit: 100}", path)
		err = cmd.Run()
	} else {
		log.Println("To format your Python code run `pip install yapf`")
	}
}
<|endoftext|>


<commit_before>package goroots

import "math"
import "testing"
//import "testing/quick" // want to use Check; unsure if it'll work with current SolveBisection for small epsilon

// Does SolveBisection correctly solve a simple linear function?
func TestLinear(t *testing.T) {
	makeLinear := func(root float64) func(float64) float64 {
		return func(x float64) float64 { return root - x }
	}
	checker := func(root float64) bool {
		scale := math.Fabs(root)
		epsilon := scale / 1e-5
		val, err := SolveBisection(makeLinear(root), root - scale, root + scale, epsilon)
		if err != nil {
			return false
		}
		return val == root
	}
	if !(checker(5) && checker(100) && checker(1e-5)) {
		t.FailNow()
	}
}

// Does BisectionFullPrecision correctly solve a simple linear function?
func TestLinearFullPrecision(t *testing.T) {
	macheps := math.Pow(2.0, -53.0)
	makeLinear := func(root float64) func(float64) float64 {
		return func(x float64) float64 { return root - x }
	}
	checker := func(root float64) bool {
		scale := math.Fabs(root)
		val, err := BisectionFullPrecision(makeLinear(root), root - scale, root + scale)
		if err != nil {
			return false
		}
		return val - root <= macheps
	}
	if !(checker(5) && checker(100) && checker(1e-5)) {
		t.FailNow()
	}
}
<commit_msg>changed TestLinearFullPrecision to use quick.Check()<commit_after>package goroots

import "math"
import "testing"
import "testing/quick"

// Does SolveBisection correctly solve a simple linear function?
func TestLinear(t *testing.T) {
	makeLinear := func(root float64) func(float64) float64 {
		return func(x float64) float64 { return root - x }
	}
	checker := func(root float64) bool {
		scale := math.Fabs(root)
		epsilon := scale / 1e-5
		val, err := SolveBisection(makeLinear(root), root - scale, root + scale, epsilon)
		if err != nil {
			return false
		}
		return val == root
	}
	if !(checker(5) && checker(100) && checker(1e-5)) {
		t.FailNow()
	}
}

// Does BisectionFullPrecision correctly solve arbitrary simple linear functions?
func TestLinearFullPrecision(t *testing.T) {
	macheps := math.Pow(2.0, -53.0)
	makeLinear := func(root float64) func(float64) float64 {
		return func(x float64) float64 { return root - x }
	}
	checker := func(root float64) bool {
		scale := math.Fabs(root)
		val, err := BisectionFullPrecision(makeLinear(root), root - scale, root + scale)
		if err != nil {
			return false
		}
		return val - root <= macheps
	}
	if err := quick.Check(checker, nil); err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before><commit_msg>multi: make ThreadSafeMultiMA wrapper private (it does not have to be public)<commit_after><|endoftext|>


<commit_before>package proxyproto

import (
	"bufio"
	"net"
	"sync"
	"time"
)

// Listener is used to wrap an underlying listener,
// whose connections may be using the HAProxy Proxy Protocol.
// If the connection is using the protocol, the RemoteAddr() will return
// the correct client address.
type Listener struct {
	Listener       net.Listener
	Policy         PolicyFunc
	ValidateHeader Validator
}

// Conn is used to wrap and underlying connection which
// may be speaking the Proxy Protocol. If it is, the RemoteAddr() will
// return the address of the client instead of the proxy address.
type Conn struct {
	bufReader         *bufio.Reader
	conn              net.Conn
	header            *Header
	once              sync.Once
	ProxyHeaderPolicy Policy
	Validate          Validator
	readErr           error
}

// Validator receives a header and decides whether it is a valid one
// In case the header is not deemed valid it should return an error.
type Validator func(*Header) error

// ValidateHeader adds given validator for proxy headers to a connection when passed as option to NewConn()
func ValidateHeader(v Validator) func(*Conn) {
	return func(c *Conn) {
		if v != nil {
			c.Validate = v
		}
	}
}

// Accept waits for and returns the next connection to the listener.
func (p *Listener) Accept() (net.Conn, error) {
	// Get the underlying connection
	conn, err := p.Listener.Accept()
	if err != nil {
		return nil, err
	}

	proxyHeaderPolicy := USE
	if p.Policy != nil {
		proxyHeaderPolicy, err = p.Policy(conn.RemoteAddr())
		if err != nil {
			// can't decide the policy, we can't accept the connection
			conn.Close()
			return nil, err
		}
	}

	newConn := NewConn(
		conn,
		WithPolicy(proxyHeaderPolicy),
		ValidateHeader(p.ValidateHeader),
	)
	return newConn, nil
}

// Close closes the underlying listener.
func (p *Listener) Close() error {
	return p.Listener.Close()
}

// Addr returns the underlying listener's network address.
func (p *Listener) Addr() net.Addr {
	return p.Listener.Addr()
}

// NewConn is used to wrap a net.Conn that may be speaking
// the proxy protocol into a proxyproto.Conn
func NewConn(conn net.Conn, opts ...func(*Conn)) *Conn {
	pConn := &Conn{
		bufReader: bufio.NewReader(conn),
		conn:      conn,
	}

	for _, opt := range opts {
		opt(pConn)
	}

	return pConn
}

// Read is check for the proxy protocol header when doing
// the initial scan. If there is an error parsing the header,
// it is returned and the socket is closed.
func (p *Conn) Read(b []byte) (int, error) {
	p.once.Do(func() {
		p.readErr = p.readHeader()
	})
	if p.readErr != nil {
		return 0, p.readErr
	}
	return p.bufReader.Read(b)
}

// Write wraps original conn.Write
func (p *Conn) Write(b []byte) (int, error) {
	return p.conn.Write(b)
}

// Close wraps original conn.Close
func (p *Conn) Close() error {
	return p.conn.Close()
}

// LocalAddr returns the address of the server if the proxy
// protocol is being used, otherwise just returns the address of
// the socket server. In case an error happens on reading the
// proxy header the original LocalAddr is returned, not the one
// from the proxy header even if the proxy header itself is
// syntactically correct.
func (p *Conn) LocalAddr() net.Addr {
	p.once.Do(func() { p.readErr = p.readHeader() })
	if p.header == nil || p.header.Command.IsLocal() || p.readErr != nil {
		return p.conn.LocalAddr()
	}

	return p.header.LocalAddr()
}

// RemoteAddr returns the address of the client if the proxy
// protocol is being used, otherwise just returns the address of
// the socket peer. In case an error happens on reading the
// proxy header the original RemoteAddr is returned, not the one
// from the proxy header even if the proxy header itself is
// syntactically correct.
func (p *Conn) RemoteAddr() net.Addr {
	p.once.Do(func() { p.readErr = p.readHeader() })
	if p.header == nil || p.header.Command.IsLocal() || p.readErr != nil {
		return p.conn.RemoteAddr()
	}

	return p.header.RemoteAddr()
}

// SetDeadline wraps original conn.SetDeadline
func (p *Conn) SetDeadline(t time.Time) error {
	return p.conn.SetDeadline(t)
}

// SetReadDeadline wraps original conn.SetReadDeadline
func (p *Conn) SetReadDeadline(t time.Time) error {
	return p.conn.SetReadDeadline(t)
}

// SetWriteDeadline wraps original conn.SetWriteDeadline
func (p *Conn) SetWriteDeadline(t time.Time) error {
	return p.conn.SetWriteDeadline(t)
}

func (p *Conn) readHeader() error {
	header, err := Read(p.bufReader)
	// For the purpose of this wrapper shamefully stolen from armon/go-proxyproto
	// let's act as if there was no error when PROXY protocol is not present.
	if err == ErrNoProxyProtocol {
		// but not if it is required that the connection has one
		if p.ProxyHeaderPolicy == REQUIRE {
			return err
		}

		return nil
	}

	// proxy protocol header was found
	if err == nil && header != nil {
		switch p.ProxyHeaderPolicy {
		case REJECT:
			// this connection is not allowed to send one
			return ErrSuperfluousProxyHeader
		case USE:
			if p.Validate != nil {
				err = p.Validate(header)
				if err != nil {
					return err
				}
			}

			p.header = header
		}
	}

	return err
}
<commit_msg>Use protocol header if policy is REQUIRED<commit_after>package proxyproto

import (
	"bufio"
	"net"
	"sync"
	"time"
)

// Listener is used to wrap an underlying listener,
// whose connections may be using the HAProxy Proxy Protocol.
// If the connection is using the protocol, the RemoteAddr() will return
// the correct client address.
type Listener struct {
	Listener       net.Listener
	Policy         PolicyFunc
	ValidateHeader Validator
}

// Conn is used to wrap and underlying connection which
// may be speaking the Proxy Protocol. If it is, the RemoteAddr() will
// return the address of the client instead of the proxy address.
type Conn struct {
	bufReader         *bufio.Reader
	conn              net.Conn
	header            *Header
	once              sync.Once
	ProxyHeaderPolicy Policy
	Validate          Validator
	readErr           error
}

// Validator receives a header and decides whether it is a valid one
// In case the header is not deemed valid it should return an error.
type Validator func(*Header) error

// ValidateHeader adds given validator for proxy headers to a connection when passed as option to NewConn()
func ValidateHeader(v Validator) func(*Conn) {
	return func(c *Conn) {
		if v != nil {
			c.Validate = v
		}
	}
}

// Accept waits for and returns the next connection to the listener.
func (p *Listener) Accept() (net.Conn, error) {
	// Get the underlying connection
	conn, err := p.Listener.Accept()
	if err != nil {
		return nil, err
	}

	proxyHeaderPolicy := USE
	if p.Policy != nil {
		proxyHeaderPolicy, err = p.Policy(conn.RemoteAddr())
		if err != nil {
			// can't decide the policy, we can't accept the connection
			conn.Close()
			return nil, err
		}
	}

	newConn := NewConn(
		conn,
		WithPolicy(proxyHeaderPolicy),
		ValidateHeader(p.ValidateHeader),
	)
	return newConn, nil
}

// Close closes the underlying listener.
func (p *Listener) Close() error {
	return p.Listener.Close()
}

// Addr returns the underlying listener's network address.
func (p *Listener) Addr() net.Addr {
	return p.Listener.Addr()
}

// NewConn is used to wrap a net.Conn that may be speaking
// the proxy protocol into a proxyproto.Conn
func NewConn(conn net.Conn, opts ...func(*Conn)) *Conn {
	pConn := &Conn{
		bufReader: bufio.NewReader(conn),
		conn:      conn,
	}

	for _, opt := range opts {
		opt(pConn)
	}

	return pConn
}

// Read is check for the proxy protocol header when doing
// the initial scan. If there is an error parsing the header,
// it is returned and the socket is closed.
func (p *Conn) Read(b []byte) (int, error) {
	p.once.Do(func() {
		p.readErr = p.readHeader()
	})
	if p.readErr != nil {
		return 0, p.readErr
	}
	return p.bufReader.Read(b)
}

// Write wraps original conn.Write
func (p *Conn) Write(b []byte) (int, error) {
	return p.conn.Write(b)
}

// Close wraps original conn.Close
func (p *Conn) Close() error {
	return p.conn.Close()
}

// LocalAddr returns the address of the server if the proxy
// protocol is being used, otherwise just returns the address of
// the socket server. In case an error happens on reading the
// proxy header the original LocalAddr is returned, not the one
// from the proxy header even if the proxy header itself is
// syntactically correct.
func (p *Conn) LocalAddr() net.Addr {
	p.once.Do(func() { p.readErr = p.readHeader() })
	if p.header == nil || p.header.Command.IsLocal() || p.readErr != nil {
		return p.conn.LocalAddr()
	}

	return p.header.LocalAddr()
}

// RemoteAddr returns the address of the client if the proxy
// protocol is being used, otherwise just returns the address of
// the socket peer. In case an error happens on reading the
// proxy header the original RemoteAddr is returned, not the one
// from the proxy header even if the proxy header itself is
// syntactically correct.
func (p *Conn) RemoteAddr() net.Addr {
	p.once.Do(func() { p.readErr = p.readHeader() })
	if p.header == nil || p.header.Command.IsLocal() || p.readErr != nil {
		return p.conn.RemoteAddr()
	}

	return p.header.RemoteAddr()
}

// SetDeadline wraps original conn.SetDeadline
func (p *Conn) SetDeadline(t time.Time) error {
	return p.conn.SetDeadline(t)
}

// SetReadDeadline wraps original conn.SetReadDeadline
func (p *Conn) SetReadDeadline(t time.Time) error {
	return p.conn.SetReadDeadline(t)
}

// SetWriteDeadline wraps original conn.SetWriteDeadline
func (p *Conn) SetWriteDeadline(t time.Time) error {
	return p.conn.SetWriteDeadline(t)
}

func (p *Conn) readHeader() error {
	header, err := Read(p.bufReader)
	// For the purpose of this wrapper shamefully stolen from armon/go-proxyproto
	// let's act as if there was no error when PROXY protocol is not present.
	if err == ErrNoProxyProtocol {
		// but not if it is required that the connection has one
		if p.ProxyHeaderPolicy == REQUIRE {
			return err
		}

		return nil
	}

	// proxy protocol header was found
	if err == nil && header != nil {
		switch p.ProxyHeaderPolicy {
		case REJECT:
			// this connection is not allowed to send one
			return ErrSuperfluousProxyHeader
		case USE, REQUIRE:
			if p.Validate != nil {
				err = p.Validate(header)
				if err != nil {
					return err
				}
			}

			p.header = header
		}
	}

	return err
}
<|endoftext|>


<commit_before>package aws

import (
	"sync"

	"github.com/awslabs/aws-sdk-go/aws/credentials"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

// Provider returns a terraform.ResourceProvider.
func Provider() terraform.ResourceProvider {
	// TODO: Move the validation to this, requires conditional schemas
	// TODO: Move the configuration to this, requires validation

	// These variables are closed within the `getCreds` function below.
	// This function is responsible for reading credentials from the
	// environment in the case that they're not explicitly specified
	// in the Terraform configuration.
	//
	// By using the getCreds function here instead of making the default
	// empty, we avoid asking for input on credentials if they're available
	// in the environment.
	var credVal credentials.Value
	var credErr error
	var once sync.Once
	getCreds := func() {
		creds := credentials.NewChainCredentials([]credentials.Provider{
			&credentials.EnvProvider{},
			&credentials.SharedCredentialsProvider{},
			&credentials.EC2RoleProvider{},
		})

		credVal, credErr = creds.Get()
	}

	// The actual provider
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"access_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					once.Do(getCreds)
					return credVal.AccessKeyID, credErr
				},
				Description: descriptions["access_key"],
			},

			"secret_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					once.Do(getCreds)
					return credVal.SecretAccessKey, credErr
				},
				Description: descriptions["secret_key"],
			},

			"token": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				DefaultFunc: func() (interface{}, error) {
					once.Do(getCreds)
					return credVal.SessionToken, credErr
				},
				Description: descriptions["token"],
			},

			"region": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: schema.MultiEnvDefaultFunc([]string{
					"AWS_REGION",
					"AWS_DEFAULT_REGION",
				}, nil),
				Description:  descriptions["region"],
				InputDefault: "us-east-1",
			},

			"max_retries": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Default:     11,
				Description: descriptions["max_retries"],
			},

			"allowed_account_ids": &schema.Schema{
				Type:          schema.TypeSet,
				Elem:          &schema.Schema{Type: schema.TypeString},
				Optional:      true,
				ConflictsWith: []string{"forbidden_account_ids"},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"forbidden_account_ids": &schema.Schema{
				Type:          schema.TypeSet,
				Elem:          &schema.Schema{Type: schema.TypeString},
				Optional:      true,
				ConflictsWith: []string{"allowed_account_ids"},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},
		},

		ResourcesMap: map[string]*schema.Resource{
			"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
			"aws_autoscaling_group":            resourceAwsAutoscalingGroup(),
			"aws_autoscaling_notification":     resourceAwsAutoscalingNotification(),
			"aws_autoscaling_policy":           resourceAwsAutoscalingPolicy(),
			"aws_cloudwatch_metric_alarm":      resourceAwsCloudWatchMetricAlarm(),
			"aws_customer_gateway":             resourceAwsCustomerGateway(),
			"aws_db_instance":                  resourceAwsDbInstance(),
			"aws_db_parameter_group":           resourceAwsDbParameterGroup(),
			"aws_db_security_group":            resourceAwsDbSecurityGroup(),
			"aws_db_subnet_group":              resourceAwsDbSubnetGroup(),
			"aws_dynamodb_table":               resourceAwsDynamoDbTable(),
			"aws_ebs_volume":                   resourceAwsEbsVolume(),
			"aws_ecs_cluster":                  resourceAwsEcsCluster(),
			"aws_ecs_service":                  resourceAwsEcsService(),
			"aws_ecs_task_definition":          resourceAwsEcsTaskDefinition(),
			"aws_eip":                          resourceAwsEip(),
			"aws_elasticache_cluster":          resourceAwsElasticacheCluster(),
			"aws_elasticache_parameter_group":  resourceAwsElasticacheParameterGroup(),
			"aws_elasticache_security_group":   resourceAwsElasticacheSecurityGroup(),
			"aws_elasticache_subnet_group":     resourceAwsElasticacheSubnetGroup(),
			"aws_elb":                          resourceAwsElb(),
			"aws_flow_log":                     resourceAwsFlowLog(),
			"aws_iam_access_key":               resourceAwsIamAccessKey(),
			"aws_iam_group_policy":             resourceAwsIamGroupPolicy(),
			"aws_iam_group":                    resourceAwsIamGroup(),
			"aws_iam_group_membership":         resourceAwsIamGroupMembership(),
			"aws_iam_instance_profile":         resourceAwsIamInstanceProfile(),
			"aws_iam_policy":                   resourceAwsIamPolicy(),
			"aws_iam_role_policy":              resourceAwsIamRolePolicy(),
			"aws_iam_role":                     resourceAwsIamRole(),
			"aws_iam_server_certificate":       resourceAwsIAMServerCertificate(),
			"aws_iam_user_policy":              resourceAwsIamUserPolicy(),
			"aws_iam_user":                     resourceAwsIamUser(),
			"aws_instance":                     resourceAwsInstance(),
			"aws_internet_gateway":             resourceAwsInternetGateway(),
			"aws_key_pair":                     resourceAwsKeyPair(),
			"aws_kinesis_stream":               resourceAwsKinesisStream(),
			"aws_lambda_function":              resourceAwsLambdaFunction(),
			"aws_launch_configuration":         resourceAwsLaunchConfiguration(),
			"aws_lb_cookie_stickiness_policy":  resourceAwsLBCookieStickinessPolicy(),
			"aws_main_route_table_association": resourceAwsMainRouteTableAssociation(),
			"aws_network_acl":                  resourceAwsNetworkAcl(),
			"aws_network_interface":            resourceAwsNetworkInterface(),
			"aws_proxy_protocol_policy":        resourceAwsProxyProtocolPolicy(),
			"aws_route53_delegation_set":       resourceAwsRoute53DelegationSet(),
			"aws_route53_record":               resourceAwsRoute53Record(),
			"aws_route53_zone_association":     resourceAwsRoute53ZoneAssociation(),
			"aws_route53_zone":                 resourceAwsRoute53Zone(),
			"aws_route53_health_check":         resourceAwsRoute53HealthCheck(),
			"aws_route_table":                  resourceAwsRouteTable(),
			"aws_route_table_association":      resourceAwsRouteTableAssociation(),
			"aws_s3_bucket":                    resourceAwsS3Bucket(),
			"aws_security_group":               resourceAwsSecurityGroup(),
			"aws_security_group_rule":          resourceAwsSecurityGroupRule(),
			"aws_spot_instance_request":        resourceAwsSpotInstanceRequest(),
			"aws_sqs_queue":                    resourceAwsSqsQueue(),
			"aws_sns_topic":                    resourceAwsSnsTopic(),
			"aws_sns_topic_subscription":       resourceAwsSnsTopicSubscription(),
			"aws_subnet":                       resourceAwsSubnet(),
			"aws_volume_attachment":            resourceAwsVolumeAttachment(),
			"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
			"aws_vpc_dhcp_options":             resourceAwsVpcDhcpOptions(),
			"aws_vpc_peering_connection":       resourceAwsVpcPeeringConnection(),
			"aws_vpc":                          resourceAwsVpc(),
			"aws_vpn_connection":               resourceAwsVpnConnection(),
			"aws_vpn_connection_route":         resourceAwsVpnConnectionRoute(),
			"aws_vpn_gateway":                  resourceAwsVpnGateway(),
		},

		ConfigureFunc: providerConfigure,
	}
}

var descriptions map[string]string

func init() {
	descriptions = map[string]string{
		"region": "The region where AWS operations will take place. Examples\n" +
			"are us-east-1, us-west-2, etc.",

		"access_key": "The access key for API operations. You can retrieve this\n" +
			"from the 'Security & Credentials' section of the AWS console.",

		"secret_key": "The secret key for API operations. You can retrieve this\n" +
			"from the 'Security & Credentials' section of the AWS console.",

		"token": "session token. A session token is only required if you are\n" +
			"using temporary security credentials.",

		"max_retries": "The maximum number of times an AWS API request is\n" +
			"being executed. If the API request still fails, an error is\n" +
			"thrown.",
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	config := Config{
		AccessKey:  d.Get("access_key").(string),
		SecretKey:  d.Get("secret_key").(string),
		Token:      d.Get("token").(string),
		Region:     d.Get("region").(string),
		MaxRetries: d.Get("max_retries").(int),
	}

	if v, ok := d.GetOk("allowed_account_ids"); ok {
		config.AllowedAccountIds = v.(*schema.Set).List()
	}

	if v, ok := d.GetOk("forbidden_account_ids"); ok {
		config.ForbiddenAccountIds = v.(*schema.Set).List()
	}

	return config.Client()
}
<commit_msg>providers/aws: implement basic fast-path for not being in EC2 for creds<commit_after>package aws

import (
	"net"
	"sync"
	"time"

	"github.com/awslabs/aws-sdk-go/aws/credentials"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

// Provider returns a terraform.ResourceProvider.
func Provider() terraform.ResourceProvider {
	// TODO: Move the validation to this, requires conditional schemas
	// TODO: Move the configuration to this, requires validation

	// These variables are closed within the `getCreds` function below.
	// This function is responsible for reading credentials from the
	// environment in the case that they're not explicitly specified
	// in the Terraform configuration.
	//
	// By using the getCreds function here instead of making the default
	// empty, we avoid asking for input on credentials if they're available
	// in the environment.
	var credVal credentials.Value
	var credErr error
	var once sync.Once
	getCreds := func() {
		// Build the list of providers to look for creds in
		providers := []credentials.Provider{
			&credentials.EnvProvider{},
			&credentials.SharedCredentialsProvider{},
		}

		// We only look in the EC2 metadata API if we can connect
		// to the metadata service within a reasonable amount of time
		conn, err := net.DialTimeout("tcp", "169.254.169.254:80", 100*time.Millisecond)
		if err == nil {
			conn.Close()
			providers = append(providers, &credentials.EC2RoleProvider{})
		}

		credVal, credErr = credentials.NewChainCredentials(providers).Get()

		// If we didn't successfully find any credentials, just
		// set the error to nil.
		if credErr == credentials.ErrNoValidProvidersFoundInChain {
			credErr = nil
		}
	}

	// getCredDefault is a function used by DefaultFunc below to
	// get the default value for various parts of the credentials.
	// This function properly handles loading the credentials, checking
	// for errors, etc.
	getCredDefault := func(def interface{}, f func() string) (interface{}, error) {
		once.Do(getCreds)

		// If there was an error, that is always first
		if credErr != nil {
			return nil, credErr
		}

		// If the value is empty string, return nil (not set)
		val := f()
		if val == "" {
			return def, nil
		}

		return val, nil
	}

	// The actual provider
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"access_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return getCredDefault(nil, func() string {
						return credVal.AccessKeyID
					})
				},
				Description: descriptions["access_key"],
			},

			"secret_key": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return getCredDefault(nil, func() string {
						return credVal.SecretAccessKey
					})
				},
				Description: descriptions["secret_key"],
			},

			"token": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				DefaultFunc: func() (interface{}, error) {
					return getCredDefault("", func() string {
						return credVal.SessionToken
					})
				},
				Description: descriptions["token"],
			},

			"region": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: schema.MultiEnvDefaultFunc([]string{
					"AWS_REGION",
					"AWS_DEFAULT_REGION",
				}, nil),
				Description:  descriptions["region"],
				InputDefault: "us-east-1",
			},

			"max_retries": &schema.Schema{
				Type:        schema.TypeInt,
				Optional:    true,
				Default:     11,
				Description: descriptions["max_retries"],
			},

			"allowed_account_ids": &schema.Schema{
				Type:          schema.TypeSet,
				Elem:          &schema.Schema{Type: schema.TypeString},
				Optional:      true,
				ConflictsWith: []string{"forbidden_account_ids"},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"forbidden_account_ids": &schema.Schema{
				Type:          schema.TypeSet,
				Elem:          &schema.Schema{Type: schema.TypeString},
				Optional:      true,
				ConflictsWith: []string{"allowed_account_ids"},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},
		},

		ResourcesMap: map[string]*schema.Resource{
			"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
			"aws_autoscaling_group":            resourceAwsAutoscalingGroup(),
			"aws_autoscaling_notification":     resourceAwsAutoscalingNotification(),
			"aws_autoscaling_policy":           resourceAwsAutoscalingPolicy(),
			"aws_cloudwatch_metric_alarm":      resourceAwsCloudWatchMetricAlarm(),
			"aws_customer_gateway":             resourceAwsCustomerGateway(),
			"aws_db_instance":                  resourceAwsDbInstance(),
			"aws_db_parameter_group":           resourceAwsDbParameterGroup(),
			"aws_db_security_group":            resourceAwsDbSecurityGroup(),
			"aws_db_subnet_group":              resourceAwsDbSubnetGroup(),
			"aws_dynamodb_table":               resourceAwsDynamoDbTable(),
			"aws_ebs_volume":                   resourceAwsEbsVolume(),
			"aws_ecs_cluster":                  resourceAwsEcsCluster(),
			"aws_ecs_service":                  resourceAwsEcsService(),
			"aws_ecs_task_definition":          resourceAwsEcsTaskDefinition(),
			"aws_eip":                          resourceAwsEip(),
			"aws_elasticache_cluster":          resourceAwsElasticacheCluster(),
			"aws_elasticache_parameter_group":  resourceAwsElasticacheParameterGroup(),
			"aws_elasticache_security_group":   resourceAwsElasticacheSecurityGroup(),
			"aws_elasticache_subnet_group":     resourceAwsElasticacheSubnetGroup(),
			"aws_elb":                          resourceAwsElb(),
			"aws_flow_log":                     resourceAwsFlowLog(),
			"aws_iam_access_key":               resourceAwsIamAccessKey(),
			"aws_iam_group_policy":             resourceAwsIamGroupPolicy(),
			"aws_iam_group":                    resourceAwsIamGroup(),
			"aws_iam_group_membership":         resourceAwsIamGroupMembership(),
			"aws_iam_instance_profile":         resourceAwsIamInstanceProfile(),
			"aws_iam_policy":                   resourceAwsIamPolicy(),
			"aws_iam_role_policy":              resourceAwsIamRolePolicy(),
			"aws_iam_role":                     resourceAwsIamRole(),
			"aws_iam_server_certificate":       resourceAwsIAMServerCertificate(),
			"aws_iam_user_policy":              resourceAwsIamUserPolicy(),
			"aws_iam_user":                     resourceAwsIamUser(),
			"aws_instance":                     resourceAwsInstance(),
			"aws_internet_gateway":             resourceAwsInternetGateway(),
			"aws_key_pair":                     resourceAwsKeyPair(),
			"aws_kinesis_stream":               resourceAwsKinesisStream(),
			"aws_lambda_function":              resourceAwsLambdaFunction(),
			"aws_launch_configuration":         resourceAwsLaunchConfiguration(),
			"aws_lb_cookie_stickiness_policy":  resourceAwsLBCookieStickinessPolicy(),
			"aws_main_route_table_association": resourceAwsMainRouteTableAssociation(),
			"aws_network_acl":                  resourceAwsNetworkAcl(),
			"aws_network_interface":            resourceAwsNetworkInterface(),
			"aws_proxy_protocol_policy":        resourceAwsProxyProtocolPolicy(),
			"aws_route53_delegation_set":       resourceAwsRoute53DelegationSet(),
			"aws_route53_record":               resourceAwsRoute53Record(),
			"aws_route53_zone_association":     resourceAwsRoute53ZoneAssociation(),
			"aws_route53_zone":                 resourceAwsRoute53Zone(),
			"aws_route53_health_check":         resourceAwsRoute53HealthCheck(),
			"aws_route_table":                  resourceAwsRouteTable(),
			"aws_route_table_association":      resourceAwsRouteTableAssociation(),
			"aws_s3_bucket":                    resourceAwsS3Bucket(),
			"aws_security_group":               resourceAwsSecurityGroup(),
			"aws_security_group_rule":          resourceAwsSecurityGroupRule(),
			"aws_spot_instance_request":        resourceAwsSpotInstanceRequest(),
			"aws_sqs_queue":                    resourceAwsSqsQueue(),
			"aws_sns_topic":                    resourceAwsSnsTopic(),
			"aws_sns_topic_subscription":       resourceAwsSnsTopicSubscription(),
			"aws_subnet":                       resourceAwsSubnet(),
			"aws_volume_attachment":            resourceAwsVolumeAttachment(),
			"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
			"aws_vpc_dhcp_options":             resourceAwsVpcDhcpOptions(),
			"aws_vpc_peering_connection":       resourceAwsVpcPeeringConnection(),
			"aws_vpc":                          resourceAwsVpc(),
			"aws_vpn_connection":               resourceAwsVpnConnection(),
			"aws_vpn_connection_route":         resourceAwsVpnConnectionRoute(),
			"aws_vpn_gateway":                  resourceAwsVpnGateway(),
		},

		ConfigureFunc: providerConfigure,
	}
}

var descriptions map[string]string

func init() {
	descriptions = map[string]string{
		"region": "The region where AWS operations will take place. Examples\n" +
			"are us-east-1, us-west-2, etc.",

		"access_key": "The access key for API operations. You can retrieve this\n" +
			"from the 'Security & Credentials' section of the AWS console.",

		"secret_key": "The secret key for API operations. You can retrieve this\n" +
			"from the 'Security & Credentials' section of the AWS console.",

		"token": "session token. A session token is only required if you are\n" +
			"using temporary security credentials.",

		"max_retries": "The maximum number of times an AWS API request is\n" +
			"being executed. If the API request still fails, an error is\n" +
			"thrown.",
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	config := Config{
		AccessKey:  d.Get("access_key").(string),
		SecretKey:  d.Get("secret_key").(string),
		Token:      d.Get("token").(string),
		Region:     d.Get("region").(string),
		MaxRetries: d.Get("max_retries").(int),
	}

	if v, ok := d.GetOk("allowed_account_ids"); ok {
		config.AllowedAccountIds = v.(*schema.Set).List()
	}

	if v, ok := d.GetOk("forbidden_account_ids"); ok {
		config.ForbiddenAccountIds = v.(*schema.Set).List()
	}

	return config.Client()
}
<|endoftext|>