<commit_before>package sflow

import (
	"encoding/binary"
	"errors"
	"io"
)

const (
	// MaximumRecordLength defines the maximum length in bytes, acceptable for records while decoding.
	// This maximum prevents from excessive memory allocation for decoding.
	// The value is derived from MAX_PKT_SIZ 65536 in sflow reference implementation
	// https://github.com/sflow/sflowtool/blob/bd3df6e11bdf8261a42734c619abfe8b46e1202f/src/sflowtool.c#L4313
	MaximumRecordLength = 65536

	// MaximumHeaderLength defines the maximum length in bytes, acceptable for packet flow samples while decoding.
	// This maximum prevents from excessive memory allocation for decoding.
	// The value is derived from INM_MAX_HEADER_SIZE 256 in sflow reference implementation
	// https://github.com/sflow/sflowtool/blob/bd3df6e11bdf8261a42734c619abfe8b46e1202f/src/sflowtool.h#L28
	MaximumHeaderLength = 256
)

var ErrUnsupportedDatagramVersion = errors.New("sflow: unsupported datagram version")

type Decoder struct {
	reader io.ReadSeeker
}

func NewDecoder(r io.ReadSeeker) *Decoder {
	return &Decoder{
		reader: r,
	}
}

func (d *Decoder) Use(r io.ReadSeeker) {
	d.reader = r
}

func (d *Decoder) Decode() (*Datagram, error) {
	// Decode headers first
	dgram := &Datagram{}
	var err error

	err = binary.Read(d.reader, binary.BigEndian, &dgram.Version)
	if err != nil {
		return nil, err
	}

	if dgram.Version != 5 {
		return nil, ErrUnsupportedDatagramVersion
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.IpVersion)
	if err != nil {
		return nil, err
	}

	ipLen := 4
	if dgram.IpVersion == 2 {
		ipLen = 16
	}

	ipBuf := make([]byte, ipLen)
	_, err = d.reader.Read(ipBuf)
	if err != nil {
		return nil, err
	}

	dgram.IpAddress = ipBuf

	err = binary.Read(d.reader, binary.BigEndian, &dgram.SubAgentId)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.SequenceNumber)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.Uptime)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.NumSamples)
	if err != nil {
		return nil, err
	}

	for i := dgram.NumSamples; i > 0; i-- {
		sample, err := decodeSample(d.reader)
		if err != nil {
			return nil, err
		}

		dgram.Samples = append(dgram.Samples, sample)
	}

	return dgram, nil
}
<commit_msg>Revert "Changed maximum header size to 256"<commit_after>package sflow

import (
	"encoding/binary"
	"errors"
	"io"
)

const (
	// MaximumRecordLength defines the maximum length in bytes, acceptable for records while decoding.
	// This maximum prevents from excessive memory allocation for decoding.
	// The value is derived from MAX_PKT_SIZ 65536 in sflow reference implementation
	// https://github.com/sflow/sflowtool/blob/bd3df6e11bdf8261a42734c619abfe8b46e1202f/src/sflowtool.c#L4313
	MaximumRecordLength = 65536

	// MaximumHeaderLength defines the maximum length in bytes, acceptable for packet flow samples while decoding.
	// This maximum prevents from excessive memory allocation for decoding.
	// The value is set to maximum transmission unit (MTU), as the header of a network packet may not exceed the MTU.
	MaximumHeaderLength = 1500
)

var ErrUnsupportedDatagramVersion = errors.New("sflow: unsupported datagram version")

type Decoder struct {
	reader io.ReadSeeker
}

func NewDecoder(r io.ReadSeeker) *Decoder {
	return &Decoder{
		reader: r,
	}
}

func (d *Decoder) Use(r io.ReadSeeker) {
	d.reader = r
}

func (d *Decoder) Decode() (*Datagram, error) {
	// Decode headers first
	dgram := &Datagram{}
	var err error

	err = binary.Read(d.reader, binary.BigEndian, &dgram.Version)
	if err != nil {
		return nil, err
	}

	if dgram.Version != 5 {
		return nil, ErrUnsupportedDatagramVersion
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.IpVersion)
	if err != nil {
		return nil, err
	}

	ipLen := 4
	if dgram.IpVersion == 2 {
		ipLen = 16
	}

	ipBuf := make([]byte, ipLen)
	_, err = d.reader.Read(ipBuf)
	if err != nil {
		return nil, err
	}

	dgram.IpAddress = ipBuf

	err = binary.Read(d.reader, binary.BigEndian, &dgram.SubAgentId)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.SequenceNumber)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.Uptime)
	if err != nil {
		return nil, err
	}

	err = binary.Read(d.reader, binary.BigEndian, &dgram.NumSamples)
	if err != nil {
		return nil, err
	}

	for i := dgram.NumSamples; i > 0; i-- {
		sample, err := decodeSample(d.reader)
		if err != nil {
			return nil, err
		}

		dgram.Samples = append(dgram.Samples, sample)
	}

	return dgram, nil
}
<|endoftext|>


<commit_before>package binny

import (
	"bufio"
	"bytes"
	"encoding"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"io"
	"reflect"
	"unsafe"
)

var (
	// ErrNoPointer gets returned if the user passes a non-pointer to Decode
	ErrNoPointer = errors.New("can't decode to a non-pointer")
)

const DefaultDecoderBufferSize = 4096

// Unmarshaler is the interface implemented by objects that can unmarshal a binary representation of themselves.
// Implementing this bypasses reflection and is generally faster.
type Unmarshaler interface {
	UnmarshalBinny(dec *Decoder) error
}

// A Decoder reads binary data from an input stream, it also does a little bit of buffering.
type Decoder struct {
	r *bufio.Reader

	buf [16]byte
}

// NewDecoder is an alias for NewDecoder(r, DefaultDecoderBufferSize)
func NewDecoder(r io.Reader) *Decoder {
	return NewDecoderSize(r, DefaultDecoderBufferSize)
}

// NewDecoder returns a new decoder that reads from r with specific buffer size.
//
// The decoder introduces its own buffering and may
// read data from r beyond the requested values.
func NewDecoderSize(r io.Reader, sz int) *Decoder {
	if sz < 16 {
		sz = 16
	}

	return &Decoder{
		r: bufio.NewReaderSize(r, sz),
	}
}

// Reset discards any buffered data, resets all state, and switches
// the buffered reader to read from r.
func (dec *Decoder) Reset(r io.Reader) {
	dec.r.Reset(r)
}

func (dec *Decoder) readType() (Type, error) {
	b, err := dec.r.ReadByte()
	return Type(b), err
}

func (dec *Decoder) peekType() Type {
	b, _ := dec.r.ReadByte()
	dec.r.UnreadByte()
	return Type(b)
}

func (dec *Decoder) expectType(et Type) error {
	if t, _ := dec.readType(); t != et {
		return DecoderTypeError{et.String(), t}
	}
	return nil
}

// ReadBool returns a bool or an error.
func (dec *Decoder) ReadBool() (bool, error) {
	ft, _ := dec.readType()
	switch ft {
	case BoolTrue:
		return true, nil
	case BoolFalse:
		return false, nil
	}
	return false, DecoderTypeError{"Bool", ft}
}

func (dec *Decoder) ReadInt8() (int8, error) {
	if err := dec.expectType(Int8); err != nil {
		return 0, err
	}
	b, err := dec.r.ReadByte()
	return int8(b), err
}

func (dec *Decoder) ReadInt16() (int16, error) {
	if err := dec.expectType(Int16); err != nil {
		return 0, err
	}
	buf := dec.buf[:2]
	_, err := dec.Read(buf)
	return *(*int16)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadInt32() (int32, error) {
	if err := dec.expectType(Int32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*int32)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadInt64() (int64, error) {
	if err := dec.expectType(Int64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*int64)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadVarInt() (int64, error) {
	if err := dec.expectType(VarInt); err != nil {
		return 0, err
	}
	return binary.ReadVarint(dec.r)
}

// ReadInt retruns an int/varint value and the size of it (8, 16, 32, 64) or an error.
func (dec *Decoder) ReadInt() (int64, uint8, error) {
	ft := dec.peekType()
	switch ft {
	case Int8:
		v, err := dec.ReadInt8()
		return int64(v), 8, err
	case Int16:
		v, err := dec.ReadInt16()
		return int64(v), 16, err
	case Int32:
		v, err := dec.ReadInt32()
		return int64(v), 32, err
	case Int64:
		v, err := dec.ReadInt64()
		return v, 64, err
	case VarInt:
		v, err := dec.ReadVarInt()
		return v, 64, err
	}
	return 0, 0, DecoderTypeError{"int", ft}
}

func (dec *Decoder) ReadUint8() (uint8, error) {
	if err := dec.expectType(Uint8); err != nil {
		return 0, err
	}
	return dec.r.ReadByte()
}

func (dec *Decoder) ReadUint16() (uint16, error) {
	if err := dec.expectType(Uint16); err != nil {
		return 0, err
	}
	buf := dec.buf[:2]
	_, err := dec.Read(buf)
	return *(*uint16)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadUint32() (uint32, error) {
	if err := dec.expectType(Uint32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*uint32)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadUint64() (uint64, error) {
	if err := dec.expectType(Uint64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*uint64)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadVarUint() (uint64, error) {
	if err := dec.expectType(VarUint); err != nil {
		return 0, err
	}
	return binary.ReadUvarint(dec.r)
}

// ReadUint retruns an uint/varuint value and the size of it (8, 16, 32, 64) or an error.
func (dec *Decoder) ReadUint() (v uint64, sz uint8, err error) {
	ft := dec.peekType()
	switch ft {
	case Uint8:
		v, err := dec.ReadUint8()
		return uint64(v), 8, err
	case Uint16:
		v, err := dec.ReadUint16()
		return uint64(v), 16, err
	case Uint32:
		v, err := dec.ReadUint32()
		return uint64(v), 32, err
	case Uint64:
		v, err := dec.ReadUint64()
		return v, 64, err
	case VarUint:
		v, err := dec.ReadVarUint()
		return v, 64, err
	}
	return 0, 0, DecoderTypeError{"uint", ft}
}

// ReadFloat32 returns a float32 or an error.
func (dec *Decoder) ReadFloat32() (float32, error) {
	if err := dec.expectType(Float32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*float32)(unsafe.Pointer(&buf[0])), err
}

// ReadFloat64 returns a float64 or an error.
func (dec *Decoder) ReadFloat64() (float64, error) {
	if err := dec.expectType(Float64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*float64)(unsafe.Pointer(&buf[0])), err
}

// ReadComplex64 returns a complex64 or an error.
func (dec *Decoder) ReadComplex64() (complex64, error) {
	if err := dec.expectType(Complex64); err != nil {
		return 0, err
	}

	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*complex64)(unsafe.Pointer(&buf[0])), err
}

// ReadComplex128 returns a complex128 or an error.
func (dec *Decoder) ReadComplex128() (complex128, error) {
	if err := dec.expectType(Complex128); err != nil {
		return 0, err
	}
	buf := dec.buf[:16]
	_, err := dec.Read(buf)
	return *(*complex128)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) readBytes(exp Type) ([]byte, error) {
	if err := dec.expectType(exp); err != nil {
		return nil, err
	}

	sz, _, err := dec.ReadUint()
	if err != nil || sz == 0 {
		return nil, err
	}

	buf := make([]byte, sz)
	_, err = io.ReadFull(dec.r, buf)
	return buf, err
}

// ReadBytes returns a byte slice.
func (dec *Decoder) ReadBytes() ([]byte, error) {
	return dec.readBytes(ByteSlice)
}

// ReadBytes returns a string.
func (dec *Decoder) ReadString() (string, error) {
	b, err := dec.readBytes(String)
	return string(b), err
}

// ReadBinary decodes and reads an object that implements the `encoding.BinaryUnmarshaler` interface.
func (dec *Decoder) ReadBinary(v encoding.BinaryUnmarshaler) error {
	b, err := dec.readBytes(Binary)
	if err != nil {
		return err
	}
	return v.UnmarshalBinary(b)
}

// ReadGob decodes and reads an object that implements the `gob.GobDecoder` interface.
func (dec *Decoder) ReadGob(v gob.GobDecoder) error {
	b, err := dec.readBytes(Gob)
	if err != nil {
		return err
	}
	return v.GobDecode(b)
}

// Decode reads the next binny-encoded value from its
// input and stores it in the value pointed to by v.
func (dec *Decoder) Decode(v interface{}) (err error) {
	switch v := v.(type) {
	case Unmarshaler:
		return v.UnmarshalBinny(dec)
	case encoding.BinaryUnmarshaler:
		return dec.ReadBinary(v)
	case gob.GobDecoder:
		return dec.ReadGob(v)
	case *string:
		*v, err = dec.ReadString()
		return
	case *[]byte:
		*v, err = dec.ReadBytes()
		return
	case *int64:
		*v, _, err = dec.ReadInt()
		return
	case *int32:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int32(i)
		return
	case *int16:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int16(i)
		return
	case *int8:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int8(i)
		return
	case *int:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int(i)
		return
	case *uint64:
		*v, _, err = dec.ReadUint()
		return
	case *uint32:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint32(i)
		return
	case *uint16:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint16(i)
		return
	case *uint8:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint8(i)
		return
	case *uint:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint(i)
		return
	case *uintptr:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uintptr(i)
		return
	case *float32:
		*v, err = dec.ReadFloat32()
		return
	case *float64:
		*v, err = dec.ReadFloat64()
		return
	case *complex64:
		*v, err = dec.ReadComplex64()
		return
	case *complex128:
		*v, err = dec.ReadComplex128()
		return
	case *bool:
		*v, err = dec.ReadBool()
		return
	}
	return dec.decodeValue(reflect.ValueOf(v))
}

func (dec *Decoder) decodeValue(v reflect.Value) error {
	if v.Kind() != reflect.Ptr || !v.Elem().CanSet() {
		return ErrNoPointer
	}
	fn := typeDecoder(v.Type())
	return fn(dec, v)
}

// Read allows the Decoder to be used as an io.Reader, note that internally this calls io.ReadFull().
func (dec *Decoder) Read(p []byte) (int, error) {
	return io.ReadFull(dec.r, p)
}

// Unmarshal is an alias for (sync.Pool'ed) NewDecoder(bytes.NewReader(b)).Decode(v)
func Unmarshal(b []byte, v interface{}) error {
	dec := getDec(bytes.NewReader(b))
	err := dec.Decode(v)
	putDec(dec)
	return err
}
<commit_msg>return an error if the decode value is nil<commit_after>package binny

import (
	"bufio"
	"bytes"
	"encoding"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"fmt"
	"io"
	"reflect"
	"unsafe"
)

var (
	// ErrNoPointer gets returned if the user passes a non-pointer to Decode
	ErrNoPointer = errors.New("can't decode to a non-pointer")
)

const DefaultDecoderBufferSize = 4096

// Unmarshaler is the interface implemented by objects that can unmarshal a binary representation of themselves.
// Implementing this bypasses reflection and is generally faster.
type Unmarshaler interface {
	UnmarshalBinny(dec *Decoder) error
}

// A Decoder reads binary data from an input stream, it also does a little bit of buffering.
type Decoder struct {
	r *bufio.Reader

	buf [16]byte
}

// NewDecoder is an alias for NewDecoder(r, DefaultDecoderBufferSize)
func NewDecoder(r io.Reader) *Decoder {
	return NewDecoderSize(r, DefaultDecoderBufferSize)
}

// NewDecoder returns a new decoder that reads from r with specific buffer size.
//
// The decoder introduces its own buffering and may
// read data from r beyond the requested values.
func NewDecoderSize(r io.Reader, sz int) *Decoder {
	if sz < 16 {
		sz = 16
	}

	return &Decoder{
		r: bufio.NewReaderSize(r, sz),
	}
}

// Reset discards any buffered data, resets all state, and switches
// the buffered reader to read from r.
func (dec *Decoder) Reset(r io.Reader) {
	dec.r.Reset(r)
}

func (dec *Decoder) readType() (Type, error) {
	b, err := dec.r.ReadByte()
	return Type(b), err
}

func (dec *Decoder) peekType() Type {
	b, _ := dec.r.ReadByte()
	dec.r.UnreadByte()
	return Type(b)
}

func (dec *Decoder) expectType(et Type) error {
	if t, _ := dec.readType(); t != et {
		return DecoderTypeError{et.String(), t}
	}
	return nil
}

// ReadBool returns a bool or an error.
func (dec *Decoder) ReadBool() (bool, error) {
	ft, _ := dec.readType()
	switch ft {
	case BoolTrue:
		return true, nil
	case BoolFalse:
		return false, nil
	}
	return false, DecoderTypeError{"Bool", ft}
}

func (dec *Decoder) ReadInt8() (int8, error) {
	if err := dec.expectType(Int8); err != nil {
		return 0, err
	}
	b, err := dec.r.ReadByte()
	return int8(b), err
}

func (dec *Decoder) ReadInt16() (int16, error) {
	if err := dec.expectType(Int16); err != nil {
		return 0, err
	}
	buf := dec.buf[:2]
	_, err := dec.Read(buf)
	return *(*int16)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadInt32() (int32, error) {
	if err := dec.expectType(Int32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*int32)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadInt64() (int64, error) {
	if err := dec.expectType(Int64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*int64)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadVarInt() (int64, error) {
	if err := dec.expectType(VarInt); err != nil {
		return 0, err
	}
	return binary.ReadVarint(dec.r)
}

// ReadInt retruns an int/varint value and the size of it (8, 16, 32, 64) or an error.
func (dec *Decoder) ReadInt() (int64, uint8, error) {
	ft := dec.peekType()
	switch ft {
	case Int8:
		v, err := dec.ReadInt8()
		return int64(v), 8, err
	case Int16:
		v, err := dec.ReadInt16()
		return int64(v), 16, err
	case Int32:
		v, err := dec.ReadInt32()
		return int64(v), 32, err
	case Int64:
		v, err := dec.ReadInt64()
		return v, 64, err
	case VarInt:
		v, err := dec.ReadVarInt()
		return v, 64, err
	}
	return 0, 0, DecoderTypeError{"int", ft}
}

func (dec *Decoder) ReadUint8() (uint8, error) {
	if err := dec.expectType(Uint8); err != nil {
		return 0, err
	}
	return dec.r.ReadByte()
}

func (dec *Decoder) ReadUint16() (uint16, error) {
	if err := dec.expectType(Uint16); err != nil {
		return 0, err
	}
	buf := dec.buf[:2]
	_, err := dec.Read(buf)
	return *(*uint16)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadUint32() (uint32, error) {
	if err := dec.expectType(Uint32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*uint32)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadUint64() (uint64, error) {
	if err := dec.expectType(Uint64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*uint64)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) ReadVarUint() (uint64, error) {
	if err := dec.expectType(VarUint); err != nil {
		return 0, err
	}
	return binary.ReadUvarint(dec.r)
}

// ReadUint retruns an uint/varuint value and the size of it (8, 16, 32, 64) or an error.
func (dec *Decoder) ReadUint() (v uint64, sz uint8, err error) {
	ft := dec.peekType()
	switch ft {
	case Uint8:
		v, err := dec.ReadUint8()
		return uint64(v), 8, err
	case Uint16:
		v, err := dec.ReadUint16()
		return uint64(v), 16, err
	case Uint32:
		v, err := dec.ReadUint32()
		return uint64(v), 32, err
	case Uint64:
		v, err := dec.ReadUint64()
		return v, 64, err
	case VarUint:
		v, err := dec.ReadVarUint()
		return v, 64, err
	}
	return 0, 0, DecoderTypeError{"uint", ft}
}

// ReadFloat32 returns a float32 or an error.
func (dec *Decoder) ReadFloat32() (float32, error) {
	if err := dec.expectType(Float32); err != nil {
		return 0, err
	}
	buf := dec.buf[:4]
	_, err := dec.Read(buf)
	return *(*float32)(unsafe.Pointer(&buf[0])), err
}

// ReadFloat64 returns a float64 or an error.
func (dec *Decoder) ReadFloat64() (float64, error) {
	if err := dec.expectType(Float64); err != nil {
		return 0, err
	}
	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*float64)(unsafe.Pointer(&buf[0])), err
}

// ReadComplex64 returns a complex64 or an error.
func (dec *Decoder) ReadComplex64() (complex64, error) {
	if err := dec.expectType(Complex64); err != nil {
		return 0, err
	}

	buf := dec.buf[:8]
	_, err := dec.Read(buf)
	return *(*complex64)(unsafe.Pointer(&buf[0])), err
}

// ReadComplex128 returns a complex128 or an error.
func (dec *Decoder) ReadComplex128() (complex128, error) {
	if err := dec.expectType(Complex128); err != nil {
		return 0, err
	}
	buf := dec.buf[:16]
	_, err := dec.Read(buf)
	return *(*complex128)(unsafe.Pointer(&buf[0])), err
}

func (dec *Decoder) readBytes(exp Type) ([]byte, error) {
	if err := dec.expectType(exp); err != nil {
		return nil, err
	}

	sz, _, err := dec.ReadUint()
	if err != nil || sz == 0 {
		return nil, err
	}

	buf := make([]byte, sz)
	_, err = io.ReadFull(dec.r, buf)
	return buf, err
}

// ReadBytes returns a byte slice.
func (dec *Decoder) ReadBytes() ([]byte, error) {
	return dec.readBytes(ByteSlice)
}

// ReadBytes returns a string.
func (dec *Decoder) ReadString() (string, error) {
	b, err := dec.readBytes(String)
	return string(b), err
}

// ReadBinary decodes and reads an object that implements the `encoding.BinaryUnmarshaler` interface.
func (dec *Decoder) ReadBinary(v encoding.BinaryUnmarshaler) error {
	b, err := dec.readBytes(Binary)
	if err != nil {
		return err
	}
	return v.UnmarshalBinary(b)
}

// ReadGob decodes and reads an object that implements the `gob.GobDecoder` interface.
func (dec *Decoder) ReadGob(v gob.GobDecoder) error {
	b, err := dec.readBytes(Gob)
	if err != nil {
		return err
	}
	return v.GobDecode(b)
}

// Decode reads the next binny-encoded value from its
// input and stores it in the value pointed to by v.
func (dec *Decoder) Decode(v interface{}) (err error) {
	switch v := v.(type) {
	case Unmarshaler:
		return v.UnmarshalBinny(dec)
	case encoding.BinaryUnmarshaler:
		return dec.ReadBinary(v)
	case gob.GobDecoder:
		return dec.ReadGob(v)
	case *string:
		*v, err = dec.ReadString()
		return
	case *[]byte:
		*v, err = dec.ReadBytes()
		return
	case *int64:
		*v, _, err = dec.ReadInt()
		return
	case *int32:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int32(i)
		return
	case *int16:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int16(i)
		return
	case *int8:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int8(i)
		return
	case *int:
		var i int64
		i, _, err = dec.ReadInt()
		*v = int(i)
		return
	case *uint64:
		*v, _, err = dec.ReadUint()
		return
	case *uint32:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint32(i)
		return
	case *uint16:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint16(i)
		return
	case *uint8:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint8(i)
		return
	case *uint:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uint(i)
		return
	case *uintptr:
		var i uint64
		i, _, err = dec.ReadUint()
		*v = uintptr(i)
		return
	case *float32:
		*v, err = dec.ReadFloat32()
		return
	case *float64:
		*v, err = dec.ReadFloat64()
		return
	case *complex64:
		*v, err = dec.ReadComplex64()
		return
	case *complex128:
		*v, err = dec.ReadComplex128()
		return
	case *bool:
		*v, err = dec.ReadBool()
		return
	case nil:
		return fmt.Errorf("can't decode a nil value")
	}
	return dec.decodeValue(reflect.ValueOf(v))
}

func (dec *Decoder) decodeValue(v reflect.Value) error {
	if v.Kind() != reflect.Ptr || !v.Elem().CanSet() {
		return ErrNoPointer
	}
	if v.IsNil() {
		return fmt.Errorf("can't decode a nil value: %v", v.Type())
	}
	fn := typeDecoder(v.Type())
	return fn(dec, v)
}

// Read allows the Decoder to be used as an io.Reader, note that internally this calls io.ReadFull().
func (dec *Decoder) Read(p []byte) (int, error) {
	return io.ReadFull(dec.r, p)
}

// Unmarshal is an alias for (sync.Pool'ed) NewDecoder(bytes.NewReader(b)).Decode(v)
func Unmarshal(b []byte, v interface{}) error {
	dec := getDec(bytes.NewReader(b))
	err := dec.Decode(v)
	putDec(dec)
	return err
}
<|endoftext|>


<commit_before>package xml2json

import (
	"encoding/xml"
	"io"
)

// A Decoder reads and decodes XML objects from an input stream.
type Decoder struct {
	r   io.Reader
	err error
}

type element struct {
	parent *element
	n      *Node
	label  string
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r: r}
}

// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
func (dec *Decoder) Decode(root *Node) error {
	xmlDec := xml.NewDecoder(dec.r)

	// Create first element from the root node
	elem := &element{
		parent: nil,
		n:      root,
	}

	for {
		t, _ := xmlDec.Token()
		if t == nil {
			break
		}

		switch se := t.(type) {
		case xml.StartElement:
			// Build new a new current element and link it to its parent
			elem = &element{
				parent: elem,
				n:      &Node{},
				label:  se.Name.Local,
			}

			// Extract attributes as children
			for _, a := range se.Attr {
				// TODO : Prefix attribute to avoid clashes
				elem.n.AddChild(a.Name.Local, &Node{Data: a.Value})
			}
		case xml.CharData:
			// Extract XML data (if any)
			elem.n.Data = string(xml.CharData(se))
		case xml.EndElement:
			// And add it to its parent list
			if elem.parent != nil {
				elem.parent.n.AddChild(elem.label, elem.n)
			}

			// Then change the current element to its parent
			elem = elem.parent
		}
	}

	return nil
}
<commit_msg>Prefix attribute names<commit_after>package xml2json

import (
	"encoding/xml"
	"io"
)

const (
	attrPrefix = "-"
)

// A Decoder reads and decodes XML objects from an input stream.
type Decoder struct {
	r   io.Reader
	err error
}

type element struct {
	parent *element
	n      *Node
	label  string
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r: r}
}

// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
func (dec *Decoder) Decode(root *Node) error {
	xmlDec := xml.NewDecoder(dec.r)

	// Create first element from the root node
	elem := &element{
		parent: nil,
		n:      root,
	}

	for {
		t, _ := xmlDec.Token()
		if t == nil {
			break
		}

		switch se := t.(type) {
		case xml.StartElement:
			// Build new a new current element and link it to its parent
			elem = &element{
				parent: elem,
				n:      &Node{},
				label:  se.Name.Local,
			}

			// Extract attributes as children
			for _, a := range se.Attr {
				elem.n.AddChild(attrPrefix+a.Name.Local, &Node{Data: a.Value})
			}
		case xml.CharData:
			// Extract XML data (if any)
			elem.n.Data = string(xml.CharData(se))
		case xml.EndElement:
			// And add it to its parent list
			if elem.parent != nil {
				elem.parent.n.AddChild(elem.label, elem.n)
			}

			// Then change the current element to its parent
			elem = elem.parent
		}
	}

	return nil
}
<|endoftext|>


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

// +build !v2v3

package v2store_test

import (
	"testing"

	"github.com/coreos/etcd/etcdserver/v2store"
	"github.com/coreos/etcd/pkg/testutil"
)

type v2TestStore struct {
	v2store.Store
}

func (s *v2TestStore) Close() {}

func newTestStore(t *testing.T, ns ...string) StoreCloser {
	return &v2TestStore{v2store.New(ns...)}
}

// Ensure that the store can recover from a previously saved state.
func TestStoreRecover(t *testing.T) {
	s := newTestStore(t)
	defer s.Close()
	var eidx uint64 = 4
	s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Create("/foo/x", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Update("/foo/x", "barbar", v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Create("/foo/y", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	b, err := s.Save()
	testutil.AssertNil(t, err)

	s2 := newTestStore(t)
	s2.Recovery(b)

	e, err := s.Get("/foo/x", false, false)
	testutil.AssertEqual(t, e.Node.CreatedIndex, uint64(2))
	testutil.AssertEqual(t, e.Node.ModifiedIndex, uint64(3))
	testutil.AssertEqual(t, e.EtcdIndex, eidx)
	testutil.AssertNil(t, err)
	testutil.AssertEqual(t, *e.Node.Value, "barbar")

	e, err = s.Get("/foo/y", false, false)
	testutil.AssertEqual(t, e.EtcdIndex, eidx)
	testutil.AssertNil(t, err)
	testutil.AssertEqual(t, *e.Node.Value, "baz")
}
<commit_msg>etcdserver/v2store: remove unused testing.T parameter<commit_after>// Copyright 2017 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build !v2v3

package v2store_test

import (
	"testing"

	"github.com/coreos/etcd/etcdserver/v2store"
	"github.com/coreos/etcd/pkg/testutil"
)

type v2TestStore struct {
	v2store.Store
}

func (s *v2TestStore) Close() {}

func newTestStore(t *testing.T, ns ...string) StoreCloser {
	if len(ns) == 0 {
		t.Logf("new v2 store with no namespace")
	}
	return &v2TestStore{v2store.New(ns...)}
}

// Ensure that the store can recover from a previously saved state.
func TestStoreRecover(t *testing.T) {
	s := newTestStore(t)
	defer s.Close()
	var eidx uint64 = 4
	s.Create("/foo", true, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Create("/foo/x", false, "bar", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Update("/foo/x", "barbar", v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	s.Create("/foo/y", false, "baz", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
	b, err := s.Save()
	testutil.AssertNil(t, err)

	s2 := newTestStore(t)
	s2.Recovery(b)

	e, err := s.Get("/foo/x", false, false)
	testutil.AssertEqual(t, e.Node.CreatedIndex, uint64(2))
	testutil.AssertEqual(t, e.Node.ModifiedIndex, uint64(3))
	testutil.AssertEqual(t, e.EtcdIndex, eidx)
	testutil.AssertNil(t, err)
	testutil.AssertEqual(t, *e.Node.Value, "barbar")

	e, err = s.Get("/foo/y", false, false)
	testutil.AssertEqual(t, e.EtcdIndex, eidx)
	testutil.AssertNil(t, err)
	testutil.AssertEqual(t, *e.Node.Value, "baz")
}
<|endoftext|>


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

// +build example

package blocks

import (
	"image/color"
	_ "image/jpeg"
	"math/rand"
	"strconv"
	"time"

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

var (
	imageEmpty    *ebiten.Image
	imageGameBG   *ebiten.Image
	imageWindows  *ebiten.Image
	imageGameover *ebiten.Image
)

func fieldWindowPosition() (x, y int) {
	return 20, 20
}

func nextWindowLabelPosition() (x, y int) {
	x, y = fieldWindowPosition()
	return x + fieldWidth + 2*blockWidth, y
}

func nextWindowPosition() (x, y int) {
	x, y = nextWindowLabelPosition()
	return x, y + blockHeight
}

func textBoxWidth() int {
	x, _ := nextWindowPosition()
	return ScreenWidth - 2*blockWidth - x
}

func scoreTextBoxPosition() (x, y int) {
	x, y = nextWindowPosition()
	return x, y + 6*blockHeight
}

func levelTextBoxPosition() (x, y int) {
	x, y = scoreTextBoxPosition()
	return x, y + 4*blockHeight
}

func linesTextBoxPosition() (x, y int) {
	x, y = levelTextBoxPosition()
	return x, y + 4*blockHeight
}

func init() {
	// Empty
	imageEmpty, _ = ebiten.NewImage(16, 16, ebiten.FilterNearest)
	imageEmpty.Fill(color.White)

	// Background
	var err error
	imageGameBG, _, err = ebitenutil.NewImageFromFile("_resources/images/gophers.jpg", ebiten.FilterLinear)
	if err != nil {
		panic(err)
	}

	// Windows
	imageWindows, _ = ebiten.NewImage(ScreenWidth, ScreenHeight, ebiten.FilterNearest)
	// Windows: Field
	x, y := fieldWindowPosition()
	drawWindow(imageWindows, x, y, fieldWidth, fieldHeight)
	// Windows: Next
	x, y = nextWindowLabelPosition()
	common.ArcadeFont.DrawTextWithShadow(imageWindows, "NEXT", x, y, 1, fontColor)
	x, y = nextWindowPosition()
	drawWindow(imageWindows, x, y, 5*blockWidth, 5*blockHeight)
	// Windows: Score
	x, y = scoreTextBoxPosition()
	drawTextBox(imageWindows, "SCORE", x, y, textBoxWidth())
	// Windows: Level
	x, y = levelTextBoxPosition()
	drawTextBox(imageWindows, "LEVEL", x, y, textBoxWidth())
	// Windows: Lines
	x, y = linesTextBoxPosition()
	drawTextBox(imageWindows, "LINES", x, y, textBoxWidth())

	// Gameover
	imageGameover, _ = ebiten.NewImage(ScreenWidth, ScreenHeight, ebiten.FilterNearest)
	imageGameover.Fill(color.NRGBA{0x00, 0x00, 0x00, 0x80})
	y = (ScreenHeight - blockHeight) / 2
	drawTextWithShadowCenter(imageGameover, "GAME OVER", 0, y, 1, color.White, ScreenWidth)
}

func drawWindow(r *ebiten.Image, x, y, width, height int) {
	op := &ebiten.DrawImageOptions{}
	w, h := imageEmpty.Size()
	op.GeoM.Scale(float64(width)/float64(w), float64(height)/float64(h))
	op.GeoM.Translate(float64(x), float64(y))
	op.ColorM.Scale(0, 0, 0, 0.75)
	r.DrawImage(imageEmpty, op)
}

var fontColor = color.NRGBA{0x40, 0x40, 0xff, 0xff}

func drawTextBox(r *ebiten.Image, label string, x, y, width int) {
	common.ArcadeFont.DrawTextWithShadow(r, label, x, y, 1, fontColor)
	y += blockWidth
	drawWindow(r, x, y, width, 2*blockHeight)
}

func drawTextBoxContent(r *ebiten.Image, content string, x, y, width int) {
	y += blockWidth
	drawTextWithShadowRight(r, content, x, y+blockHeight*3/4, 1, color.White, width-blockWidth/2)
}

type GameScene struct {
	field              *Field
	rand               *rand.Rand
	currentPiece       *Piece
	currentPieceX      int
	currentPieceY      int
	currentPieceYCarry int
	currentPieceAngle  Angle
	nextPiece          *Piece
	landingCount       int
	currentFrame       int
	score              int
	lines              int
	gameover           bool
}

func NewGameScene() *GameScene {
	return &GameScene{
		field: NewField(),
		rand:  rand.New(rand.NewSource(time.Now().UnixNano())),
	}
}

func (s *GameScene) drawBackground(r *ebiten.Image) {
	r.Fill(color.White)

	w, h := imageGameBG.Size()
	scaleW := ScreenWidth / float64(w)
	scaleH := ScreenHeight / float64(h)
	scale := scaleW
	if scale < scaleH {
		scale = scaleH
	}

	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
	op.GeoM.Scale(scale, scale)
	op.GeoM.Translate(ScreenWidth/2, ScreenHeight/2)

	a := 0.7
	m := ebiten.Monochrome()
	m.Scale(a, a, a, a)
	op.ColorM.Scale(1-a, 1-a, 1-a, 1-a)
	op.ColorM.Add(m)
	op.ColorM.Translate(0.3, 0.3, 0.3, 0)
	r.DrawImage(imageGameBG, op)
}

const fieldWidth = blockWidth * fieldBlockNumX
const fieldHeight = blockHeight * fieldBlockNumY

func (s *GameScene) choosePiece() *Piece {
	num := int(BlockTypeMax)
	blockType := BlockType(s.rand.Intn(num) + 1)
	return Pieces[blockType]
}

func (s *GameScene) initCurrentPiece(piece *Piece) {
	s.currentPiece = piece
	x, y := s.currentPiece.InitialPosition()
	s.currentPieceX = x
	s.currentPieceY = y
	s.currentPieceYCarry = 0
	s.currentPieceAngle = Angle0
}

func (s *GameScene) level() int {
	return s.lines / 10
}

func (s *GameScene) addScore(lines int) {
	base := 0
	switch lines {
	case 1:
		base = 100
	case 2:
		base = 300
	case 3:
		base = 600
	case 4:
		base = 1000
	default:
		panic("not reach")
	}
	s.score += (s.level() + 1) * base
}

func (s *GameScene) Update(state *GameState) error {
	s.field.Update()

	if s.gameover {
		// TODO: Gamepad key?
		if state.Input.StateForKey(ebiten.KeySpace) == 1 {
			state.SceneManager.GoTo(NewTitleScene())
		}
		return nil
	}

	s.currentFrame++

	const maxLandingCount = ebiten.FPS
	if s.currentPiece == nil {
		s.initCurrentPiece(s.choosePiece())
	}
	if s.nextPiece == nil {
		s.nextPiece = s.choosePiece()
	}

	moved := false
	piece := s.currentPiece
	angle := s.currentPieceAngle

	// Move piece by user input.
	if !s.field.Flushing() {
		piece := s.currentPiece
		x := s.currentPieceX
		y := s.currentPieceY
		if state.Input.IsRotateRightTrigger() {
			s.currentPieceAngle = s.field.RotatePieceRight(piece, x, y, angle)
			moved = angle != s.currentPieceAngle
		} else if state.Input.IsRotateLeftTrigger() {
			s.currentPieceAngle = s.field.RotatePieceLeft(piece, x, y, angle)
			moved = angle != s.currentPieceAngle
		} else if l := state.Input.StateForLeft(); l == 1 || (10 <= l && l%2 == 0) {
			s.currentPieceX = s.field.MovePieceToLeft(piece, x, y, angle)
			moved = x != s.currentPieceX
		} else if r := state.Input.StateForRight(); r == 1 || (10 <= r && r%2 == 0) {
			s.currentPieceX = s.field.MovePieceToRight(piece, x, y, angle)
			moved = y != s.currentPieceX
		} else if d := state.Input.StateForDown(); (d-1)%2 == 0 {
			s.currentPieceY = s.field.DropPiece(piece, x, y, angle)
			moved = y != s.currentPieceY
			if moved {
				s.score++
			}
		}
	}

	// Drop the current piece with gravity.
	if !s.field.Flushing() {
		angle := s.currentPieceAngle
		s.currentPieceYCarry += 2*s.level() + 1
		const maxCarry = 60
		for maxCarry <= s.currentPieceYCarry {
			s.currentPieceYCarry -= maxCarry
			s.currentPieceY = s.field.DropPiece(piece, s.currentPieceX, s.currentPieceY, angle)
		}
	}

	if !s.field.Flushing() && !s.field.PieceDroppable(piece, s.currentPieceX, s.currentPieceY, angle) {
		if 0 < state.Input.StateForDown() {
			s.landingCount += 10
		} else {
			s.landingCount++
		}
		if maxLandingCount <= s.landingCount {
			s.field.AbsorbPiece(piece, s.currentPieceX, s.currentPieceY, angle)
			if s.field.Flushing() {
				s.field.SetEndFlushing(func(lines int) {
					s.lines += lines
					if 0 < lines {
						s.addScore(lines)
					}
					s.goNextPiece()
				})
			} else {
				s.goNextPiece()
			}

		}
	}
	return nil
}

func (s *GameScene) goNextPiece() {
	s.initCurrentPiece(s.nextPiece)
	s.nextPiece = s.choosePiece()
	s.landingCount = 0
	if s.currentPiece.Collides(s.field, s.currentPieceX, s.currentPieceY, s.currentPieceAngle) {
		s.gameover = true
	}
}

func (s *GameScene) Draw(r *ebiten.Image) {
	s.drawBackground(r)

	r.DrawImage(imageWindows, nil)

	// Draw score
	x, y := scoreTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.score), x, y, textBoxWidth())

	// Draw level
	x, y = levelTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.level()), x, y, textBoxWidth())

	// Draw lines
	x, y = linesTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.lines), x, y, textBoxWidth())

	// Draw blocks
	fieldX, fieldY := fieldWindowPosition()
	s.field.Draw(r, fieldX, fieldY)
	if s.currentPiece != nil && !s.field.Flushing() {
		x := fieldX + s.currentPieceX*blockWidth
		y := fieldY + s.currentPieceY*blockHeight
		s.currentPiece.Draw(r, x, y, s.currentPieceAngle)
	}
	if s.nextPiece != nil {
		// TODO: Make functions to get these values.
		x := fieldX + fieldWidth + blockWidth*2
		y := fieldY + blockHeight
		s.nextPiece.DrawAtCenter(r, x, y, blockWidth*5, blockHeight*5, 0)
	}

	if s.gameover {
		r.DrawImage(imageGameover, nil)
	}
}
<commit_msg>examples/blocks: Use ebitenutil.DrawRect<commit_after>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build example

package blocks

import (
	"image/color"
	_ "image/jpeg"
	"math/rand"
	"strconv"
	"time"

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

var (
	imageGameBG   *ebiten.Image
	imageWindows  *ebiten.Image
	imageGameover *ebiten.Image
)

func fieldWindowPosition() (x, y int) {
	return 20, 20
}

func nextWindowLabelPosition() (x, y int) {
	x, y = fieldWindowPosition()
	return x + fieldWidth + 2*blockWidth, y
}

func nextWindowPosition() (x, y int) {
	x, y = nextWindowLabelPosition()
	return x, y + blockHeight
}

func textBoxWidth() int {
	x, _ := nextWindowPosition()
	return ScreenWidth - 2*blockWidth - x
}

func scoreTextBoxPosition() (x, y int) {
	x, y = nextWindowPosition()
	return x, y + 6*blockHeight
}

func levelTextBoxPosition() (x, y int) {
	x, y = scoreTextBoxPosition()
	return x, y + 4*blockHeight
}

func linesTextBoxPosition() (x, y int) {
	x, y = levelTextBoxPosition()
	return x, y + 4*blockHeight
}

func init() {
	// Background
	var err error
	imageGameBG, _, err = ebitenutil.NewImageFromFile("_resources/images/gophers.jpg", ebiten.FilterLinear)
	if err != nil {
		panic(err)
	}

	// Windows
	imageWindows, _ = ebiten.NewImage(ScreenWidth, ScreenHeight, ebiten.FilterNearest)
	// Windows: Field
	x, y := fieldWindowPosition()
	drawWindow(imageWindows, x, y, fieldWidth, fieldHeight)
	// Windows: Next
	x, y = nextWindowLabelPosition()
	common.ArcadeFont.DrawTextWithShadow(imageWindows, "NEXT", x, y, 1, fontColor)
	x, y = nextWindowPosition()
	drawWindow(imageWindows, x, y, 5*blockWidth, 5*blockHeight)
	// Windows: Score
	x, y = scoreTextBoxPosition()
	drawTextBox(imageWindows, "SCORE", x, y, textBoxWidth())
	// Windows: Level
	x, y = levelTextBoxPosition()
	drawTextBox(imageWindows, "LEVEL", x, y, textBoxWidth())
	// Windows: Lines
	x, y = linesTextBoxPosition()
	drawTextBox(imageWindows, "LINES", x, y, textBoxWidth())

	// Gameover
	imageGameover, _ = ebiten.NewImage(ScreenWidth, ScreenHeight, ebiten.FilterNearest)
	imageGameover.Fill(color.NRGBA{0x00, 0x00, 0x00, 0x80})
	y = (ScreenHeight - blockHeight) / 2
	drawTextWithShadowCenter(imageGameover, "GAME OVER", 0, y, 1, color.White, ScreenWidth)
}

func drawWindow(r *ebiten.Image, x, y, width, height int) {
	ebitenutil.DrawRect(r, float64(x), float64(y), float64(width), float64(height), color.RGBA{0, 0, 0, 0xc0})
}

var fontColor = color.NRGBA{0x40, 0x40, 0xff, 0xff}

func drawTextBox(r *ebiten.Image, label string, x, y, width int) {
	common.ArcadeFont.DrawTextWithShadow(r, label, x, y, 1, fontColor)
	y += blockWidth
	drawWindow(r, x, y, width, 2*blockHeight)
}

func drawTextBoxContent(r *ebiten.Image, content string, x, y, width int) {
	y += blockWidth
	drawTextWithShadowRight(r, content, x, y+blockHeight*3/4, 1, color.White, width-blockWidth/2)
}

type GameScene struct {
	field              *Field
	rand               *rand.Rand
	currentPiece       *Piece
	currentPieceX      int
	currentPieceY      int
	currentPieceYCarry int
	currentPieceAngle  Angle
	nextPiece          *Piece
	landingCount       int
	currentFrame       int
	score              int
	lines              int
	gameover           bool
}

func NewGameScene() *GameScene {
	return &GameScene{
		field: NewField(),
		rand:  rand.New(rand.NewSource(time.Now().UnixNano())),
	}
}

func (s *GameScene) drawBackground(r *ebiten.Image) {
	r.Fill(color.White)

	w, h := imageGameBG.Size()
	scaleW := ScreenWidth / float64(w)
	scaleH := ScreenHeight / float64(h)
	scale := scaleW
	if scale < scaleH {
		scale = scaleH
	}

	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
	op.GeoM.Scale(scale, scale)
	op.GeoM.Translate(ScreenWidth/2, ScreenHeight/2)

	a := 0.7
	m := ebiten.Monochrome()
	m.Scale(a, a, a, a)
	op.ColorM.Scale(1-a, 1-a, 1-a, 1-a)
	op.ColorM.Add(m)
	op.ColorM.Translate(0.3, 0.3, 0.3, 0)
	r.DrawImage(imageGameBG, op)
}

const fieldWidth = blockWidth * fieldBlockNumX
const fieldHeight = blockHeight * fieldBlockNumY

func (s *GameScene) choosePiece() *Piece {
	num := int(BlockTypeMax)
	blockType := BlockType(s.rand.Intn(num) + 1)
	return Pieces[blockType]
}

func (s *GameScene) initCurrentPiece(piece *Piece) {
	s.currentPiece = piece
	x, y := s.currentPiece.InitialPosition()
	s.currentPieceX = x
	s.currentPieceY = y
	s.currentPieceYCarry = 0
	s.currentPieceAngle = Angle0
}

func (s *GameScene) level() int {
	return s.lines / 10
}

func (s *GameScene) addScore(lines int) {
	base := 0
	switch lines {
	case 1:
		base = 100
	case 2:
		base = 300
	case 3:
		base = 600
	case 4:
		base = 1000
	default:
		panic("not reach")
	}
	s.score += (s.level() + 1) * base
}

func (s *GameScene) Update(state *GameState) error {
	s.field.Update()

	if s.gameover {
		// TODO: Gamepad key?
		if state.Input.StateForKey(ebiten.KeySpace) == 1 {
			state.SceneManager.GoTo(NewTitleScene())
		}
		return nil
	}

	s.currentFrame++

	const maxLandingCount = ebiten.FPS
	if s.currentPiece == nil {
		s.initCurrentPiece(s.choosePiece())
	}
	if s.nextPiece == nil {
		s.nextPiece = s.choosePiece()
	}

	moved := false
	piece := s.currentPiece
	angle := s.currentPieceAngle

	// Move piece by user input.
	if !s.field.Flushing() {
		piece := s.currentPiece
		x := s.currentPieceX
		y := s.currentPieceY
		if state.Input.IsRotateRightTrigger() {
			s.currentPieceAngle = s.field.RotatePieceRight(piece, x, y, angle)
			moved = angle != s.currentPieceAngle
		} else if state.Input.IsRotateLeftTrigger() {
			s.currentPieceAngle = s.field.RotatePieceLeft(piece, x, y, angle)
			moved = angle != s.currentPieceAngle
		} else if l := state.Input.StateForLeft(); l == 1 || (10 <= l && l%2 == 0) {
			s.currentPieceX = s.field.MovePieceToLeft(piece, x, y, angle)
			moved = x != s.currentPieceX
		} else if r := state.Input.StateForRight(); r == 1 || (10 <= r && r%2 == 0) {
			s.currentPieceX = s.field.MovePieceToRight(piece, x, y, angle)
			moved = y != s.currentPieceX
		} else if d := state.Input.StateForDown(); (d-1)%2 == 0 {
			s.currentPieceY = s.field.DropPiece(piece, x, y, angle)
			moved = y != s.currentPieceY
			if moved {
				s.score++
			}
		}
	}

	// Drop the current piece with gravity.
	if !s.field.Flushing() {
		angle := s.currentPieceAngle
		s.currentPieceYCarry += 2*s.level() + 1
		const maxCarry = 60
		for maxCarry <= s.currentPieceYCarry {
			s.currentPieceYCarry -= maxCarry
			s.currentPieceY = s.field.DropPiece(piece, s.currentPieceX, s.currentPieceY, angle)
		}
	}

	if !s.field.Flushing() && !s.field.PieceDroppable(piece, s.currentPieceX, s.currentPieceY, angle) {
		if 0 < state.Input.StateForDown() {
			s.landingCount += 10
		} else {
			s.landingCount++
		}
		if maxLandingCount <= s.landingCount {
			s.field.AbsorbPiece(piece, s.currentPieceX, s.currentPieceY, angle)
			if s.field.Flushing() {
				s.field.SetEndFlushing(func(lines int) {
					s.lines += lines
					if 0 < lines {
						s.addScore(lines)
					}
					s.goNextPiece()
				})
			} else {
				s.goNextPiece()
			}

		}
	}
	return nil
}

func (s *GameScene) goNextPiece() {
	s.initCurrentPiece(s.nextPiece)
	s.nextPiece = s.choosePiece()
	s.landingCount = 0
	if s.currentPiece.Collides(s.field, s.currentPieceX, s.currentPieceY, s.currentPieceAngle) {
		s.gameover = true
	}
}

func (s *GameScene) Draw(r *ebiten.Image) {
	s.drawBackground(r)

	r.DrawImage(imageWindows, nil)

	// Draw score
	x, y := scoreTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.score), x, y, textBoxWidth())

	// Draw level
	x, y = levelTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.level()), x, y, textBoxWidth())

	// Draw lines
	x, y = linesTextBoxPosition()
	drawTextBoxContent(r, strconv.Itoa(s.lines), x, y, textBoxWidth())

	// Draw blocks
	fieldX, fieldY := fieldWindowPosition()
	s.field.Draw(r, fieldX, fieldY)
	if s.currentPiece != nil && !s.field.Flushing() {
		x := fieldX + s.currentPieceX*blockWidth
		y := fieldY + s.currentPieceY*blockHeight
		s.currentPiece.Draw(r, x, y, s.currentPieceAngle)
	}
	if s.nextPiece != nil {
		// TODO: Make functions to get these values.
		x := fieldX + fieldWidth + blockWidth*2
		y := fieldY + blockHeight
		s.nextPiece.DrawAtCenter(r, x, y, blockWidth*5, blockHeight*5, 0)
	}

	if s.gameover {
		r.DrawImage(imageGameover, nil)
	}
}
<|endoftext|>


<commit_before>package logbuf

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"
)

func (lb *LogBuffer) addHttpHandlers() {
	http.HandleFunc("/logs", lb.httpListHandler)
	http.HandleFunc("/logs/dump", lb.httpDumpHandler)
	http.HandleFunc("/logs/showLast", lb.httpShowLastHandler)
}

func (lb *LogBuffer) httpListHandler(w http.ResponseWriter, req *http.Request) {
	if lb.logDir == "" {
		return
	}
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	file, err := os.Open(lb.logDir)
	if err != nil {
		fmt.Fprintln(writer, err)
		return
	}
	names, err := file.Readdirnames(-1)
	file.Close()
	if err != nil {
		fmt.Fprintln(writer, err)
		return
	}
	tmpNames := make([]string, 0, len(names))
	for _, name := range names {
		if strings.Index(name, ":") >= 0 {
			tmpNames = append(tmpNames, name)

		}
	}
	names = tmpNames
	sort.Strings(names)
	flags, _ := parseQuery(req.URL.RawQuery)
	recentFirstString := ""
	_, recentFirst := flags["recentFirst"]
	if recentFirst {
		recentFirstString = "&recentFirst"
		reverseStrings(names)
	}
	if _, ok := flags["text"]; ok {
		for _, name := range names {
			fmt.Fprintln(writer, name)
		}
		return
	}
	fmt.Fprintln(writer, "")
	fmt.Fprint(writer, "Logs: ")
	if recentFirst {
		fmt.Fprintf(writer, "showing recent first ")
		fmt.Fprintln(writer, `<a href="logs">show recent last</a><br>`)
	} else {
		fmt.Fprintf(writer, "showing recent last ")
		fmt.Fprintln(writer,
			`<a href="logs?recentFirst">show recent first</a><br>`)
	}
	// TODO(rgooch): Enable when ready.
	// showRecentLinks(writer, recentFirstString)
	fmt.Fprintln(writer, "
")
	currentName := ""
	lb.rwMutex.Lock()
	if lb.file != nil {
		currentName = path.Base(lb.file.Name())
	}
	lb.rwMutex.Unlock()
	for _, name := range names {
		if name == currentName {
			fmt.Fprintf(writer,
				"%s (current)
\n",
				recentFirstString, name)
		} else {
			fmt.Fprintf(writer, "%s
\n",
				name, recentFirstString, name)
		}
	}
	fmt.Fprintln(writer, "")
}

func showRecentLinks(writer io.Writer, recentFirstString string) {
	fmt.Fprintln(writer, `Show last: <a href="logs/showLast?1m%s">min</a>`,
		recentFirstString)
	fmt.Fprintln(writer, `           <a href="logs/showLast?10m%s">10 min</a>`,
		recentFirstString)
	fmt.Fprintln(writer, `           <a href="logs/showLast?1h%s">hour</a>`,
		recentFirstString)
	fmt.Fprintln(writer, `           <a href="logs/showLast?1d%s">day</a>`,
		recentFirstString)
}

func (lb *LogBuffer) httpDumpHandler(w http.ResponseWriter, req *http.Request) {
	flags, pairs := parseQuery(req.URL.RawQuery)
	name, ok := pairs["name"]
	if !ok {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	recentFirst := false
	if _, ok := flags["recentFirst"]; ok {
		recentFirst = true
	}
	if name == "latest" {
		writer := bufio.NewWriter(w)
		defer writer.Flush()
		lb.Dump(writer, "", "", recentFirst)
		return
	}
	file, err := os.Open(path.Join(lb.logDir, path.Base(path.Clean(name))))
	if err != nil {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusNotFound)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	if recentFirst {
		scanner := bufio.NewScanner(file)
		lines := make([]string, 0)
		for scanner.Scan() {
			line := scanner.Text()
			if len(line) < 1 {
				continue
			}
			lines = append(lines, line)
		}
		if err = scanner.Err(); err == nil {
			reverseStrings(lines)
			for _, line := range lines {
				fmt.Fprintln(writer, line)
			}
		}
	} else {
		_, err = io.Copy(writer, bufio.NewReader(file))
	}
	if err != nil {
		fmt.Fprintln(writer, err)
	}
	return
}

func (lb *LogBuffer) httpShowLastHandler(w http.ResponseWriter,
	req *http.Request) {
	flags, _ := parseQuery(req.URL.RawQuery)
	_, recentFirst := flags["recentFirst"]
	for flag := range flags {
		length := len(flag)
		unitChar := flag[length-1]
		var unit time.Duration
		switch unitChar {
		case 's':
			unit = time.Second
		case 'm':
			unit = time.Minute
		case 'h':
			unit = time.Hour
		case 'd':
			unit = time.Hour * 24
		default:
			continue
		}
		if val, err := strconv.ParseUint(flag[:length-1], 10, 64); err != nil {
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
			w.WriteHeader(http.StatusBadRequest)
			return
		} else {
			lb.showRecent(w, time.Duration(val)*unit, recentFirst)
		}
	}
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusBadRequest)
}

func (lb *LogBuffer) showRecent(w io.Writer, duration time.Duration,
	recentFirst bool) {
}

func (lb *LogBuffer) writeHtml(writer io.Writer) {
	fmt.Fprintln(writer, `<a href="logs">Logs:</a><br>`)
	fmt.Fprintln(writer, "
")
	lb.Dump(writer, "", "", false)
	fmt.Fprintln(writer, "
")
}

func parseQuery(rawQuery string) (map[string]struct{}, map[string]string) {
	flags := make(map[string]struct{})
	table := make(map[string]string)
	for _, pair := range strings.Split(rawQuery, "&") {
		splitPair := strings.Split(pair, "=")
		if len(splitPair) == 1 {
			flags[splitPair[0]] = struct{}{}
		}
		if len(splitPair) == 2 {
			table[splitPair[0]] = splitPair[1]
		}
	}
	return flags, table
}
<commit_msg>Fix links in lib/logbuf/showRecentLinks() function.<commit_after>package logbuf

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"
)

func (lb *LogBuffer) addHttpHandlers() {
	http.HandleFunc("/logs", lb.httpListHandler)
	http.HandleFunc("/logs/dump", lb.httpDumpHandler)
	http.HandleFunc("/logs/showLast", lb.httpShowLastHandler)
}

func (lb *LogBuffer) httpListHandler(w http.ResponseWriter, req *http.Request) {
	if lb.logDir == "" {
		return
	}
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	file, err := os.Open(lb.logDir)
	if err != nil {
		fmt.Fprintln(writer, err)
		return
	}
	names, err := file.Readdirnames(-1)
	file.Close()
	if err != nil {
		fmt.Fprintln(writer, err)
		return
	}
	tmpNames := make([]string, 0, len(names))
	for _, name := range names {
		if strings.Index(name, ":") >= 0 {
			tmpNames = append(tmpNames, name)

		}
	}
	names = tmpNames
	sort.Strings(names)
	flags, _ := parseQuery(req.URL.RawQuery)
	recentFirstString := ""
	_, recentFirst := flags["recentFirst"]
	if recentFirst {
		recentFirstString = "&recentFirst"
		reverseStrings(names)
	}
	if _, ok := flags["text"]; ok {
		for _, name := range names {
			fmt.Fprintln(writer, name)
		}
		return
	}
	fmt.Fprintln(writer, "")
	fmt.Fprint(writer, "Logs: ")
	if recentFirst {
		fmt.Fprintf(writer, "showing recent first ")
		fmt.Fprintln(writer, `<a href="logs">show recent last</a><br>`)
	} else {
		fmt.Fprintf(writer, "showing recent last ")
		fmt.Fprintln(writer,
			`<a href="logs?recentFirst">show recent first</a><br>`)
	}
	// TODO(rgooch): Enable when ready.
	// showRecentLinks(writer, recentFirstString)
	fmt.Fprintln(writer, "
")
	currentName := ""
	lb.rwMutex.Lock()
	if lb.file != nil {
		currentName = path.Base(lb.file.Name())
	}
	lb.rwMutex.Unlock()
	for _, name := range names {
		if name == currentName {
			fmt.Fprintf(writer,
				"%s (current)
\n",
				recentFirstString, name)
		} else {
			fmt.Fprintf(writer, "%s
\n",
				name, recentFirstString, name)
		}
	}
	fmt.Fprintln(writer, "")
}

func showRecentLinks(w io.Writer, recentFirstString string) {
	fmt.Fprintf(w, "Show last: minute\n",
		recentFirstString)
	fmt.Fprintf(w, "           10 min\n",
		recentFirstString)
	fmt.Fprintf(w, "           hour\n",
		recentFirstString)
	fmt.Fprintf(w, "           day\n",
		recentFirstString)
}

func (lb *LogBuffer) httpDumpHandler(w http.ResponseWriter, req *http.Request) {
	flags, pairs := parseQuery(req.URL.RawQuery)
	name, ok := pairs["name"]
	if !ok {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	recentFirst := false
	if _, ok := flags["recentFirst"]; ok {
		recentFirst = true
	}
	if name == "latest" {
		writer := bufio.NewWriter(w)
		defer writer.Flush()
		lb.Dump(writer, "", "", recentFirst)
		return
	}
	file, err := os.Open(path.Join(lb.logDir, path.Base(path.Clean(name))))
	if err != nil {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusNotFound)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(w)
	defer writer.Flush()
	if recentFirst {
		scanner := bufio.NewScanner(file)
		lines := make([]string, 0)
		for scanner.Scan() {
			line := scanner.Text()
			if len(line) < 1 {
				continue
			}
			lines = append(lines, line)
		}
		if err = scanner.Err(); err == nil {
			reverseStrings(lines)
			for _, line := range lines {
				fmt.Fprintln(writer, line)
			}
		}
	} else {
		_, err = io.Copy(writer, bufio.NewReader(file))
	}
	if err != nil {
		fmt.Fprintln(writer, err)
	}
	return
}

func (lb *LogBuffer) httpShowLastHandler(w http.ResponseWriter,
	req *http.Request) {
	flags, _ := parseQuery(req.URL.RawQuery)
	_, recentFirst := flags["recentFirst"]
	for flag := range flags {
		length := len(flag)
		unitChar := flag[length-1]
		var unit time.Duration
		switch unitChar {
		case 's':
			unit = time.Second
		case 'm':
			unit = time.Minute
		case 'h':
			unit = time.Hour
		case 'd':
			unit = time.Hour * 24
		default:
			continue
		}
		if val, err := strconv.ParseUint(flag[:length-1], 10, 64); err != nil {
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
			w.WriteHeader(http.StatusBadRequest)
			return
		} else {
			lb.showRecent(w, time.Duration(val)*unit, recentFirst)
		}
	}
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusBadRequest)
}

func (lb *LogBuffer) showRecent(w io.Writer, duration time.Duration,
	recentFirst bool) {
}

func (lb *LogBuffer) writeHtml(writer io.Writer) {
	fmt.Fprintln(writer, `<a href="logs">Logs:</a><br>`)
	fmt.Fprintln(writer, "
")
	lb.Dump(writer, "", "", false)
	fmt.Fprintln(writer, "
")
}

func parseQuery(rawQuery string) (map[string]struct{}, map[string]string) {
	flags := make(map[string]struct{})
	table := make(map[string]string)
	for _, pair := range strings.Split(rawQuery, "&") {
		splitPair := strings.Split(pair, "=")
		if len(splitPair) == 1 {
			flags[splitPair[0]] = struct{}{}
		}
		if len(splitPair) == 2 {
			table[splitPair[0]] = splitPair[1]
		}
	}
	return flags, table
}
<|endoftext|>


<commit_before>package inputoutput

import (
	"log"

	"github.com/djhworld/gomeboycolor/components"
	"github.com/djhworld/gomeboycolor/constants"
	"github.com/djhworld/gomeboycolor/types"

	"github.com/go-gl/gl/v2.1/gl"
	"github.com/go-gl/glfw/v3.2/glfw"
)

const PREFIX string = "IO"
const ROW_1 byte = 0x10
const ROW_2 byte = 0x20
const SCREEN_WIDTH int = 160
const SCREEN_HEIGHT int = 144

var DefaultControlScheme ControlScheme = ControlScheme{1, 2, 3, 4, 90, 88, 294, 288}

type ControlScheme struct {
	UP     int
	DOWN   int
	LEFT   int
	RIGHT  int
	A      int
	B      int
	START  int
	SELECT int
}

type KeyHandler struct {
	controlScheme ControlScheme
	colSelect     byte
	rows          [2]byte
	irqHandler    components.IRQHandler
}

func (k *KeyHandler) Init(cs ControlScheme) {
	k.controlScheme = cs
	k.Reset()
}

func (k *KeyHandler) Name() string {
	return PREFIX + "-KEYB"
}

func (k *KeyHandler) Reset() {
	log.Printf("%s: Resetting", k.Name())
	k.rows[0], k.rows[1] = 0x0F, 0x0F
	k.colSelect = 0x00
}

func (k *KeyHandler) LinkIRQHandler(m components.IRQHandler) {
	k.irqHandler = m
	log.Printf("%s: Linked IRQ Handler to Keyboard Handler", k.Name())
}

func (k *KeyHandler) Read(addr types.Word) byte {
	var value byte

	switch k.colSelect {
	case ROW_1:
		value = k.rows[1]
	case ROW_2:
		value = k.rows[0]
	default:
		value = 0x00
	}

	return value
}

func (k *KeyHandler) Write(addr types.Word, value byte) {
	k.colSelect = value & 0x30
}

//released sets bit for key to 0
func (k *KeyHandler) KeyDown(key int) {
	k.irqHandler.RequestInterrupt(constants.JOYP_HILO_IRQ)
	switch key {
	case k.controlScheme.UP:
		k.rows[0] &= 0xB
	case k.controlScheme.DOWN:
		k.rows[0] &= 0x7
	case k.controlScheme.LEFT:
		k.rows[0] &= 0xD
	case k.controlScheme.RIGHT:
		k.rows[0] &= 0xE
	case k.controlScheme.A:
		k.rows[1] &= 0xE
	case k.controlScheme.B:
		k.rows[1] &= 0xD
	case k.controlScheme.START:
		k.rows[1] &= 0x7
	case k.controlScheme.SELECT:
		k.rows[1] &= 0xB
	}
}

//released sets bit for key to 1
func (k *KeyHandler) KeyUp(key int) {
	switch key {
	case k.controlScheme.UP:
		k.rows[0] |= 0x4
	case k.controlScheme.DOWN:
		k.rows[0] |= 0x8
	case k.controlScheme.LEFT:
		k.rows[0] |= 0x2
	case k.controlScheme.RIGHT:
		k.rows[0] |= 0x1
	case k.controlScheme.A:
		k.rows[1] |= 0x1
	case k.controlScheme.B:
		k.rows[1] |= 0x2
	case k.controlScheme.START:
		k.rows[1] |= 0x8
	case k.controlScheme.SELECT:
		k.rows[1] |= 0x4
	}
}

type IO struct {
	KeyHandler          *KeyHandler
	Display             *Display
	ScreenOutputChannel chan *types.Screen
	AudioOutputChannel  chan int
}

func NewIO() *IO {
	var i *IO = new(IO)
	i.KeyHandler = new(KeyHandler)
	i.Display = new(Display)
	i.ScreenOutputChannel = make(chan *types.Screen)
	i.AudioOutputChannel = make(chan int)
	return i
}

func (i *IO) Init(title string, screenSize int, onCloseHandler func()) error {
	var err error

	err = i.Display.init(title, screenSize, onCloseHandler)
	if err != nil {
		return err
	}

	/*
		i.KeyHandler.Init(DefaultControlScheme) //TODO: allow user to define controlscheme
		i.Display.window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
			if action == glfw.Press {
				i.KeyHandler.KeyDown(key)
			} else {
				i.KeyHandler.KeyUp(key)
			}
		})
	*/

	return nil
}

//This will wait for updates to the display or audio and dispatch them accordingly
func (i *IO) Run() {
	for {
		select {
		case data := <-i.ScreenOutputChannel:
			i.Display.drawFrame(data)
		case data := <-i.AudioOutputChannel:
			log.Println("Writing %d to audio!", data)
		}
	}
}

type Display struct {
	Name                 string
	ScreenSizeMultiplier int
	window               *glfw.Window
}

func (s *Display) init(title string, screenSizeMultiplier int, onCloseHandler func()) error {
	var err error

	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to initialize glfw:", err)
	}

	s.Name = PREFIX + "-SCREEN"

	log.Printf("%s: Initialising display", s.Name)

	s.ScreenSizeMultiplier = screenSizeMultiplier
	log.Printf("%s: Set screen size multiplier to %dx", s.Name, s.ScreenSizeMultiplier)

	glfw.WindowHint(glfw.Resizable, glfw.False)
	window, err := glfw.CreateWindow(SCREEN_WIDTH*s.ScreenSizeMultiplier, SCREEN_HEIGHT*s.ScreenSizeMultiplier, "Testing", nil, nil)
	if err != nil {
		return err
	}

	window.SetTitle(title)

	//TODO fix desktop mode
	window.SetPos((s.ScreenSizeMultiplier)/2, (s.ScreenSizeMultiplier)/2)

	window.SetCloseCallback(func(w *glfw.Window) {
		w.Destroy()
		glfw.Terminate()
		onCloseHandler()
	})

	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		return err
	}

	gl.ClearColor(0.255, 0.255, 0.255, 0)

	//resize functionTrue
	/*
		onResize := func(window *glfw.Window, w, h int) {
			gl.Viewport(0, 0, int32(w), int32(h))
			gl.MatrixMode(gl.PROJECTION)
			gl.LoadIdentity()
			gl.Ortho(0, float64(w), float64(h), 0, -1, 1)
			gl.ClearColor(0.255, 0.255, 0.255, 0)
			gl.Clear(gl.COLOR_BUFFER_BIT)
			gl.MatrixMode(gl.MODELVIEW)
			gl.LoadIdentity()
		}

		window.SetSizeCallback(onResize)
	*/

	s.window = window

	return nil

}

func (s *Display) drawFrame(screenData *types.Screen) {
	gl.Viewport(0, 0, int32(SCREEN_WIDTH)*2, int32(SCREEN_HEIGHT)*2)
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(SCREEN_WIDTH), float64(SCREEN_HEIGHT), 0, -1, 1)
	gl.ClearColor(0.255, 0.255, 0.255, 0)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()

	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Disable(gl.DEPTH_TEST)
	gl.PointSize(float32(s.ScreenSizeMultiplier) + 1.0)
	gl.Begin(gl.POINTS)
	for y := 0; y < SCREEN_HEIGHT; y++ {
		for x := 0; x < SCREEN_WIDTH; x++ {
			var pixel types.RGB = screenData[y][x]
			gl.Color3ub(pixel.Red, pixel.Green, pixel.Blue)
			gl.Vertex2i(int32(x*s.ScreenSizeMultiplier), int32(y*s.ScreenSizeMultiplier))
		}
	}

	gl.End()
	glfw.PollEvents()
	s.window.SwapBuffers()
}
<commit_msg>Fixed keyboard<commit_after>package inputoutput

import (
	"log"

	"github.com/djhworld/gomeboycolor/components"
	"github.com/djhworld/gomeboycolor/constants"
	"github.com/djhworld/gomeboycolor/types"

	"github.com/go-gl/gl/v2.1/gl"
	"github.com/go-gl/glfw/v3.2/glfw"
)

const PREFIX string = "IO"
const ROW_1 byte = 0x10
const ROW_2 byte = 0x20
const SCREEN_WIDTH int = 160
const SCREEN_HEIGHT int = 144

var DefaultControlScheme ControlScheme = ControlScheme{
	glfw.KeyUp,
	glfw.KeyDown,
	glfw.KeyLeft,
	glfw.KeyRight,
	glfw.KeyZ,
	glfw.KeyX,
	glfw.KeyA,
	glfw.KeyS,
}

type ControlScheme struct {
	UP     glfw.Key
	DOWN   glfw.Key
	LEFT   glfw.Key
	RIGHT  glfw.Key
	A      glfw.Key
	B      glfw.Key
	START  glfw.Key
	SELECT glfw.Key
}

type KeyHandler struct {
	controlScheme ControlScheme
	colSelect     byte
	rows          [2]byte
	irqHandler    components.IRQHandler
}

func (k *KeyHandler) Init(cs ControlScheme) {
	k.controlScheme = cs
	k.Reset()
}

func (k *KeyHandler) Name() string {
	return PREFIX + "-KEYB"
}

func (k *KeyHandler) Reset() {
	log.Printf("%s: Resetting", k.Name())
	k.rows[0], k.rows[1] = 0x0F, 0x0F
	k.colSelect = 0x00
}

func (k *KeyHandler) LinkIRQHandler(m components.IRQHandler) {
	k.irqHandler = m
	log.Printf("%s: Linked IRQ Handler to Keyboard Handler", k.Name())
}

func (k *KeyHandler) Read(addr types.Word) byte {
	var value byte

	switch k.colSelect {
	case ROW_1:
		value = k.rows[1]
	case ROW_2:
		value = k.rows[0]
	default:
		value = 0x00
	}

	return value
}

func (k *KeyHandler) Write(addr types.Word, value byte) {
	k.colSelect = value & 0x30
}

//released sets bit for key to 0
func (k *KeyHandler) KeyDown(key glfw.Key) {
	k.irqHandler.RequestInterrupt(constants.JOYP_HILO_IRQ)
	switch key {
	case k.controlScheme.UP:
		k.rows[0] &= 0xB
	case k.controlScheme.DOWN:
		k.rows[0] &= 0x7
	case k.controlScheme.LEFT:
		k.rows[0] &= 0xD
	case k.controlScheme.RIGHT:
		k.rows[0] &= 0xE
	case k.controlScheme.A:
		k.rows[1] &= 0xE
	case k.controlScheme.B:
		k.rows[1] &= 0xD
	case k.controlScheme.START:
		k.rows[1] &= 0x7
	case k.controlScheme.SELECT:
		k.rows[1] &= 0xB
	}
}

//released sets bit for key to 1
func (k *KeyHandler) KeyUp(key glfw.Key) {
	switch key {
	case k.controlScheme.UP:
		k.rows[0] |= 0x4
	case k.controlScheme.DOWN:
		k.rows[0] |= 0x8
	case k.controlScheme.LEFT:
		k.rows[0] |= 0x2
	case k.controlScheme.RIGHT:
		k.rows[0] |= 0x1
	case k.controlScheme.A:
		k.rows[1] |= 0x1
	case k.controlScheme.B:
		k.rows[1] |= 0x2
	case k.controlScheme.START:
		k.rows[1] |= 0x8
	case k.controlScheme.SELECT:
		k.rows[1] |= 0x4
	}
}

type IO struct {
	KeyHandler          *KeyHandler
	Display             *Display
	ScreenOutputChannel chan *types.Screen
	AudioOutputChannel  chan int
}

func NewIO() *IO {
	var i *IO = new(IO)
	i.KeyHandler = new(KeyHandler)
	i.Display = new(Display)
	i.ScreenOutputChannel = make(chan *types.Screen)
	i.AudioOutputChannel = make(chan int)
	return i
}

func (i *IO) Init(title string, screenSize int, onCloseHandler func()) error {
	var err error

	err = i.Display.init(title, screenSize, onCloseHandler)
	if err != nil {
		return err
	}

	i.KeyHandler.Init(DefaultControlScheme) //TODO: allow user to define controlscheme
	i.Display.window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
		if action == glfw.Repeat {
			i.KeyHandler.KeyDown(key)
			return
		}

		if action == glfw.Press {
			i.KeyHandler.KeyDown(key)
		} else {
			i.KeyHandler.KeyUp(key)
		}
	})

	return nil
}

//This will wait for updates to the display or audio and dispatch them accordingly
func (i *IO) Run() {
	for {
		select {
		case data := <-i.ScreenOutputChannel:
			i.Display.drawFrame(data)
		case data := <-i.AudioOutputChannel:
			log.Println("Writing %d to audio!", data)
		}
	}
}

type Display struct {
	Name                 string
	ScreenSizeMultiplier int
	window               *glfw.Window
}

func (s *Display) init(title string, screenSizeMultiplier int, onCloseHandler func()) error {
	var err error

	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to initialize glfw:", err)
	}

	s.Name = PREFIX + "-SCREEN"

	log.Printf("%s: Initialising display", s.Name)

	s.ScreenSizeMultiplier = screenSizeMultiplier
	log.Printf("%s: Set screen size multiplier to %dx", s.Name, s.ScreenSizeMultiplier)

	glfw.WindowHint(glfw.Resizable, glfw.False)
	window, err := glfw.CreateWindow(SCREEN_WIDTH*s.ScreenSizeMultiplier, SCREEN_HEIGHT*s.ScreenSizeMultiplier, "Testing", nil, nil)
	if err != nil {
		return err
	}

	window.SetTitle(title)

	//TODO fix desktop mode
	window.SetPos((s.ScreenSizeMultiplier)/2, (s.ScreenSizeMultiplier)/2)

	window.SetCloseCallback(func(w *glfw.Window) {
		w.Destroy()
		glfw.Terminate()
		onCloseHandler()
	})

	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		return err
	}

	gl.ClearColor(0.255, 0.255, 0.255, 0)

	//resize functionTrue
	/*
		onResize := func(window *glfw.Window, w, h int) {
			gl.Viewport(0, 0, int32(w), int32(h))
			gl.MatrixMode(gl.PROJECTION)
			gl.LoadIdentity()
			gl.Ortho(0, float64(w), float64(h), 0, -1, 1)
			gl.ClearColor(0.255, 0.255, 0.255, 0)
			gl.Clear(gl.COLOR_BUFFER_BIT)
			gl.MatrixMode(gl.MODELVIEW)
			gl.LoadIdentity()
		}

		window.SetSizeCallback(onResize)
	*/

	s.window = window

	return nil

}

func (s *Display) drawFrame(screenData *types.Screen) {
	gl.Viewport(0, 0, int32(SCREEN_WIDTH*s.ScreenSizeMultiplier)*2, int32(SCREEN_HEIGHT*s.ScreenSizeMultiplier)*2)
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(SCREEN_WIDTH*s.ScreenSizeMultiplier), float64(SCREEN_HEIGHT*s.ScreenSizeMultiplier), 0, -1, 1)
	gl.ClearColor(0.255, 0.255, 0.255, 0)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()

	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Disable(gl.DEPTH_TEST)
	gl.PointSize(float32(s.ScreenSizeMultiplier) + 1.0)
	gl.Begin(gl.POINTS)
	for y := 0; y < SCREEN_HEIGHT; y++ {
		for x := 0; x < SCREEN_WIDTH; x++ {
			var pixel types.RGB = screenData[y][x]
			gl.Color3ub(pixel.Red, pixel.Green, pixel.Blue)
			gl.Vertex2i(int32(x*s.ScreenSizeMultiplier), int32(y*s.ScreenSizeMultiplier))
		}
	}

	gl.End()
	glfw.PollEvents()
	s.window.SwapBuffers()
}
<|endoftext|>


<commit_before>// Copyright 2017 Monax Industries Limited
//
// 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 integration

import (
	"context"
	"encoding/binary"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/hyperledger/burrow/acm"
	"github.com/hyperledger/burrow/acm/validator"
	"github.com/hyperledger/burrow/config"
	"github.com/hyperledger/burrow/consensus/tendermint"
	"github.com/hyperledger/burrow/core"
	"github.com/hyperledger/burrow/crypto/sha3"
	"github.com/hyperledger/burrow/execution"
	"github.com/hyperledger/burrow/execution/evm"
	"github.com/hyperledger/burrow/genesis"
	"github.com/hyperledger/burrow/keys/mock"
	"github.com/hyperledger/burrow/logging"
	"github.com/hyperledger/burrow/logging/lifecycle"
	lConfig "github.com/hyperledger/burrow/logging/logconfig"
	"github.com/hyperledger/burrow/permission"
)

const (
	ChainName = "Integration_Test_Chain"
	testDir   = "./test_scratch/tm_test"
)

// Enable logger output during tests

// Starting point for assigning range of ports for tests
// Start at unprivileged port (hoping for the best)
const startingPort uint16 = 1024

// For each port claimant assign a bucket
const startingPortSeparation uint16 = 10
const startingPortBuckets = 1000

// Mutable port to assign to next claimant
var port = uint32(startingPort)

var node uint64 = 0

// We use this to wrap tests
func TestKernel(validatorAccount *acm.PrivateAccount, keysAccounts []*acm.PrivateAccount,
	testConfig *config.BurrowConfig, loggingConfig *lConfig.LoggingConfig) *core.Kernel {
	fmt.Println("Creating integration test Kernel...")

	logger := logging.NewNoopLogger()
	if loggingConfig != nil {
		var err error
		// Change config as needed
		logger, err = lifecycle.NewLoggerFromLoggingConfig(loggingConfig)
		if err != nil {
			panic(err)
		}
	}

	privValidator := tendermint.NewPrivValidatorMemory(validatorAccount, validatorAccount)
	keyClient := mock.NewKeyClient(keysAccounts...)
	kernel, err := core.NewKernel(context.Background(), keyClient, privValidator,
		testConfig.GenesisDoc,
		testConfig.Tendermint.TendermintConfig(),
		testConfig.RPC,
		testConfig.Keys,
		nil,
		[]execution.ExecutionOption{execution.VMOptions(evm.DebugOpcodes)},
		testConfig.Tendermint.DefaultAuthorizedPeersProvider(),
		logger)
	if err != nil {
		panic(err)
	}

	return kernel
}

func EnterTestDirectory() (cleanup func()) {
	os.RemoveAll(testDir)
	os.MkdirAll(testDir, 0777)
	os.Chdir(testDir)
	os.MkdirAll("config", 0777)
	return func() { os.RemoveAll(testDir) }
}

func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc {
	accounts := make(map[string]*acm.Account, len(addressables))
	for i, pa := range addressables {
		account := acm.FromAddressable(pa)
		account.Balance += 1 << 32
		account.Permissions = permission.AllAccountPermissions.Clone()
		accounts[fmt.Sprintf("user_%v", i)] = account
	}
	genesisTime, err := time.Parse("02-01-2006", "27-10-2017")
	if err != nil {
		panic("could not parse test genesis time")
	}
	return genesis.MakeGenesisDocFromAccounts(ChainName, nil, genesisTime, accounts,
		map[string]validator.Validator{
			"genesis_validator": validator.FromAccount(accounts["user_0"], 1<<16),
		})
}

// Deterministic account generation helper. Pass number of accounts to make
func MakePrivateAccounts(n int) []*acm.PrivateAccount {
	accounts := make([]*acm.PrivateAccount, n)
	for i := 0; i < n; i++ {
		accounts[i] = acm.GeneratePrivateAccountFromSecret("mysecret" + strconv.Itoa(i))
	}
	return accounts
}

// Some helpers for setting Burrow's various ports in non-colliding ranges for tests
func ClaimPorts() uint16 {
	_, file, _, _ := runtime.Caller(1)
	startIndex := uint16(binary.LittleEndian.Uint16(sha3.Sha3([]byte(file)))) % startingPortBuckets
	newPort := startingPort + startIndex*startingPortSeparation
	// In case overflow
	if newPort < startingPort {
		newPort += startingPort
	}
	if !atomic.CompareAndSwapUint32(&port, uint32(startingPort), uint32(newPort)) {
		panic("GetPort() called before ClaimPorts() or ClaimPorts() called twice")
	}
	return uint16(atomic.LoadUint32(&port))
}

func GetPort() uint16 {
	return uint16(atomic.AddUint32(&port, 1))
}

// Gets an name based on an incrementing counter for running multiple nodes
func GetName() string {
	nodeNumber := atomic.AddUint64(&node, 1)
	return fmt.Sprintf("node_%03d", nodeNumber)
}

func GetLocalAddress() string {
	return fmt.Sprintf("127.0.0.1:%v", GetPort())
}

func GetTCPLocalAddress() string {
	return fmt.Sprintf("tcp://127.0.0.1:%v", GetPort())
}

func NewTestConfig(genesisDoc *genesis.GenesisDoc) *config.BurrowConfig {
	name := GetName()
	cnf := config.DefaultBurrowConfig()
	cnf.GenesisDoc = genesisDoc
	cnf.Tendermint.Moniker = name
	cnf.Tendermint.TendermintRoot = fmt.Sprintf(".burrow_%s", name)
	cnf.Tendermint.ListenAddress = GetTCPLocalAddress()
	cnf.Tendermint.ExternalAddress = cnf.Tendermint.ListenAddress
	cnf.RPC.GRPC.ListenAddress = GetLocalAddress()
	cnf.RPC.Metrics.ListenAddress = GetTCPLocalAddress()
	cnf.RPC.Info.ListenAddress = GetTCPLocalAddress()
	cnf.Keys.RemoteAddress = ""
	return cnf
}
<commit_msg>Put integration scratch in tmp<commit_after>// Copyright 2017 Monax Industries Limited
//
// 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 integration

import (
	"context"
	"encoding/binary"
	"fmt"
	"io/ioutil"
	"os"
	"runtime"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/hyperledger/burrow/acm"
	"github.com/hyperledger/burrow/acm/validator"
	"github.com/hyperledger/burrow/config"
	"github.com/hyperledger/burrow/consensus/tendermint"
	"github.com/hyperledger/burrow/core"
	"github.com/hyperledger/burrow/crypto/sha3"
	"github.com/hyperledger/burrow/execution"
	"github.com/hyperledger/burrow/execution/evm"
	"github.com/hyperledger/burrow/genesis"
	"github.com/hyperledger/burrow/keys/mock"
	"github.com/hyperledger/burrow/logging"
	"github.com/hyperledger/burrow/logging/lifecycle"
	lConfig "github.com/hyperledger/burrow/logging/logconfig"
	"github.com/hyperledger/burrow/permission"
)

const (
	ChainName = "Integration_Test_Chain"
	scratchDir   = "test_scratch"
)

// Enable logger output during tests

// Starting point for assigning range of ports for tests
// Start at unprivileged port (hoping for the best)
const startingPort uint16 = 1024

// For each port claimant assign a bucket
const startingPortSeparation uint16 = 10
const startingPortBuckets = 1000

// Mutable port to assign to next claimant
var port = uint32(startingPort)

var node uint64 = 0

// We use this to wrap tests
func TestKernel(validatorAccount *acm.PrivateAccount, keysAccounts []*acm.PrivateAccount,
	testConfig *config.BurrowConfig, loggingConfig *lConfig.LoggingConfig) *core.Kernel {
	fmt.Println("Creating integration test Kernel...")

	logger := logging.NewNoopLogger()
	if loggingConfig != nil {
		var err error
		// Change config as needed
		logger, err = lifecycle.NewLoggerFromLoggingConfig(loggingConfig)
		if err != nil {
			panic(err)
		}
	}

	privValidator := tendermint.NewPrivValidatorMemory(validatorAccount, validatorAccount)
	keyClient := mock.NewKeyClient(keysAccounts...)
	kernel, err := core.NewKernel(context.Background(), keyClient, privValidator,
		testConfig.GenesisDoc,
		testConfig.Tendermint.TendermintConfig(),
		testConfig.RPC,
		testConfig.Keys,
		nil,
		[]execution.ExecutionOption{execution.VMOptions(evm.DebugOpcodes)},
		testConfig.Tendermint.DefaultAuthorizedPeersProvider(),
		logger)
	if err != nil {
		panic(err)
	}

	return kernel
}

func EnterTestDirectory() (cleanup func()) {
	testDir, err := ioutil.TempDir("", scratchDir)
	if err != nil {
		panic(fmt.Errorf("couldnot make temp dir for integration tests: %v", err))
	}
	os.RemoveAll(testDir)
	os.MkdirAll(testDir, 0777)
	os.Chdir(testDir)
	os.MkdirAll("config", 0777)
	return func() { os.RemoveAll(testDir) }
}

func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc {
	accounts := make(map[string]*acm.Account, len(addressables))
	for i, pa := range addressables {
		account := acm.FromAddressable(pa)
		account.Balance += 1 << 32
		account.Permissions = permission.AllAccountPermissions.Clone()
		accounts[fmt.Sprintf("user_%v", i)] = account
	}
	genesisTime, err := time.Parse("02-01-2006", "27-10-2017")
	if err != nil {
		panic("could not parse test genesis time")
	}
	return genesis.MakeGenesisDocFromAccounts(ChainName, nil, genesisTime, accounts,
		map[string]validator.Validator{
			"genesis_validator": validator.FromAccount(accounts["user_0"], 1<<16),
		})
}

// Deterministic account generation helper. Pass number of accounts to make
func MakePrivateAccounts(n int) []*acm.PrivateAccount {
	accounts := make([]*acm.PrivateAccount, n)
	for i := 0; i < n; i++ {
		accounts[i] = acm.GeneratePrivateAccountFromSecret("mysecret" + strconv.Itoa(i))
	}
	return accounts
}

// Some helpers for setting Burrow's various ports in non-colliding ranges for tests
func ClaimPorts() uint16 {
	_, file, _, _ := runtime.Caller(1)
	startIndex := uint16(binary.LittleEndian.Uint16(sha3.Sha3([]byte(file)))) % startingPortBuckets
	newPort := startingPort + startIndex*startingPortSeparation
	// In case overflow
	if newPort < startingPort {
		newPort += startingPort
	}
	if !atomic.CompareAndSwapUint32(&port, uint32(startingPort), uint32(newPort)) {
		panic("GetPort() called before ClaimPorts() or ClaimPorts() called twice")
	}
	return uint16(atomic.LoadUint32(&port))
}

func GetPort() uint16 {
	return uint16(atomic.AddUint32(&port, 1))
}

// Gets an name based on an incrementing counter for running multiple nodes
func GetName() string {
	nodeNumber := atomic.AddUint64(&node, 1)
	return fmt.Sprintf("node_%03d", nodeNumber)
}

func GetLocalAddress() string {
	return fmt.Sprintf("127.0.0.1:%v", GetPort())
}

func GetTCPLocalAddress() string {
	return fmt.Sprintf("tcp://127.0.0.1:%v", GetPort())
}

func NewTestConfig(genesisDoc *genesis.GenesisDoc) *config.BurrowConfig {
	name := GetName()
	cnf := config.DefaultBurrowConfig()
	cnf.GenesisDoc = genesisDoc
	cnf.Tendermint.Moniker = name
	cnf.Tendermint.TendermintRoot = fmt.Sprintf(".burrow_%s", name)
	cnf.Tendermint.ListenAddress = GetTCPLocalAddress()
	cnf.Tendermint.ExternalAddress = cnf.Tendermint.ListenAddress
	cnf.RPC.GRPC.ListenAddress = GetLocalAddress()
	cnf.RPC.Metrics.ListenAddress = GetTCPLocalAddress()
	cnf.RPC.Info.ListenAddress = GetTCPLocalAddress()
	cnf.Keys.RemoteAddress = ""
	return cnf
}
<|endoftext|>


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

package frontend

import (
	"github.com/sirupsen/logrus"
	"open-match.dev/open-match/examples/scale/tickets"
	"open-match.dev/open-match/internal/config"
	"open-match.dev/open-match/internal/logging"
)

var (
	logger = logrus.WithFields(logrus.Fields{
		"app":       "openmatch",
		"component": "scale.frontend",
	})
)

// Run triggers execution of the scale frontend component that creates
// tickets at scale in Open Match.
func Run() {
	cfg, err := config.Read()
	if err != nil {
		logger.WithFields(logrus.Fields{
			"error": err.Error(),
		}).Fatal("cannot read configuration.")
	}

	logging.ConfigureLogging(cfg)

	// TODO: This is a placeholder - add the actual implementation.
	concurrent := cfg.GetInt("testConfig.concurrent-creates")
	for i := 0; i <= concurrent; i++ {
		_ = tickets.Ticket(cfg)
	}
}
<commit_msg>Implement test frontend that creates tickets in Open Match continuously (#803)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package frontend

import (
	"context"
	"sync"
	"sync/atomic"
	"time"

	"github.com/sirupsen/logrus"
	"open-match.dev/open-match/examples/scale/tickets"
	"open-match.dev/open-match/internal/config"
	"open-match.dev/open-match/internal/logging"
	"open-match.dev/open-match/internal/rpc"
	"open-match.dev/open-match/pkg/pb"
)

var (
	logger = logrus.WithFields(logrus.Fields{
		"app":       "openmatch",
		"component": "scale.frontend",
	})
)

// Run triggers execution of the scale frontend component that creates
// tickets at scale in Open Match.
func Run() {
	cfg, err := config.Read()
	if err != nil {
		logger.WithFields(logrus.Fields{
			"error": err.Error(),
		}).Fatal("cannot read configuration.")
	}

	logging.ConfigureLogging(cfg)
	doCreate(cfg)
}

func doCreate(cfg config.View) {
	concurrent := cfg.GetInt("testConfig.concurrent-creates")
	conn, err := rpc.GRPCClientFromConfig(cfg, "api.frontend")
	if err != nil {
		logger.WithFields(logrus.Fields{
			"error": err.Error(),
		}).Fatal("failed to get Frontend connection")
	}

	defer conn.Close()
	fe := pb.NewFrontendClient(conn)

	var created uint64
	var failed uint64
	start := time.Now()
	for {
		var wg sync.WaitGroup
		for i := 0; i <= concurrent; i++ {
			wg.Add(1)
			go func(wg *sync.WaitGroup) {
				defer wg.Done()
				req := &pb.CreateTicketRequest{
					Ticket: tickets.Ticket(cfg),
				}

				if _, err := fe.CreateTicket(context.Background(), req); err != nil {
					logger.WithFields(logrus.Fields{
						"error": err.Error(),
					}).Error("failed to create a ticket.")
					atomic.AddUint64(&failed, 1)
					return
				}

				atomic.AddUint64(&created, 1)
			}(&wg)
		}

		// Wait for all concurrent creates to complete.
		wg.Wait()
		logger.Infof("%v tickets created, %v failed in %v", created, failed, time.Since(start))
	}
}
<|endoftext|>