<commit_before>package lorawan

import (
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
)

// DevAddr represents the device address.
type DevAddr [4]byte

// NetIDType returns the NetID type of the DevAddr.
func (a DevAddr) NetIDType() int {
	for i := 7; i >= 0; i-- {
		if a[0]&(1<<byte(i)) == 0 {
			return 7 - i
		}
	}
	panic("NetIDType bug!")
}

// NwkID returns the NwkID bits of the DevAddr.
func (a DevAddr) NwkID() []byte {
	switch a.NetIDType() {
	case 0:
		return a.getNwkID(1, 6)
	case 1:
		return a.getNwkID(2, 6)
	case 2:
		return a.getNwkID(3, 9)
	case 3:
		return a.getNwkID(4, 11)
	case 4:
		return a.getNwkID(5, 12)
	case 5:
		return a.getNwkID(6, 13)
	case 6:
		return a.getNwkID(7, 15)
	case 7:
		return a.getNwkID(8, 17)
	default:
		return nil
	}
}

// SetAddrPrefix sets the NetID based AddrPrefix.
func (a *DevAddr) SetAddrPrefix(netID NetID) {
	switch netID.Type() {
	case 0:
		a.setAddrPrefix(1, 6, netID)
	case 1:
		a.setAddrPrefix(2, 6, netID)
	case 2:
		a.setAddrPrefix(3, 9, netID)
	case 3:
		a.setAddrPrefix(4, 11, netID)
	case 4:
		a.setAddrPrefix(5, 12, netID)
	case 5:
		a.setAddrPrefix(6, 13, netID)
	case 6:
		a.setAddrPrefix(7, 15, netID)
	case 7:
		a.setAddrPrefix(8, 17, netID)
	}
}

// IsNetID returns a bool indicating if the NwkID matches the given NetID.
func (a DevAddr) IsNetID(netID NetID) bool {
	tempDevAddr := a
	tempDevAddr.SetAddrPrefix(netID)

	if a == tempDevAddr {
		return true
	}

	return false
}

func (a *DevAddr) setAddrPrefix(prefixLength, nwkIDBits int, netID NetID) {
	// convert DevAddr to uint32
	devAddr := binary.BigEndian.Uint32(a[:])

	// clear the bits for the prefix and NwkID
	var mask uint32
	mask-- // sets all uint32 bits to 1
	devAddr &^= mask << uint32(32-prefixLength-nwkIDBits)

	// set the type prefix
	prefix := uint32(254) << uint32(32-prefixLength)
	devAddr |= prefix

	// set the nwkID
	nwkIDBytes := make([]byte, 4)
	id := netID.ID()
	copy(nwkIDBytes[len(nwkIDBytes)-len(id):], id)

	nwkID := binary.BigEndian.Uint32(nwkIDBytes)
	nwkID = nwkID << uint32(32-nwkIDBits) // truncate the MSB of the NetID ID field
	nwkID = nwkID >> uint32(prefixLength) // shift back for the prefix MSB
	devAddr |= nwkID

	binary.BigEndian.PutUint32(a[:], devAddr)
}

func (a DevAddr) getNwkID(prefixLength, nwkIDBits int) []byte {
	// convert DevAddr to uint32
	temp := binary.BigEndian.Uint32(a[:])

	// clear prefix
	temp = temp << uint32(prefixLength)

	// shift to starting of NwkID
	temp = temp >> (32 - uint32(nwkIDBits))

	// back to bytes
	out := make([]byte, 4)
	binary.BigEndian.PutUint32(out, temp)

	bLen := nwkIDBits / 8
	if nwkIDBits%8 != 0 {
		bLen++
	}

	return out[len(out)-bLen:]
}

// MarshalBinary marshals the object in binary form.
func (a DevAddr) MarshalBinary() ([]byte, error) {
	out := make([]byte, len(a))
	for i, v := range a {
		// little endian
		out[len(a)-i-1] = v
	}
	return out, nil
}

// UnmarshalBinary decodes the object from binary form.
func (a *DevAddr) UnmarshalBinary(data []byte) error {
	if len(data) != len(a) {
		return fmt.Errorf("lorawan: %d bytes of data are expected", len(a))
	}
	for i, v := range data {
		// little endian
		a[len(a)-i-1] = v
	}
	return nil
}

// MarshalText implements encoding.TextMarshaler.
func (a DevAddr) MarshalText() ([]byte, error) {
	return []byte(a.String()), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.
func (a *DevAddr) UnmarshalText(text []byte) error {
	b, err := hex.DecodeString(string(text))
	if err != nil {
		return err
	}

	if len(b) != len(a) {
		return fmt.Errorf("lorawan: exactly %d bytes are expected", len(a))
	}
	copy(a[:], b)
	return nil
}

// String implements fmt.Stringer.
func (a DevAddr) String() string {
	return hex.EncodeToString(a[:])
}

// Scan implements sql.Scanner.
func (a *DevAddr) Scan(src interface{}) error {
	b, ok := src.([]byte)
	if !ok {
		return errors.New("lorawan: []byte type expected")
	}
	if len(b) != len(a) {
		return fmt.Errorf("lorawan []byte must have length %d", len(a))
	}
	copy(a[:], b)
	return nil
}

// FCtrl represents the FCtrl (frame control) field.
// Please note that the FPending and ClassB are mapped to the same bit. This
// means that when unmarshaling from a byte-slice, both fields will contain
// the same value (either true or false).
type FCtrl struct {
	ADR       bool  `json:"adr"`
	ADRACKReq bool  `json:"adrAckReq"`
	ACK       bool  `json:"ack"`
	FPending  bool  `json:"fPending"` // only used for downlink messages
	ClassB    bool  `json:"classB"`   // only used for uplink messages
	fOptsLen  uint8 // will be set automatically by the FHDR when serialized to []byte
}

// MarshalBinary marshals the object in binary form.
func (c FCtrl) MarshalBinary() ([]byte, error) {
	if c.fOptsLen > 15 {
		return []byte{}, errors.New("lorawan: max value of FOptsLen is 15")
	}

	var b byte
	if c.ADR {
		b |= 0x80
	}
	if c.ADRACKReq {
		b |= 0x40
	}
	if c.ACK {
		b |= 0x20
	}
	if c.ClassB || c.FPending {
		b |= 0x10
	}
	b |= byte(c.fOptsLen) & 0x0f

	return []byte{b}, nil
}

// UnmarshalBinary decodes the object from binary form.
func (c *FCtrl) UnmarshalBinary(data []byte) error {
	if len(data) != 1 {
		return errors.New("lorawan: 1 byte of data is expected")
	}

	c.ADR = data[0]&0x80 != 0
	c.ADRACKReq = data[0]&0x40 != 0
	c.ACK = data[0]&0x20 != 0
	c.ClassB = data[0]&0x10 != 0
	c.FPending = data[0]&0x10 != 0
	c.fOptsLen = data[0] & 0x0f

	return nil
}

// FHDR represents the frame header.
type FHDR struct {
	DevAddr DevAddr   `json:"devAddr"`
	FCtrl   FCtrl     `json:"fCtrl"`
	FCnt    uint32    `json:"fCnt"`  // only the least-significant 16 bits will be marshalled
	FOpts   []Payload `json:"fOpts"` // max. number of allowed bytes is 15
}

// MarshalBinary marshals the object in binary form.
func (h FHDR) MarshalBinary() ([]byte, error) {
	var b []byte
	var err error
	var opts []byte

	for _, mac := range h.FOpts {
		b, err = mac.MarshalBinary()
		if err != nil {
			return []byte{}, err
		}
		opts = append(opts, b...)
	}
	h.FCtrl.fOptsLen = uint8(len(opts))
	if h.FCtrl.fOptsLen > 15 {
		return []byte{}, errors.New("lorawan: max number of FOpts bytes is 15")
	}

	out := make([]byte, 0, 7+h.FCtrl.fOptsLen)
	b, err = h.DevAddr.MarshalBinary()
	if err != nil {
		return []byte{}, err
	}
	out = append(out, b...)

	b, err = h.FCtrl.MarshalBinary()
	if err != nil {
		return []byte{}, err
	}
	out = append(out, b...)
	fCntBytes := make([]byte, 4)
	binary.LittleEndian.PutUint32(fCntBytes, h.FCnt)
	out = append(out, fCntBytes[0:2]...)
	out = append(out, opts...)

	return out, nil
}

// UnmarshalBinary decodes the object from binary form.
func (h *FHDR) UnmarshalBinary(uplink bool, data []byte) error {
	if len(data) < 7 {
		return errors.New("lorawan: at least 7 bytes are expected")
	}

	if err := h.DevAddr.UnmarshalBinary(data[0:4]); err != nil {
		return err
	}
	if err := h.FCtrl.UnmarshalBinary(data[4:5]); err != nil {
		return err
	}
	fCntBytes := make([]byte, 4)
	copy(fCntBytes, data[5:7])
	h.FCnt = binary.LittleEndian.Uint32(fCntBytes)

	if len(data) > 7 {
		h.FOpts = []Payload{
			&DataPayload{Bytes: data[7:]},
		}
	}

	return nil
}
<commit_msg>Implements driver.Valuer for DevAddr. (#48)<commit_after>package lorawan

import (
	"database/sql/driver"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
)

// DevAddr represents the device address.
type DevAddr [4]byte

// NetIDType returns the NetID type of the DevAddr.
func (a DevAddr) NetIDType() int {
	for i := 7; i >= 0; i-- {
		if a[0]&(1<<byte(i)) == 0 {
			return 7 - i
		}
	}
	panic("NetIDType bug!")
}

// NwkID returns the NwkID bits of the DevAddr.
func (a DevAddr) NwkID() []byte {
	switch a.NetIDType() {
	case 0:
		return a.getNwkID(1, 6)
	case 1:
		return a.getNwkID(2, 6)
	case 2:
		return a.getNwkID(3, 9)
	case 3:
		return a.getNwkID(4, 11)
	case 4:
		return a.getNwkID(5, 12)
	case 5:
		return a.getNwkID(6, 13)
	case 6:
		return a.getNwkID(7, 15)
	case 7:
		return a.getNwkID(8, 17)
	default:
		return nil
	}
}

// SetAddrPrefix sets the NetID based AddrPrefix.
func (a *DevAddr) SetAddrPrefix(netID NetID) {
	switch netID.Type() {
	case 0:
		a.setAddrPrefix(1, 6, netID)
	case 1:
		a.setAddrPrefix(2, 6, netID)
	case 2:
		a.setAddrPrefix(3, 9, netID)
	case 3:
		a.setAddrPrefix(4, 11, netID)
	case 4:
		a.setAddrPrefix(5, 12, netID)
	case 5:
		a.setAddrPrefix(6, 13, netID)
	case 6:
		a.setAddrPrefix(7, 15, netID)
	case 7:
		a.setAddrPrefix(8, 17, netID)
	}
}

// IsNetID returns a bool indicating if the NwkID matches the given NetID.
func (a DevAddr) IsNetID(netID NetID) bool {
	tempDevAddr := a
	tempDevAddr.SetAddrPrefix(netID)

	if a == tempDevAddr {
		return true
	}

	return false
}

func (a *DevAddr) setAddrPrefix(prefixLength, nwkIDBits int, netID NetID) {
	// convert DevAddr to uint32
	devAddr := binary.BigEndian.Uint32(a[:])

	// clear the bits for the prefix and NwkID
	var mask uint32
	mask-- // sets all uint32 bits to 1
	devAddr &^= mask << uint32(32-prefixLength-nwkIDBits)

	// set the type prefix
	prefix := uint32(254) << uint32(32-prefixLength)
	devAddr |= prefix

	// set the nwkID
	nwkIDBytes := make([]byte, 4)
	id := netID.ID()
	copy(nwkIDBytes[len(nwkIDBytes)-len(id):], id)

	nwkID := binary.BigEndian.Uint32(nwkIDBytes)
	nwkID = nwkID << uint32(32-nwkIDBits) // truncate the MSB of the NetID ID field
	nwkID = nwkID >> uint32(prefixLength) // shift back for the prefix MSB
	devAddr |= nwkID

	binary.BigEndian.PutUint32(a[:], devAddr)
}

func (a DevAddr) getNwkID(prefixLength, nwkIDBits int) []byte {
	// convert DevAddr to uint32
	temp := binary.BigEndian.Uint32(a[:])

	// clear prefix
	temp = temp << uint32(prefixLength)

	// shift to starting of NwkID
	temp = temp >> (32 - uint32(nwkIDBits))

	// back to bytes
	out := make([]byte, 4)
	binary.BigEndian.PutUint32(out, temp)

	bLen := nwkIDBits / 8
	if nwkIDBits%8 != 0 {
		bLen++
	}

	return out[len(out)-bLen:]
}

// MarshalBinary marshals the object in binary form.
func (a DevAddr) MarshalBinary() ([]byte, error) {
	out := make([]byte, len(a))
	for i, v := range a {
		// little endian
		out[len(a)-i-1] = v
	}
	return out, nil
}

// UnmarshalBinary decodes the object from binary form.
func (a *DevAddr) UnmarshalBinary(data []byte) error {
	if len(data) != len(a) {
		return fmt.Errorf("lorawan: %d bytes of data are expected", len(a))
	}
	for i, v := range data {
		// little endian
		a[len(a)-i-1] = v
	}
	return nil
}

// MarshalText implements encoding.TextMarshaler.
func (a DevAddr) MarshalText() ([]byte, error) {
	return []byte(a.String()), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.
func (a *DevAddr) UnmarshalText(text []byte) error {
	b, err := hex.DecodeString(string(text))
	if err != nil {
		return err
	}

	if len(b) != len(a) {
		return fmt.Errorf("lorawan: exactly %d bytes are expected", len(a))
	}
	copy(a[:], b)
	return nil
}

// String implements fmt.Stringer.
func (a DevAddr) String() string {
	return hex.EncodeToString(a[:])
}

// Scan implements sql.Scanner.
func (a *DevAddr) Scan(src interface{}) error {
	b, ok := src.([]byte)
	if !ok {
		return errors.New("lorawan: []byte type expected")
	}
	if len(b) != len(a) {
		return fmt.Errorf("lorawan []byte must have length %d", len(a))
	}
	copy(a[:], b)
	return nil
}

// Value implements driver.Valuer.
func (a DevAddr) Value() (driver.Value, error) {
	return a[:], nil
}

// FCtrl represents the FCtrl (frame control) field.
// Please note that the FPending and ClassB are mapped to the same bit. This
// means that when unmarshaling from a byte-slice, both fields will contain
// the same value (either true or false).
type FCtrl struct {
	ADR       bool  `json:"adr"`
	ADRACKReq bool  `json:"adrAckReq"`
	ACK       bool  `json:"ack"`
	FPending  bool  `json:"fPending"` // only used for downlink messages
	ClassB    bool  `json:"classB"`   // only used for uplink messages
	fOptsLen  uint8 // will be set automatically by the FHDR when serialized to []byte
}

// MarshalBinary marshals the object in binary form.
func (c FCtrl) MarshalBinary() ([]byte, error) {
	if c.fOptsLen > 15 {
		return []byte{}, errors.New("lorawan: max value of FOptsLen is 15")
	}

	var b byte
	if c.ADR {
		b |= 0x80
	}
	if c.ADRACKReq {
		b |= 0x40
	}
	if c.ACK {
		b |= 0x20
	}
	if c.ClassB || c.FPending {
		b |= 0x10
	}
	b |= byte(c.fOptsLen) & 0x0f

	return []byte{b}, nil
}

// UnmarshalBinary decodes the object from binary form.
func (c *FCtrl) UnmarshalBinary(data []byte) error {
	if len(data) != 1 {
		return errors.New("lorawan: 1 byte of data is expected")
	}

	c.ADR = data[0]&0x80 != 0
	c.ADRACKReq = data[0]&0x40 != 0
	c.ACK = data[0]&0x20 != 0
	c.ClassB = data[0]&0x10 != 0
	c.FPending = data[0]&0x10 != 0
	c.fOptsLen = data[0] & 0x0f

	return nil
}

// FHDR represents the frame header.
type FHDR struct {
	DevAddr DevAddr   `json:"devAddr"`
	FCtrl   FCtrl     `json:"fCtrl"`
	FCnt    uint32    `json:"fCnt"`  // only the least-significant 16 bits will be marshalled
	FOpts   []Payload `json:"fOpts"` // max. number of allowed bytes is 15
}

// MarshalBinary marshals the object in binary form.
func (h FHDR) MarshalBinary() ([]byte, error) {
	var b []byte
	var err error
	var opts []byte

	for _, mac := range h.FOpts {
		b, err = mac.MarshalBinary()
		if err != nil {
			return []byte{}, err
		}
		opts = append(opts, b...)
	}
	h.FCtrl.fOptsLen = uint8(len(opts))
	if h.FCtrl.fOptsLen > 15 {
		return []byte{}, errors.New("lorawan: max number of FOpts bytes is 15")
	}

	out := make([]byte, 0, 7+h.FCtrl.fOptsLen)
	b, err = h.DevAddr.MarshalBinary()
	if err != nil {
		return []byte{}, err
	}
	out = append(out, b...)

	b, err = h.FCtrl.MarshalBinary()
	if err != nil {
		return []byte{}, err
	}
	out = append(out, b...)
	fCntBytes := make([]byte, 4)
	binary.LittleEndian.PutUint32(fCntBytes, h.FCnt)
	out = append(out, fCntBytes[0:2]...)
	out = append(out, opts...)

	return out, nil
}

// UnmarshalBinary decodes the object from binary form.
func (h *FHDR) UnmarshalBinary(uplink bool, data []byte) error {
	if len(data) < 7 {
		return errors.New("lorawan: at least 7 bytes are expected")
	}

	if err := h.DevAddr.UnmarshalBinary(data[0:4]); err != nil {
		return err
	}
	if err := h.FCtrl.UnmarshalBinary(data[4:5]); err != nil {
		return err
	}
	fCntBytes := make([]byte, 4)
	copy(fCntBytes, data[5:7])
	h.FCnt = binary.LittleEndian.Uint32(fCntBytes)

	if len(data) > 7 {
		h.FOpts = []Payload{
			&DataPayload{Bytes: data[7:]},
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package simtime

import (
	"container/heap"
	"runtime/debug"
	"time"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
)

var log = logger.GetLogger("simtime")

var enabled = config.Bool(false, "simtime.enable")
var startOffset = config.Duration(time.Hour*24*30, "simtime.startOffset")
var offset = config.Duration(0, "simtime.offset")
var allowFuture = config.Bool(false, "simtime.allowFuture")

var currentTime = time.Now()

var addQueue = make(chan *event)
var queue = eventQueue{}

var added = make(chan bool)
var tick = make(chan bool)
var start = make(chan bool)

func addQueuedEvents() {
	for {
		select {
		case e := <-addQueue:
			heap.Push(&queue, e)
		default:
			if len(queue) > 0 {
				return
			}
		}

	}
}

func init() {

	log.Infof("Starting. Enabled %t", enabled)

	if !enabled {
		return
	}

	SetCurrentTime(time.Now().Add(-startOffset))

	go func() {
		<-start
		for {

			//spew.Dump("Adding queued events")
			// Add any to-be-queued events (the heap isn't threadsafe)
			addQueuedEvents()

			//spew.Dump("pop")

			event := heap.Pop(&queue).(*event)

			//spew.Dump("event", event)

			currentTime = time.Unix(0, event.fireAt)

			if !allowFuture && currentTime.After(time.Now().Add(-offset)) {
				//spew.Dump("Sleeping")
				time.Sleep(currentTime.Sub(time.Now()))
			}

			if event.c != nil {
				select {
				case event.c <- currentTime:
				case <-time.After(time.Minute * 5):
					panic("An simtime channel listener didn't respond. (Check that you aren't calling simtime.Continue() more than once per tick.)")
				}

				select {
				case <-tick:
				case <-time.After(time.Minute * 5):
					panic("When using simtime, you MUST call simtime.Continue() when you are done with your time event with 5 minutes.")
				}
			} else {
				event.f(currentTime)
			}

			if event.interval > 0 {
				event.fireAt = currentTime.Add(event.interval).UnixNano()
				heap.Push(&queue, event)
			}

		}
	}()

}

func Start() {
	log.Infof("Starting. Time: %s", Now())
	select {
	case start <- true:
	default:
	}
}

func Continue() {
	if enabled {
		select {
		case tick <- true:
		case <-time.After(time.Minute * 5):
			panic("Continue took more than 5 seconds. Check that you are only calling it once per channel tick.")
		}
	}
}

func SetCurrentTime(time time.Time) {
	log.Infof("Setting time to %s", time)
	currentTime = time
	queue = eventQueue{}
}

func Now() time.Time {
	if !enabled {
		return time.Now()
	}
	return currentTime
}

func Enabled() bool {
	return enabled
}

func Tick(d time.Duration) <-chan time.Time {
	if !enabled {
		return time.Tick(d)
	}
	return addChannelEvent(d, true)
}

func After(d time.Duration) <-chan time.Time {
	if !enabled {
		return time.After(d)
	}
	return addChannelEvent(d, false)
}

func Sleep(d time.Duration) {
	<-After(d)
}

func addFuncEvent(f func(time.Time), d time.Duration, interval bool) {
	e := &event{
		fireAt: currentTime.Add(d).UnixNano(),
		f:      f,
		stack:  string(debug.Stack()),
	}

	if interval {
		e.interval = d
	}

	addEvent(e)

}

func addChannelEvent(d time.Duration, interval bool) chan time.Time {

	e := &event{
		fireAt: currentTime.Add(d).UnixNano(),
		c:      make(chan time.Time),
		stack:  string(debug.Stack()),
	}

	if interval {
		e.interval = d
	}

	addEvent(e)

	return e.c
}

func addEvent(e *event) {
	addQueue <- e

	select {
	case added <- true:
	default:
	}
}

type event struct {
	f        func(time.Time)
	c        chan time.Time
	fireAt   int64
	interval time.Duration
	stack    string
}

// A eventQueue implements heap.Interface and holds Events.
type eventQueue []*event

func (pq eventQueue) Len() int { return len(pq) }

func (pq eventQueue) Less(i, j int) bool {
	return pq[i].fireAt < pq[j].fireAt
}

func (pq eventQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}

func (pq *eventQueue) Push(x interface{}) {
	item := x.(*event)
	*pq = append(*pq, item)
}

func (pq *eventQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}
<commit_msg>Fix offset<commit_after>package simtime

import (
	"container/heap"
	"runtime/debug"
	"time"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
)

var log = logger.GetLogger("simtime")

var enabled = config.Bool(false, "simtime.enable")
var startOffset = config.Duration(time.Hour*24*30, "simtime.startOffset")
var offset = config.Duration(0, "simtime.offset")
var allowFuture = config.Bool(false, "simtime.allowFuture")

var currentTime = time.Now()

var addQueue = make(chan *event)
var queue = eventQueue{}

var added = make(chan bool)
var tick = make(chan bool)
var start = make(chan bool)

func addQueuedEvents() {
	for {
		select {
		case e := <-addQueue:
			heap.Push(&queue, e)
		default:
			if len(queue) > 0 {
				return
			}
		}

	}
}

func init() {

	log.Infof("Starting. Enabled %t", enabled)

	if !enabled {
		return
	}

	SetCurrentTime(time.Now().Add(-startOffset))

	go func() {
		<-start
		for {

			//spew.Dump("Adding queued events")
			// Add any to-be-queued events (the heap isn't threadsafe)
			addQueuedEvents()

			//spew.Dump("pop")

			event := heap.Pop(&queue).(*event)

			//spew.Dump("event", event)

			currentTime = time.Unix(0, event.fireAt)

			if !allowFuture && currentTime.After(time.Now().Add(-offset)) {
				//spew.Dump("Sleeping")
				time.Sleep(currentTime.Sub(time.Now().Add(-offset)))
			}

			if event.c != nil {
				select {
				case event.c <- currentTime:
				case <-time.After(time.Minute * 5):
					panic("An simtime channel listener didn't respond. (Check that you aren't calling simtime.Continue() more than once per tick.)")
				}

				select {
				case <-tick:
				case <-time.After(time.Minute * 5):
					panic("When using simtime, you MUST call simtime.Continue() when you are done with your time event with 5 minutes.")
				}
			} else {
				event.f(currentTime)
			}

			if event.interval > 0 {
				event.fireAt = currentTime.Add(event.interval).UnixNano()
				heap.Push(&queue, event)
			}

		}
	}()

}

func Start() {
	log.Infof("Starting. Time: %s", Now())
	select {
	case start <- true:
	default:
	}
}

func Continue() {
	if enabled {
		select {
		case tick <- true:
		case <-time.After(time.Minute * 5):
			panic("Continue took more than 5 seconds. Check that you are only calling it once per channel tick.")
		}
	}
}

func SetCurrentTime(time time.Time) {
	log.Infof("Setting time to %s", time)
	currentTime = time
	queue = eventQueue{}
}

func Now() time.Time {
	if !enabled {
		return time.Now()
	}
	return currentTime
}

func Enabled() bool {
	return enabled
}

func Tick(d time.Duration) <-chan time.Time {
	if !enabled {
		return time.Tick(d)
	}
	return addChannelEvent(d, true)
}

func After(d time.Duration) <-chan time.Time {
	if !enabled {
		return time.After(d)
	}
	return addChannelEvent(d, false)
}

func Sleep(d time.Duration) {
	<-After(d)
}

func addFuncEvent(f func(time.Time), d time.Duration, interval bool) {
	e := &event{
		fireAt: currentTime.Add(d).UnixNano(),
		f:      f,
		stack:  string(debug.Stack()),
	}

	if interval {
		e.interval = d
	}

	addEvent(e)

}

func addChannelEvent(d time.Duration, interval bool) chan time.Time {

	e := &event{
		fireAt: currentTime.Add(d).UnixNano(),
		c:      make(chan time.Time),
		stack:  string(debug.Stack()),
	}

	if interval {
		e.interval = d
	}

	addEvent(e)

	return e.c
}

func addEvent(e *event) {
	addQueue <- e

	select {
	case added <- true:
	default:
	}
}

type event struct {
	f        func(time.Time)
	c        chan time.Time
	fireAt   int64
	interval time.Duration
	stack    string
}

// A eventQueue implements heap.Interface and holds Events.
type eventQueue []*event

func (pq eventQueue) Len() int { return len(pq) }

func (pq eventQueue) Less(i, j int) bool {
	return pq[i].fireAt < pq[j].fireAt
}

func (pq eventQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}

func (pq *eventQueue) Push(x interface{}) {
	item := x.(*event)
	*pq = append(*pq, item)
}

func (pq *eventQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	*pq = old[0 : n-1]
	return item
}
<|endoftext|>


<commit_before>package engine

import (
	"github.com/ghthor/gospec/src/gospec"
	. "github.com/ghthor/gospec/src/gospec"
	"strconv"
)

type noopConn int

func (c noopConn) SendMessage(msg, payload string) error {
	c++
	return nil
}

var conn noopConn

type spyConn struct {
	packets chan string
}

func (c spyConn) SendMessage(msg, payload string) error {
	c.packets <- msg + ":" + payload
	return nil
}

func DescribeSimulation(c gospec.Context) {
	sim := newSimulation(40)

	c.Specify("starting and stopping", func() {

		sim.Start()
		c.Expect(sim.IsRunning(), IsTrue)

		sim.Stop()
		c.Expect(sim.IsRunning(), IsFalse)
	})

	c.Specify("clock ticks during each step", func() {
		c.Assume(sim.clock, Equals, Clock(0))

		sim.step()

		c.Expect(sim.clock, Equals, Clock(1))
	})

	c.Specify("Adding and removing players", func() {
		c.Assume(sim.nextEntityId, Equals, EntityId(0))

		// Need a Client endpoint
		var conn noopConn

		pd := PlayerDef{
			Name:          "thundercleese",
			Facing:        North,
			Coord:         WorldCoord{0, 0},
			MovementSpeed: 40,
			Conn:          conn,
		}

		c.Specify("adding", func() {
			player := sim.addPlayer(pd)

			c.Expect(player.Id(), Equals, EntityId(0))
			c.Expect(len(sim.state.entities), Equals, 1)
			c.Expect(len(sim.state.movableEntities), Equals, 1)
			c.Expect(len(sim.clients), Equals, 1)
		})

		c.Specify("adding while the simulation is running", func() {
			sim.Start()

			player := sim.AddPlayer(pd)

			sim.Stop()

			c.Expect(player.Id(), Equals, EntityId(0))
			c.Expect(len(sim.state.entities), Equals, 1)
			c.Expect(len(sim.state.movableEntities), Equals, 1)
			c.Expect(len(sim.clients), Equals, 1)
		})

		c.Specify("removing", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.removePlayer(player)

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})

		c.Specify("removing while the simulation is running", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.Start()

			sim.RemovePlayer(player)

			sim.Stop()

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})

		c.Specify("player removes self while simulation is running", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.Start()

			player.Disconnect()

			sim.Stop()

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})
	})

	c.Specify("simulation loop runs at the intended fps", nil)
}

func DescribeWorldState(c gospec.Context) {
	c.Specify("processes movement requests and generates PathActions", func() {
		playerA := &Player{
			Name:     "thundercleese",
			entityId: 0,
			mi:       newMotionInfo(WorldCoord{0, 0}, South, 35),
			conn:     conn,
		}
		playerB := &Player{
			Name:     "zorak",
			entityId: 1,
			mi:       newMotionInfo(WorldCoord{1, 0}, North, 40),
			conn:     conn,
		}

		playerA.mux()
		playerB.mux()

		worldState := newWorldState(Clock(0))
		worldState.AddMovableEntity(playerA)
		worldState.AddMovableEntity(playerB)

		c.Assume(len(worldState.entities), Equals, 2)
		c.Assume(len(worldState.movableEntities), Equals, 2)

		c.Specify("consume moveRequest's and produce PathActions", func() {
			playerA.SubmitInput("move=0", "north")
			playerB.SubmitInput("move=0", "south")

			worldState.stepTo(WorldTime(1))

			c.Expect(playerA.mi.moveRequest, IsNil)
			c.Expect(playerA.mi.facing, Equals, North)
			c.Expect(len(playerA.mi.pathActions), Equals, 1)

			pathActionA := playerA.mi.pathActions[0]
			c.Expect(pathActionA.Orig, Equals, WorldCoord{0, 0})
			c.Expect(pathActionA.Dest, Equals, WorldCoord{0, 0}.Neighbor(North))
			c.Expect(pathActionA.duration, Equals, int64(35))

			c.Expect(playerB.mi.moveRequest, IsNil)
			c.Expect(playerB.mi.facing, Equals, South)
			c.Expect(len(playerB.mi.pathActions), Equals, 1)

			pathActionB := playerB.mi.pathActions[0]
			c.Expect(pathActionB.Orig, Equals, WorldCoord{1, 0})
			c.Expect(pathActionB.Dest, Equals, WorldCoord{1, 0}.Neighbor(South))
			c.Expect(pathActionB.duration, Equals, int64(40))

			c.Specify("and the pathActions are removed when they have completed", func() {
				aEnd := worldState.time + WorldTime(playerA.mi.speed)
				bEnd := worldState.time + WorldTime(playerB.mi.speed)

				for i := worldState.time + 1; i < aEnd; i++ {
					worldState.stepTo(i)
					c.Expect(len(playerA.mi.pathActions), Equals, 1)
					c.Expect(len(playerB.mi.pathActions), Equals, 1)
				}
				worldState.step()

				c.Expect(len(playerA.mi.pathActions), Equals, 0)
				c.Expect(len(playerB.mi.pathActions), Equals, 1)

				for i := worldState.time + 1; i < bEnd; i++ {
					worldState.stepTo(i)
					c.Expect(len(playerA.mi.pathActions), Equals, 0)
					c.Expect(len(playerB.mi.pathActions), Equals, 1)
				}
				worldState.step()

				c.Expect(len(playerA.mi.pathActions), Equals, 0)
				c.Expect(len(playerB.mi.pathActions), Equals, 0)
			})
		})
	})
}

func DescribePlayer(c gospec.Context) {
	conn := spyConn{make(chan string)}

	player := &Player{
		Name:     "thundercleese",
		entityId: 0,
		mi:       newMotionInfo(WorldCoord{0, 0}, North, 40),
		conn:     conn,
	}

	player.mux()
	defer player.stopMux()

	c.Specify("motionInfo becomes locked when accessed by the simulation until the worldstate is published", func() {
		_ = player.motionInfo()

		locked := make(chan bool)

		go func() {
			select {
			case player.collectInput <- InputCmd{0, "move", "north"}:
				panic("MotionInfo not locked")
			case <-conn.packets:
				locked <- true
			}
		}()

		player.SendWorldState(newWorldState(Clock(0)))
		c.Expect(<-locked, IsTrue)

		c.Specify("and is unlocked afterwards", func() {
			select {
			case player.collectInput <- InputCmd{0, "move", "north"}:
			default:
				panic("MotionInfo not unlocked")
			}
		})
	})

	c.Specify("a request to move is generated when the user inputs a move cmd", func() {
		player.SubmitInput("move=0", "north")

		moveRequest := player.motionInfo().moveRequest

		c.Expect(moveRequest, Not(IsNil))
	})
}

func DescribeInputCommands(c gospec.Context) {
	c.Specify("creating movement requests from InputCmds", func() {
		c.Specify("north", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"north",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, North)
		})

		c.Specify("east", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"east",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, East)
		})

		c.Specify("south", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"south",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, South)
		})

		c.Specify("west", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"west",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, West)
		})
	})

	c.Specify("embedding worldtime in the cmd msg", func() {
		player := &Player{
			Name:         "thundercleese",
			entityId:     0,
			mi:           newMotionInfo(WorldCoord{0, 0}, North, 40),
			conn:         conn,
			collectInput: make(chan InputCmd, 1),
		}

		c.Specify("string splits on = and parses 64bit int", func() {
			player.SubmitInput("move=0", "north")
			input := <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(0))

			player.SubmitInput("move=1824081", "north")
			input = <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(1824081))

			player.SubmitInput("move=99", "north")
			input = <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(99))
		})

		c.Specify("errors with invalid input and doesn't publish the command", func() {
			err := player.SubmitInput("move=a", "north")
			e := err.(*strconv.NumError)

			c.Expect(e, Not(IsNil))
			c.Expect(e.Err, Equals, strconv.ErrSyntax)

			err = player.SubmitInput("move=", "north")
			e = err.(*strconv.NumError)

			c.Expect(e, Not(IsNil))
			c.Expect(e.Err, Equals, strconv.ErrSyntax)
		})
	})
}
<commit_msg>A spec that may need to be implemented later<commit_after>package engine

import (
	"github.com/ghthor/gospec/src/gospec"
	. "github.com/ghthor/gospec/src/gospec"
	"strconv"
)

type noopConn int

func (c noopConn) SendMessage(msg, payload string) error {
	c++
	return nil
}

var conn noopConn

type spyConn struct {
	packets chan string
}

func (c spyConn) SendMessage(msg, payload string) error {
	c.packets <- msg + ":" + payload
	return nil
}

func DescribeSimulation(c gospec.Context) {
	sim := newSimulation(40)

	c.Specify("starting and stopping", func() {

		sim.Start()
		c.Expect(sim.IsRunning(), IsTrue)

		sim.Stop()
		c.Expect(sim.IsRunning(), IsFalse)
	})

	c.Specify("clock ticks during each step", func() {
		c.Assume(sim.clock, Equals, Clock(0))

		sim.step()

		c.Expect(sim.clock, Equals, Clock(1))
	})

	c.Specify("Adding and removing players", func() {
		c.Assume(sim.nextEntityId, Equals, EntityId(0))

		// Need a Client endpoint
		var conn noopConn

		pd := PlayerDef{
			Name:          "thundercleese",
			Facing:        North,
			Coord:         WorldCoord{0, 0},
			MovementSpeed: 40,
			Conn:          conn,
		}

		c.Specify("adding", func() {
			player := sim.addPlayer(pd)

			c.Expect(player.Id(), Equals, EntityId(0))
			c.Expect(len(sim.state.entities), Equals, 1)
			c.Expect(len(sim.state.movableEntities), Equals, 1)
			c.Expect(len(sim.clients), Equals, 1)
		})

		c.Specify("adding while the simulation is running", func() {
			sim.Start()

			player := sim.AddPlayer(pd)

			sim.Stop()

			c.Expect(player.Id(), Equals, EntityId(0))
			c.Expect(len(sim.state.entities), Equals, 1)
			c.Expect(len(sim.state.movableEntities), Equals, 1)
			c.Expect(len(sim.clients), Equals, 1)
		})

		c.Specify("removing", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.removePlayer(player)

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})

		c.Specify("removing while the simulation is running", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.Start()

			sim.RemovePlayer(player)

			sim.Stop()

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})

		c.Specify("player removes self while simulation is running", func() {
			player := sim.addPlayer(pd)

			c.Assume(player.Id(), Equals, EntityId(0))
			c.Assume(len(sim.state.entities), Equals, 1)
			c.Assume(len(sim.state.movableEntities), Equals, 1)
			c.Assume(len(sim.clients), Equals, 1)

			sim.Start()

			player.Disconnect()

			sim.Stop()

			c.Expect(len(sim.state.entities), Equals, 0)
			c.Expect(len(sim.state.movableEntities), Equals, 0)
			c.Expect(len(sim.clients), Equals, 0)
		})

		// TODO drain the newPlayer/dcedPlayer channels after the loop has broken
		c.Specify("when the simulation is stopping shouldn't block", nil)
	})

	c.Specify("simulation loop runs at the intended fps", nil)
}

func DescribeWorldState(c gospec.Context) {
	c.Specify("processes movement requests and generates PathActions", func() {
		playerA := &Player{
			Name:     "thundercleese",
			entityId: 0,
			mi:       newMotionInfo(WorldCoord{0, 0}, South, 35),
			conn:     conn,
		}
		playerB := &Player{
			Name:     "zorak",
			entityId: 1,
			mi:       newMotionInfo(WorldCoord{1, 0}, North, 40),
			conn:     conn,
		}

		playerA.mux()
		playerB.mux()

		worldState := newWorldState(Clock(0))
		worldState.AddMovableEntity(playerA)
		worldState.AddMovableEntity(playerB)

		c.Assume(len(worldState.entities), Equals, 2)
		c.Assume(len(worldState.movableEntities), Equals, 2)

		c.Specify("consume moveRequest's and produce PathActions", func() {
			playerA.SubmitInput("move=0", "north")
			playerB.SubmitInput("move=0", "south")

			worldState.stepTo(WorldTime(1))

			c.Expect(playerA.mi.moveRequest, IsNil)
			c.Expect(playerA.mi.facing, Equals, North)
			c.Expect(len(playerA.mi.pathActions), Equals, 1)

			pathActionA := playerA.mi.pathActions[0]
			c.Expect(pathActionA.Orig, Equals, WorldCoord{0, 0})
			c.Expect(pathActionA.Dest, Equals, WorldCoord{0, 0}.Neighbor(North))
			c.Expect(pathActionA.duration, Equals, int64(35))

			c.Expect(playerB.mi.moveRequest, IsNil)
			c.Expect(playerB.mi.facing, Equals, South)
			c.Expect(len(playerB.mi.pathActions), Equals, 1)

			pathActionB := playerB.mi.pathActions[0]
			c.Expect(pathActionB.Orig, Equals, WorldCoord{1, 0})
			c.Expect(pathActionB.Dest, Equals, WorldCoord{1, 0}.Neighbor(South))
			c.Expect(pathActionB.duration, Equals, int64(40))

			c.Specify("and the pathActions are removed when they have completed", func() {
				aEnd := worldState.time + WorldTime(playerA.mi.speed)
				bEnd := worldState.time + WorldTime(playerB.mi.speed)

				for i := worldState.time + 1; i < aEnd; i++ {
					worldState.stepTo(i)
					c.Expect(len(playerA.mi.pathActions), Equals, 1)
					c.Expect(len(playerB.mi.pathActions), Equals, 1)
				}
				worldState.step()

				c.Expect(len(playerA.mi.pathActions), Equals, 0)
				c.Expect(len(playerB.mi.pathActions), Equals, 1)

				for i := worldState.time + 1; i < bEnd; i++ {
					worldState.stepTo(i)
					c.Expect(len(playerA.mi.pathActions), Equals, 0)
					c.Expect(len(playerB.mi.pathActions), Equals, 1)
				}
				worldState.step()

				c.Expect(len(playerA.mi.pathActions), Equals, 0)
				c.Expect(len(playerB.mi.pathActions), Equals, 0)
			})
		})
	})
}

func DescribePlayer(c gospec.Context) {
	conn := spyConn{make(chan string)}

	player := &Player{
		Name:     "thundercleese",
		entityId: 0,
		mi:       newMotionInfo(WorldCoord{0, 0}, North, 40),
		conn:     conn,
	}

	player.mux()
	defer player.stopMux()

	c.Specify("motionInfo becomes locked when accessed by the simulation until the worldstate is published", func() {
		_ = player.motionInfo()

		locked := make(chan bool)

		go func() {
			select {
			case player.collectInput <- InputCmd{0, "move", "north"}:
				panic("MotionInfo not locked")
			case <-conn.packets:
				locked <- true
			}
		}()

		player.SendWorldState(newWorldState(Clock(0)))
		c.Expect(<-locked, IsTrue)

		c.Specify("and is unlocked afterwards", func() {
			select {
			case player.collectInput <- InputCmd{0, "move", "north"}:
			default:
				panic("MotionInfo not unlocked")
			}
		})
	})

	c.Specify("a request to move is generated when the user inputs a move cmd", func() {
		player.SubmitInput("move=0", "north")

		moveRequest := player.motionInfo().moveRequest

		c.Expect(moveRequest, Not(IsNil))
	})
}

func DescribeInputCommands(c gospec.Context) {
	c.Specify("creating movement requests from InputCmds", func() {
		c.Specify("north", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"north",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, North)
		})

		c.Specify("east", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"east",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, East)
		})

		c.Specify("south", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"south",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, South)
		})

		c.Specify("west", func() {
			moveRequest := newMoveRequest(InputCmd{
				0,
				"move",
				"west",
			})

			c.Expect(moveRequest.t, Equals, WorldTime(0))
			c.Expect(moveRequest.Direction, Equals, West)
		})
	})

	c.Specify("embedding worldtime in the cmd msg", func() {
		player := &Player{
			Name:         "thundercleese",
			entityId:     0,
			mi:           newMotionInfo(WorldCoord{0, 0}, North, 40),
			conn:         conn,
			collectInput: make(chan InputCmd, 1),
		}

		c.Specify("string splits on = and parses 64bit int", func() {
			player.SubmitInput("move=0", "north")
			input := <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(0))

			player.SubmitInput("move=1824081", "north")
			input = <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(1824081))

			player.SubmitInput("move=99", "north")
			input = <-player.collectInput

			c.Expect(input.timeIssued, Equals, WorldTime(99))
		})

		c.Specify("errors with invalid input and doesn't publish the command", func() {
			err := player.SubmitInput("move=a", "north")
			e := err.(*strconv.NumError)

			c.Expect(e, Not(IsNil))
			c.Expect(e.Err, Equals, strconv.ErrSyntax)

			err = player.SubmitInput("move=", "north")
			e = err.(*strconv.NumError)

			c.Expect(e, Not(IsNil))
			c.Expect(e.Err, Equals, strconv.ErrSyntax)
		})
	})
}
<|endoftext|>


<commit_before>package stripe

import (
	"bytes"
	"encoding/json"
	"io"
	"mime/multipart"
	"net/url"
	"path/filepath"

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

// FilePurpose is the purpose of a particular file.
type FilePurpose string

// List of values that FilePurpose can take.
const (
	FilePurposeAdditionalVerification           FilePurpose = "additional_verification"
	FilePurposeBusinessIcon                     FilePurpose = "business_icon"
	FilePurposeBusinessLogo                     FilePurpose = "business_logo"
	FilePurposeCustomerSignature                FilePurpose = "customer_signature"
	FilePurposeDocumentProviderIdentityDocument FilePurpose = "document_provider_identity_document"
	FilePurposeDisputeEvidence                  FilePurpose = "dispute_evidence"
	FilePurposeFinanceReportRun                 FilePurpose = "finance_report_run"
	FilePurposeFoundersStockDocument            FilePurpose = "founders_stock_document"
	FilePurposeIdentityDocument                 FilePurpose = "identity_document"
	FilePurposePCIDocument                      FilePurpose = "pci_document"
	FilePurposeSigmaScheduledQuery              FilePurpose = "sigma_scheduled_query"
	FilePurposeTaxDocumentUserUpload            FilePurpose = "tax_document_user_upload"
)

// FileParams is the set of parameters that can be used when creating a file.
// For more details see https://stripe.com/docs/api#create_file.
type FileParams struct {
	Params `form:"*"`

	// FileReader is a reader with the contents of the file that should be uploaded.
	FileReader io.Reader

	// Filename is just the name of the file without path information.
	Filename *string

	Purpose *string

	FileLinkData *FileFileLinkDataParams
}

// FileFileLinkDataParams is the set of parameters allowed for the
// file_link_data hash.
type FileFileLinkDataParams struct {
	Params    `form:"*"`
	Create    *bool  `form:"create"`
	ExpiresAt *int64 `form:"expires_at"`
}

// FileListParams is the set of parameters that can be used when listing
// files. For more details see https://stripe.com/docs/api#list_files.
type FileListParams struct {
	ListParams   `form:"*"`
	Created      *int64            `form:"created"`
	CreatedRange *RangeQueryParams `form:"created"`
	Purpose      *string           `form:"purpose"`
}

// File is the resource representing a Stripe file.
// For more details see https://stripe.com/docs/api#file_object.
type File struct {
	APIResource
	Created  int64         `json:"created"`
	ID       string        `json:"id"`
	Filename string        `json:"filename"`
	Links    *FileLinkList `json:"links"`
	Purpose  FilePurpose   `json:"purpose"`
	Size     int64         `json:"size"`
	Type     string        `json:"type"`
	URL      string        `json:"url"`
}

// FileList is a list of files as retrieved from a list endpoint.
type FileList struct {
	APIResource
	ListMeta
	Data []*File `json:"data"`
}

// GetBody gets an appropriate multipart form payload to use in a request body
// to create a new file.
func (f *FileParams) GetBody() (*bytes.Buffer, string, error) {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	if f.Purpose != nil {
		err := writer.WriteField("purpose", StringValue(f.Purpose))
		if err != nil {
			return nil, "", err
		}
	}

	if f.FileReader != nil && f.Filename != nil {
		part, err := writer.CreateFormFile("file", filepath.Base(StringValue(f.Filename)))
		if err != nil {
			return nil, "", err
		}

		_, err = io.Copy(part, f.FileReader)
		if err != nil {
			return nil, "", err
		}
	}

	if f.FileLinkData != nil {
		values := &form.Values{}
		form.AppendToPrefixed(values, f.FileLinkData, []string{"file_link_data"})

		params, err := url.ParseQuery(values.Encode())
		if err != nil {
			return nil, "", err
		}
		for key, values := range params {
			err := writer.WriteField(key, values[0])
			if err != nil {
				return nil, "", err
			}
		}
	}

	err := writer.Close()
	if err != nil {
		return nil, "", err
	}

	return body, writer.Boundary(), nil
}

// UnmarshalJSON handles deserialization of a File.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (f *File) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		f.ID = id
		return nil
	}

	type file File
	var v file
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*f = File(v)
	return nil
}
<commit_msg>Add support for `ExpiresAt` on `File`<commit_after>package stripe

import (
	"bytes"
	"encoding/json"
	"io"
	"mime/multipart"
	"net/url"
	"path/filepath"

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

// FilePurpose is the purpose of a particular file.
type FilePurpose string

// List of values that FilePurpose can take.
const (
	FilePurposeAdditionalVerification           FilePurpose = "additional_verification"
	FilePurposeBusinessIcon                     FilePurpose = "business_icon"
	FilePurposeBusinessLogo                     FilePurpose = "business_logo"
	FilePurposeCustomerSignature                FilePurpose = "customer_signature"
	FilePurposeDocumentProviderIdentityDocument FilePurpose = "document_provider_identity_document"
	FilePurposeDisputeEvidence                  FilePurpose = "dispute_evidence"
	FilePurposeFinanceReportRun                 FilePurpose = "finance_report_run"
	FilePurposeFoundersStockDocument            FilePurpose = "founders_stock_document"
	FilePurposeIdentityDocument                 FilePurpose = "identity_document"
	FilePurposePCIDocument                      FilePurpose = "pci_document"
	FilePurposeSigmaScheduledQuery              FilePurpose = "sigma_scheduled_query"
	FilePurposeTaxDocumentUserUpload            FilePurpose = "tax_document_user_upload"
)

// FileParams is the set of parameters that can be used when creating a file.
// For more details see https://stripe.com/docs/api#create_file.
type FileParams struct {
	Params `form:"*"`

	// FileReader is a reader with the contents of the file that should be uploaded.
	FileReader io.Reader

	// Filename is just the name of the file without path information.
	Filename *string

	Purpose *string

	FileLinkData *FileFileLinkDataParams
}

// FileFileLinkDataParams is the set of parameters allowed for the
// file_link_data hash.
type FileFileLinkDataParams struct {
	Params    `form:"*"`
	Create    *bool  `form:"create"`
	ExpiresAt *int64 `form:"expires_at"`
}

// FileListParams is the set of parameters that can be used when listing
// files. For more details see https://stripe.com/docs/api#list_files.
type FileListParams struct {
	ListParams   `form:"*"`
	Created      *int64            `form:"created"`
	CreatedRange *RangeQueryParams `form:"created"`
	Purpose      *string           `form:"purpose"`
}

// File is the resource representing a Stripe file.
// For more details see https://stripe.com/docs/api#file_object.
type File struct {
	APIResource
	Created   int64         `json:"created"`
	ExpiresAt int64         `json:"expires_at"`
	Filename  string        `json:"filename"`
	ID        string        `json:"id"`
	Links     *FileLinkList `json:"links"`
	Object    string        `json:"object"`
	Purpose   FilePurpose   `json:"purpose"`
	Size      int64         `json:"size"`
	Type      string        `json:"type"`
	URL       string        `json:"url"`
}

// FileList is a list of files as retrieved from a list endpoint.
type FileList struct {
	APIResource
	ListMeta
	Data []*File `json:"data"`
}

// GetBody gets an appropriate multipart form payload to use in a request body
// to create a new file.
func (f *FileParams) GetBody() (*bytes.Buffer, string, error) {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	if f.Purpose != nil {
		err := writer.WriteField("purpose", StringValue(f.Purpose))
		if err != nil {
			return nil, "", err
		}
	}

	if f.FileReader != nil && f.Filename != nil {
		part, err := writer.CreateFormFile("file", filepath.Base(StringValue(f.Filename)))
		if err != nil {
			return nil, "", err
		}

		_, err = io.Copy(part, f.FileReader)
		if err != nil {
			return nil, "", err
		}
	}

	if f.FileLinkData != nil {
		values := &form.Values{}
		form.AppendToPrefixed(values, f.FileLinkData, []string{"file_link_data"})

		params, err := url.ParseQuery(values.Encode())
		if err != nil {
			return nil, "", err
		}
		for key, values := range params {
			err := writer.WriteField(key, values[0])
			if err != nil {
				return nil, "", err
			}
		}
	}

	err := writer.Close()
	if err != nil {
		return nil, "", err
	}

	return body, writer.Boundary(), nil
}

// UnmarshalJSON handles deserialization of a File.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (f *File) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		f.ID = id
		return nil
	}

	type file File
	var v file
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*f = File(v)
	return nil
}
<|endoftext|>


<commit_before>package multiconfig

import (
	"flag"
	"fmt"
	"os"
	"reflect"
	"strings"

	"github.com/fatih/camelcase"
	"github.com/fatih/structs"
)

// FlagLoader satisfies the loader interface. It creates on the fly flags based
// on the field names and parses them to load into the given pointer of struct
// s.
type FlagLoader struct {
	// Prefix prepends the prefix to each flag name i.e:
	// --foo is converted to --prefix-foo.
	// --foo-bar is converted to --prefix-foo-bar.
	Prefix string

	// Flatten doesn't add prefixes for nested structs. So previously if we had
	// a nested struct `type T struct{Name struct{ ...}}`, this would generate
	// --name-foo, --name-bar, etc. When Flatten is enabled, the flags will be
	// flattend to the form: --foo, --bar, etc.. Panics if the nested structs
	// has a duplicate field name in the root level of the struct (outer
	// struct). Use this option only if you know what you do.
	Flatten bool

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a flag name "--accesskey". If
	// CamelCase is enabled, the flag name will be generated in the form of
	// "--access-key"
	CamelCase bool

	// EnvPrefix is just a placeholder to print the correct usages when an
	// EnvLoader is used
	EnvPrefix string

	// Args defines a custom argument list. If nil, os.Args[1:] is used.
	Args []string

	// FlagUsageFunc an optional function that is called to set a flag.Usage value
	// The input is the raw flag name, and the output should be a string
	// that will used in passed into the flag for Usage.
	FlagUsageFunc func(name string) string

	// only exists for testing.  This is the raw flagset that is to parse
	flagSet *flag.FlagSet
}

// Load loads the source into the config defined by struct s
func (f *FlagLoader) Load(s interface{}) error {
	strct := structs.New(s)
	structName := strct.Name()

	flagSet := flag.NewFlagSet(structName, flag.ExitOnError)
	f.flagSet = flagSet

	for _, field := range strct.Fields() {
		f.processField(field.Name(), field)
	}

	flagSet.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		flagSet.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\nGenerated environment variables:\n")
		e := &EnvironmentLoader{
			Prefix:    f.EnvPrefix,
			CamelCase: f.CamelCase,
		}
		e.PrintEnvs(s)
		fmt.Println("")
	}

	args := os.Args[1:]
	if f.Args != nil {
		args = f.Args
	}

	return flagSet.Parse(args)
}

// processField generates a flag based on the given field and fieldName. If a
// nested struct is detected, a flag for each field of that nested struct is
// generated too.
func (f *FlagLoader) processField(fieldName string, field *structs.Field) error {
	if f.CamelCase {
		fieldName = strings.Join(camelcase.Split(fieldName), "-")
	}

	switch field.Kind() {
	case reflect.Struct:
		for _, ff := range field.Fields() {
			flagName := field.Name() + "-" + ff.Name()

			if f.Flatten {
				// first check if it's set or not, because if we have duplicate
				// we don't want to break the flag. Panic by giving a readable
				// output
				f.flagSet.VisitAll(func(fl *flag.Flag) {
					if strings.ToLower(ff.Name()) == fl.Name {
						// already defined
						panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name))
					}
				})

				flagName = ff.Name()
			}

			if err := f.processField(flagName, ff); err != nil {
				return err
			}
		}
	default:
		// Add custom prefix to the flag if it's set
		if f.Prefix != "" {
			fieldName = f.Prefix + "-" + fieldName
		}

		// we only can get the value from expored fields, unexported fields panics
		if field.IsExported() {
			// use built-in or custom flag usage message
			flagUsageFunc := flagUsageDefault
			if f.FlagUsageFunc != nil {
				flagUsageFunc = f.FlagUsageFunc
			}
			f.flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsageFunc(fieldName))
		}
	}

	return nil
}

// fieldValue satisfies the flag.Value and flag.Getter interfaces
type fieldValue structs.Field

func newFieldValue(f *structs.Field) *fieldValue {
	fl := fieldValue(*f)
	return &fl
}

func (f *fieldValue) Set(val string) error {
	field := (*structs.Field)(f)
	return fieldSet(field, val)
}

func (f *fieldValue) String() string {
	fl := (*structs.Field)(f)
	return fmt.Sprintf("%v", fl.Value())
}

func (f *fieldValue) Get() interface{} {
	fl := (*structs.Field)(f)
	return fl.Value()
}

// This is an unexported interface, be careful about it.
// https://code.google.com/p/go/source/browse/src/pkg/flag/flag.go?name=release#101
func (f *fieldValue) IsBoolFlag() bool {
	fl := (*structs.Field)(f)
	if fl.Kind() == reflect.Bool {
		return true
	}
	return false
}

// flagUsageDefault is the default "FlagUsageFunc" use in filling out
// the usage of a flag.
func flagUsageDefault(name string) string { return fmt.Sprintf("Change value of %s.", name) }

func flagName(name string) string { return strings.ToLower(name) }
<commit_msg>fix fieldValue for go1.7 flag package<commit_after>package multiconfig

import (
	"flag"
	"fmt"
	"os"
	"reflect"
	"strings"

	"github.com/fatih/camelcase"
	"github.com/fatih/structs"
)

// FlagLoader satisfies the loader interface. It creates on the fly flags based
// on the field names and parses them to load into the given pointer of struct
// s.
type FlagLoader struct {
	// Prefix prepends the prefix to each flag name i.e:
	// --foo is converted to --prefix-foo.
	// --foo-bar is converted to --prefix-foo-bar.
	Prefix string

	// Flatten doesn't add prefixes for nested structs. So previously if we had
	// a nested struct `type T struct{Name struct{ ...}}`, this would generate
	// --name-foo, --name-bar, etc. When Flatten is enabled, the flags will be
	// flattend to the form: --foo, --bar, etc.. Panics if the nested structs
	// has a duplicate field name in the root level of the struct (outer
	// struct). Use this option only if you know what you do.
	Flatten bool

	// CamelCase adds a separator for field names in camelcase form. A
	// fieldname of "AccessKey" would generate a flag name "--accesskey". If
	// CamelCase is enabled, the flag name will be generated in the form of
	// "--access-key"
	CamelCase bool

	// EnvPrefix is just a placeholder to print the correct usages when an
	// EnvLoader is used
	EnvPrefix string

	// Args defines a custom argument list. If nil, os.Args[1:] is used.
	Args []string

	// FlagUsageFunc an optional function that is called to set a flag.Usage value
	// The input is the raw flag name, and the output should be a string
	// that will used in passed into the flag for Usage.
	FlagUsageFunc func(name string) string

	// only exists for testing.  This is the raw flagset that is to parse
	flagSet *flag.FlagSet
}

// Load loads the source into the config defined by struct s
func (f *FlagLoader) Load(s interface{}) error {
	strct := structs.New(s)
	structName := strct.Name()

	flagSet := flag.NewFlagSet(structName, flag.ExitOnError)
	f.flagSet = flagSet

	for _, field := range strct.Fields() {
		f.processField(field.Name(), field)
	}

	flagSet.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		flagSet.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\nGenerated environment variables:\n")
		e := &EnvironmentLoader{
			Prefix:    f.EnvPrefix,
			CamelCase: f.CamelCase,
		}
		e.PrintEnvs(s)
		fmt.Println("")
	}

	args := os.Args[1:]
	if f.Args != nil {
		args = f.Args
	}

	return flagSet.Parse(args)
}

// processField generates a flag based on the given field and fieldName. If a
// nested struct is detected, a flag for each field of that nested struct is
// generated too.
func (f *FlagLoader) processField(fieldName string, field *structs.Field) error {
	if f.CamelCase {
		fieldName = strings.Join(camelcase.Split(fieldName), "-")
	}

	switch field.Kind() {
	case reflect.Struct:
		for _, ff := range field.Fields() {
			flagName := field.Name() + "-" + ff.Name()

			if f.Flatten {
				// first check if it's set or not, because if we have duplicate
				// we don't want to break the flag. Panic by giving a readable
				// output
				f.flagSet.VisitAll(func(fl *flag.Flag) {
					if strings.ToLower(ff.Name()) == fl.Name {
						// already defined
						panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name))
					}
				})

				flagName = ff.Name()
			}

			if err := f.processField(flagName, ff); err != nil {
				return err
			}
		}
	default:
		// Add custom prefix to the flag if it's set
		if f.Prefix != "" {
			fieldName = f.Prefix + "-" + fieldName
		}

		// we only can get the value from expored fields, unexported fields panics
		if field.IsExported() {
			// use built-in or custom flag usage message
			flagUsageFunc := flagUsageDefault
			if f.FlagUsageFunc != nil {
				flagUsageFunc = f.FlagUsageFunc
			}
			f.flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsageFunc(fieldName))
		}
	}

	return nil
}

// fieldValue satisfies the flag.Value and flag.Getter interfaces
type fieldValue struct {
	field *structs.Field
}

func newFieldValue(f *structs.Field) *fieldValue {
	return &fieldValue{
		field: f,
	}
}

func (f *fieldValue) Set(val string) error {
	return fieldSet(f.field, val)
}

func (f *fieldValue) String() string {
	if f.IsZero() {
		return ""
	}

	return fmt.Sprintf("%v", f.field.Value())
}

func (f *fieldValue) Get() interface{} {
	if f.IsZero() {
		return nil
	}

	return f.field.Value()
}

func (f *fieldValue) IsZero() bool {
	return f.field == nil
}

// This is an unexported interface, be careful about it.
// https://code.google.com/p/go/source/browse/src/pkg/flag/flag.go?name=release#101
func (f *fieldValue) IsBoolFlag() bool {
	return f.field.Kind() == reflect.Bool
}

// flagUsageDefault is the default "FlagUsageFunc" use in filling out
// the usage of a flag.
func flagUsageDefault(name string) string { return fmt.Sprintf("Change value of %s.", name) }

func flagName(name string) string { return strings.ToLower(name) }
<|endoftext|>


<commit_before>package flow

import (
	"bytes"
	"fmt"
	"os"
	"os/signal"
	"path"
	"reflect"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

var (
	pkgPath      = reflect.TypeOf(Flow{}).PkgPath()
	DefaultDebug = false
)

type debugInfo struct {
	Stack string
	Info  string
}

func (d *debugInfo) String() string {
	return d.Stack + " - " + d.Info
}

type Flow struct {
	errChan  chan error
	stopChan chan struct{}
	ref      *int32
	wg       sync.WaitGroup
	Parent   *Flow
	Children []*Flow
	stoped   int32
	exited   int32
	onClose  []func()
	id       uintptr

	mutex   sync.Mutex
	debug   []debugInfo
	printed int32
}

func NewEx(n int) *Flow {
	f := &Flow{
		errChan:  make(chan error, 1),
		stopChan: make(chan struct{}),
		ref:      new(int32),
	}
	f.appendDebug("init")
	return f
}

func New() *Flow {
	return NewEx(0)
}

func (f *Flow) MarkExit() bool {
	return atomic.CompareAndSwapInt32(&f.exited, 0, 1)
}

func (f *Flow) IsExit() bool {
	return atomic.LoadInt32(&f.exited) == 1
}

func (f *Flow) printDebug() {
	buf := bytes.NewBuffer(nil)
	maxLength := 0
	for _, d := range f.debug {
		if maxLength < len(d.Stack) {
			maxLength = len(d.Stack)
		}
	}
	fill := func(a string, n int) string {
		return a + strings.Repeat(" ", n-len(a))
	}
	buf.WriteString("\n")
	for _, d := range f.debug {
		buf.WriteString(fmt.Sprint(&f) + " ")
		buf.WriteString(fill(d.Stack, maxLength) + " - " + d.Info + "\n")
	}
	print(buf.String())
}

func (f *Flow) appendDebug(info string) {
	pc, fp, line, _ := runtime.Caller(f.getCaller())
	name := runtime.FuncForPC(pc).Name()
	stack := fmt.Sprintf("%v:%v %v", path.Base(fp), line, path.Base(name))
	f.debug = append(f.debug, debugInfo{stack, info})
}

func (f *Flow) SetOnClose(exit func()) *Flow {
	f.onClose = []func(){exit}
	return f
}

func (f *Flow) AddOnClose(exit func()) *Flow {
	f.onClose = append(f.onClose, exit)
	return f
}

const (
	F_CLOSED  = true
	F_TIMEOUT = false
)

func (f *Flow) Tick(t *time.Ticker) bool {
	select {
	case <-t.C:
		return F_TIMEOUT
	case <-f.IsClose():
		return F_CLOSED
	}
}

func (f *Flow) CloseOrWait(duration time.Duration) bool {
	select {
	case <-time.After(duration):
		return F_TIMEOUT
	case <-f.IsClose():
		return F_CLOSED
	}
}

func (f *Flow) Error(err error) {
	f.errChan <- err
}

func (f *Flow) ForkTo(ref **Flow, exit func()) {
	*ref = f.Fork(0).AddOnClose(exit)
}

func (f *Flow) Fork(n int) *Flow {
	f2 := NewEx(n)
	f2.Parent = f
	// TODO(chzyer): test it !
	f2.errChan = f.errChan
	f.Children = append(f.Children, f2)
	f.Add(1) // for f2
	return f2
}

func (f *Flow) StopAll() {
	flow := f
	for flow.Parent != nil {
		flow = flow.Parent
	}
	flow.Stop()
}

func (f *Flow) Close() {
	f.appendDebug("close")
	f.close()
}

func (f *Flow) close() {
	f.Stop()
	f.wait()
}

func (f *Flow) Stop() {
	if !atomic.CompareAndSwapInt32(&f.stoped, 0, 1) {
		return
	}
	f.appendDebug("stop")

	close(f.stopChan)
	for _, cf := range f.Children {
		cf.Stop()
	}
	if len(f.onClose) > 0 {
		go func() {
			for _, f := range f.onClose {
				f()
			}
		}()
	}
}

func (f *Flow) IsClosed() bool {
	return atomic.LoadInt32(&f.stoped) == 1
}

func (f *Flow) IsClose() chan struct{} {
	return f.stopChan
}

func (f *Flow) Add(n int) {
	atomic.AddInt32(f.ref, int32(n))
	f.appendDebug(fmt.Sprintf("add: %v, ref: %v", n, *f.ref))
	f.wg.Add(n)
}

func (f *Flow) getCaller() int {
	for i := 0; ; i++ {
		pc, _, _, ok := runtime.Caller(i)
		if !ok {
			break
		}
		f := runtime.FuncForPC(pc).Name()
		if !strings.HasPrefix(f, pkgPath) {
			return i - 1
		}
	}
	return 0
}

func (f *Flow) Done() {
	f.wg.Done()
	if atomic.AddInt32(f.ref, -1) == 0 {
		f.Stop()
	}
}

func (f *Flow) DoneAndClose() {
	f.Done()
	f.appendDebug(fmt.Sprintf("done and close, ref: %v", *f.ref))
	f.close()
}

func (f *Flow) wait() {
	f.appendDebug("wait")

	done := make(chan struct{})
	printed := int32(0)
	if DefaultDebug && atomic.CompareAndSwapInt32(&f.printed, 0, 1) {
		go func() {
			select {
			case <-done:
				return
			case <-time.After(1000 * time.Millisecond):
				f.printDebug()
				atomic.StoreInt32(&printed, 1)
			}
		}()
	}
	<-f.stopChan
	f.wg.Wait()
	close(done)
	if atomic.LoadInt32(&printed) == 1 {
		println(fmt.Sprint(&f) + " - exit")
	}

	if f.Parent != nil {
		f.Parent.Done()
		f.Parent = nil
	}
}

func (f *Flow) Wait() error {
	signalChan := make(chan os.Signal)
	signal.Notify(signalChan,
		os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGHUP)
	var err error
	select {
	case <-f.IsClose():
		f.appendDebug("got closed")
	case <-signalChan:
		f.appendDebug("got signal")
		f.Stop()
	case err = <-f.errChan:
		f.appendDebug(fmt.Sprintf("got error: %v", err))

		if err != nil {
			f.Stop()
		}
	}

	go func() {
		<-signalChan
		// force close
		println("force close")
		os.Exit(1)
	}()

	f.wait()
	return err
}
<commit_msg>change close to stop<commit_after>package flow

import (
	"bytes"
	"fmt"
	"os"
	"os/signal"
	"path"
	"reflect"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

var (
	pkgPath      = reflect.TypeOf(Flow{}).PkgPath()
	DefaultDebug = false
)

type debugInfo struct {
	Stack string
	Info  string
}

func (d *debugInfo) String() string {
	return d.Stack + " - " + d.Info
}

type Flow struct {
	errChan  chan error
	stopChan chan struct{}
	ref      *int32
	wg       sync.WaitGroup
	Parent   *Flow
	Children []*Flow
	stoped   int32
	exited   int32
	onClose  []func()
	id       uintptr

	mutex   sync.Mutex
	debug   []debugInfo
	printed int32
}

func NewEx(n int) *Flow {
	f := &Flow{
		errChan:  make(chan error, 1),
		stopChan: make(chan struct{}),
		ref:      new(int32),
	}
	f.appendDebug("init")
	return f
}

func New() *Flow {
	return NewEx(0)
}

func (f *Flow) MarkExit() bool {
	return atomic.CompareAndSwapInt32(&f.exited, 0, 1)
}

func (f *Flow) IsExit() bool {
	return atomic.LoadInt32(&f.exited) == 1
}

func (f *Flow) printDebug() {
	buf := bytes.NewBuffer(nil)
	maxLength := 0
	for _, d := range f.debug {
		if maxLength < len(d.Stack) {
			maxLength = len(d.Stack)
		}
	}
	fill := func(a string, n int) string {
		return a + strings.Repeat(" ", n-len(a))
	}
	buf.WriteString("\n")
	for _, d := range f.debug {
		buf.WriteString(fmt.Sprint(&f) + " ")
		buf.WriteString(fill(d.Stack, maxLength) + " - " + d.Info + "\n")
	}
	print(buf.String())
}

func (f *Flow) appendDebug(info string) {
	pc, fp, line, _ := runtime.Caller(f.getCaller())
	name := runtime.FuncForPC(pc).Name()
	stack := fmt.Sprintf("%v:%v %v", path.Base(fp), line, path.Base(name))
	f.debug = append(f.debug, debugInfo{stack, info})
}

func (f *Flow) SetOnClose(exit func()) *Flow {
	f.onClose = []func(){exit}
	return f
}

func (f *Flow) AddOnClose(exit func()) *Flow {
	f.onClose = append(f.onClose, exit)
	return f
}

const (
	F_CLOSED  = true
	F_TIMEOUT = false
)

func (f *Flow) Tick(t *time.Ticker) bool {
	select {
	case <-t.C:
		return F_TIMEOUT
	case <-f.IsClose():
		return F_CLOSED
	}
}

func (f *Flow) CloseOrWait(duration time.Duration) bool {
	select {
	case <-time.After(duration):
		return F_TIMEOUT
	case <-f.IsClose():
		return F_CLOSED
	}
}

func (f *Flow) Error(err error) {
	f.errChan <- err
}

func (f *Flow) ForkTo(ref **Flow, exit func()) {
	*ref = f.Fork(0).AddOnClose(exit)
}

func (f *Flow) Fork(n int) *Flow {
	f2 := NewEx(n)
	f2.Parent = f
	// TODO(chzyer): test it !
	f2.errChan = f.errChan
	f.Children = append(f.Children, f2)
	f.Add(1) // for f2
	return f2
}

func (f *Flow) StopAll() {
	flow := f
	for flow.Parent != nil {
		flow = flow.Parent
	}
	flow.Stop()
}

func (f *Flow) Close() {
	f.appendDebug("close")
	f.close()
}

func (f *Flow) close() {
	f.Stop()
	f.wait()
}

func (f *Flow) Stop() {
	if !atomic.CompareAndSwapInt32(&f.stoped, 0, 1) {
		return
	}
	f.appendDebug("stop")

	close(f.stopChan)
	for _, cf := range f.Children {
		cf.Stop()
	}
	if len(f.onClose) > 0 {
		go func() {
			for _, f := range f.onClose {
				f()
			}
		}()
	}
}

func (f *Flow) IsClosed() bool {
	return atomic.LoadInt32(&f.stoped) == 1
}

func (f *Flow) IsClose() chan struct{} {
	return f.stopChan
}

func (f *Flow) Add(n int) {
	atomic.AddInt32(f.ref, int32(n))
	f.appendDebug(fmt.Sprintf("add: %v, ref: %v", n, *f.ref))
	f.wg.Add(n)
}

func (f *Flow) getCaller() int {
	for i := 0; ; i++ {
		pc, _, _, ok := runtime.Caller(i)
		if !ok {
			break
		}
		f := runtime.FuncForPC(pc).Name()
		if !strings.HasPrefix(f, pkgPath) {
			return i - 1
		}
	}
	return 0
}

func (f *Flow) Done() {
	f.wg.Done()
	if atomic.AddInt32(f.ref, -1) == 0 {
		f.Stop()
	}
}

func (f *Flow) DoneAndClose() {
	f.Done()
	f.appendDebug(fmt.Sprintf("done and close, ref: %v", *f.ref))
	f.Stop()
}

func (f *Flow) wait() {
	f.appendDebug("wait")

	done := make(chan struct{})
	printed := int32(0)
	if DefaultDebug && atomic.CompareAndSwapInt32(&f.printed, 0, 1) {
		go func() {
			select {
			case <-done:
				return
			case <-time.After(1000 * time.Millisecond):
				f.printDebug()
				atomic.StoreInt32(&printed, 1)
			}
		}()
	}
	<-f.stopChan
	f.wg.Wait()
	close(done)
	if atomic.LoadInt32(&printed) == 1 {
		println(fmt.Sprint(&f) + " - exit")
	}

	if f.Parent != nil {
		f.Parent.Done()
		f.Parent = nil
	}
}

func (f *Flow) Wait() error {
	signalChan := make(chan os.Signal)
	signal.Notify(signalChan,
		os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGHUP)
	var err error
	select {
	case <-f.IsClose():
		f.appendDebug("got closed")
	case <-signalChan:
		f.appendDebug("got signal")
		f.Stop()
	case err = <-f.errChan:
		f.appendDebug(fmt.Sprintf("got error: %v", err))

		if err != nil {
			f.Stop()
		}
	}

	go func() {
		<-signalChan
		// force close
		println("force close")
		os.Exit(1)
	}()

	f.wait()
	return err
}
<|endoftext|>


<commit_before>package cairo

//#cgo pkg-config: cairo
//#include <stdlib.h>
//#include <cairo/cairo.h>
import "C"

import (
	"runtime"
	"unsafe"
)

//FontOptions specify how fonts should be rendered.
//Most of the time the font options implied by a surface are just right
//and do not need changes, but, for pixel-based targets, tweaking font options
//may result in superior output on a particular display.
//
//Originally cairo_font_options_t.
type FontOptions struct {
	fo *C.cairo_font_options_t
}

//NewFontOptions creates a new FontOptions with the default values.
//
//Originally cairo_font_options_create.
func NewFontOptions() *FontOptions {
	fo := &FontOptions{C.cairo_font_options_create()}
	runtime.SetFinalizer(fo, (*FontOptions).Close)
	return fo
}

func initFontOptions(opt *C.cairo_font_options_t) *FontOptions {
	fo := &FontOptions{opt}
	runtime.SetFinalizer(fo, (*FontOptions).Close)
	return fo
}

//Close destroys the FontOptions. Close is idempotent.
//
//Originally cairo_font_options_destroy.
func (f *FontOptions) Close() error {
	if f == nil || f.fo == nil {
		return nil
	}
	C.cairo_font_options_destroy(f.fo)
	f.fo = nil
	runtime.SetFinalizer(f, nil)
	return nil
}

//Error queries f to see if there is an error.
//
//Originally cairo_font_options_status.
func (f *FontOptions) Err() error {
	return toerr(C.cairo_font_options_status(f.fo))
}

//Merge merges non-default options from o into f and return f.
//
//Originally cairo_font_options_merge.
func (f *FontOptions) Merge(o *FontOptions) *FontOptions {
	C.cairo_font_options_merge(f.fo, o.fo)
	return f
}

//Clone creates a new FontOptions with the same values as f.
//
//Originally cairo_font_options_copy.
func (f *FontOptions) Clone() *FontOptions {
	return &FontOptions{C.cairo_font_options_copy(f.fo)}
}

//Equal compares f with o.
//
//Originally cairo_font_options_equal.
func (f *FontOptions) Equal(o *FontOptions) bool {
	return C.cairo_font_options_equal(f.fo, o.fo) == 1
}

//SetAntialiasMode sets the antialiasing mode of f and returns f.
//
//Originally cairo_font_options_set_antialias.
func (f *FontOptions) SetAntialiasMode(a antialias) *FontOptions {
	C.cairo_font_options_set_antialias(f.fo, C.cairo_antialias_t(a))
	return f
}

//AntialiasMode reports the antialiasing mode of f.
//
//Originally cairo_font_topns_get_antialias.
func (f *FontOptions) AntialiasMode() antialias {
	return antialias(C.cairo_font_options_get_antialias(f.fo))
}

//SetSubpixelOrder sets the subpixel ordering of f and returns f.
//
//Originally cairo_font_options_set_subpixel_order.
func (f *FontOptions) SetSubpixelOrder(s subpixelOrder) *FontOptions {
	C.cairo_font_options_set_subpixel_order(f.fo, C.cairo_subpixel_order_t(s))
	return f
}

//SubpixelOrder reports the subpixel ordering of f.
//
//Originally cairo_font_options_get_subpixel_order.
func (f *FontOptions) SubpixelOrder() subpixelOrder {
	return subpixelOrder(C.cairo_font_options_get_subpixel_order(f.fo))
}

//SetHintStyle sets the hint style of f and returns f.
//
//Originally cairo_font_options_set_hint_style.
func (f *FontOptions) SetHintStyle(h hintStyle) *FontOptions {
	C.cairo_font_options_set_hint_style(f.fo, C.cairo_hint_style_t(h))
	return f
}

//HintStyle reports the hint style of f.
//
//Originally cairo_font_options_get_hint_style.
func (f *FontOptions) HintStyle() hintStyle {
	return hintStyle(C.cairo_font_options_get_hint_style(f.fo))
}

//SetHintMetrics sets the hint metrics of f and returns f.
//
//Originally cairo_font_options_set_hint_metrics.
func (f *FontOptions) SetHintMetrics(h hintMetrics) *FontOptions {
	C.cairo_font_options_set_hint_metrics(f.fo, C.cairo_hint_metrics_t(h))
	return f
}

//HintMetrics reports the hint metrics of f.
//
//Originally cairo_font_options_get_hint_metrics.
func (f *FontOptions) HintMetrics() hintMetrics {
	return hintMetrics(C.cairo_font_options_get_hint_metrics(f.fo))
}

//FontExtents stores metric information for a font.
//Values are given in the current user-space coordinate system.
//
//Because font metrics are in user-space coordinates, they are mostly,
//but not entirely, independent of the current transformation matrix.
//They will, however, change slightly due to hinting but otherwise remain
//unchanged.
//
//Originally cairo_font_extents_t.
type FontExtents struct {
	//Ascent is the distance the font extends above the baseline.
	Ascent float64
	//Descent is the distance the font extends below the baseline.
	Descent float64
	//Height is the recommended vertical distance between baselines
	//when setting consecutive lines of text with the font.
	Height float64
	//MaxAdvanceX is the maximum distance in the X direction that
	//the origin is advanced for any glyph in the font.
	//
	//Originally max_y_advance.
	MaxAdvanceX float64
	//MaxAdvanceY is the maximum distance in the Y direction that
	//the origin is advanced for any glyph in the font.
	//
	//This will be zero for most fonts used for horizontal writing.
	//
	//Originally max_x_advance.
	MaxAdvanceY float64
}

func newFontExtents(fe C.cairo_font_extents_t) FontExtents {
	return FontExtents{
		float64(fe.ascent),
		float64(fe.descent),
		float64(fe.height),
		float64(fe.max_x_advance),
		float64(fe.max_y_advance),
	}
}

//ExternalLeading reports the difference between the Height and the sum
//of the Ascent and Descent. Also known as "line spacing".
func (f FontExtents) ExternalLeading() float64 {
	return f.Height - (f.Ascent + f.Descent)
}

//TextExtents stores the extents of a single glyph or string of glyphs
//in user-space coordinates.
//Because text extents are in user-space coordinates, they are mostly,
//but not entirely, independent of the current transformation matrix.
//They will, however, change slightly due to hinting.
//
//Originally cairo_text_extents_t.
type TextExtents struct {
	//The horizontal distance from the origin to the leftmost part of the glyhps
	//as drawn.
	//Positive if the glyphs lie entirely to the right of the origin.
	//
	//Originally x_bearing.
	BearingX float64
	//The vertical distance from the origin to the topmost part of the glyhps
	//as drawn.
	//Positive if the glyphs lie entirely below the origin.
	//
	//Originally y_bearing.
	BearingY float64
	//Width of the glyphs as drawn.
	Width float64
	//Height of the glyphs as drawn.
	Height float64
	//AdvanceX is the distance in the X direction to advance after drawing
	//these glyphs.
	//
	//Originally x_advance.
	AdvanceX float64
	//AdvanceY is the distance in the Y direction to advance after drawing
	//these glyphs.
	//
	//This will be zero for most fonts used for horizontal writing.
	//
	//Originally y_advance.
	AdvanceY float64
}

func newTextExtents(te C.cairo_text_extents_t) TextExtents {
	return TextExtents{
		BearingX: float64(te.x_bearing),
		BearingY: float64(te.y_bearing),
		Width:    float64(te.width),
		Height:   float64(te.height),
		AdvanceX: float64(te.x_advance),
		AdvanceY: float64(te.y_advance),
	}
}

//Glyph holds information about a single glyph when drawing or measuring text.
//A font is (in simple terms) a collection of shapes used to draw text.
//A glyph is one of these shapes.
//There can be multiple glyphs for a single character (alternates to be used
//in different contexts, for example), or a glyph can be a ligature of multiple
//characters.
//Cairo doesn't expose any way of converting input text into glyphs,
//so in order to use the Cairo interfaces that take arrays of glyphs, you must
//directly access the appropriate underlying font system.
//
//Note that the offsets given by Point.X and Point.Y are not cumulative.
//When drawing or measuring text, each glyph is individually positioned with respect to the overall origin
//
//Originally cairo_glyph_t.
type Glyph struct {
	Index uint64
	Point Point
}

func cGlyph(g C.cairo_glyph_t) Glyph {
	return Glyph{
		Index: uint64(g.index),
		Point: cPt(g.x, g.y),
	}
}

func cGlyphs(glyphs *C.cairo_glyph_t, N C.int) []Glyph {
	n := int(N)
	gs := (*[1 << 30]C.cairo_glyph_t)(unsafe.Pointer(glyphs))[:n:n]
	out := make([]Glyph, n)
	for i, v := range gs {
		out[i] = cGlyph(v)
	}
	return out
}

func glyphsC(gs []Glyph) (glyphs *C.cairo_glyph_t, N C.int) {
	n := len(gs)
	N = C.int(n)
	var t C.cairo_glyph_t
	glyphs = (*C.cairo_glyph_t)(C.malloc(C.size_t(uintptr(n) * unsafe.Sizeof(t))))
	iter := (*[1 << 30]C.cairo_glyph_t)(unsafe.Pointer(glyphs))[:n:n]
	for i, g := range gs {
		iter[i] = g.c()
	}
	return
}

func (g Glyph) c() C.cairo_glyph_t {
	out := C.cairo_glyph_t{}
	out.index = C.ulong(g.Index)
	out.x, out.y = g.Point.c()
	return out
}

type Font interface {
	Type() fontType
	Close() error
	Err() error
	//TODO
	XtensionRaw() *C.cairo_font_face_t
}

type XtensionFont struct {
	f *C.cairo_font_face_t
}

func cFont(f *C.cairo_font_face_t) (Font, error) {
	return nil, nil //TODO
}

type ScaledFont struct {
	//TODO
	f *C.cairo_scaled_font_t
}

func cNewScaledFont(f *C.cairo_scaled_font_t) *ScaledFont {
	return nil //TODO
}

//Originally cairo_text_cluster_t.
type TextCluster struct {
	RuneLength, NumGlyphs int
}

func clustersC(tcs []TextCluster) (*C.cairo_text_cluster_t, C.int) {
	return nil, 0 //TODO
}
<commit_msg>docs, extension api, and toy fonts added<commit_after>package cairo

//#cgo pkg-config: cairo
//#include <stdlib.h>
//#include <cairo/cairo.h>
import "C"

import (
	"runtime"
	"unsafe"
)

//FontOptions specify how fonts should be rendered.
//Most of the time the font options implied by a surface are just right
//and do not need changes, but, for pixel-based targets, tweaking font options
//may result in superior output on a particular display.
//
//Originally cairo_font_options_t.
type FontOptions struct {
	fo *C.cairo_font_options_t
}

//NewFontOptions creates a new FontOptions with the default values.
//
//Originally cairo_font_options_create.
func NewFontOptions() *FontOptions {
	return initFontOptions(C.cairo_font_options_create())
}

func initFontOptions(opt *C.cairo_font_options_t) *FontOptions {
	fo := &FontOptions{opt}
	runtime.SetFinalizer(fo, (*FontOptions).Close)
	return fo
}

//Close destroys the FontOptions. Close is idempotent.
//
//Originally cairo_font_options_destroy.
func (f *FontOptions) Close() error {
	if f == nil || f.fo == nil {
		return nil
	}
	err := f.Err()
	C.cairo_font_options_destroy(f.fo)
	f.fo = nil
	runtime.SetFinalizer(f, nil)
	return err
}

//Error queries f to see if there is an error.
//
//Originally cairo_font_options_status.
func (f *FontOptions) Err() error {
	return toerr(C.cairo_font_options_status(f.fo))
}

//Merge merges non-default options from o into f and return f.
//
//Originally cairo_font_options_merge.
func (f *FontOptions) Merge(o *FontOptions) *FontOptions {
	C.cairo_font_options_merge(f.fo, o.fo)
	return f
}

//Clone creates a new FontOptions with the same values as f.
//
//Originally cairo_font_options_copy.
func (f *FontOptions) Clone() *FontOptions {
	return &FontOptions{C.cairo_font_options_copy(f.fo)}
}

//Equal compares f with o.
//
//Originally cairo_font_options_equal.
func (f *FontOptions) Equal(o *FontOptions) bool {
	return C.cairo_font_options_equal(f.fo, o.fo) == 1
}

//SetAntialiasMode sets the antialiasing mode of f and returns f.
//
//Originally cairo_font_options_set_antialias.
func (f *FontOptions) SetAntialiasMode(a antialias) *FontOptions {
	C.cairo_font_options_set_antialias(f.fo, C.cairo_antialias_t(a))
	return f
}

//AntialiasMode reports the antialiasing mode of f.
//
//Originally cairo_font_topns_get_antialias.
func (f *FontOptions) AntialiasMode() antialias {
	return antialias(C.cairo_font_options_get_antialias(f.fo))
}

//SetSubpixelOrder sets the subpixel ordering of f and returns f.
//
//Originally cairo_font_options_set_subpixel_order.
func (f *FontOptions) SetSubpixelOrder(s subpixelOrder) *FontOptions {
	C.cairo_font_options_set_subpixel_order(f.fo, C.cairo_subpixel_order_t(s))
	return f
}

//SubpixelOrder reports the subpixel ordering of f.
//
//Originally cairo_font_options_get_subpixel_order.
func (f *FontOptions) SubpixelOrder() subpixelOrder {
	return subpixelOrder(C.cairo_font_options_get_subpixel_order(f.fo))
}

//SetHintStyle sets the hint style of f and returns f.
//
//Originally cairo_font_options_set_hint_style.
func (f *FontOptions) SetHintStyle(h hintStyle) *FontOptions {
	C.cairo_font_options_set_hint_style(f.fo, C.cairo_hint_style_t(h))
	return f
}

//HintStyle reports the hint style of f.
//
//Originally cairo_font_options_get_hint_style.
func (f *FontOptions) HintStyle() hintStyle {
	return hintStyle(C.cairo_font_options_get_hint_style(f.fo))
}

//SetHintMetrics sets the hint metrics of f and returns f.
//
//Originally cairo_font_options_set_hint_metrics.
func (f *FontOptions) SetHintMetrics(h hintMetrics) *FontOptions {
	C.cairo_font_options_set_hint_metrics(f.fo, C.cairo_hint_metrics_t(h))
	return f
}

//HintMetrics reports the hint metrics of f.
//
//Originally cairo_font_options_get_hint_metrics.
func (f *FontOptions) HintMetrics() hintMetrics {
	return hintMetrics(C.cairo_font_options_get_hint_metrics(f.fo))
}

//FontExtents stores metric information for a font.
//Values are given in the current user-space coordinate system.
//
//Because font metrics are in user-space coordinates, they are mostly,
//but not entirely, independent of the current transformation matrix.
//They will, however, change slightly due to hinting but otherwise remain
//unchanged.
//
//Originally cairo_font_extents_t.
type FontExtents struct {
	//Ascent is the distance the font extends above the baseline.
	Ascent float64
	//Descent is the distance the font extends below the baseline.
	Descent float64
	//Height is the recommended vertical distance between baselines
	//when setting consecutive lines of text with the font.
	Height float64
	//MaxAdvanceX is the maximum distance in the X direction that
	//the origin is advanced for any glyph in the font.
	//
	//Originally max_y_advance.
	MaxAdvanceX float64
	//MaxAdvanceY is the maximum distance in the Y direction that
	//the origin is advanced for any glyph in the font.
	//
	//This will be zero for most fonts used for horizontal writing.
	//
	//Originally max_x_advance.
	MaxAdvanceY float64
}

func newFontExtents(fe C.cairo_font_extents_t) FontExtents {
	return FontExtents{
		float64(fe.ascent),
		float64(fe.descent),
		float64(fe.height),
		float64(fe.max_x_advance),
		float64(fe.max_y_advance),
	}
}

//ExternalLeading reports the difference between the Height and the sum
//of the Ascent and Descent. Also known as "line spacing".
func (f FontExtents) ExternalLeading() float64 {
	return f.Height - (f.Ascent + f.Descent)
}

//TextExtents stores the extents of a single glyph or string of glyphs
//in user-space coordinates.
//Because text extents are in user-space coordinates, they are mostly,
//but not entirely, independent of the current transformation matrix.
//They will, however, change slightly due to hinting.
//
//Originally cairo_text_extents_t.
type TextExtents struct {
	//The horizontal distance from the origin to the leftmost part of the glyhps
	//as drawn.
	//Positive if the glyphs lie entirely to the right of the origin.
	//
	//Originally x_bearing.
	BearingX float64
	//The vertical distance from the origin to the topmost part of the glyhps
	//as drawn.
	//Positive if the glyphs lie entirely below the origin.
	//
	//Originally y_bearing.
	BearingY float64
	//Width of the glyphs as drawn.
	Width float64
	//Height of the glyphs as drawn.
	Height float64
	//AdvanceX is the distance in the X direction to advance after drawing
	//these glyphs.
	//
	//Originally x_advance.
	AdvanceX float64
	//AdvanceY is the distance in the Y direction to advance after drawing
	//these glyphs.
	//
	//This will be zero for most fonts used for horizontal writing.
	//
	//Originally y_advance.
	AdvanceY float64
}

func newTextExtents(te C.cairo_text_extents_t) TextExtents {
	return TextExtents{
		BearingX: float64(te.x_bearing),
		BearingY: float64(te.y_bearing),
		Width:    float64(te.width),
		Height:   float64(te.height),
		AdvanceX: float64(te.x_advance),
		AdvanceY: float64(te.y_advance),
	}
}

//Glyph holds information about a single glyph when drawing or measuring text.
//A font is (in simple terms) a collection of shapes used to draw text.
//A glyph is one of these shapes.
//There can be multiple glyphs for a single character (alternates to be used
//in different contexts, for example), or a glyph can be a ligature of multiple
//characters.
//Cairo doesn't expose any way of converting input text into glyphs,
//so in order to use the Cairo interfaces that take arrays of glyphs, you must
//directly access the appropriate underlying font system.
//
//Note that the offsets given by Point.X and Point.Y are not cumulative.
//When drawing or measuring text, each glyph is individually positioned with respect to the overall origin
//
//Originally cairo_glyph_t.
type Glyph struct {
	Index uint64
	Point Point
}

func cGlyph(g C.cairo_glyph_t) Glyph {
	return Glyph{
		Index: uint64(g.index),
		Point: cPt(g.x, g.y),
	}
}

func cGlyphs(glyphs *C.cairo_glyph_t, N C.int) []Glyph {
	n := int(N)
	gs := (*[1 << 30]C.cairo_glyph_t)(unsafe.Pointer(glyphs))[:n:n]
	out := make([]Glyph, n)
	for i, v := range gs {
		out[i] = cGlyph(v)
	}
	return out
}

func glyphsC(gs []Glyph) (glyphs *C.cairo_glyph_t, N C.int) {
	n := len(gs)
	N = C.int(n)
	var t C.cairo_glyph_t
	glyphs = (*C.cairo_glyph_t)(C.malloc(C.size_t(uintptr(n) * unsafe.Sizeof(t))))
	iter := (*[1 << 30]C.cairo_glyph_t)(unsafe.Pointer(glyphs))[:n:n]
	for i, g := range gs {
		iter[i] = g.c()
	}
	return
}

func (g Glyph) c() C.cairo_glyph_t {
	out := C.cairo_glyph_t{}
	out.index = C.ulong(g.Index)
	out.x, out.y = g.Point.c()
	return out
}

//Font specifies all aspects of a font other than the size or font matrix.
//
//All methods are documented on XtensionFont
//
//Originally cairo_font_face_t.
type Font interface {
	Type() fontType
	Close() error
	Err() error
	XtensionRaw() *C.cairo_font_face_t
}

//XtensionFont is the "base class" of cairo fonts.
//
//It is meant only for embedding in new font types and should NEVER
//be used directly.
type XtensionFont struct {
	f *C.cairo_font_face_t
}

//NewXtensionFont creates a base go font from a c font face.
//
//This is only for extension builders.
func NewXtensionFont(f *C.cairo_font_face_t) *XtensionFont {
	x := &XtensionFont{
		f: f,
	}
	runtime.SetFinalizer(f, (*XtensionFont).Close)
	return x
}

var cfonttogofont = map[fontType]func(*C.cairo_font_face_t) (Font, error){
	FontTypeToy: newToyFont,
}

//XtensionRegisterRawToFont registers a factory to convert a libcairo
//font face into a properly formed cairo Font of the appropriate
//underlying type.
//
//It is mandatory for extensions defining new font types to call this
//during init, otherwise users will get random not implemented panics
//for your font.
func XtensionRegisterRawToFont(t fontType, f func(*C.cairo_font_face_t) (Font, error)) {
	cfonttogofont[t] = f
}

func cFont(f *C.cairo_font_face_t) (Font, error) {
	t := fontType(C.cairo_font_face_get_type(f))
	fac, ok := cfonttogofont[t]
	if !ok {
		panic("No C → Go font converter registered for " + t.String())
	}
	F, err := fac(f)
	if err != nil {
		return nil, err
	}
	err = F.Err()
	if err != nil {
		return nil, err
	}
	return F, nil
}

//Originally cairo_font_face_get_type.
func (f *XtensionFont) Type() fontType {
	return fontType(C.cairo_font_face_get_type(f.f))
}

//Close frees the resources used by this font.
//
//Originally cairo_font_face_destroy.
func (f *XtensionFont) Close() error {
	if f == nil || f.f == nil {
		return nil
	}
	err := f.Err()
	C.cairo_font_face_destroy(f.f)
	f.f = nil
	runtime.SetFinalizer(f, nil)
	return err
}

//Err reports any errors on this font.
//
//Originally cairo_font_face_status.
func (f *XtensionFont) Err() error {
	return toerr(C.cairo_font_face_status(f.f))
}

//XtensionRaw return the raw cairo_font_face_t pointer.
//
//XtensionRaw is only meant for creating new font types and should NEVER
//be used directly.
func (f *XtensionFont) XtensionRaw() *C.cairo_font_face_t {
	return f.f
}

//ToyFont is a Font created by the libcairo "toy" font API.
//
//See Context.SelectFace for more details.
type ToyFont struct {
	*XtensionFont
	slant  slant
	weight weight
	family string
}

func cNewToyFont(f *C.cairo_font_face_t, family string, s slant, w weight) ToyFont {
	return ToyFont{
		XtensionFont: NewXtensionFont(f),
		slant:        s,
		weight:       w,
		family:       family,
	}
}

func newToyFont(f *C.cairo_font_face_t) (Font, error) {
	family := C.GoString(C.cairo_toy_font_face_get_family(f))
	s := slant(C.cairo_toy_font_face_get_slant(f))
	w := weight(C.cairo_toy_font_face_get_weight(f))
	F := cNewToyFont(f, family, s, w)
	return F, F.Err()
}

//NewToyFont creates a toy font of the given family, slant, and weight.
//
//If family is "", the default toy font for the given platform will be used,
//typically sans-serif.
//
//See Context.SelectFont for more details.
//
//Originally cairo_toy_font_face_create.
func NewToyFont(family string, slant slant, weight weight) ToyFont {
	s := C.CString(family)
	f := C.cairo_toy_font_face_create(s, slant.c(), weight.c())
	C.free(unsafe.Pointer(s))
	return cNewToyFont(f, family, slant, weight)
}

type ScaledFont struct {
	//TODO
	f *C.cairo_scaled_font_t
}

func cNewScaledFont(f *C.cairo_scaled_font_t) *ScaledFont {
	return nil //TODO
}

//Originally cairo_text_cluster_t.
type TextCluster struct {
	RuneLength, NumGlyphs int
}

func clustersC(tcs []TextCluster) (*C.cairo_text_cluster_t, C.int) {
	return nil, 0 //TODO
}
<|endoftext|>


<commit_before>package moka

import (
	"fmt"
	"reflect"
	"strings"
)

type Interaction interface {
	Call(methodName string, args []interface{}) ([]interface{}, bool)
	Verify() error
}

type AllowedInteraction struct {
	methodName   string
	args         []interface{}
	returnValues []interface{}
}

func NewInteraction(methodName string, args []interface{}, returnValues []interface{}) Interaction {
	return AllowedInteraction{methodName: methodName, args: args, returnValues: returnValues}
}

func (i AllowedInteraction) Call(methodName string, args []interface{}) ([]interface{}, bool) {
	methodNamesAreEqual := i.methodName == methodName
	argsAreEqual := reflect.DeepEqual(i.args, args)

	if methodNamesAreEqual && argsAreEqual {
		return i.returnValues, true
	}

	return nil, false
}

func (i AllowedInteraction) Verify() error {
	return nil
}

func (i AllowedInteraction) String() string {
	stringArgs := []string{}
	for _, arg := range i.args {
		stringArgs = append(stringArgs, fmt.Sprintf("%#v", arg))
	}

	return fmt.Sprintf("%s(%s)", i.methodName, strings.Join(stringArgs, ", "))
}

type ExpectedInteraction struct {
	Interaction
	called bool
}

func NewExpectedInteraction(interaction Interaction) Interaction {
	return &ExpectedInteraction{Interaction: interaction}
}

func (i *ExpectedInteraction) Call(methodName string, args []interface{}) ([]interface{}, bool) {
	returnValues, matches := i.Interaction.Call(methodName, args)
	i.called = matches
	return returnValues, matches
}

func (i *ExpectedInteraction) Verify() error {
	if !i.called {
		return fmt.Errorf("Expected interaction: %s", i.Interaction)
	}

	return nil
}
<commit_msg>Make the concrete Interaction types private<commit_after>package moka

import (
	"fmt"
	"reflect"
	"strings"
)

type Interaction interface {
	Call(methodName string, args []interface{}) ([]interface{}, bool)
	Verify() error
}

type allowedInteraction struct {
	methodName   string
	args         []interface{}
	returnValues []interface{}
}

func NewInteraction(methodName string, args []interface{}, returnValues []interface{}) Interaction {
	return allowedInteraction{methodName: methodName, args: args, returnValues: returnValues}
}

func (i allowedInteraction) Call(methodName string, args []interface{}) ([]interface{}, bool) {
	methodNamesAreEqual := i.methodName == methodName
	argsAreEqual := reflect.DeepEqual(i.args, args)

	if methodNamesAreEqual && argsAreEqual {
		return i.returnValues, true
	}

	return nil, false
}

func (i allowedInteraction) Verify() error {
	return nil
}

func (i allowedInteraction) String() string {
	stringArgs := []string{}
	for _, arg := range i.args {
		stringArgs = append(stringArgs, fmt.Sprintf("%#v", arg))
	}

	return fmt.Sprintf("%s(%s)", i.methodName, strings.Join(stringArgs, ", "))
}

type expectedInteraction struct {
	interaction Interaction
	called      bool
}

func NewExpectedInteraction(interaction Interaction) Interaction {
	return &expectedInteraction{interaction: interaction}
}

func (i *expectedInteraction) Call(methodName string, args []interface{}) ([]interface{}, bool) {
	returnValues, matches := i.interaction.Call(methodName, args)
	i.called = matches
	return returnValues, matches
}

func (i *expectedInteraction) Verify() error {
	if !i.called {
		return fmt.Errorf("Expected interaction: %s", i.interaction)
	}

	return nil
}
<|endoftext|>


<commit_before>package lbricks

type Game struct {
	Pool        EntityPool
	EventSystem Responder
}

func (g *Game) InitContext() {
	g.EventSystem := &EventSystem{}
	graphPool := CreateGraphPool()
	g.EntityPool = CreateEntityPool(graphPool)
}
<commit_msg>GameGraphs<commit_after>package lbricks

type Game struct {
	Pool        EntityPool
	EventSystem Responder
}

func (g *Game) InitContext() {
	g.EventSystem := &EventSystem{}
	graphPool := CreateGraphPool()
	graphPool.AddProvider("preloadGraph", preloadGraph)
	graphPool.AddProvider("setupGraph", setupGraph)
	g.EntityPool = CreateEntityPool(graphPool)
}

func preloadGraph() (*flow.Graph, map[string]chan *EventPacked){

}

func setupGraph() (*flow.Graph, map[string]chan *EventPacked){

}

<|endoftext|>


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

package tagging

import (
	"k8s.io/klog/v2"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)

// eksResourceTagPrefix is the prefix for tag to group resources that are used by eks
// for a particular cluster, this tag is added to the existing tags.
// Example: "Key1=Val1,aws:eks:cluster-name:my-cluster=Val2"
const eksResourceTagPrefix = "aws:eks:cluster-name:"

// TaggingController is the controller implementation for tagging cluster resources
type TaggingController struct {
}

// NewTaggingController creates a NewTaggingController object
func NewTaggingController() (*TaggingController, error) {
	tc := &TaggingController{
	}

	return tc, nil
}

// Run will start the controller to tag resources attached to a cluster
// and untag resources detached from a cluster.
func (tc *TaggingController) Run(stopCh <-chan struct{}) {
	defer utilruntime.HandleCrash()
	klog.Infof("Running the TaggingController, eksResourceTagPrefix is %s.", eksResourceTagPrefix)

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

package tagging

import (
	"k8s.io/klog/v2"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)

// TaggingController is the controller implementation for tagging cluster resources
type TaggingController struct {
}

// NewTaggingController creates a NewTaggingController object
func NewTaggingController() (*TaggingController, error) {
	tc := &TaggingController{
	}

	return tc, nil
}

// Run will start the controller to tag resources attached to a cluster
// and untag resources detached from a cluster.
func (tc *TaggingController) Run(stopCh <-chan struct{}) {
	defer utilruntime.HandleCrash()
	klog.Infof("Running the TaggingController")

	<-stopCh
}<|endoftext|>