<commit_before>// Package recording handles the encoding and decoding of recorded games to
// files.
package recording

//go:generate ffjson $GOFILE

import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"io"
	"os"
	"sync"
	"syscall"
	"time"

	"github.com/1lann/countwriter"
	"github.com/pquerna/ffjson/ffjson"
)

// FormatVersion is the version number of the recording format. As of right
// now, recording formats are not forwards or backwards compatible.
const FormatVersion = 6

const versionPosition = -2
const headerSizePosition = -4
const bufferSize = 200000

type segment struct {
	Position int64
	Length   int
}

type recordingHeader struct {
	GameMetadata   segment
	FirstChunkInfo ChunkInfo
	LastChunkInfo  ChunkInfo
	KeyFrameMap    map[int]segment
	ChunkMap       map[int]segment
	Info           GameInfo
	UserMetadata   segment
	IsComplete     bool
}

// GameInfo represents meta information for a game required to play it back
// at a stored recording level.
type GameInfo struct {
	Platform      string
	Version       string
	GameID        string
	EncryptionKey string
	RecordTime    time.Time
}

// Recording manages the reading and writing of recording data to an
// io.ReadWriteSeeker such as an *os.File
type Recording struct {
	file     io.ReadWriteSeeker
	position int64
	header   recordingHeader
	mutex    *sync.Mutex
}

// ChunkInfo is used to store and decode relevant chunk information from the
// recorded game. It is used to store the
type ChunkInfo struct {
	CurrentChunk    int `json:"chunkId"`
	AvailableSince  int `json:"availableSince"`
	NextUpdate      int `json:"nextAvailableChunk"`
	CurrentKeyFrame int `json:"keyFrameId"`
	NextChunk       int `json:"nextChunkId"`
	EndStartupChunk int `json:"endStartupChunkId"`
	StartGameChunk  int `json:"startGameChunkId"`
	EndGameChunk    int `json:"endGameChunkId"`
	Duration        int `json:"duration"`
}

// Error variables to check what errors have occurred.
var (
	ErrMissingData         = errors.New("recording: missing data")
	ErrCannotModify        = errors.New("recording: cannot modify read-only data")
	ErrCorruptRecording    = errors.New("recording: corrupt recording")
	ErrIncompatibleVersion = errors.New("recording: incompatible or invalid format version")
	ErrHeaderTooLarge      = errors.New("recording: header is too large")
)

var bufferPool *sync.Pool

// NewRecording creates a new recording for writing to, or reads an existing
// recording to read from using the io.ReadWriteSeeker, such as an *os.File.
func NewRecording(file io.ReadWriteSeeker) (*Recording, error) {
	recording := &Recording{
		file:     file,
		position: 0,
		mutex:    new(sync.Mutex),
		header: recordingHeader{
			ChunkMap:    make(map[int]segment),
			KeyFrameMap: make(map[int]segment),
		},
	}

	if err := recording.readHeader(); err != nil {
		if err != ErrMissingData {
			return nil, err
		}
	}

	return recording, nil
}

func (r *Recording) readHeaderUnit16(offset int) (uint16, int, error) {
	pos, err := r.file.Seek(int64(offset), 2)
	if err != nil {
		if pathErr, ok := err.(*os.PathError); ok {
			if pathErr.Err == syscall.EINVAL {
				// Cannot seek to this point, declare data as missing
				return 0, 0, ErrMissingData
			}
		}

		return 0, 0, err
	}

	var number uint16
	err = binary.Read(r.file, binary.LittleEndian, &number)
	if err != nil {
		return 0, int(pos), err
	}

	return number, int(pos), nil
}

func (r *Recording) readHeader() error {
	// Read preamble headers
	// Read the version
	version, _, err := r.readHeaderUnit16(versionPosition)
	if err != nil {
		return err
	}

	if version != FormatVersion {
		return ErrIncompatibleVersion
	}

	// Read the header size
	size, pos, err := r.readHeaderUnit16(headerSizePosition)
	if err != nil {
		return err
	}

	r.position = int64(pos)

	// Read the header data
	if _, err = r.file.Seek(-(int64(size))-4, 2); err != nil {
		if pathErr, ok := err.(*os.PathError); ok {
			if pathErr.Err == syscall.EINVAL {
				// Header size is too long, recording is corrupt
				return ErrCorruptRecording
			}
		}

		return err
	}

	reader := io.LimitReader(r.file, int64(size))
	decoder := gob.NewDecoder(reader)
	err = decoder.Decode(&r.header)
	if err != nil {
		return ErrCorruptRecording
	}

	return nil
}

func (r *Recording) writeHeader() error {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return err
	}

	writer := countwriter.NewWriter(r.file)
	gob.NewEncoder(writer).Encode(r.header)

	if writer.Count() > 65535 {
		return ErrHeaderTooLarge
	}

	// Write preamble headers
	// The size of the header
	if err := binary.Write(r.file, binary.LittleEndian,
		uint16(writer.Count())); err != nil {
		return err
	}

	// The version of the recording format
	if err := binary.Write(r.file, binary.LittleEndian,
		uint16(FormatVersion)); err != nil {
		return err
	}

	return nil
}

func (r *Recording) storeInStack(data []byte) (segment, error) {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return segment{}, err
	}

	writtenPosition := r.position

	written, err := r.file.Write(data)
	r.position += int64(written)
	return segment{writtenPosition, written}, err
}

func (r *Recording) writeToStack(rd io.Reader) (segment, error) {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return segment{}, err
	}

	writtenPosition := r.position

	written, err := io.Copy(r.file, rd)
	r.position += written
	return segment{writtenPosition, int(written)}, err
}

// WriteTo encodes the ChunkInfo as JSON and writes it to a writer.
func (c ChunkInfo) WriteTo(w io.Writer) (int64, error) {
	cw := countwriter.NewWriter(w)
	encoder := ffjson.NewEncoder(cw)
	err := encoder.EncodeFast(&c)
	return int64(cw.Count()), err
}

func init() {
	bufferPool = new(sync.Pool)
	bufferPool.New = func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, bufferSize))
	}

	gob.Register(recordingHeader{})
}
<commit_msg>Increment format version :( Sorry!<commit_after>// Package recording handles the encoding and decoding of recorded games to
// files.
package recording

//go:generate ffjson $GOFILE

import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"io"
	"os"
	"sync"
	"syscall"
	"time"

	"github.com/1lann/countwriter"
	"github.com/pquerna/ffjson/ffjson"
)

// FormatVersion is the version number of the recording format. As of right
// now, recording formats are not forwards or backwards compatible.
const FormatVersion = 7

const versionPosition = -2
const headerSizePosition = -4
const bufferSize = 200000

type segment struct {
	Position int64
	Length   int
}

type recordingHeader struct {
	GameMetadata   segment
	FirstChunkInfo ChunkInfo
	LastChunkInfo  ChunkInfo
	KeyFrameMap    map[int]segment
	ChunkMap       map[int]segment
	Info           GameInfo
	UserMetadata   segment
	IsComplete     bool
}

// GameInfo represents meta information for a game required to play it back
// at a stored recording level.
type GameInfo struct {
	Platform      string
	Version       string
	GameID        string
	EncryptionKey string
	RecordTime    time.Time
}

// Recording manages the reading and writing of recording data to an
// io.ReadWriteSeeker such as an *os.File
type Recording struct {
	file     io.ReadWriteSeeker
	position int64
	header   recordingHeader
	mutex    *sync.Mutex
}

// ChunkInfo is used to store and decode relevant chunk information from the
// recorded game. It is used to store the
type ChunkInfo struct {
	CurrentChunk    int `json:"chunkId"`
	AvailableSince  int `json:"availableSince"`
	NextUpdate      int `json:"nextAvailableChunk"`
	CurrentKeyFrame int `json:"keyFrameId"`
	NextChunk       int `json:"nextChunkId"`
	EndStartupChunk int `json:"endStartupChunkId"`
	StartGameChunk  int `json:"startGameChunkId"`
	EndGameChunk    int `json:"endGameChunkId"`
	Duration        int `json:"duration"`
}

// Error variables to check what errors have occurred.
var (
	ErrMissingData         = errors.New("recording: missing data")
	ErrCannotModify        = errors.New("recording: cannot modify read-only data")
	ErrCorruptRecording    = errors.New("recording: corrupt recording")
	ErrIncompatibleVersion = errors.New("recording: incompatible or invalid format version")
	ErrHeaderTooLarge      = errors.New("recording: header is too large")
)

var bufferPool *sync.Pool

// NewRecording creates a new recording for writing to, or reads an existing
// recording to read from using the io.ReadWriteSeeker, such as an *os.File.
func NewRecording(file io.ReadWriteSeeker) (*Recording, error) {
	recording := &Recording{
		file:     file,
		position: 0,
		mutex:    new(sync.Mutex),
		header: recordingHeader{
			ChunkMap:    make(map[int]segment),
			KeyFrameMap: make(map[int]segment),
		},
	}

	if err := recording.readHeader(); err != nil {
		if err != ErrMissingData {
			return nil, err
		}
	}

	return recording, nil
}

func (r *Recording) readHeaderUnit16(offset int) (uint16, int, error) {
	pos, err := r.file.Seek(int64(offset), 2)
	if err != nil {
		if pathErr, ok := err.(*os.PathError); ok {
			if pathErr.Err == syscall.EINVAL {
				// Cannot seek to this point, declare data as missing
				return 0, 0, ErrMissingData
			}
		}

		return 0, 0, err
	}

	var number uint16
	err = binary.Read(r.file, binary.LittleEndian, &number)
	if err != nil {
		return 0, int(pos), err
	}

	return number, int(pos), nil
}

func (r *Recording) readHeader() error {
	// Read preamble headers
	// Read the version
	version, _, err := r.readHeaderUnit16(versionPosition)
	if err != nil {
		return err
	}

	if version != FormatVersion {
		return ErrIncompatibleVersion
	}

	// Read the header size
	size, pos, err := r.readHeaderUnit16(headerSizePosition)
	if err != nil {
		return err
	}

	r.position = int64(pos)

	// Read the header data
	if _, err = r.file.Seek(-(int64(size))-4, 2); err != nil {
		if pathErr, ok := err.(*os.PathError); ok {
			if pathErr.Err == syscall.EINVAL {
				// Header size is too long, recording is corrupt
				return ErrCorruptRecording
			}
		}

		return err
	}

	reader := io.LimitReader(r.file, int64(size))
	decoder := gob.NewDecoder(reader)
	err = decoder.Decode(&r.header)
	if err != nil {
		return ErrCorruptRecording
	}

	return nil
}

func (r *Recording) writeHeader() error {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return err
	}

	writer := countwriter.NewWriter(r.file)
	gob.NewEncoder(writer).Encode(r.header)

	if writer.Count() > 65535 {
		return ErrHeaderTooLarge
	}

	// Write preamble headers
	// The size of the header
	if err := binary.Write(r.file, binary.LittleEndian,
		uint16(writer.Count())); err != nil {
		return err
	}

	// The version of the recording format
	if err := binary.Write(r.file, binary.LittleEndian,
		uint16(FormatVersion)); err != nil {
		return err
	}

	return nil
}

func (r *Recording) storeInStack(data []byte) (segment, error) {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return segment{}, err
	}

	writtenPosition := r.position

	written, err := r.file.Write(data)
	r.position += int64(written)
	return segment{writtenPosition, written}, err
}

func (r *Recording) writeToStack(rd io.Reader) (segment, error) {
	if _, err := r.file.Seek(int64(r.position), 0); err != nil {
		return segment{}, err
	}

	writtenPosition := r.position

	written, err := io.Copy(r.file, rd)
	r.position += written
	return segment{writtenPosition, int(written)}, err
}

// WriteTo encodes the ChunkInfo as JSON and writes it to a writer.
func (c ChunkInfo) WriteTo(w io.Writer) (int64, error) {
	cw := countwriter.NewWriter(w)
	encoder := ffjson.NewEncoder(cw)
	err := encoder.EncodeFast(&c)
	return int64(cw.Count()), err
}

func init() {
	bufferPool = new(sync.Pool)
	bufferPool.New = func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, bufferSize))
	}

	gob.Register(recordingHeader{})
}
<|endoftext|>


<commit_before>// Package bankaccount provides the /bank_accounts APIs
package bankaccount

import (
	"errors"
	"fmt"
	"strconv"

	stripe "github.com/stripe/stripe-go"
)

// Client is used to invoke /bank_accounts APIs.
type Client struct {
	B   stripe.Backend
	Key string
}

const (
	NewAccount       stripe.BankAccountStatus = "new"
	VerifiedAccount  stripe.BankAccountStatus = "verified"
	ValidatedAccount stripe.BankAccountStatus = "validated"
	ErroredAccount   stripe.BankAccountStatus = "errored"
)

// New POSTs a new bank account.
func New(params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().New(params)
}

func (c Client) New(params *stripe.BankAccountParams) (*stripe.BankAccount, error) {

	body := &stripe.RequestValues{}

	// Use token (if exists) or a dictionary containing a user’s bank account details.
	if len(params.Token) > 0 {
		body.Add("external_account", params.Token)

		if params.Default {
			body.Add("default_for_currency", strconv.FormatBool(params.Default))
		}
	} else {
		body.Add("external_account[object]", "bank_account")
		body.Add("external_account[country]", params.Country)
		body.Add("external_account[account_number]", params.Account)
		body.Add("external_account[currency]", params.Currency)

		if len(params.Routing) > 0 {
			body.Add("external_account[routing_number]", params.Routing)
		}

		if params.Default {
			body.Add("external_account[default_for_currency]", strconv.FormatBool(params.Default))
		}
	}
	params.AppendTo(body)

	ba := &stripe.BankAccount{}
	err := c.B.Call("POST", fmt.Sprintf("/accounts/%v/bank_accounts", params.AccountID), c.Key, body, &params.Params, ba)

	return ba, err
}

// Get returns the details of a bank account.
func Get(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Get(id, params)
}

func (c Client) Get(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	var body *stripe.RequestValues
	var commonParams *stripe.Params

	if params != nil {
		commonParams = &params.Params
		body = &stripe.RequestValues{}
		params.AppendTo(body)
	}

	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("GET", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("GET", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// Update updates a bank account.
func Update(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Update(id, params)
}

func (c Client) Update(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	var body *stripe.RequestValues
	var commonParams *stripe.Params

	if params != nil {
		commonParams = &params.Params
		body = &stripe.RequestValues{}

		if params.Default {
			body.Add("default_for_currency", strconv.FormatBool(params.Default))
		}

		params.AppendTo(body)
	}

	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("POST", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.Customer, id), c.Key, body, commonParams, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("POST", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// Del removes a bank account.
func Del(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Del(id, params)
}

func (c Client) Del(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("DELETE", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.Customer, id), c.Key, nil, nil, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("DELETE", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, nil, nil, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// List returns a list of bank accounts.
func List(params *stripe.BankAccountListParams) *Iter {
	return getC().List(params)
}

func (c Client) List(params *stripe.BankAccountListParams) *Iter {
	body := &stripe.RequestValues{}
	var lp *stripe.ListParams
	var p *stripe.Params

	params.AppendTo(body)
	lp = &params.ListParams
	p = params.ToParams()

	return &Iter{stripe.GetIter(lp, body, func(b *stripe.RequestValues) ([]interface{}, stripe.ListMeta, error) {
		list := &stripe.BankAccountList{}
		var err error

		if len(params.Customer) > 0 {
			err = c.B.Call("GET", fmt.Sprintf("/customers/%v/bank_accounts", params.Customer), c.Key, b, p, list)
		} else if len(params.AccountID) > 0 {
			err = c.B.Call("GET", fmt.Sprintf("/accounts/%v/bank_accounts", params.AccountID), c.Key, b, p, list)
		} else {
			err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
		}

		ret := make([]interface{}, len(list.Values))
		for i, v := range list.Values {
			ret[i] = v
		}

		return ret, list.ListMeta, err
	})}
}

// Iter is an iterator for lists of BankAccount.
// The embedded Iter carries methods with it;
// see its documentation for details.
type Iter struct {
	*stripe.Iter
}

// BankAccount returns the most recent BankAccount
// visited by a call to Next.
func (i *Iter) BankAccount() *stripe.BankAccount {
	return i.Current().(*stripe.BankAccount)
}

func getC() Client {
	return Client{stripe.GetBackend(stripe.APIBackend), stripe.Key}
}
<commit_msg>Add creating a bank account on a customer<commit_after>// Package bankaccount provides the /bank_accounts APIs
package bankaccount

import (
	"errors"
	"fmt"
	"strconv"

	stripe "github.com/stripe/stripe-go"
)

// Client is used to invoke /bank_accounts APIs.
type Client struct {
	B   stripe.Backend
	Key string
}

const (
	NewAccount       stripe.BankAccountStatus = "new"
	VerifiedAccount  stripe.BankAccountStatus = "verified"
	ValidatedAccount stripe.BankAccountStatus = "validated"
	ErroredAccount   stripe.BankAccountStatus = "errored"
)

// New POSTs a new bank account.
func New(params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().New(params)
}

func (c Client) New(params *stripe.BankAccountParams) (*stripe.BankAccount, error) {

	body := &stripe.RequestValues{}
	isCustomer := len(params.Customer) > 0

	var sourceType string
	if isCustomer {
		sourceType = "source"
	} else {
		sourceType = "external_account"
	}

	// Use token (if exists) or a dictionary containing a user’s bank account details.
	if len(params.Token) > 0 {
		body.Add(sourceType, params.Token)

		if params.Default {
			body.Add("default_for_currency", strconv.FormatBool(params.Default))
		}
	} else {
		body.Add(sourceType+"[object]", "bank_account")
		body.Add(sourceType+"[country]", params.Country)
		body.Add(sourceType+"[account_number]", params.Account)
		body.Add(sourceType+"[currency]", params.Currency)

		if isCustomer {
			body.Add(sourceType+"[account_holder_name]", params.AccountHolderName)
			body.Add(sourceType+"[account_holder_type]", params.AccountHolderType)
		}

		if len(params.Routing) > 0 {
			body.Add(sourceType+"[routing_number]", params.Routing)
		}

		if params.Default {
			body.Add(sourceType+"[default_for_currency]", strconv.FormatBool(params.Default))
		}
	}
	params.AppendTo(body)

	ba := &stripe.BankAccount{}
	var err error
	if isCustomer {
		err = c.B.Call("POST", fmt.Sprintf("/customers/%v/sources", params.Customer), c.Key, body, &params.Params, ba)
	} else {
		err = c.B.Call("POST", fmt.Sprintf("/accounts/%v/bank_accounts", params.AccountID), c.Key, body, &params.Params, ba)
	}

	return ba, err
}

// Get returns the details of a bank account.
func Get(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Get(id, params)
}

func (c Client) Get(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	var body *stripe.RequestValues
	var commonParams *stripe.Params

	if params != nil {
		commonParams = &params.Params
		body = &stripe.RequestValues{}
		params.AppendTo(body)
	}

	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("GET", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("GET", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// Update updates a bank account.
func Update(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Update(id, params)
}

func (c Client) Update(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	var body *stripe.RequestValues
	var commonParams *stripe.Params

	if params != nil {
		commonParams = &params.Params
		body = &stripe.RequestValues{}

		if params.Default {
			body.Add("default_for_currency", strconv.FormatBool(params.Default))
		}

		params.AppendTo(body)
	}

	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("POST", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.Customer, id), c.Key, body, commonParams, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("POST", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, body, commonParams, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// Del removes a bank account.
func Del(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	return getC().Del(id, params)
}

func (c Client) Del(id string, params *stripe.BankAccountParams) (*stripe.BankAccount, error) {
	ba := &stripe.BankAccount{}
	var err error

	if len(params.Customer) > 0 {
		err = c.B.Call("DELETE", fmt.Sprintf("/customers/%v/bank_accounts/%v", params.Customer, id), c.Key, nil, nil, ba)
	} else if len(params.AccountID) > 0 {
		err = c.B.Call("DELETE", fmt.Sprintf("/accounts/%v/bank_accounts/%v", params.AccountID, id), c.Key, nil, nil, ba)
	} else {
		err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
	}

	return ba, err
}

// List returns a list of bank accounts.
func List(params *stripe.BankAccountListParams) *Iter {
	return getC().List(params)
}

func (c Client) List(params *stripe.BankAccountListParams) *Iter {
	body := &stripe.RequestValues{}
	var lp *stripe.ListParams
	var p *stripe.Params

	params.AppendTo(body)
	lp = &params.ListParams
	p = params.ToParams()

	return &Iter{stripe.GetIter(lp, body, func(b *stripe.RequestValues) ([]interface{}, stripe.ListMeta, error) {
		list := &stripe.BankAccountList{}
		var err error

		if len(params.Customer) > 0 {
			err = c.B.Call("GET", fmt.Sprintf("/customers/%v/bank_accounts", params.Customer), c.Key, b, p, list)
		} else if len(params.AccountID) > 0 {
			err = c.B.Call("GET", fmt.Sprintf("/accounts/%v/bank_accounts", params.AccountID), c.Key, b, p, list)
		} else {
			err = errors.New("Invalid bank account params: either Customer or AccountID need to be set")
		}

		ret := make([]interface{}, len(list.Values))
		for i, v := range list.Values {
			ret[i] = v
		}

		return ret, list.ListMeta, err
	})}
}

// Iter is an iterator for lists of BankAccount.
// The embedded Iter carries methods with it;
// see its documentation for details.
type Iter struct {
	*stripe.Iter
}

// BankAccount returns the most recent BankAccount
// visited by a call to Next.
func (i *Iter) BankAccount() *stripe.BankAccount {
	return i.Current().(*stripe.BankAccount)
}

func getC() Client {
	return Client{stripe.GetBackend(stripe.APIBackend), stripe.Key}
}
<|endoftext|>


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

package diff

import "testing"

type Foo struct {
	IntVal    int
	FloatVal  float32
	StringVal string
	Bar       Bar
	FooPtr    *Foo
	IntList   []int
}

type Bar struct {
	StringVal string
}

func TestCompute(t *testing.T) {
	f1 := Foo{
		IntVal:    42,
		FloatVal:  53.032,
		StringVal: "bar",
		Bar: Bar{
			StringVal: "ok",
		},
		FooPtr:  nil,
		IntList: []int{1, 3, 4},
	}
	f2 := Foo{
		IntVal:    42,
		FloatVal:  53.042,
		StringVal: "baraca",
		Bar: Bar{
			StringVal: "ok",
		},
		FooPtr: &Foo{
			IntVal: 42,
		},
		IntList: []int{1, 2, 4, 5},
	}
	delta, err := Compute(f1, f2, false)
	if err != nil {
		t.Fatal("Failed to compute diff: ", err)
	}
	t.Log(string(delta.PrettyJSON()))
}
<commit_msg>diff: add one more test case<commit_after>// Copyright 2016 e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package diff

import "testing"

type Foo struct {
	IntVal    int
	FloatVal  float32
	StringVal string
	Bar       Bar
	FooPtr    *Foo
	IntList   []int
	BarList   []Bar
}

type Bar struct {
	StringVal string
}

func TestCompute(t *testing.T) {
	f1 := Foo{
		IntVal:    42,
		FloatVal:  53.032,
		StringVal: "bar",
		Bar: Bar{
			StringVal: "ok",
		},
		FooPtr:  nil,
		IntList: []int{1, 3, 4},
		BarList: []Bar{{StringVal: "aaa"}, {StringVal: "bbb"}},
	}
	f2 := Foo{
		IntVal:    42,
		FloatVal:  53.042,
		StringVal: "baraca",
		Bar: Bar{
			StringVal: "ok",
		},
		FooPtr: &Foo{
			IntVal: 42,
		},
		IntList: []int{1, 2, 4, 5},
		BarList: []Bar{{StringVal: "ccc"}, {StringVal: "ddd"}},
	}
	delta, err := Compute(f1, f2, false)
	if err != nil {
		t.Fatal("Failed to compute diff: ", err)
	}
	t.Log(string(delta.PrettyJSON()))
}
<|endoftext|>


<commit_before>// Package smtpd implements a basic SMTP server.
package smtpd

import (
	"bufio"
	"bytes"
	"fmt"
	"net"
	"os"
	"regexp"
	"strings"
	"time"
)

var (
	rcptToRE   = regexp.MustCompile(`[Tt][Oo]:<(.+)>`)
	mailFromRE = regexp.MustCompile(`[Ff][Rr][Oo][Mm]:<(.*)>`) // Delivery Status Notifications are sent with "MAIL FROM:<>"
)

// Handler function called upon successful receipt of an email.
type Handler func(remoteAddr net.Addr, from string, to []string, data []byte)

// ListenAndServe listens on the TCP network address addr
// and then calls Serve with handler to handle requests
// on incoming connections.
func ListenAndServe(addr string, handler Handler, appname string, hostname string) error {
	srv := &Server{Addr: addr, Handler: handler, Appname: appname, Hostname: hostname}
	return srv.ListenAndServe()
}

// Server is an SMTP server.
type Server struct {
	Addr     string // TCP address to listen on, defaults to ":25" (all addresses, port 25) if empty
	Handler  Handler
	Appname  string
	Hostname string
	Timeout  time.Duration
}

// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections.  If
// srv.Addr is blank, ":25" is used.
func (srv *Server) ListenAndServe() error {
	if srv.Addr == "" {
		srv.Addr = ":25"
	}
	if srv.Appname == "" {
		srv.Appname = "smtpd"
	}
	if srv.Hostname == "" {
		srv.Hostname, _ = os.Hostname()
	}
	if srv.Timeout == 0 {
		srv.Timeout = 5 * time.Minute
	}

	ln, err := net.Listen("tcp", srv.Addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

// Serve creates a new SMTP session after a network connection is established.
func (srv *Server) Serve(ln net.Listener) error {
	defer ln.Close()
	for {
		conn, err := ln.Accept()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				continue
			}
			return err
		}
		session, err := srv.newSession(conn)
		if err != nil {
			continue
		}
		go session.serve()
	}
}

type session struct {
	srv        *Server
	conn       net.Conn
	br         *bufio.Reader
	bw         *bufio.Writer
	remoteIP   string // Remote IP address
	remoteHost string // Remote hostname according to reverse DNS lookup
	remoteName string // Remote hostname as supplied with EHLO
}

// Create new session from connection.
func (srv *Server) newSession(conn net.Conn) (s *session, err error) {
	s = &session{
		srv:  srv,
		conn: conn,
		br:   bufio.NewReader(conn),
		bw:   bufio.NewWriter(conn),
	}
	return
}

// Function called to handle connection requests.
func (s *session) serve() {
	defer s.conn.Close()
	var from string
	var to []string
	var buffer bytes.Buffer

	// Get remote end info for the Received header.
	s.remoteIP, _, _ = net.SplitHostPort(s.conn.RemoteAddr().String())
	names, err := net.LookupAddr(s.remoteIP)
	if err == nil && len(names) > 0 {
		s.remoteHost = names[0]
	} else {
		s.remoteHost = "unknown"
	}

	// Send banner.
	s.writef("220 %s %s SMTP Service ready", s.srv.Hostname, s.srv.Appname)

loop:
	for {
		// Attempt to read a line from the socket.
		// On timeout, send a timeout message and return from serve().
		// On error, assume the client has gone away i.e. return from serve().
		line, err := s.readLine()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
				s.writef("421 4.4.2 %s %s SMTP Service closing transmission channel after timeout exceeded", s.srv.Hostname, s.srv.Appname)
			}
			break
		}
		verb, args := s.parseLine(line)

		switch verb {
		case "EHLO", "HELO":
			s.remoteName = args
			s.writef("250 %s greets %s", s.srv.Hostname, s.remoteName)

			// RFC 2821 section 4.1.4 specifies that EHLO has the same effect as RSET.
			from = ""
			to = nil
			buffer.Reset()
		case "MAIL":
			match := mailFromRE.FindStringSubmatch(args)
			if match == nil {
				s.writef("501 Syntax error in parameters or arguments (invalid FROM parameter)")
			} else {
				from = match[1]
				s.writef("250 Ok")
			}
			to = nil
			buffer.Reset()
		case "RCPT":
			if from == "" {
				s.writef("503 Bad sequence of commands (MAIL required before RCPT)")
				break
			}

			match := rcptToRE.FindStringSubmatch(args)
			if match == nil {
				s.writef("501 Syntax error in parameters or arguments (invalid TO parameter)")
			} else {
				// RFC 5321 specifies 100 minimum recipients
				if len(to) == 100 {
					s.writef("452 Too many recipients")
				} else {
					to = append(to, match[1])
					s.writef("250 Ok")
				}
			}
		case "DATA":
			if from == "" || to == nil {
				s.writef("503 Bad sequence of commands (MAIL & RCPT required before DATA)")
				break
			}

			s.writef("354 Start mail input; end with <CR><LF>.<CR><LF>")

			// Attempt to read message body from the socket.
			// On timeout, send a timeout message and return from serve().
			// On error, assume the client has gone away i.e. return from serve().
			data, err := s.readData()
			if err != nil {
				if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
					s.writef("421 4.4.2 %s %s SMTP Service closing transmission channel after timeout exceeded", s.srv.Hostname, s.srv.Appname)
				}
				break loop
			}

			// Create Received header & write message body into buffer.
			buffer.Reset()
			buffer.Write(s.makeHeaders(to))
			buffer.Write(data)
			s.writef("250 Ok: queued")

			// Pass mail on to handler.
			if s.srv.Handler != nil {
				go s.srv.Handler(s.conn.RemoteAddr(), from, to, buffer.Bytes())
			}

			// Reset for next mail.
			from = ""
			to = nil
			buffer.Reset()
		case "QUIT":
			s.writef("221 %s %s SMTP Service closing transmission channel", s.srv.Hostname, s.srv.Appname)
			break loop
		case "RSET":
			s.writef("250 Ok")
			from = ""
			to = nil
			buffer.Reset()
		case "NOOP":
			s.writef("250 Ok")
		case "HELP", "VRFY", "EXPN":
			// See RFC 5321 section 4.2.4 for usage of 500 & 502 reply codes
			s.writef("502 Command not implemented")
		default:
			// See RFC 5321 section 4.2.4 for usage of 500 & 502 reply codes
			s.writef("500 Syntax error, command unrecognized")
		}
	}
}

// Wrapper function for writing a complete line to the socket.
func (s *session) writef(format string, args ...interface{}) {
	fmt.Fprintf(s.bw, format+"\r\n", args...)
	s.bw.Flush()
}

// Read a complete line from the socket.
func (s *session) readLine() (string, error) {
	if s.srv.Timeout > 0 {
		s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout))
	}

	line, err := s.br.ReadString('\n')
	if err != nil {
		return "", err
	}
	line = strings.TrimSpace(line) // Strip trailing \r\n
	return line, err
}

// Parse a line read from the socket.
func (s *session) parseLine(line string) (verb string, args string) {
	if idx := strings.Index(line, " "); idx != -1 {
		verb = strings.ToUpper(line[:idx])
		args = strings.TrimSpace(line[idx+1:])
	} else {
		verb = strings.ToUpper(line)
		args = ""
	}
	return verb, args
}

// Read the message data following a DATA command.
func (s *session) readData() ([]byte, error) {
	var data []byte
	for {
		if s.srv.Timeout > 0 {
			s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout))
		}

		line, err := s.br.ReadBytes('\n')
		if err != nil {
			return nil, err
		}
		// Handle end of data denoted by lone period (\r\n.\r\n)
		if bytes.Equal(line, []byte(".\r\n")) {
			break
		}
		// Remove leading period (RFC 5321 section 4.5.2)
		if line[0] == '.' {
			line = line[1:]
		}
		data = append(data, line...)

	}
	return data, nil
}

// Create the Received header to comply with RFC 2821 section 3.8.2.
// TODO: Work out what to do with multiple to addresses.
func (s *session) makeHeaders(to []string) []byte {
	var buffer bytes.Buffer
	now := time.Now().Format("Mon, _2 Jan 2006 15:04:05 -0700 (MST)")
	buffer.WriteString(fmt.Sprintf("Received: from %s (%s [%s])\r\n", s.remoteName, s.remoteHost, s.remoteIP))
	buffer.WriteString(fmt.Sprintf("        by %s (%s) with SMTP\r\n", s.srv.Hostname, s.srv.Appname))
	buffer.WriteString(fmt.Sprintf("        for <%s>; %s\r\n", to[0], now))
	return buffer.Bytes()
}
<commit_msg>Add a write timeout that will be ignored for now.<commit_after>// Package smtpd implements a basic SMTP server.
package smtpd

import (
	"bufio"
	"bytes"
	"fmt"
	"net"
	"os"
	"regexp"
	"strings"
	"time"
)

var (
	rcptToRE   = regexp.MustCompile(`[Tt][Oo]:<(.+)>`)
	mailFromRE = regexp.MustCompile(`[Ff][Rr][Oo][Mm]:<(.*)>`) // Delivery Status Notifications are sent with "MAIL FROM:<>"
)

// Handler function called upon successful receipt of an email.
type Handler func(remoteAddr net.Addr, from string, to []string, data []byte)

// ListenAndServe listens on the TCP network address addr
// and then calls Serve with handler to handle requests
// on incoming connections.
func ListenAndServe(addr string, handler Handler, appname string, hostname string) error {
	srv := &Server{Addr: addr, Handler: handler, Appname: appname, Hostname: hostname}
	return srv.ListenAndServe()
}

// Server is an SMTP server.
type Server struct {
	Addr     string // TCP address to listen on, defaults to ":25" (all addresses, port 25) if empty
	Handler  Handler
	Appname  string
	Hostname string
	Timeout  time.Duration
}

// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections.  If
// srv.Addr is blank, ":25" is used.
func (srv *Server) ListenAndServe() error {
	if srv.Addr == "" {
		srv.Addr = ":25"
	}
	if srv.Appname == "" {
		srv.Appname = "smtpd"
	}
	if srv.Hostname == "" {
		srv.Hostname, _ = os.Hostname()
	}
	if srv.Timeout == 0 {
		srv.Timeout = 5 * time.Minute
	}

	ln, err := net.Listen("tcp", srv.Addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

// Serve creates a new SMTP session after a network connection is established.
func (srv *Server) Serve(ln net.Listener) error {
	defer ln.Close()
	for {
		conn, err := ln.Accept()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				continue
			}
			return err
		}
		session, err := srv.newSession(conn)
		if err != nil {
			continue
		}
		go session.serve()
	}
}

type session struct {
	srv        *Server
	conn       net.Conn
	br         *bufio.Reader
	bw         *bufio.Writer
	remoteIP   string // Remote IP address
	remoteHost string // Remote hostname according to reverse DNS lookup
	remoteName string // Remote hostname as supplied with EHLO
}

// Create new session from connection.
func (srv *Server) newSession(conn net.Conn) (s *session, err error) {
	s = &session{
		srv:  srv,
		conn: conn,
		br:   bufio.NewReader(conn),
		bw:   bufio.NewWriter(conn),
	}
	return
}

// Function called to handle connection requests.
func (s *session) serve() {
	defer s.conn.Close()
	var from string
	var to []string
	var buffer bytes.Buffer

	// Get remote end info for the Received header.
	s.remoteIP, _, _ = net.SplitHostPort(s.conn.RemoteAddr().String())
	names, err := net.LookupAddr(s.remoteIP)
	if err == nil && len(names) > 0 {
		s.remoteHost = names[0]
	} else {
		s.remoteHost = "unknown"
	}

	// Send banner.
	s.writef("220 %s %s SMTP Service ready", s.srv.Hostname, s.srv.Appname)

loop:
	for {
		// Attempt to read a line from the socket.
		// On timeout, send a timeout message and return from serve().
		// On error, assume the client has gone away i.e. return from serve().
		line, err := s.readLine()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
				s.writef("421 4.4.2 %s %s SMTP Service closing transmission channel after timeout exceeded", s.srv.Hostname, s.srv.Appname)
			}
			break
		}
		verb, args := s.parseLine(line)

		switch verb {
		case "EHLO", "HELO":
			s.remoteName = args
			s.writef("250 %s greets %s", s.srv.Hostname, s.remoteName)

			// RFC 2821 section 4.1.4 specifies that EHLO has the same effect as RSET.
			from = ""
			to = nil
			buffer.Reset()
		case "MAIL":
			match := mailFromRE.FindStringSubmatch(args)
			if match == nil {
				s.writef("501 Syntax error in parameters or arguments (invalid FROM parameter)")
			} else {
				from = match[1]
				s.writef("250 Ok")
			}
			to = nil
			buffer.Reset()
		case "RCPT":
			if from == "" {
				s.writef("503 Bad sequence of commands (MAIL required before RCPT)")
				break
			}

			match := rcptToRE.FindStringSubmatch(args)
			if match == nil {
				s.writef("501 Syntax error in parameters or arguments (invalid TO parameter)")
			} else {
				// RFC 5321 specifies 100 minimum recipients
				if len(to) == 100 {
					s.writef("452 Too many recipients")
				} else {
					to = append(to, match[1])
					s.writef("250 Ok")
				}
			}
		case "DATA":
			if from == "" || to == nil {
				s.writef("503 Bad sequence of commands (MAIL & RCPT required before DATA)")
				break
			}

			s.writef("354 Start mail input; end with <CR><LF>.<CR><LF>")

			// Attempt to read message body from the socket.
			// On timeout, send a timeout message and return from serve().
			// On error, assume the client has gone away i.e. return from serve().
			data, err := s.readData()
			if err != nil {
				if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
					s.writef("421 4.4.2 %s %s SMTP Service closing transmission channel after timeout exceeded", s.srv.Hostname, s.srv.Appname)
				}
				break loop
			}

			// Create Received header & write message body into buffer.
			buffer.Reset()
			buffer.Write(s.makeHeaders(to))
			buffer.Write(data)
			s.writef("250 Ok: queued")

			// Pass mail on to handler.
			if s.srv.Handler != nil {
				go s.srv.Handler(s.conn.RemoteAddr(), from, to, buffer.Bytes())
			}

			// Reset for next mail.
			from = ""
			to = nil
			buffer.Reset()
		case "QUIT":
			s.writef("221 %s %s SMTP Service closing transmission channel", s.srv.Hostname, s.srv.Appname)
			break loop
		case "RSET":
			s.writef("250 Ok")
			from = ""
			to = nil
			buffer.Reset()
		case "NOOP":
			s.writef("250 Ok")
		case "HELP", "VRFY", "EXPN":
			// See RFC 5321 section 4.2.4 for usage of 500 & 502 reply codes
			s.writef("502 Command not implemented")
		default:
			// See RFC 5321 section 4.2.4 for usage of 500 & 502 reply codes
			s.writef("500 Syntax error, command unrecognized")
		}
	}
}

// Wrapper function for writing a complete line to the socket.
func (s *session) writef(format string, args ...interface{}) error {
	if s.srv.Timeout > 0 {
		s.conn.SetWriteDeadline(time.Now().Add(s.srv.Timeout))
	}

	fmt.Fprintf(s.bw, format+"\r\n", args...)
	err := s.bw.Flush()
	return err
}

// Read a complete line from the socket.
func (s *session) readLine() (string, error) {
	if s.srv.Timeout > 0 {
		s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout))
	}

	line, err := s.br.ReadString('\n')
	if err != nil {
		return "", err
	}
	line = strings.TrimSpace(line) // Strip trailing \r\n
	return line, err
}

// Parse a line read from the socket.
func (s *session) parseLine(line string) (verb string, args string) {
	if idx := strings.Index(line, " "); idx != -1 {
		verb = strings.ToUpper(line[:idx])
		args = strings.TrimSpace(line[idx+1:])
	} else {
		verb = strings.ToUpper(line)
		args = ""
	}
	return verb, args
}

// Read the message data following a DATA command.
func (s *session) readData() ([]byte, error) {
	var data []byte
	for {
		if s.srv.Timeout > 0 {
			s.conn.SetReadDeadline(time.Now().Add(s.srv.Timeout))
		}

		line, err := s.br.ReadBytes('\n')
		if err != nil {
			return nil, err
		}
		// Handle end of data denoted by lone period (\r\n.\r\n)
		if bytes.Equal(line, []byte(".\r\n")) {
			break
		}
		// Remove leading period (RFC 5321 section 4.5.2)
		if line[0] == '.' {
			line = line[1:]
		}
		data = append(data, line...)

	}
	return data, nil
}

// Create the Received header to comply with RFC 2821 section 3.8.2.
// TODO: Work out what to do with multiple to addresses.
func (s *session) makeHeaders(to []string) []byte {
	var buffer bytes.Buffer
	now := time.Now().Format("Mon, _2 Jan 2006 15:04:05 -0700 (MST)")
	buffer.WriteString(fmt.Sprintf("Received: from %s (%s [%s])\r\n", s.remoteName, s.remoteHost, s.remoteIP))
	buffer.WriteString(fmt.Sprintf("        by %s (%s) with SMTP\r\n", s.srv.Hostname, s.srv.Appname))
	buffer.WriteString(fmt.Sprintf("        for <%s>; %s\r\n", to[0], now))
	return buffer.Bytes()
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"runtime"
	"time"

	"github.com/futurespaceio/space/core"
	"github.com/futurespaceio/space/plugins/drafts"
	"github.com/futurespaceio/space/plugins/markdown"
	"github.com/futurespaceio/space/plugins/permalinks"
	mw "github.com/futurespaceio/ware"
)

const APP_VER = "0.0.0"

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {
	s := space.Classic()
	s.Use(func(c mw.Context, fs space.Filesystem, log *log.Logger) {
		c.Next()
		log.Printf("Compiled %v files\n", len(fs.Files()))
	})
	// File Processor Middleware
	p := s.Processor
	p.Use(func(c mw.Context, f *space.File, log *log.Logger) {
		start := time.Now()
		log.Printf("File Started %s", f.Info.Name())
		c.Next()
		log.Printf("File Rendered %v \n", time.Since(start))
	})
	p.Use(drafts.Handle())
	p.Use(markdown.Render())
	p.Use(permalinks.Handle("pertty"))
	s.Run()
}
<commit_msg>use pretty pattern for permalinks<commit_after>package main

import (
	"log"
	"runtime"
	"time"

	"github.com/futurespaceio/space/core"
	"github.com/futurespaceio/space/plugins/drafts"
	"github.com/futurespaceio/space/plugins/markdown"
	"github.com/futurespaceio/space/plugins/permalinks"
	mw "github.com/futurespaceio/ware"
)

const APP_VER = "0.0.0"

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {
	s := space.Classic()
	s.Use(func(c mw.Context, fs space.Filesystem, log *log.Logger) {
		c.Next()
		log.Printf("Compiled %v files\n", len(fs.Files()))
	})
	// File Processor Middleware
	p := s.Processor
	p.Use(func(c mw.Context, f *space.File, log *log.Logger) {
		start := time.Now()
		log.Printf("File Started %s", f.Info.Name())
		c.Next()
		log.Printf("File Rendered %v \n", time.Since(start))
	})
	p.Use(drafts.Handle())
	p.Use(markdown.Render())
	p.Use(permalinks.Handle("pretty"))
	s.Run()
}
<|endoftext|>


<commit_before>package blocks

import (
	"errors"
	"os"
	"path/filepath"
	"sync"
)

var ErrNoManifest = errors.New("no manifest file found")
var ErrPartitionNotFound = errors.New("the block store doesn't have the correct partition for the key")
var ErrMissingPartitions = errors.New("existing block store missing partitions")

type Compression string

const SnappyCompression Compression = "snappy"
const NoCompression Compression = "none"

// A BlockStore stores ingested key/value data in discrete blocks, each stored
// as a separate CDB file. The blocks are arranged and sorted in a way that
// takes advantage of the way that the output of hadoop jobs are laid out.
type BlockStore struct {
	path          string
	compression   Compression
	blockSize     int
	numPartitions int

	newBlocks map[int]*blockWriter
	Blocks    []*Block
	BlockMap  map[int][]*Block

	blockMapLock sync.RWMutex
}

func New(path string, numPartitions int, compression Compression, blockSize int) *BlockStore {
	return &BlockStore{
		path:          path,
		compression:   compression,
		blockSize:     blockSize,
		numPartitions: numPartitions,

		newBlocks: make(map[int]*blockWriter),
		Blocks:    make([]*Block, 0),
		BlockMap:  make(map[int][]*Block),
	}
}

// NewFromManifest loads a block store from a directory with a manifest, and
// returns it, the parsed manifest, and any error encountered while loading.
func NewFromManifest(path string) (*BlockStore, Manifest, error) {
	manifestPath := filepath.Join(path, ".manifest")
	manifest, err := readManifest(manifestPath)
	if os.IsNotExist(err) {
		return nil, manifest, ErrNoManifest
	} else if err != nil {
		return nil, manifest, err
	}

	store := New(path, manifest.NumPartitions, manifest.Compression, manifest.BlockSize)
	for _, blockManifest := range manifest.Blocks {
		block, err := loadBlock(path, blockManifest)
		if err != nil {
			return nil, Manifest{}, err
		}

		partition := blockManifest.Partition
		store.Blocks = append(store.Blocks, block)
		store.BlockMap[partition] = append(store.BlockMap[partition], block)
	}

	return store, manifest, nil
}

// Add adds a single key/value pair to the block store.
func (store *BlockStore) Add(key, value []byte) error {
	partition, _ := KeyPartition(key, store.numPartitions)

	block, ok := store.newBlocks[partition]
	var err error
	if !ok {
		block, err = newBlock(store.path, partition, store.compression, store.blockSize)
		if err != nil {
			return err
		}

		store.newBlocks[partition] = block
	}

	err = block.add(key, value)
	if err != nil {
		return err
	}

	return nil
}

// Save saves flushes any newly created blocks, and writes a manifest file to
// the directory.
func (store *BlockStore) Save(selectedPartitions map[int]bool) error {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	// Flush any buffered blocks.
	for partition, block := range store.newBlocks {
		savedBlock, err := block.save()
		if err != nil {
			return err
		}

		store.Blocks = append(store.Blocks, savedBlock)
		store.BlockMap[partition] = append(store.BlockMap[partition], savedBlock)
	}

	store.newBlocks = make(map[int]*blockWriter)

	// Save the manifest.
	var partitions []int
	partitions = make([]int, 0, len(selectedPartitions))
	for partition := range selectedPartitions {
		partitions = append(partitions, partition)
	}

	manifest := Manifest{
		Version:            manifestVersion,
		Blocks:             make([]BlockManifest, len(store.Blocks)),
		NumPartitions:      store.numPartitions,
		SelectedPartitions: partitions,
	}

	for i, block := range store.Blocks {
		blockManifest := block.manifest()
		manifest.Blocks[i] = blockManifest
	}

	return writeManifest(filepath.Join(store.path, ".manifest"), manifest)
}

// Revert removes any unflushed blocks, and resets the state to when the
// manifest was last saved. If the block store was never saved, then it reverts
// to being empty.
func (store *BlockStore) Revert() {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	for _, block := range store.newBlocks {
		block.close()
		block.delete()
	}

	store.newBlocks = make(map[int]*blockWriter)
	return
}

// Get returns the value for a given key. It returns ErrPartitionNotFound if
// the partition requested is not available locally.
func (store *BlockStore) Get(key string) (*Record, error) {
	store.blockMapLock.RLock()
	defer store.blockMapLock.RUnlock()

	partition, alternatePartition := KeyPartition([]byte(key), store.numPartitions)
	if store.BlockMap[partition] == nil && store.BlockMap[alternatePartition] == nil {
		return nil, ErrPartitionNotFound
	}

	// There can be multiple blocks for each partition - in that case, we need to
	// check each one sequentially.
	for _, block := range store.BlockMap[partition] {
		res, err := block.Get([]byte(key))
		if err != nil {
			return nil, err
		} else if res != nil {
			return res, nil
		}
	}

	// See the comment for alternatePathologicalKeyPartition.
	if alternatePartition != partition {
		for _, block := range store.BlockMap[alternatePartition] {
			res, err := block.Get([]byte(key))
			if err != nil {
				return nil, err
			} else if res != nil {
				return res, nil
			}
		}
	}

	return nil, nil
}

// Close closes the BlockStore, and any files it has open.
func (store *BlockStore) Close() {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	for _, block := range store.Blocks {
		block.Close()
	}

	for _, newBlock := range store.newBlocks {
		newBlock.close()
	}
}

// Delete removes any local data the BlockStore has stored.
func (store *BlockStore) Delete() error {
	return os.RemoveAll(store.path)
}
<commit_msg>Fix a bug where 404s are turned into 500s<commit_after>package blocks

import (
	"errors"
	"os"
	"path/filepath"
	"sync"
)

var ErrNoManifest = errors.New("no manifest file found")
var ErrMissingPartitions = errors.New("existing block store missing partitions")

type Compression string

const SnappyCompression Compression = "snappy"
const NoCompression Compression = "none"

// A BlockStore stores ingested key/value data in discrete blocks, each stored
// as a separate CDB file. The blocks are arranged and sorted in a way that
// takes advantage of the way that the output of hadoop jobs are laid out.
type BlockStore struct {
	path          string
	compression   Compression
	blockSize     int
	numPartitions int

	newBlocks map[int]*blockWriter
	Blocks    []*Block
	BlockMap  map[int][]*Block

	blockMapLock sync.RWMutex
}

func New(path string, numPartitions int, compression Compression, blockSize int) *BlockStore {
	return &BlockStore{
		path:          path,
		compression:   compression,
		blockSize:     blockSize,
		numPartitions: numPartitions,

		newBlocks: make(map[int]*blockWriter),
		Blocks:    make([]*Block, 0),
		BlockMap:  make(map[int][]*Block),
	}
}

// NewFromManifest loads a block store from a directory with a manifest, and
// returns it, the parsed manifest, and any error encountered while loading.
func NewFromManifest(path string) (*BlockStore, Manifest, error) {
	manifestPath := filepath.Join(path, ".manifest")
	manifest, err := readManifest(manifestPath)
	if os.IsNotExist(err) {
		return nil, manifest, ErrNoManifest
	} else if err != nil {
		return nil, manifest, err
	}

	store := New(path, manifest.NumPartitions, manifest.Compression, manifest.BlockSize)
	for _, blockManifest := range manifest.Blocks {
		block, err := loadBlock(path, blockManifest)
		if err != nil {
			return nil, Manifest{}, err
		}

		partition := blockManifest.Partition
		store.Blocks = append(store.Blocks, block)
		store.BlockMap[partition] = append(store.BlockMap[partition], block)
	}

	return store, manifest, nil
}

// Add adds a single key/value pair to the block store.
func (store *BlockStore) Add(key, value []byte) error {
	partition, _ := KeyPartition(key, store.numPartitions)

	block, ok := store.newBlocks[partition]
	var err error
	if !ok {
		block, err = newBlock(store.path, partition, store.compression, store.blockSize)
		if err != nil {
			return err
		}

		store.newBlocks[partition] = block
	}

	err = block.add(key, value)
	if err != nil {
		return err
	}

	return nil
}

// Save saves flushes any newly created blocks, and writes a manifest file to
// the directory.
func (store *BlockStore) Save(selectedPartitions map[int]bool) error {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	// Flush any buffered blocks.
	for partition, block := range store.newBlocks {
		savedBlock, err := block.save()
		if err != nil {
			return err
		}

		store.Blocks = append(store.Blocks, savedBlock)
		store.BlockMap[partition] = append(store.BlockMap[partition], savedBlock)
	}

	store.newBlocks = make(map[int]*blockWriter)

	// Save the manifest.
	var partitions []int
	partitions = make([]int, 0, len(selectedPartitions))
	for partition := range selectedPartitions {
		partitions = append(partitions, partition)
	}

	manifest := Manifest{
		Version:            manifestVersion,
		Blocks:             make([]BlockManifest, len(store.Blocks)),
		NumPartitions:      store.numPartitions,
		SelectedPartitions: partitions,
	}

	for i, block := range store.Blocks {
		blockManifest := block.manifest()
		manifest.Blocks[i] = blockManifest
	}

	return writeManifest(filepath.Join(store.path, ".manifest"), manifest)
}

// Revert removes any unflushed blocks, and resets the state to when the
// manifest was last saved. If the block store was never saved, then it reverts
// to being empty.
func (store *BlockStore) Revert() {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	for _, block := range store.newBlocks {
		block.close()
		block.delete()
	}

	store.newBlocks = make(map[int]*blockWriter)
	return
}

// Get returns the value for a given key.
func (store *BlockStore) Get(key string) (*Record, error) {
	store.blockMapLock.RLock()
	defer store.blockMapLock.RUnlock()

	partition, alternatePartition := KeyPartition([]byte(key), store.numPartitions)
	if store.BlockMap[partition] == nil && store.BlockMap[alternatePartition] == nil {
		return nil, nil
	}

	keyBytes := []byte(key)
	res, err := store.get(keyBytes, partition)
	if err != nil {
		return nil, err
	}

	// See the comment for alternatePathologicalKeyPartition.
	if res == nil && err == nil && alternatePartition != partition {
		res, err = store.get(keyBytes, alternatePartition)
	}

	return res, err
}

func (store *BlockStore) get(key []byte, partition int) (*Record, error) {

	// There can be multiple blocks for each partition - in that case, we need to
	// check each one sequentially.
	for _, block := range store.BlockMap[partition] {
		res, err := block.Get(key)
		if err != nil {
			return nil, err
		} else if res != nil {
			return res, nil
		}
	}

	return nil, nil
}

// Close closes the BlockStore, and any files it has open.
func (store *BlockStore) Close() {
	store.blockMapLock.Lock()
	defer store.blockMapLock.Unlock()

	for _, block := range store.Blocks {
		block.Close()
	}

	for _, newBlock := range store.newBlocks {
		newBlock.close()
	}
}

// Delete removes any local data the BlockStore has stored.
func (store *BlockStore) Delete() error {
	return os.RemoveAll(store.path)
}
<|endoftext|>


<commit_before>package main

type stack struct {
	data []int
}

func (s *stack) push(n int) {
	s.data = append(s.data, n)
}

func (s *stack) pop() (n int) {
	if len(s.data) != 0 {
		n, s.data = s.data[len(s.data)-1], s.data[0:len(s.data)-1]
	}
	return
}

func (s *stack) add() {
	x, y := s.pop(), s.pop()
	s.push(x + y)
}

func (s *stack) subtract() {
	top, second := s.pop(), s.pop()
	s.push(second - top)
}

func (s *stack) multiply() {
	x, y := s.pop(), s.pop()
	s.push(x * y)
}

func (s *stack) divide() {
	top, second := s.pop(), s.pop()
	if top == 0 {
		// Put them back so this becomes a no-op.
		s.push(second)
		s.push(top)
	} else {
		s.push(second / top)
	}
}

func (s *stack) mod() {
	top, second := s.pop(), s.pop()
	if top != 0 {
		// Put them back so this becomes a no-op.
		s.push(second)
		s.push(top)
	}
	s.push(second % top)
}

func (s *stack) not() {
	top := s.pop()
	if top == 0 {
		s.push(1)
	} else {
		s.push(0)
	}
}

func (s *stack) greater() {
	top, second := s.pop(), s.pop()
	if second > top {
		s.push(1)
	} else {
		s.push(0)
	}
}

func (s *stack) duplicate() {
	if len(s.data) != 0 {
		top := s.data[len(s.data)-1]
		s.data = append(s.data, top)
	}
}

func (s *stack) roll() {
	numRolls, depth := s.pop(), s.pop()
	// TODO
	_, _ = numRolls, depth
}
<commit_msg>Better checking of stack size + panic for roll()<commit_after>package main

type stack struct {
	data []int
}

func (s stack) hasAtLeast1() bool {
	return len(s.data) >= 1
}

func (s stack) hasAtLeast2() bool {
	return len(s.data) >= 2
}

func (s *stack) push(n int) {
	s.data = append(s.data, n)
}

func (s *stack) pop() (n int) {
	if s.hasAtLeast1() {
		n, s.data = s.data[len(s.data)-1], s.data[0:len(s.data)-1]
	}
	return
}

func (s *stack) add() {
	if s.hasAtLeast2() {
		x, y := s.pop(), s.pop()
		s.push(x + y)
	}
}

func (s *stack) subtract() {
	if s.hasAtLeast2() {
		top, second := s.pop(), s.pop()
		s.push(second - top)
	}
}

func (s *stack) multiply() {
	if s.hasAtLeast2() {
		x, y := s.pop(), s.pop()
		s.push(x * y)
	}
}

func (s *stack) divide() {
	if !s.hasAtLeast2() {
		return
	}
	top, second := s.pop(), s.pop()
	if top == 0 {
		// Put them back so this becomes a no-op.
		s.push(second)
		s.push(top)
	} else {
		s.push(second / top)
	}
}

func (s *stack) mod() {
	if !s.hasAtLeast2() {
		return
	}
	top, second := s.pop(), s.pop()
	if top != 0 {
		// Put them back so this becomes a no-op.
		s.push(second)
		s.push(top)
	}
	s.push(second % top)
}

func (s *stack) not() {
	if s.hasAtLeast1() {
		top := s.pop()
		if top == 0 {
			s.push(1)
		} else {
			s.push(0)
		}
	}
}

func (s *stack) greater() {
	if s.hasAtLeast2() {
		top, second := s.pop(), s.pop()
		if second > top {
			s.push(1)
		} else {
			s.push(0)
		}
	}
}

func (s *stack) duplicate() {
	if s.hasAtLeast1() {
		top := s.data[len(s.data)-1]
		s.data = append(s.data, top)
	}
}

func (s *stack) roll() {
	numRolls, depth := s.pop(), s.pop()
	_, _ = numRolls, depth
	panic("Not implemented")
}
<|endoftext|>


<commit_before>package main

type State struct {
	// stuff.
}
<commit_msg>Updated state representation<commit_after>package main

type State struct {
	Reactor
	Systems
	Engines
	Thrusters
	Sensors
}

type Reactor struct {
	Reactant    float64
	Coolant     float64
	PowerOutput float64
	Temperature float64
}

type Systems []*System

type System struct {
	ID         uint32
	Name       string
	State      bool
	PowerLevel float64
}

type Engines struct {
	Left  float64
	Right float64
}

type Thrusters struct {
	ForwardLeft  float64
	ForwardRight float64
	RearLeft     float64
	RearRight    float64
}

type Sensors []*SpaceObject

type SpaceObject struct {
	Type     SpaceObjectType
	Position Point
}

type SpaceObjectType uint8

const (
	SHIP SpaceObjectType = iota
	ASTEROID
)

type Point struct {
	X, Y float64
}
<|endoftext|>


<commit_before>// Copyright 2013 Jari Takkala and Brian Dignan. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"time"
)

type Stats struct {
	Left       int
	Uploaded   int
	Downloaded int
	Errors     int
	peerCh     chan PeerStats
	ticker     <-chan time.Time
}

func NewStats() *Stats {
	return &Stats{
		peerCh: make(chan PeerStats),
		ticker: make(chan time.Time),
	}
}

func (s *Stats) Run() {
	log.Println("Stats : Run : Started")
	defer log.Println("Stats : Run : Stopped")

	s.ticker = time.Tick(time.Second * 1)

	for {
		select {
		case stat := <-s.peerCh:
			s.Downloaded += stat.read
			s.Uploaded += stat.write
			s.Errors += stat.errors
		case <-s.ticker:
			fmt.Printf("\033[31mDownloaded: %d, Uploaded: %d, Errors: %d\033[0m\n", s.Downloaded, s.Uploaded, s.Errors)
		}
	}
}
<commit_msg>Updated stats to print bytes left<commit_after>// Copyright 2013 Jari Takkala and Brian Dignan. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"time"
)

type Stats struct {
	Left       int
	Uploaded   int
	Downloaded int
	Errors     int
	peerCh     chan PeerStats
	ticker     <-chan time.Time
}

func NewStats() *Stats {
	return &Stats{
		peerCh: make(chan PeerStats),
		ticker: make(chan time.Time),
	}
}

func (s *Stats) Run() {
	log.Println("Stats : Run : Started")
	defer log.Println("Stats : Run : Stopped")

	s.ticker = time.Tick(time.Second * 1)

	for {
		select {
		case stat := <-s.peerCh:
			s.Downloaded += stat.read
			s.Uploaded += stat.write
			s.Errors += stat.errors
		case <-s.ticker:
			fmt.Printf("\033[31mDownloaded: %d, Left: %d, Uploaded: %d, Errors: %d\033[0m\n", s.Downloaded, s.Left,s.Uploaded, s.Errors)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

type Stepper struct {
	iperm    Index
	index    Index
	operm    Index
	pattern  Triple
	pred     func(Triple) bool
	fs       []func(Path)
	previous *Stepper
}

type Chants chan []Triple

// We wrap because Otto wants us to.
type Chan struct {
	c Chants
}

type Vertex []byte

type Path []Triple

func (v *Vertex) ToTriple() Triple {
	return Triple{nil, nil, *v, nil}
}

func (g *Graph) Walk(o Vertex, ss []*Stepper) *Chan {
	c := &Chan{make(Chants)}
	go g.Launch(c, o.ToTriple(), ss)
	return c
}

func (g *Graph) Launch(c *Chan, at Triple, ss []*Stepper) {
	g.Step(c, Path{at}, ss)
	(*c).c <- nil
}

func last(ts Path) *Triple {
	t := ts[len(ts)-1]
	return &t
}

func (s *Stepper) exec(path Path) {
	for _, f := range s.fs {
		f(path)
	}
}

func (g *Graph) Step(c *Chan, ts Path, ss []*Stepper) {
	if len(ss) == 0 {
		(*c).c <- ts[1:]
	} else {
		at := last(ts)
		s := ss[0]
		if s.pred != nil {
			if s.pred(*at) {
				s.exec(ts[1:])
				g.Step(c, ts, ss[1:])
			}
		} else {
			u := at.Permute(s.iperm)
			if s.pattern.S != nil {
				u.S = s.pattern.S
			}
			if s.pattern.P != nil {
				u.P = s.pattern.P
			}
			u.O = nil
			i := g.NewIndexIterator(s.index, u, nil)
			for i.Next() {
				t := IndexedTripleFromBytes(s.index, i.Key(), i.Value())
				t = t.Permute(s.index).Permute(s.operm)
				path := append(ts, *t)
				s.exec(path[1:])
				g.Step(c, path, ss[1:])
			}
		}
	}
}

func Out(p []byte) *Stepper {
	return &Stepper{OPS, SPO, SPO, Triple{nil, p, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) Out(p []byte) *Stepper {
	next := Out(p)
	next.previous = s
	return next
}

func AllOut() *Stepper {
	return &Stepper{OPS, SPO, SPO, Triple{nil, nil, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) AllOut() *Stepper {
	next := AllOut()
	next.previous = s
	return next
}

func In(p []byte) *Stepper {
	return &Stepper{OPS, OPS, OPS, Triple{nil, p, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) In(p []byte) *Stepper {
	next := In(p)
	next.previous = s
	return next
}

func AllIn() *Stepper {
	return &Stepper{OPS, OPS, OPS, Triple{nil, nil, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) AllIn() *Stepper {
	next := AllIn()
	next.previous = s
	return next
}

func Has(pred func(Triple) bool) *Stepper {
	return &Stepper{SPO, SPO, SPO, Triple{}, pred, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) Has(pred func(Triple) bool) *Stepper {
	next := Has(pred)
	next.previous = s
	return next
}

// func (s *Stepper) Emitter(f func(Path) interface{}) *Stepper {
// 	replacement := &Stepper{s.iperm, s.index, s.operm, s.pattern, s.pred, f, nil}
// 	replacement.previous = s.previous
// 	return replacement
// }

// func (s *Stepper) Emit() *Stepper {
// 	return s.Emitter(func(ts Path) interface{} { return ts })
// }

func (s *Stepper) Do(f func(Path)) *Stepper {
	s.fs = append(s.fs, f)
	return s
}

func (path *Path) ToString() string {
	acc := "Path:"
	for _, t := range *path {
		acc += fmt.Sprintf(" %v", t.ToString())
	}
	return acc
}

func (s *Stepper) Walk(g *Graph, from Vertex) *Chan {
	at := s
	ss := make([]*Stepper, 0, 1)
	ss = append(ss, at)
	for at.previous != nil {
		ss = append([]*Stepper{at.previous}, ss...)
		at = at.previous
	}
	return g.Walk(from, ss)
}

func (c *Chan) Do(f func(Path)) {
	for {
		x := <-(*c).c
		if x == nil {
			break
		}
		f(x)
	}
	close((*c).c)
}

func (c *Chan) Print() {
	c.Do(func(path Path) { fmt.Printf("path %v\n", path.ToString()) })
}

func (c *Chan) Collect() []Path {
	acc := make([]Path, 0, 0)
	c.Do(func(ts Path) {
		acc = append(acc, ts)
	})
	return acc
}

func StepsTest() {

	g, _ := GetGraph("config.test")

	g.WriteIndexedTriple(TripleFromStrings("a", "p1", "b", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("a", "p1", "f", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("a", "p5", "j", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("b", "p2", "c", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("c", "p3", "d", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("c", "p3", "e", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p4", "c", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p1", "h", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p1", "i", "today"), nil)

	has := func(t Triple) bool {
		return string(t.O) == "i"
	}

	v := Vertex([]byte("a"))
	g.Walk(v, []*Stepper{AllOut()}).Print()

	v = Vertex([]byte("a"))
	g.Walk(v, []*Stepper{
		Out([]byte("p1")),
		Out([]byte("p2")),
		In([]byte("p4")),
		Out([]byte("p1")),
		Has(has)}).Print()

	fmt.Printf("again\n")

	Out([]byte("p1")).
		Out([]byte("p2")).
		In([]byte("p4")).
		Out([]byte("p1")).
		Has(has).
		Walk(g, v).
		Print()

	fmt.Printf("again again\n")

	Out(nil).
		Out([]byte("p2")).
		In([]byte("p4")).
		Out([]byte("p1")).
		Has(has).
		Walk(g, v).
		Print()

	fmt.Printf("map print\n")

	Out(nil).
		Do(func(path Path) { fmt.Printf("doing s %v\n", path.ToString()) }).
		Out([]byte("p2")).
		Do(func(path Path) { fmt.Printf("doing 0 %v\n", path.ToString()) }).
		In([]byte("p4")).
		Do(func(path Path) { fmt.Printf("doing 1 %v\n", path.ToString()) }).
		Out([]byte("p1")).
		Has(func(t Triple) bool { return string(t.O) == "i" }).
		Walk(g, v).
		Do(func(path Path) { fmt.Printf("got %v\n", path.ToString()) })

	fmt.Printf("for repl print\n")

	Out([]byte("p1")).
		Walk(g, v).
		Print()

	fmt.Printf("collected %v\n", Out([]byte("p1")).
		Walk(g, v).
		Collect())
}
<commit_msg>CollectSome.<commit_after>package main

import (
	"fmt"
)

type Stepper struct {
	iperm    Index
	index    Index
	operm    Index
	pattern  Triple
	pred     func(Triple) bool
	fs       []func(Path)
	previous *Stepper
}

type Chants chan []Triple

// We wrap because Otto wants us to.
type Chan struct {
	c Chants
}

type Vertex []byte

type Path []Triple

func (v *Vertex) ToTriple() Triple {
	return Triple{nil, nil, *v, nil}
}

func (g *Graph) Walk(o Vertex, ss []*Stepper) *Chan {
	c := &Chan{make(Chants)}
	go g.Launch(c, o.ToTriple(), ss)
	return c
}

func (g *Graph) Launch(c *Chan, at Triple, ss []*Stepper) {
	g.Step(c, Path{at}, ss)
	(*c).c <- nil
}

func last(ts Path) *Triple {
	t := ts[len(ts)-1]
	return &t
}

func (s *Stepper) exec(path Path) {
	for _, f := range s.fs {
		f(path)
	}
}

func (g *Graph) Step(c *Chan, ts Path, ss []*Stepper) {
	if len(ss) == 0 {
		(*c).c <- ts[1:]
	} else {
		at := last(ts)
		s := ss[0]
		if s.pred != nil {
			if s.pred(*at) {
				s.exec(ts[1:])
				g.Step(c, ts, ss[1:])
			}
		} else {
			u := at.Permute(s.iperm)
			if s.pattern.S != nil {
				u.S = s.pattern.S
			}
			if s.pattern.P != nil {
				u.P = s.pattern.P
			}
			u.O = nil
			i := g.NewIndexIterator(s.index, u, nil)
			for i.Next() {
				t := IndexedTripleFromBytes(s.index, i.Key(), i.Value())
				t = t.Permute(s.index).Permute(s.operm)
				path := append(ts, *t)
				s.exec(path[1:])
				g.Step(c, path, ss[1:])
			}
		}
	}
}

func Out(p []byte) *Stepper {
	return &Stepper{OPS, SPO, SPO, Triple{nil, p, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) Out(p []byte) *Stepper {
	next := Out(p)
	next.previous = s
	return next
}

func AllOut() *Stepper {
	return &Stepper{OPS, SPO, SPO, Triple{nil, nil, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) AllOut() *Stepper {
	next := AllOut()
	next.previous = s
	return next
}

func In(p []byte) *Stepper {
	return &Stepper{OPS, OPS, OPS, Triple{nil, p, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) In(p []byte) *Stepper {
	next := In(p)
	next.previous = s
	return next
}

func AllIn() *Stepper {
	return &Stepper{OPS, OPS, OPS, Triple{nil, nil, nil, nil}, nil, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) AllIn() *Stepper {
	next := AllIn()
	next.previous = s
	return next
}

func Has(pred func(Triple) bool) *Stepper {
	return &Stepper{SPO, SPO, SPO, Triple{}, pred, make([]func(Path), 0, 0), nil}
}

func (s *Stepper) Has(pred func(Triple) bool) *Stepper {
	next := Has(pred)
	next.previous = s
	return next
}

// func (s *Stepper) Emitter(f func(Path) interface{}) *Stepper {
// 	replacement := &Stepper{s.iperm, s.index, s.operm, s.pattern, s.pred, f, nil}
// 	replacement.previous = s.previous
// 	return replacement
// }

// func (s *Stepper) Emit() *Stepper {
// 	return s.Emitter(func(ts Path) interface{} { return ts })
// }

func (s *Stepper) Do(f func(Path)) *Stepper {
	s.fs = append(s.fs, f)
	return s
}

func (path *Path) ToString() string {
	acc := "Path:"
	for _, t := range *path {
		acc += fmt.Sprintf(" %v", t.ToString())
	}
	return acc
}

func (s *Stepper) Walk(g *Graph, from Vertex) *Chan {
	at := s
	ss := make([]*Stepper, 0, 1)
	ss = append(ss, at)
	for at.previous != nil {
		ss = append([]*Stepper{at.previous}, ss...)
		at = at.previous
	}
	return g.Walk(from, ss)
}

func (c *Chan) Do(f func(Path)) {
	for {
		x := <-(*c).c
		if x == nil {
			break
		}
		f(x)
	}
	close((*c).c)
}

func (c *Chan) DoSome(f func(Path), limit int64) {
	n := int64(0)
	for {
		x := <-(*c).c
		if x == nil || n == limit {
			break
		}
		f(x)
	}
	close((*c).c)
}

func (c *Chan) Print() {
	c.Do(func(path Path) { fmt.Printf("path %v\n", path.ToString()) })
}

func (c *Chan) Collect() []Path {
	acc := make([]Path, 0, 0)
	c.Do(func(ts Path) {
		acc = append(acc, ts)
	})
	return acc
}

func (c *Chan) CollectSome(limit int64) []Path {
	acc := make([]Path, 0, 0)
	c.DoSome(func(ts Path) {
		acc = append(acc, ts)
	}, limit)
	return acc
}

func StepsTest() {

	g, _ := GetGraph("config.test")

	g.WriteIndexedTriple(TripleFromStrings("a", "p1", "b", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("a", "p1", "f", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("a", "p5", "j", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("b", "p2", "c", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("c", "p3", "d", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("c", "p3", "e", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p4", "c", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p1", "h", "today"), nil)
	g.WriteIndexedTriple(TripleFromStrings("g", "p1", "i", "today"), nil)

	has := func(t Triple) bool {
		return string(t.O) == "i"
	}

	v := Vertex([]byte("a"))
	g.Walk(v, []*Stepper{AllOut()}).Print()

	v = Vertex([]byte("a"))
	g.Walk(v, []*Stepper{
		Out([]byte("p1")),
		Out([]byte("p2")),
		In([]byte("p4")),
		Out([]byte("p1")),
		Has(has)}).Print()

	fmt.Printf("again\n")

	Out([]byte("p1")).
		Out([]byte("p2")).
		In([]byte("p4")).
		Out([]byte("p1")).
		Has(has).
		Walk(g, v).
		Print()

	fmt.Printf("again again\n")

	Out(nil).
		Out([]byte("p2")).
		In([]byte("p4")).
		Out([]byte("p1")).
		Has(has).
		Walk(g, v).
		Print()

	fmt.Printf("map print\n")

	Out(nil).
		Do(func(path Path) { fmt.Printf("doing s %v\n", path.ToString()) }).
		Out([]byte("p2")).
		Do(func(path Path) { fmt.Printf("doing 0 %v\n", path.ToString()) }).
		In([]byte("p4")).
		Do(func(path Path) { fmt.Printf("doing 1 %v\n", path.ToString()) }).
		Out([]byte("p1")).
		Has(func(t Triple) bool { return string(t.O) == "i" }).
		Walk(g, v).
		Do(func(path Path) { fmt.Printf("got %v\n", path.ToString()) })

	fmt.Printf("for repl print\n")

	Out([]byte("p1")).
		Walk(g, v).
		Print()

	fmt.Printf("collected %v\n", Out([]byte("p1")).
		Walk(g, v).
		Collect())
}
<|endoftext|>


<commit_before>// Package store automatically configures a database to store structured information in an sql database
package store

import (
	"database/sql"
	"errors"
	"reflect"
	"strings"
	"sync"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

type field struct {
	isStruct bool
	pos      int
	name     string
}

type typeInfo struct {
	primary    int
	fields     []field
	statements []*sql.Stmt
}

type Store struct {
	db    *sql.DB
	types map[string]typeInfo
	mutex sync.Mutex
}

func New(driverName, dataSourceName string) (*Store, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:    db,
		types: make(map[string]typeInfo),
	}, nil
}

func (s *Store) Close() error {
	err := s.db.Close()
	s.db = nil
	return err
}

func isPointerStruct(i interface{}) bool {
	t := reflect.TypeOf(i)
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}

func (s *Store) Register(i interface{}) error {
	if s.db == nil {
		return DBClosed
	} else if !isPointerStruct(i) {
		return NoPointerStruct
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.defineType(i)
}

func (s *Store) defineType(i interface{}) error {
	name := typeName(i)
	if _, ok := s.types[name]; ok {
		return nil
	}

	s.types[name] = typeInfo{}

	v := reflect.ValueOf(i).Elem()
	numFields := v.Type().NumField()
	fields := make([]field, 0, numFields)
	id := 0
	idType := 0

	for n := 0; n < numFields; n++ {
		f := v.Type().Field(n)
		if f.PkgPath != "" { // not exported
			continue
		}
		fieldName := f.Name
		if fn := f.Tag.Get("store"); fn != "" {
			fieldName = fn
		}
		if fieldName == "-" { // Skip field
			continue
		}
		tmp := strings.ToLower(fieldName)
		for _, tf := range fields {
			if strings.ToLower(tf.name) == tmp {
				return DuplicateColumn
			}
		}
		isPointer := f.Type.Kind() == reflect.Ptr
		var iface interface{}
		if isPointer {
			iface = v.Field(n).Interface()
		} else {
			iface = v.Field(n).Addr().Interface()
		}
		isStruct := false
		if isPointerStruct(iface) {
			s.defineType(iface)
			isStruct = true
		} else if !isValidType(iface) {
			continue
		}
		if isValidKeyType(iface) {
			if idType < 3 && f.Tag.Get("key") == "1" {
				idType = 3
				id = len(fields)
			} else if idType < 2 && strings.ToLower(fieldName) == "id" {
				idType = 2
				id = len(fields)
			} else if idType < 1 {
				idType = 1
				id = len(fields)
			}
		}
		fields = append(fields, field{
			isStruct,
			n,
			fieldName,
		})
	}
	if idType == 0 {
		return NoKey
	}
	s.types[name] = typeInfo{
		primary: id,
	}

	// create statements
	var (
		sqlVars, sqlParams, setSQLParams, tableVars string
		doneFirst, doneFirstNonKey                  bool
	)

	for pos, f := range fields {
		if doneFirst {
			tableVars += ", "
		} else {
			doneFirst = true
		}
		if pos != id {
			if doneFirstNonKey {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			} else {
				doneFirstNonKey = true
			}
		}
		var varType string
		if f.isStruct {
			varType = "INTEGER"
		} else {
			varType = getType(i, f.pos)
		}
		tableVars += "[" + f.name + "] " + varType
		if pos == id {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + f.name + "]"
			setSQLParams += "[" + f.name + "] = ?"
			sqlParams += "?"
		}
	}

	statements := make([]*sql.Stmt, 6)

	sql := "CREATE TABLE IF NOT EXISTS [" + name + "](" + tableVars + ");"
	_, err := s.db.Exec(sql)
	if err != nil {
		return err
	}

	sql = "INSERT INTO [" + name + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[add] = stmt

	sql = "SELECT " + sqlVars + " FROM [" + name + "] WHERE [" + fields[id].name + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[get] = stmt

	sql = "UPDATE [" + name + "] SET " + setSQLParams + " WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[update] = stmt

	sql = "DELETE FROM [" + name + "] WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[remove] = stmt

	sql = "SELECT " + sqlVars + ", [" + fields[id].name + "] FROM [" + name + "] ORDER BY [" + fields[id].name + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[getPage] = stmt

	sql = "SELECT COUNT(1) FROM [" + name + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[count] = stmt

	s.types[name] = typeInfo{
		primary:    id,
		fields:     fields,
		statements: statements,
	}
	return nil
}

func (s *Store) Set(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	var toSet []interface{}
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		toSet = toSet[:0]
		err := s.Set(i, &t, &toSet)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) set(i interface{}, t *typeInfo, toSet *[]interface{}) error {
	for _, oi := range *toSet {
		if oi == i {
			return nil
		}
	}
	(*toSet) = append(*toSet, i)
	id := t.GetID(i)
	isUpdate := id != 0
	vars := make([]interface{}, 0, len(t.fields))
	for pos, f := range t.fields {
		if pos == t.primary {
			continue
		}
		if f.isStruct {
			ni := getFieldPointer(i, f.pos)
			nt := s.types[typeName(ni)]
			err := s.Set(ni, &nt, toSet)
			if err != nil {
				return err
			}
			vars = append(vars, getField(ni, nt.fields[nt.primary].pos))
		} else {
			vars = append(vars, getField(i, f.pos))
		}
	}
	if isUpdate {
		vars = append(vars, id)
		_, err := t.statements[update].Exec(vars...)
		return err
	}
	r, err := t.statements[add].Exec(vars...)
	if err != nil {
		return err
	}
	lid, err := r.LastInsertId()
	if err != nil {
		return err
	}
	t.SetID(i, lid)
	return nil
}

func (s *Store) Get(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.get(is...)
}
func (s *Store) get(is ...interface{}) error {
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		id := t.GetID(i)
		if id == 0 {
			continue
		}
		vars := make([]interface{}, 0, len(t.fields))
		var toGet []interface{}
		for pos, f := range t.fields {
			if pos == t.primary {
				continue
			}
			if f.isStruct {
				ni := getFieldPointer(i, f.pos)
				nt := s.types[typeName(ni)]
				toGet = append(toGet, ni)
				vars = append(vars, getFieldPointer(ni, nt.fields[nt.primary].pos))
			} else {
				vars = append(vars, getFieldPointer(i, f.pos))
			}
		}
		row := t.statements[get].QueryRow(id)
		err := row.Scan(vars...)
		if err != nil {
			return err
		}
		if len(toGet) > 0 {
			if err = s.get(toGet...); err != nil {
				return err
			}
		}
	}
	return nil
}

func (s *Store) Remove(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		_, err := t.statements[remove].Exec(t.GetID(i))
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) Count(i interface{}) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if !isPointerStruct(i) {
		return 0, NoPointerStruct
	}
	name := typeName(i)
	stmt := s.types[name].statements[count]
	res, err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = res.Scan(&num)
	return num, err
}

// Errors

var (
	DBClosed         = errors.New("database already closed")
	NoPointerStruct  = errors.New("given variable is not a pointer to a struct")
	NoKey            = errors.New("could not determine key")
	DuplicateColumn  = errors.New("duplicate column name found")
	UnregisteredType = errors.New("type not registered")
)
<commit_msg>Added initial GetPage implementation<commit_after>// Package store automatically configures a database to store structured information in an sql database
package store

import (
	"database/sql"
	"errors"
	"reflect"
	"strings"
	"sync"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

type field struct {
	isStruct bool
	pos      int
	name     string
}

type typeInfo struct {
	primary    int
	fields     []field
	statements []*sql.Stmt
}

type Store struct {
	db    *sql.DB
	types map[string]typeInfo
	mutex sync.Mutex
}

func New(driverName, dataSourceName string) (*Store, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:    db,
		types: make(map[string]typeInfo),
	}, nil
}

func (s *Store) Close() error {
	err := s.db.Close()
	s.db = nil
	return err
}

func isPointerStruct(i interface{}) bool {
	t := reflect.TypeOf(i)
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}

func (s *Store) Register(i interface{}) error {
	if s.db == nil {
		return DBClosed
	} else if !isPointerStruct(i) {
		return NoPointerStruct
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.defineType(i)
}

func (s *Store) defineType(i interface{}) error {
	name := typeName(i)
	if _, ok := s.types[name]; ok {
		return nil
	}

	s.types[name] = typeInfo{}

	v := reflect.ValueOf(i).Elem()
	numFields := v.Type().NumField()
	fields := make([]field, 0, numFields)
	id := 0
	idType := 0

	for n := 0; n < numFields; n++ {
		f := v.Type().Field(n)
		if f.PkgPath != "" { // not exported
			continue
		}
		fieldName := f.Name
		if fn := f.Tag.Get("store"); fn != "" {
			fieldName = fn
		}
		if fieldName == "-" { // Skip field
			continue
		}
		tmp := strings.ToLower(fieldName)
		for _, tf := range fields {
			if strings.ToLower(tf.name) == tmp {
				return DuplicateColumn
			}
		}
		isPointer := f.Type.Kind() == reflect.Ptr
		var iface interface{}
		if isPointer {
			iface = v.Field(n).Interface()
		} else {
			iface = v.Field(n).Addr().Interface()
		}
		isStruct := false
		if isPointerStruct(iface) {
			s.defineType(iface)
			isStruct = true
		} else if !isValidType(iface) {
			continue
		}
		if isValidKeyType(iface) {
			if idType < 3 && f.Tag.Get("key") == "1" {
				idType = 3
				id = len(fields)
			} else if idType < 2 && strings.ToLower(fieldName) == "id" {
				idType = 2
				id = len(fields)
			} else if idType < 1 {
				idType = 1
				id = len(fields)
			}
		}
		fields = append(fields, field{
			isStruct,
			n,
			fieldName,
		})
	}
	if idType == 0 {
		return NoKey
	}
	s.types[name] = typeInfo{
		primary: id,
	}

	// create statements
	var (
		sqlVars, sqlParams, setSQLParams, tableVars string
		doneFirst, doneFirstNonKey                  bool
	)

	for pos, f := range fields {
		if doneFirst {
			tableVars += ", "
		} else {
			doneFirst = true
		}
		if pos != id {
			if doneFirstNonKey {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			} else {
				doneFirstNonKey = true
			}
		}
		var varType string
		if f.isStruct {
			varType = "INTEGER"
		} else {
			varType = getType(i, f.pos)
		}
		tableVars += "[" + f.name + "] " + varType
		if pos == id {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + f.name + "]"
			setSQLParams += "[" + f.name + "] = ?"
			sqlParams += "?"
		}
	}

	statements := make([]*sql.Stmt, 6)

	sql := "CREATE TABLE IF NOT EXISTS [" + name + "](" + tableVars + ");"
	_, err := s.db.Exec(sql)
	if err != nil {
		return err
	}

	sql = "INSERT INTO [" + name + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[add] = stmt

	sql = "SELECT " + sqlVars + " FROM [" + name + "] WHERE [" + fields[id].name + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[get] = stmt

	sql = "UPDATE [" + name + "] SET " + setSQLParams + " WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[update] = stmt

	sql = "DELETE FROM [" + name + "] WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[remove] = stmt

	sql = "SELECT [" + fields[id].name + "] FROM [" + name + "] ORDER BY [" + fields[id].name + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[getPage] = stmt

	sql = "SELECT COUNT(1) FROM [" + name + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[count] = stmt

	s.types[name] = typeInfo{
		primary:    id,
		fields:     fields,
		statements: statements,
	}
	return nil
}

func (s *Store) Set(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	var toSet []interface{}
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		toSet = toSet[:0]
		err := s.Set(i, &t, &toSet)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) set(i interface{}, t *typeInfo, toSet *[]interface{}) error {
	for _, oi := range *toSet {
		if oi == i {
			return nil
		}
	}
	(*toSet) = append(*toSet, i)
	id := t.GetID(i)
	isUpdate := id != 0
	vars := make([]interface{}, 0, len(t.fields))
	for pos, f := range t.fields {
		if pos == t.primary {
			continue
		}
		if f.isStruct {
			ni := getFieldPointer(i, f.pos)
			nt := s.types[typeName(ni)]
			err := s.Set(ni, &nt, toSet)
			if err != nil {
				return err
			}
			vars = append(vars, getField(ni, nt.fields[nt.primary].pos))
		} else {
			vars = append(vars, getField(i, f.pos))
		}
	}
	if isUpdate {
		vars = append(vars, id)
		_, err := t.statements[update].Exec(vars...)
		return err
	}
	r, err := t.statements[add].Exec(vars...)
	if err != nil {
		return err
	}
	lid, err := r.LastInsertId()
	if err != nil {
		return err
	}
	t.SetID(i, lid)
	return nil
}

func (s *Store) Get(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.get(is...)
}
func (s *Store) get(is ...interface{}) error {
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		id := t.GetID(i)
		if id == 0 {
			continue
		}
		vars := make([]interface{}, 0, len(t.fields)-1)
		var toGet []interface{}
		for pos, f := range t.fields {
			if pos == t.primary {
				continue
			}
			if f.isStruct {
				ni := getFieldPointer(i, f.pos)
				nt := s.types[typeName(ni)]
				toGet = append(toGet, ni)
				vars = append(vars, getFieldPointer(ni, nt.fields[nt.primary].pos))
			} else {
				vars = append(vars, getFieldPointer(i, f.pos))
			}
		}
		row := t.statements[get].QueryRow(id)
		err := row.Scan(vars...)
		if err == sql.ErrNoRows {
			t.SetID(i, 0)
		} else if err != nil {
			return err
		}
		if len(toGet) > 0 {
			if err = s.get(toGet...); err != nil {
				return err
			}
		}
	}
	return nil
}

func (s *Store) GetPage(is []interface{}, offset int) (int, error) {
	if len(is) == 0 {
		return 0, nil
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	t := s.types[typeName(is[0])]
	rows, err := t.statements[getPage].Query(len(data), offset)
	if err != nil {
		return 0, err
	}
	defer rows.Close()
	var toGet []interface{}
	n := 0
	for rows.Next() {
		var id int64
		if err := rows.Scan(&id); err != nil {
			return 0, err
		}
		t.SetID(is[n], id)
		n++
	}
	is = is[:n]
	if err := rows.Err(); err == sql.ErrNoRows {
		return 0, nil
	} else if err != nil {
		return 0, err
	} else if err = s.get(is...); err != nil {
		return 0, err
	}
	return n, nil
}

func (s *Store) Remove(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		_, err := t.statements[remove].Exec(t.GetID(i))
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) Count(i interface{}) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if !isPointerStruct(i) {
		return 0, NoPointerStruct
	}
	name := typeName(i)
	stmt := s.types[name].statements[count]
	res, err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = res.Scan(&num)
	return num, err
}

// Errors

var (
	DBClosed         = errors.New("database already closed")
	NoPointerStruct  = errors.New("given variable is not a pointer to a struct")
	NoKey            = errors.New("could not determine key")
	DuplicateColumn  = errors.New("duplicate column name found")
	UnregisteredType = errors.New("type not registered")
)
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/HearthSim/stove/bnet"
	"github.com/HearthSim/stove/pegasus"
	_ "github.com/mattn/go-sqlite3"
	"strings"
)

const (
	CONN_DEFAULT_HOST = "localhost"
	CONN_DEFAULT_PORT = 1119
)

func main() {
	addr := fmt.Sprintf("%s:%d", CONN_DEFAULT_HOST, CONN_DEFAULT_PORT)
	flag.StringVar(&addr, "bind", addr, "The address to run on")
	runMigrate := flag.Bool("migrate", false, "Perform a database migration and exit")
	flag.Parse()

	if !strings.Contains(addr, ":") {
		addr = fmt.Sprintf("%s:%d", addr, CONN_DEFAULT_PORT)
	}

	if *runMigrate {
		fmt.Printf("Performing database migration\n")
		pegasus.Migrate()
		return
	}

	serv := bnet.NewServer()
	serv.RegisterGameServer("WTCG", pegasus.NewServer(serv))

	fmt.Printf("Listening on %s ...\n", addr)
	err := serv.ListenAndServe(addr)
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>Add pprof server and gom support<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/HearthSim/stove/bnet"
	"github.com/HearthSim/stove/pegasus"
	_ "github.com/rakyll/gom/http"
	"net/http"
	"strings"
)

const (
	CONN_DEFAULT_HOST = "localhost"
	CONN_DEFAULT_PORT = 1119
)

func main() {
	addr := fmt.Sprintf("%s:%d", CONN_DEFAULT_HOST, CONN_DEFAULT_PORT)
	flag.StringVar(&addr, "bind", addr, "The address to run on")
	runMigrate := flag.Bool("migrate", false, "Perform a database migration and exit")
	flag.Parse()

	if !strings.Contains(addr, ":") {
		addr = fmt.Sprintf("%s:%d", addr, CONN_DEFAULT_PORT)
	}

	if *runMigrate {
		fmt.Printf("Performing database migration\n")
		pegasus.Migrate()
		return
	}

	go func() {
		httpAddr := "localhost:6060"
		fmt.Printf("Debug http server listening on %s ...\n", httpAddr)
		fmt.Println(http.ListenAndServe(httpAddr, nil))
	}()

	serv := bnet.NewServer()
	serv.RegisterGameServer("WTCG", pegasus.NewServer(serv))

	fmt.Printf("Listening on %s ...\n", addr)
	err := serv.ListenAndServe(addr)
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package termtable

import (
	"bytes"
	"math"
	"strings"
)

type Table struct {
	Rows    [][]string
	Columns [][]string
	Options *TableOptions

	HasHeader bool

	numColumns   int
	columnsWidth []int
}

type TableOptions struct {
	Padding      int
	UseSeparator bool
}

var defaultTableOptions = &TableOptions{
	Padding:      1,
	UseSeparator: false,
}

func NewTable(rows [][]string, options *TableOptions) *Table {
	t := &Table{
		Options: options,
	}
	if t.Options == nil {
		t.Options = defaultTableOptions
	}
	if rows != nil {
		t.Rows = rows
		t.computeProperties()
	}
	return t
}

func (t *Table) SetHeader(header []string) {
	t.HasHeader = true
	// There is a better way to do this
	t.Rows = append([][]string{header}, t.Rows...)
	t.computeProperties()
}

func (t *Table) AddRow(row []string) {
	t.Rows = append(t.Rows, row)
	t.computeProperties()
}

func (t *Table) computeProperties() {
	if len(t.Rows) > 0 {
		t.numColumns = len(t.Rows[0])
		t.columnsWidth = make([]int, t.numColumns)
		t.recalculate()
	}
}

func (t *Table) recalculate() {
	t.Columns = [][]string{}
	for i := 0; i < t.numColumns; i++ {
		t.Columns = append(t.Columns, []string{})
	}
	for _, row := range t.Rows {
		for j, cellContent := range row {
			t.Columns[j] = append(t.Columns[j], cellContent)
			t.columnsWidth[j] = int(math.Max(float64(len(cellContent)), float64(t.columnsWidth[j])))
		}
	}
}

func (t *Table) Render() string {
	// allocate a 1k byte buffer
	bb := make([]byte, 0, 1024)
	buf := bytes.NewBuffer(bb)

	i := 0

	if t.HasHeader {
		if t.Options.UseSeparator {
			buf.WriteString(t.separatorLine())
			buf.WriteRune('\n')
		}
		for j := range t.Rows[0] {
			buf.WriteString(t.getCell(i, j))
		}
		i = 1
		buf.WriteRune('\n')
	}

	if t.Options.UseSeparator {
		buf.WriteString(t.separatorLine())
		buf.WriteRune('\n')
	}

	for i < len(t.Rows) {
		row := t.Rows[i]
		for j := range row {
			buf.WriteString(t.getCell(i, j))
		}
		if i < len(t.Rows)-1 {
			buf.WriteRune('\n')
		}
		i++
	}

	if t.Options.UseSeparator {
		buf.WriteRune('\n')
		buf.WriteString(t.separatorLine())
	}

	return buf.String()
}

func (t *Table) separatorLine() string {
	sep := "+"
	for _, w := range t.columnsWidth {
		sep += strings.Repeat("-", w+2*t.Options.Padding)
		sep += "+"
	}
	return sep
}

func (t *Table) getCell(row, col int) string {
	cellContent := t.Rows[row][col]
	spacePadding := strings.Repeat(" ", t.Options.Padding)

	var cellStr string

	if t.Options.UseSeparator {
		cellStr += "|"
		cellStr += spacePadding
	}

	cellStr += cellContent
	cellStr += strings.Repeat(" ", t.columnsWidth[col]-len(cellContent))
	cellStr += spacePadding

	if t.Options.UseSeparator {
		if col == t.numColumns-1 {
			cellStr += "|"
		}
	}

	return cellStr
}
<commit_msg>correct column with when the content has asni colors<commit_after>package termtable

import (
	"bytes"
	"math"
	"regexp"
	"strings"
)

var ansiRegexp = regexp.MustCompile("\x1b[^m]*m")

type Table struct {
	Rows    [][]string
	Columns [][]string
	Options *TableOptions

	HasHeader bool

	numColumns   int
	columnsWidth []int
}

type TableOptions struct {
	Padding      int
	UseSeparator bool
}

var defaultTableOptions = &TableOptions{
	Padding:      1,
	UseSeparator: false,
}

func NewTable(rows [][]string, options *TableOptions) *Table {
	t := &Table{
		Options: options,
	}
	if t.Options == nil {
		t.Options = defaultTableOptions
	}
	if rows != nil {
		t.Rows = rows
		t.computeProperties()
	}
	return t
}

func (t *Table) SetHeader(header []string) {
	t.HasHeader = true
	// There is a better way to do this
	t.Rows = append([][]string{header}, t.Rows...)
	t.computeProperties()
}

func (t *Table) AddRow(row []string) {
	t.Rows = append(t.Rows, row)
	t.computeProperties()
}

func (t *Table) computeProperties() {
	if len(t.Rows) > 0 {
		t.numColumns = len(t.Rows[0])
		t.columnsWidth = make([]int, t.numColumns)
		t.recalculate()
	}
}

func (t *Table) recalculate() {
	t.Columns = [][]string{}
	for i := 0; i < t.numColumns; i++ {
		t.Columns = append(t.Columns, []string{})
	}
	for _, row := range t.Rows {
		for j, cellContent := range row {
			t.Columns[j] = append(t.Columns[j], cellContent)
			t.columnsWidth[j] = int(math.Max(float64(visibleLen(cellContent)), float64(t.columnsWidth[j])))
		}
	}
}

func (t *Table) Render() string {
	// allocate a 1k byte buffer
	bb := make([]byte, 0, 1024)
	buf := bytes.NewBuffer(bb)

	i := 0

	if t.HasHeader {
		if t.Options.UseSeparator {
			buf.WriteString(t.separatorLine())
			buf.WriteRune('\n')
		}
		for j := range t.Rows[0] {
			buf.WriteString(t.getCell(i, j))
		}
		i = 1
		buf.WriteRune('\n')
	}

	if t.Options.UseSeparator {
		buf.WriteString(t.separatorLine())
		buf.WriteRune('\n')
	}

	for i < len(t.Rows) {
		row := t.Rows[i]
		for j := range row {
			buf.WriteString(t.getCell(i, j))
		}
		if i < len(t.Rows)-1 {
			buf.WriteRune('\n')
		}
		i++
	}

	if t.Options.UseSeparator {
		buf.WriteRune('\n')
		buf.WriteString(t.separatorLine())
	}

	return buf.String()
}

func (t *Table) separatorLine() string {
	sep := "+"
	for _, w := range t.columnsWidth {
		sep += strings.Repeat("-", w+2*t.Options.Padding)
		sep += "+"
	}
	return sep
}

func (t *Table) getCell(row, col int) string {
	cellContent := t.Rows[row][col]
	spacePadding := strings.Repeat(" ", t.Options.Padding)

	var cellStr string

	if t.Options.UseSeparator {
		cellStr += "|"
		cellStr += spacePadding
	}

	cellStr += cellContent
	cellStr += strings.Repeat(" ", t.columnsWidth[col]-visibleLen(cellContent))
	cellStr += spacePadding

	if t.Options.UseSeparator {
		if col == t.numColumns-1 {
			cellStr += "|"
		}
	}

	return cellStr
}

func visibleLen(s string) int {
	return len(ansiRegexp.ReplaceAllLiteralString(s, ""))
}
<|endoftext|>