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

package main

import (
	"fmt"
	"os"
	"os/exec"
	"io/ioutil"
	"path/filepath"
	"encoding/json"
)

type ImageManifest struct {
	ACVersion     string `json:"acVersion"`
	ACKind        string `json:"acKind"`
	Name          string `json:"name"`
	Labels        string `json:"labels,omitempty"`
	App           string `json:"app,omitempty"`
	Annotations   string `json:"annotations,omitempty"`
	Dependencies  string `json:"dependencies,omitempty"`
	PathWhitelist string `json:"pathWhitelist,omitempty"`
}

func blankImageManifest() *ImageManifest {
	return &ImageManifest{ACKind: "ImageManifest", ACVersion: "0.6.1+git", Name: "test"}
}

func runOCI2ACI(path string, flagDebug bool) error {
	if flagDebug {
		InitDebug()
	}
	if bValidate := validateOCIProc(path); bValidate != true {
                fmt.Println("Conversion stop.")
                return nil
        }

	dirWork := createWorkDir()

	convertProc(path, dirWork)

	buildACI(dirWork)

	return nil
}

func createWorkDir() string {
	idir, err := ioutil.TempDir("", "oci2aci")
        if err != nil {
                return ""
        }
        rootfs := filepath.Join(idir, "rootfs")
        os.MkdirAll(rootfs, 0755)

	data := []byte{}
	if err := ioutil.WriteFile(filepath.Join(idir, "manifest"), data, 0644); err != nil {
		return ""
	}
	return idir
}

func genManifest() *ImageManifest {
	return blankImageManifest()
}

func convertProc(srcPath, dstPath string) error {
	src := srcPath + "/rootfs"
	if err := run(exec.Command("cp", "-rf", src, dstPath)); err != nil {
		return err
	}

	m := genManifest()
	fmt.Println(m)

	bytes, err := json.Marshal(m)
	if err != nil {
		return err
	}

	manifestPath := dstPath + "/manifest"

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

package main

import (
	"fmt"
	"os"
	"os/exec"
	"io/ioutil"
	"path/filepath"
	"encoding/json"
	"github.com/opencontainers/specs"
	"github.com/appc/spec/schema/types"
	"github.com/appc/spec/schema"
)

func runOCI2ACI(path string, flagDebug bool) error {
	if flagDebug {
		InitDebug()
	}
	if bValidate := validateOCIProc(path); bValidate != true {
                fmt.Println("Conversion stop.")
                return nil
        }

	dirWork := createWorkDir()

	convertProc(path, dirWork)

	buildACI(dirWork)

	return nil
}

func createWorkDir() string {
	idir, err := ioutil.TempDir("", "oci2aci")
        if err != nil {
                return ""
        }
        rootfs := filepath.Join(idir, "rootfs")
        os.MkdirAll(rootfs, 0755)

	data := []byte{}
	if err := ioutil.WriteFile(filepath.Join(idir, "manifest"), data, 0644); err != nil {
		return ""
	}
	return idir
}

func genManifest(path string) *schema.ImageManifest {
	//runtimePath := path + "/runtime.json"
	configPath := path + "/config.json"

	/*runtime, err := ioutil.ReadFile(runtimePath)
	if err != nil {
		return nil
	}*/

	config, err := ioutil.ReadFile(configPath)
	if err != nil {
		return nil
	}

	var spec specs.Spec
	err = json.Unmarshal(config, &spec)
	if err != nil {
		return nil
	}

	m := new(schema.ImageManifest)
	semVer, _ := types.NewSemVer(spec.Version)
	m.ACVersion = *semVer
	m.ACKind = "ImageManifest"
	m.Name = "example"

	return m
}

func convertProc(srcPath, dstPath string) error {
	src := srcPath + "/rootfs"
	if err := run(exec.Command("cp", "-rf", src, dstPath)); err != nil {
		return err
	}

	m := genManifest(srcPath)

	bytes, err := json.Marshal(m)
	if err != nil {
		return err
	}

	manifestPath := dstPath + "/manifest"

	ioutil.WriteFile(manifestPath, bytes, 0644)
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 The Prometheus 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 !windows,!plan9,!solaris

package tsdb

import (
	"os"
	"syscall"
)

func mmap(f *os.File, length int) ([]byte, error) {
	return syscall.Mmap(int(f.Fd()), 0, length, syscall.PROT_READ, syscall.MAP_SHARED)
}

func munmap(b []byte) (err error) {
	return syscall.Munmap(b)
}
<commit_msg>Ensure tsdb can be built on SmartOS/Illumos/Solaris<commit_after>// Copyright 2017 The Prometheus 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 !windows,!plan9

package tsdb

import (
	"os"

	"golang.org/x/sys/unix"
)

func mmap(f *os.File, length int) ([]byte, error) {
	return unix.Mmap(int(f.Fd()), 0, length, unix.PROT_READ, unix.MAP_SHARED)
}

func munmap(b []byte) (err error) {
	return unix.Munmap(b)
}
<|endoftext|>


<commit_before>package hdhomerun

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"os"
	"runtime/debug"
)

var (
	ErrCrc error = errors.New("Invalid CRC")
)

type Decoder struct {
	r io.Reader
}

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

func (d *Decoder) Next() (*Packet, error) {
	pd := &packetDecoder{
		r: d.r,
	}
	return pd.decode()
}

type packetDecoder struct {
	r   io.Reader
	err error
}

func (pd *packetDecoder) Read(b []byte) (int, error) {
	n := 0
	if pd.err == nil {
		n, pd.err = pd.r.Read(b)
		if pd.err != nil {
			fmt.Fprintf(os.Stderr, "Failed to read: %v", pd.err)
			debug.PrintStack()
		}
	}
	return n, pd.err
}

func (pd *packetDecoder) binaryRead(byteOrder binary.ByteOrder, data interface{}) {
	if pd.err == nil {
		pd.err = binary.Read(pd, byteOrder, data)
	}
}

func (pd *packetDecoder) decode() (p *Packet, err error) {
	incomingCrc := uint32(0)
	length := uint16(0)
	p = &Packet{}

	pd.binaryRead(binary.BigEndian, &p.Type)
	pd.binaryRead(binary.BigEndian, &length)

	data := make([]byte, length)
	pd.Read(data)
	computedCrc := crc32.Update(0, crc32.IEEETable, []byte{byte(p.Type >> 8), byte(p.Type)})
	computedCrc = crc32.Update(computedCrc, crc32.IEEETable, []byte{byte(length >> 8), byte(length)})
	computedCrc = crc32.Update(computedCrc, crc32.IEEETable, data)

	pd.binaryRead(binary.LittleEndian, &incomingCrc)
	if pd.err == nil && incomingCrc != computedCrc {
		pd.err = ErrCrc
	}

	var tagLength uint16
	buffer := bytes.NewReader(data)
	pd.r = buffer
	for pd.err == nil && buffer.Len() > 0 {
		t := Tag{}
		var lsb, msb uint8

		pd.binaryRead(binary.BigEndian, &t.Tag)
		pd.binaryRead(binary.BigEndian, &lsb)

		// two byte length
		if lsb&0x80 == 0x80 {
			pd.binaryRead(binary.BigEndian, &msb)
			tagLength = uint16(lsb&0x7f) | uint16(msb)<<7
		} else {
			tagLength = uint16(lsb)
		}

		t.Value = make([]byte, tagLength)
		pd.Read(t.Value)
		if pd.err == nil {
			p.Tags = append(p.Tags, t)
		}
	}
	return p, pd.err
}
<commit_msg>Removed debugging line<commit_after>package hdhomerun

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"os"
)

var (
	ErrCrc error = errors.New("Invalid CRC")
)

type Decoder struct {
	r io.Reader
}

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

func (d *Decoder) Next() (*Packet, error) {
	pd := &packetDecoder{
		r: d.r,
	}
	return pd.decode()
}

type packetDecoder struct {
	r   io.Reader
	err error
}

func (pd *packetDecoder) Read(b []byte) (int, error) {
	n := 0
	if pd.err == nil {
		n, pd.err = pd.r.Read(b)
	}
	return n, pd.err
}

func (pd *packetDecoder) binaryRead(byteOrder binary.ByteOrder, data interface{}) {
	if pd.err == nil {
		pd.err = binary.Read(pd, byteOrder, data)
	}
}

func (pd *packetDecoder) decode() (p *Packet, err error) {
	incomingCrc := uint32(0)
	length := uint16(0)
	p = &Packet{}

	pd.binaryRead(binary.BigEndian, &p.Type)
	pd.binaryRead(binary.BigEndian, &length)

	data := make([]byte, length)
	pd.Read(data)
	computedCrc := crc32.Update(0, crc32.IEEETable, []byte{byte(p.Type >> 8), byte(p.Type)})
	computedCrc = crc32.Update(computedCrc, crc32.IEEETable, []byte{byte(length >> 8), byte(length)})
	computedCrc = crc32.Update(computedCrc, crc32.IEEETable, data)

	pd.binaryRead(binary.LittleEndian, &incomingCrc)
	if pd.err == nil && incomingCrc != computedCrc {
		pd.err = ErrCrc
	}

	var tagLength uint16
	buffer := bytes.NewReader(data)
	pd.r = buffer
	for pd.err == nil && buffer.Len() > 0 {
		t := Tag{}
		var lsb, msb uint8

		pd.binaryRead(binary.BigEndian, &t.Tag)
		pd.binaryRead(binary.BigEndian, &lsb)

		// two byte length
		if lsb&0x80 == 0x80 {
			pd.binaryRead(binary.BigEndian, &msb)
			tagLength = uint16(lsb&0x7f) | uint16(msb)<<7
		} else {
			tagLength = uint16(lsb)
		}

		t.Value = make([]byte, tagLength)
		pd.Read(t.Value)
		if pd.err == nil {
			p.Tags = append(p.Tags, t)
		}
	}
	return p, pd.err
}
<|endoftext|>


<commit_before>package sse

import (
	"bufio"
	"bytes"
	"io"
)

const (
	defaultBufferSize = 8096
)

var (
	// DefaultDecoder is the decoder used by EventSource by default.
	DefaultDecoder = NewDecoder(defaultBufferSize)

	bytesLF    = []byte("\n")
	bytesCRLF  = []byte("\r\n")
	bytesSPACE = []byte(" ")
	bytesCOLON = []byte(":")
)

type (
	// Decoder interface decodes events from a reader input
	Decoder interface {
		Decode(in io.Reader) (out <-chan Event)
	}
	decoder struct {
		bufferSize int
	}
)

// NewDecoder builds an SSE decoder with the specified buffer size.
func NewDecoder(bufferSize int) Decoder {
	d := &decoder{}
	d.initialise(bufferSize)
	return d
}

func (d *decoder) initialise(bufferSize int) {
	d.bufferSize = bufferSize
}

// Returns a channel of SSE events from a reader input.
func (d *decoder) Decode(in io.Reader) <-chan Event {
	buffIn := bufio.NewReaderSize(in, d.bufferSize)
	out := make(chan Event)
	go process(buffIn, out)
	return out
}

// Processes a reader and sends the parsed SSE events
// to the output channel.
// This function is intended to run in a go-routine.
func process(in *bufio.Reader, out chan Event) {
	// Stores event data, which is filled after one or many lines from the reader
	var eventID, eventType, dataBuffer = new(bytes.Buffer), new(bytes.Buffer), new(bytes.Buffer)

	// Stores data about the current line being processed
	var field, value = new(bytes.Buffer), new(bytes.Buffer)

	for {
		line, err := in.ReadSlice('\n')
		if err != nil {
			close(out)
			return
		}

		// Dispatch the event.
		// Note the event source spec as defined by w3.org requires skips the event dispatching if
		// the event name collides with the name of any event as defined in the DOM Events spec.
		// Decoder does not perform this check, hence it could yield events that would not be valid
		// in a browser.
		if bytes.Equal(line, bytesLF) || bytes.Equal(line, bytesCRLF) {
			// Skip event if Data buffer its empty
			if dataBuffer.Len() == 0 {
				dataBuffer.Reset()
				eventType.Reset()
				continue
			}

			data := dataBuffer.Bytes()

			// Trim last byte if line feed
			data = bytes.TrimSuffix(data, bytesLF)

			// Create event
			event := newEvent(eventID.String(), eventType.String(), data)

			// Clear event buffers
			eventType.Reset()
			dataBuffer.Reset()

			// Dispatch event
			out <- event
			continue
		}

		// Sanitise line feeds
		line = sanitiseLineFeed(line)

		// Extract field/value for current line
		field.Reset()
		value.Reset()

		colonIndex := bytes.Index(line, bytesCOLON)
		switch colonIndex {
		case 0:
			continue
		case -1:
			field.Write(line)
		default:
			field.Write(line[:colonIndex])
			line = line[colonIndex+1:]
			line = bytes.TrimPrefix(line, bytesSPACE)
			value.Write(line)
		}

		// Process field
		fieldName := field.String()
		switch fieldName {
		case "event":
			eventType.Write(value.Bytes())
		case "data":
			dataBuffer.Write(value.Bytes())
			dataBuffer.WriteByte('\n')
		case "id":
			eventID.Reset()
			eventID.Write(value.Bytes())
		case "retry":
			// TODO(alevinval): unused at the moment, will need refactor
			// or change on the internal API, as decoder has no knowledge on the underlying connection.
		default:
			// Ignore field
		}
	}
}

// Sanitises line feed ending.
func sanitiseLineFeed(line []byte) []byte {
	if bytes.HasSuffix(line, bytesCRLF) {
		return bytes.TrimSuffix(line, bytesCRLF)
	} else {
		return bytes.TrimSuffix(line, bytesLF)
	}
}
<commit_msg>Solve conflicts and add small docstrings where standard library has been replaced by optimized code.<commit_after>package sse

import (
	"bufio"
	"bytes"
	"io"
)

const (
	defaultBufferSize = 8096
)

const (
	byteLF    = '\n'
	byteCR    = '\r'
	byteSPACE = ' '
	byteCOLON = ':'
)

var (
	// DefaultDecoder is the decoder used by EventSource by default.
	DefaultDecoder = NewDecoder(defaultBufferSize)
)

type (
	// Decoder interface decodes events from a reader input
	Decoder interface {
		Decode(in io.Reader) (out <-chan Event)
	}
	decoder struct {
		bufferSize int
	}
)

// NewDecoder builds an SSE decoder with the specified buffer size.
func NewDecoder(bufferSize int) Decoder {
	d := &decoder{}
	d.initialise(bufferSize)
	return d
}

func (d *decoder) initialise(bufferSize int) {
	d.bufferSize = bufferSize
}

// Returns a channel of SSE events from a reader input.
func (d *decoder) Decode(in io.Reader) <-chan Event {
	buffIn := bufio.NewReaderSize(in, d.bufferSize)
	out := make(chan Event)
	go process(buffIn, out)
	return out
}

// Processes a reader and sends the parsed SSE events
// to the output channel.
// This function is intended to run in a go-routine.
func process(in *bufio.Reader, out chan Event) {
	// Stores event data, which is filled after one or many lines from the reader
	var eventID, eventType, dataBuffer = new(bytes.Buffer), new(bytes.Buffer), new(bytes.Buffer)

	// Stores data about the current line being processed
	var field, value = new(bytes.Buffer), new(bytes.Buffer)

	for {
		line, err := in.ReadSlice(byteLF)
		if err != nil {
			close(out)
			return
		}

		// Empty line? => Dispatch event
		// Note the event source spec as defined by w3.org requires skips the event dispatching if
		// the event name collides with the name of any event as defined in the DOM Events spec.
		// Decoder does not perform this check, hence it could yield events that would not be valid
		// in a browser.
		if len(line) == 1 || (len(line) == 2 && line[0] == byteCR) {
			// Skip event if Data buffer is empty
			if dataBuffer.Len() == 0 {
				dataBuffer.Reset()
				eventType.Reset()
				continue
			}

			data := dataBuffer.Bytes()

			// Trim last byte if line feed
			if data[len(data)-1] == byteLF {
				data = data[:len(data)-1]
			}

			// Create event
			event := newEvent(eventID.String(), eventType.String(), data)

			// Clear event buffers
			eventType.Reset()
			dataBuffer.Reset()

			// Dispatch event
			out <- event
			continue
		}

		// Sanitise line feeds
		line = sanitiseLineFeed(line)

		// Extract field/value for current line
		field.Reset()
		value.Reset()

		colonIndex := bytes.IndexByte(line, byteCOLON)
		switch colonIndex {
		case 0:
			continue
		case -1:
			field.Write(line)
		default:
			field.Write(line[:colonIndex])
			line = line[colonIndex+1:]
			// Trim prefixed space.
			if len(line) > 0 && line[0] == byteSPACE {
				line = line[1:]
			}
			value.Write(line)
		}

		// Process field
		fieldName := field.String()
		switch fieldName {
		case "event":
			eventType.Write(value.Bytes())
		case "data":
			dataBuffer.Write(value.Bytes())
			dataBuffer.WriteByte(byteLF)
		case "id":
			eventID.Reset()
			eventID.Write(value.Bytes())
		case "retry":
			// TODO(alevinval): unused at the moment, will need refactor
			// or change on the internal API, as decoder has no knowledge on the underlying connection.
		default:
			// Ignore field
		}
	}
}

// Sanitises line feed ending.
func sanitiseLineFeed(line []byte) []byte {
	l := len(line)
	// Trim LF
	if l > 0 && line[l-1] == byteLF {
		l--
		// Trim CR
		if l > 0 && line[l-1] == byteCR {
			l--
		}
		line = line[:l]
	}
	return line
}
<|endoftext|>


<commit_before>package rmarsh

import (
	"fmt"
	"io"
	"reflect"
	"strconv"
	"strings"
	"sync"
)

// A Decoder decodes a Ruby Marshal stream into concrete Golang structures.
type Decoder struct {
	p        *Parser
	objCache []reflect.Value
	curToken Token
}

// NewDecoder builds a new Decoder that uses given Parser to decode a Ruby Marshal stream.
func NewDecoder(p *Parser) *Decoder {
	return &Decoder{p: p}
}

// ReadValue will consume a full Ruby Marshal stream from the given io.Reader and return a fully decoded Golang object.
func ReadValue(r io.Reader, val interface{}) error {
	// TODO: grab Parser instance from a sync.Pool
	return NewDecoder(NewParser(r)).Decode(val)
}

// Decode will consume a value from the underlying parser and marshal it into the provided Golang type.
func (d *Decoder) Decode(val interface{}) error {
	v := reflect.ValueOf(val)
	if v.Kind() != reflect.Ptr {
		return fmt.Errorf("Invalid decode target %T, did you forget to pass a pointer?", val)
	}

	return d.valueDecoder(v.Elem())(d, v.Elem())
}

func (d *Decoder) nextToken() (Token, error) {
	if d.curToken != tokenInvalid {
		tok := d.curToken
		d.curToken = tokenInvalid
		return tok, nil
	}
	return d.p.Next()
}

type decoderFunc func(*Decoder, reflect.Value) error

func (d *Decoder) valueDecoder(v reflect.Value) decoderFunc {
	return d.typeDecoder(v.Type())
}

var decCache struct {
	sync.RWMutex
	m map[reflect.Type]decoderFunc
}

func (d *Decoder) typeDecoder(t reflect.Type) decoderFunc {
	decCache.RLock()
	dec := decCache.m[t]
	decCache.RUnlock()
	if dec != nil {
		return dec
	}

	decCache.Lock()
	defer decCache.Unlock()
	if decCache.m == nil {
		decCache.m = make(map[reflect.Type]decoderFunc)
	}
	decCache.m[t] = newTypeDecoder(t)
	return decCache.m[t]
}

func newTypeDecoder(t reflect.Type) decoderFunc {
	switch t.Kind() {
	case reflect.Invalid:
		return skipDecoder
	case reflect.Bool:
		return boolDecoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intDecoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintDecoder
	case reflect.Float32, reflect.Float64:
		return floatDecoder
	case reflect.String:
		return stringDecoder
	case reflect.Slice:
		return newSliceDecoder(t)
	case reflect.Struct:
		return newStructDecoder(t)
	case reflect.Ptr:
		return newPtrDecoder(t)
	}
	return unsupportedTypeDecoder
}

func skipDecoder(d *Decoder, v reflect.Value) error {
	_, err := d.p.readNext()
	if err != nil {
		return err
	}
	return d.p.Skip()
}

func boolDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenTrue, TokenFalse:
		v.SetBool(tok == TokenTrue)
		return nil
	default:
		// TODO: build a path
		return fmt.Errorf("Unexpected token %v encountered while decoding bool", tok)
	}
}
func intDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFixnum:
		n, err := d.p.Int()
		if err != nil {
			return err
		}
		nn := int64(n)
		if v.OverflowInt(nn) {
			return fmt.Errorf("Decoded int %d exceeds maximum width of %s", n, v.Type())
		}
		v.SetInt(nn)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding int", tok)
	}
}

func uintDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFixnum:
		n, err := d.p.Int()
		if err != nil {
			return err
		}
		un := uint64(n)
		if v.OverflowUint(un) {
			return fmt.Errorf("Decoded uint %d exceeds maximum width of %s", n, v.Type())
		}
		v.SetUint(un)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding uint", tok)
	}
}

func floatDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFloat:
		f, err := d.p.Float()
		if err != nil {
			return err
		}
		if v.OverflowFloat(f) {
			return fmt.Errorf("Decoded float %f exceeds maximum width of %s", f, v.Type())
		}
		v.SetFloat(f)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding float", tok)
	}
}

func stringDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenUsrMarshal:
		return fmt.Errorf("nope")
	case TokenStartIVar:
		// We're okay with an IVar as long as the next token is a String.
		if err := d.p.ExpectNext(TokenString); err != nil {
			return err
		}

		str, err := d.p.Text()
		if err != nil {
			return err
		}
		v.SetString(str)

		lnkID := d.p.LinkID()
		if lnkID > -1 {
			d.objCache = append(d.objCache, v.Addr())
		}

		if err := d.p.ExpectNext(TokenIVarProps); err != nil {
			return err
		}
		// TODO: properly parse IVar. For now, we just skip over encoding and such.
		if err := d.p.Skip(); err != nil {
			return err
		}
		return nil
	case TokenString, TokenSymbol:
		str, err := d.p.Text()
		if err != nil {
			return err
		}
		v.SetString(str)

		lnkID := d.p.LinkID()
		if lnkID > -1 {
			d.objCache = append(d.objCache, v.Addr())
		}

		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding string", tok)
	}
}

type sliceDecoder struct {
	elemDec decoderFunc
}

func (sliceDec *sliceDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	if tok != TokenStartArray {
		return fmt.Errorf("Unexpected token %v encountered while decoding slice", tok)
	}

	l := d.p.Len()

	// If the underlying slice already has enough capacity for this array, then we just resize
	// and use it.
	cap := v.Cap()
	if cap >= l {
		v.SetLen(l)
		v.SetCap(l)
	} else {
		v.Set(reflect.MakeSlice(v.Type(), l, l))
	}

	lnkID := d.p.LinkID()
	if lnkID > -1 {
		d.objCache = append(d.objCache, v.Addr())
	}

	for i := 0; i < l; i++ {
		if err := sliceDec.elemDec(d, v.Index(i)); err != nil {
			return err
		}
	}

	if err := d.p.ExpectNext(TokenEndArray); err != nil {
		return err
	}

	return nil
}

func newSliceDecoder(t reflect.Type) decoderFunc {
	dec := &sliceDecoder{newTypeDecoder(t.Elem())}
	return dec.decode
}

type idxStructField struct {
	idx int // index in the struct
	dec decoderFunc
}
type idxStructDecoder struct {
	fields []idxStructField
}

func (idxDec *idxStructDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenStartArray:
		l := d.p.Len()

		for i := 0; i < l; i++ {
			if i < len(idxDec.fields) {
				f := idxDec.fields[i]
				if f.dec != nil {
					if err := f.dec(d, v.Field(f.idx)); err != nil {
						return err
					}
					continue
				}
			}

			if _, err := d.p.Next(); err != nil {
				return err
			}

			if err := d.p.Skip(); err != nil {
				return err
			}
		}
		if err := d.p.ExpectNext(TokenEndArray); err != nil {
			return err
		}

		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding indexed struct", tok)
	}

}

func newStructDecoder(t reflect.Type) decoderFunc {
	// A struct decoder can either be indexed or named.
	// Indexed decoders expect to decode a Ruby Array into a Go struct.
	// Named decoders expecet to decode a Ruby Hash/Struct into a Go struct.
	var idxFields []idxStructField
	named := make(map[string]decoderFunc)

	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)

		if f.PkgPath != "" {
			continue
		}

		fdec := newTypeDecoder(f.Type)

		meta := strings.Split(f.Tag.Get("rmarsh"), ",")
		if meta[0] == "" {
			continue
		}
		if meta[0] == "_indexed" {
			if len(named) > 0 {
				return newErrorDecoder(fmt.Errorf("Cannot mix named and _indexed fields in struct %s", t))
			}
			idx, err := strconv.ParseInt(meta[1], 10, 32)
			if err != nil {
				return newErrorDecoder(fmt.Errorf("Struct %s field %q has invalid _indexed value %q", t, f.Name, meta[1]))
			}
			if len(idxFields) <= int(idx) {
				idxFields = append(idxFields, make([]idxStructField, int(idx)-len(idxFields)+1)...)
			}
			idxFields[idx] = idxStructField{idx: i, dec: fdec}
		} else {
			if len(idxFields) > 0 {
				return newErrorDecoder(fmt.Errorf("Cannot mix named and _indexed fields in struct %s", t))
			}
			named[f.Name] = fdec
		}
	}

	if len(idxFields) > 0 {
		dec := &idxStructDecoder{idxFields}
		return dec.decode
	}
	if len(named) > 0 {
		dec := &idxStructDecoder{}
		return dec.decode
	}
	return skipDecoder
}

type ptrDecoder struct {
	elemDec decoderFunc
}

func (ptrDec *ptrDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	// If the token is nil, then we nil the ptr and move on.
	if tok == TokenNil {
		v.Set(reflect.Zero(v.Type()))
		return nil
	}

	// If we've just parsed a link, then we see if we've cached the object already.
	// If we we have, and it's directly assignable to the pointer type we have, then
	// we can just immediately assign it and continue.
	// Otherwise we start a replay parser and run it on the target.
	if tok == TokenLink {
		lnkID := d.p.LinkID()
		if len(d.objCache) > lnkID {
			cached := d.objCache[lnkID]
			if cached.Type().AssignableTo(v.Type()) {
				v.Set(cached)
				return nil
			}
		}

		// TODO: setup a replay parser and run it against the target.
		return fmt.Errorf("Unhandled link encountered. %d", lnkID)
	}

	// Push the token back and decode against resolved ptr.
	d.curToken = tok

	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return ptrDec.elemDec(d, v.Elem())
}

func newPtrDecoder(t reflect.Type) decoderFunc {
	dec := &ptrDecoder{newTypeDecoder(t.Elem())}
	return dec.decode
}

type errorDecoder struct {
	err error
}

func (errDec errorDecoder) decode(d *Decoder, v reflect.Value) error {
	return errDec.err
}

func newErrorDecoder(err error) decoderFunc {
	return errorDecoder{err}.decode
}

func unsupportedTypeDecoder(d *Decoder, v reflect.Value) error {
	return fmt.Errorf("unsupported type %s", v.Type())
}
<commit_msg>decoder: handle links in stringDecoder<commit_after>package rmarsh

import (
	"fmt"
	"io"
	"reflect"
	"strconv"
	"strings"
	"sync"
)

// A Decoder decodes a Ruby Marshal stream into concrete Golang structures.
type Decoder struct {
	p        *Parser
	objCache map[int]reflect.Value
	curToken Token
}

// NewDecoder builds a new Decoder that uses given Parser to decode a Ruby Marshal stream.
func NewDecoder(p *Parser) *Decoder {
	return &Decoder{p: p, objCache: make(map[int]reflect.Value)}
}

// ReadValue will consume a full Ruby Marshal stream from the given io.Reader and return a fully decoded Golang object.
func ReadValue(r io.Reader, val interface{}) error {
	// TODO: grab Parser instance from a sync.Pool
	return NewDecoder(NewParser(r)).Decode(val)
}

// Decode will consume a value from the underlying parser and marshal it into the provided Golang type.
func (d *Decoder) Decode(val interface{}) error {
	v := reflect.ValueOf(val)
	if v.Kind() != reflect.Ptr {
		return fmt.Errorf("Invalid decode target %T, did you forget to pass a pointer?", val)
	}

	return d.valueDecoder(v.Elem())(d, v.Elem())
}

func (d *Decoder) nextToken() (Token, error) {
	if d.curToken != tokenInvalid {
		tok := d.curToken
		d.curToken = tokenInvalid
		return tok, nil
	}
	return d.p.Next()
}

type decoderFunc func(*Decoder, reflect.Value) error

func (d *Decoder) valueDecoder(v reflect.Value) decoderFunc {
	return d.typeDecoder(v.Type())
}

var decCache struct {
	sync.RWMutex
	m map[reflect.Type]decoderFunc
}

func (d *Decoder) typeDecoder(t reflect.Type) decoderFunc {
	decCache.RLock()
	dec := decCache.m[t]
	decCache.RUnlock()
	if dec != nil {
		return dec
	}

	decCache.Lock()
	defer decCache.Unlock()
	if decCache.m == nil {
		decCache.m = make(map[reflect.Type]decoderFunc)
	}
	decCache.m[t] = newTypeDecoder(t)
	return decCache.m[t]
}

func newTypeDecoder(t reflect.Type) decoderFunc {
	switch t.Kind() {
	case reflect.Invalid:
		return skipDecoder
	case reflect.Bool:
		return boolDecoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intDecoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintDecoder
	case reflect.Float32, reflect.Float64:
		return floatDecoder
	case reflect.String:
		return stringDecoder
	case reflect.Slice:
		return newSliceDecoder(t)
	case reflect.Struct:
		return newStructDecoder(t)
	case reflect.Ptr:
		return newPtrDecoder(t)
	}
	return unsupportedTypeDecoder
}

func skipDecoder(d *Decoder, v reflect.Value) error {
	_, err := d.p.readNext()
	if err != nil {
		return err
	}
	return d.p.Skip()
}

func boolDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenTrue, TokenFalse:
		v.SetBool(tok == TokenTrue)
		return nil
	default:
		// TODO: build a path
		return fmt.Errorf("Unexpected token %v encountered while decoding bool", tok)
	}
}
func intDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFixnum:
		n, err := d.p.Int()
		if err != nil {
			return err
		}
		nn := int64(n)
		if v.OverflowInt(nn) {
			return fmt.Errorf("Decoded int %d exceeds maximum width of %s", n, v.Type())
		}
		v.SetInt(nn)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding int", tok)
	}
}

func uintDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFixnum:
		n, err := d.p.Int()
		if err != nil {
			return err
		}
		un := uint64(n)
		if v.OverflowUint(un) {
			return fmt.Errorf("Decoded uint %d exceeds maximum width of %s", n, v.Type())
		}
		v.SetUint(un)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding uint", tok)
	}
}

func floatDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenFloat:
		f, err := d.p.Float()
		if err != nil {
			return err
		}
		if v.OverflowFloat(f) {
			return fmt.Errorf("Decoded float %f exceeds maximum width of %s", f, v.Type())
		}
		v.SetFloat(f)
		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding float", tok)
	}
}

func stringDecoder(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenLink:
		lnkID := d.p.LinkID()
		cached, ok := d.objCache[lnkID]
		if ok {
			if cached.Elem().Kind() == reflect.String {
				v.Set(cached.Elem())
				return nil
			}
		}
		return fmt.Errorf("Unknown link id %d", lnkID)
	case TokenStartIVar:
		// We're okay with an IVar as long as the next token is a String.
		if err := d.p.ExpectNext(TokenString); err != nil {
			return err
		}

		str, err := d.p.Text()
		if err != nil {
			return err
		}
		v.SetString(str)

		lnkID := d.p.LinkID()
		if lnkID > -1 {
			d.objCache[lnkID] = v.Addr()
		}

		if err := d.p.ExpectNext(TokenIVarProps); err != nil {
			return err
		}
		// TODO: properly parse IVar. For now, we just skip over encoding and such.
		if err := d.p.Skip(); err != nil {
			return err
		}
		return nil
	case TokenString, TokenSymbol:
		str, err := d.p.Text()
		if err != nil {
			return err
		}
		v.SetString(str)

		lnkID := d.p.LinkID()
		if lnkID > -1 {
			d.objCache[lnkID] = v.Addr()
		}

		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding string", tok)
	}
}

type sliceDecoder struct {
	elemDec decoderFunc
}

func (sliceDec *sliceDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	if tok != TokenStartArray {
		return fmt.Errorf("Unexpected token %v encountered while decoding slice", tok)
	}

	l := d.p.Len()

	// If the underlying slice already has enough capacity for this array, then we just resize
	// and use it.
	cap := v.Cap()
	if cap >= l {
		v.SetLen(l)
		v.SetCap(l)
	} else {
		v.Set(reflect.MakeSlice(v.Type(), l, l))
	}

	lnkID := d.p.LinkID()
	if lnkID > -1 {
		d.objCache[lnkID] = v.Addr()
	}

	for i := 0; i < l; i++ {
		if err := sliceDec.elemDec(d, v.Index(i)); err != nil {
			return err
		}
	}

	if err := d.p.ExpectNext(TokenEndArray); err != nil {
		return err
	}

	return nil
}

func newSliceDecoder(t reflect.Type) decoderFunc {
	dec := &sliceDecoder{newTypeDecoder(t.Elem())}
	return dec.decode
}

type idxStructField struct {
	idx int // index in the struct
	dec decoderFunc
}
type idxStructDecoder struct {
	fields []idxStructField
}

func (idxDec *idxStructDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	switch tok {
	case TokenStartArray:
		l := d.p.Len()

		for i := 0; i < l; i++ {
			if i < len(idxDec.fields) {
				f := idxDec.fields[i]
				if f.dec != nil {
					if err := f.dec(d, v.Field(f.idx)); err != nil {
						return err
					}
					continue
				}
			}

			if _, err := d.p.Next(); err != nil {
				return err
			}

			if err := d.p.Skip(); err != nil {
				return err
			}
		}
		if err := d.p.ExpectNext(TokenEndArray); err != nil {
			return err
		}

		return nil
	default:
		return fmt.Errorf("Unexpected token %v encountered while decoding indexed struct", tok)
	}

}

func newStructDecoder(t reflect.Type) decoderFunc {
	// A struct decoder can either be indexed or named.
	// Indexed decoders expect to decode a Ruby Array into a Go struct.
	// Named decoders expecet to decode a Ruby Hash/Struct into a Go struct.
	var idxFields []idxStructField
	named := make(map[string]decoderFunc)

	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)

		if f.PkgPath != "" {
			continue
		}

		fdec := newTypeDecoder(f.Type)

		meta := strings.Split(f.Tag.Get("rmarsh"), ",")
		if meta[0] == "" {
			continue
		}
		if meta[0] == "_indexed" {
			if len(named) > 0 {
				return newErrorDecoder(fmt.Errorf("Cannot mix named and _indexed fields in struct %s", t))
			}
			idx, err := strconv.ParseInt(meta[1], 10, 32)
			if err != nil {
				return newErrorDecoder(fmt.Errorf("Struct %s field %q has invalid _indexed value %q", t, f.Name, meta[1]))
			}
			if len(idxFields) <= int(idx) {
				idxFields = append(idxFields, make([]idxStructField, int(idx)-len(idxFields)+1)...)
			}
			idxFields[idx] = idxStructField{idx: i, dec: fdec}
		} else {
			if len(idxFields) > 0 {
				return newErrorDecoder(fmt.Errorf("Cannot mix named and _indexed fields in struct %s", t))
			}
			named[f.Name] = fdec
		}
	}

	if len(idxFields) > 0 {
		dec := &idxStructDecoder{idxFields}
		return dec.decode
	}
	if len(named) > 0 {
		dec := &idxStructDecoder{}
		return dec.decode
	}
	return skipDecoder
}

type ptrDecoder struct {
	elemDec decoderFunc
}

func (ptrDec *ptrDecoder) decode(d *Decoder, v reflect.Value) error {
	tok, err := d.nextToken()
	if err != nil {
		return err
	}

	// If the token is nil, then we nil the ptr and move on.
	if tok == TokenNil {
		v.Set(reflect.Zero(v.Type()))
		return nil
	}

	// If we've just parsed a link, then we see if we've cached the object already.
	// If we we have, and it's directly assignable to the pointer type we have, then
	// we can just immediately assign it and continue.
	// Otherwise we start a replay parser and run it on the target.
	if tok == TokenLink {
		lnkID := d.p.LinkID()
		if len(d.objCache) > lnkID {
			cached := d.objCache[lnkID]
			if cached.Type().AssignableTo(v.Type()) {
				v.Set(cached)
				return nil
			}
		}

		// TODO: setup a replay parser and run it against the target.
		return fmt.Errorf("Unhandled link encountered. %d", lnkID)
	}

	// Push the token back and decode against resolved ptr.
	d.curToken = tok

	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return ptrDec.elemDec(d, v.Elem())
}

func newPtrDecoder(t reflect.Type) decoderFunc {
	dec := &ptrDecoder{newTypeDecoder(t.Elem())}
	return dec.decode
}

type errorDecoder struct {
	err error
}

func (errDec errorDecoder) decode(d *Decoder, v reflect.Value) error {
	return errDec.err
}

func newErrorDecoder(err error) decoderFunc {
	return errorDecoder{err}.decode
}

func unsupportedTypeDecoder(d *Decoder, v reflect.Value) error {
	return fmt.Errorf("unsupported type %s", v.Type())
}
<|endoftext|>


<commit_before>// Package dep provides a  Dependency struct, a DependencyMap from nicknames (strings) to Dependencies,
// and functions to read and write a DependencyMap to a deps.json file
package dep

// Copyright 2013 Vubeology, Inc.

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/vube/depman/colors"
	"github.com/vube/depman/util"
)

// Dependency Types
const (
	TypeGit      = "git"
	TypeHg       = "hg"
	TypeBzr      = "bzr"
	TypeGitClone = "git-clone"
)

var (
	ErrUnknownType  = errors.New("unknown dependency type")
	ErrMissingAlias = errors.New("dependency type git-clone requires alias field")
)

// The name of the dependency file
const DepsFile string = "deps.json"

// Dependency defines a single dependency
type Dependency struct {
	Repo      string         `json:"repo"`
	Version   string         `json:"version"`
	Type      string         `json:"type"`
	Alias     string         `json:"alias,omitempty"`
	SkipCache bool           `json:"skip-cache,omitempty"`
	VCS       VersionControl `json:"-"`
}

type VersionControl interface {
	Clone(d *Dependency) (err error)

	// Get changes from the server
	Fetch(d *Dependency) (err error)

	// Pull/Merge/Update this branch
	Update(d *Dependency) (err error)

	Checkout(d *Dependency) (err error)

	LastCommit(d *Dependency, branch string) (hash string, err error)
	GetHead(d *Dependency) (to_return string, err error)

	Clean(d *Dependency)
}

// DependencyMap defines a set of dependencies
type DependencyMap struct {
	Map  map[string]*Dependency
	Path string
}

// New returns a newly constructed DependencyMap
func New() (d DependencyMap) {
	d.Map = make(map[string]*Dependency)
	return
}

// Read reads filename and parses the content into a DependencyMap
func Read(filename string) (deps DependencyMap, err error) {
	deps.Map = make(map[string]*Dependency)
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	err = json.Unmarshal(data, &deps.Map)
	if err != nil {
		return
	}

	// traverse map and look for empty version fields - provide a default if such found
	for key, _ := range deps.Map {
		val := deps.Map[key]
		if val.Version == "" {
			switch val.Type {
			case TypeGit, TypeGitClone:
				val.Version = "master"
			case TypeHg:
				val.Version = "tip"
			case TypeBzr:
				val.Version = "trunk"
			default:
				val.Version = ""
			}
			deps.Map[key] = val
		}
	}

	for name, d := range deps.Map {
		err := d.SetupVCS(name)
		if err != nil {
			delete(deps.Map, name)
		}

	}

	deps.Path = filename

	return
}

// Write the dependencyMap back into to the file it was read from
func (d *DependencyMap) Write() (err error) {

	var buf bytes.Buffer
	str, err := json.Marshal(d.Map)
	json.Indent(&buf, str, "", "    ")

	if err == nil {
		data := []byte(buf.String() + "\n")
		ioutil.WriteFile(d.Path, data, 0644)
	}
	return
}

// Configures the VCS depending on the type
func (d *Dependency) SetupVCS(name string) (err error) {
	switch d.Type {
	case TypeGitClone:
		if d.Alias == "" {
			util.PrintIndent(colors.Red("Error: Dependency " + name + ": Repo '" + d.Repo + "' Type '" + d.Type + "' requires 'alias' field"))
			err = ErrMissingAlias
			return
		}

		d.VCS = new(Git)
	case TypeGit:
		d.VCS = new(Git)
	case TypeBzr:
		d.VCS = new(Bzr)
	case TypeHg:
		d.VCS = new(Hg)
	default:
		util.PrintIndent(colors.Red(d.Repo + ": Unknown repository type (" + d.Type + "), skipping..."))
		util.PrintIndent(colors.Red("Valid Repository types: " + TypeGit + ", " + TypeHg + ", " + TypeBzr + ", " + TypeGitClone))
		err = ErrUnknownType
	}

	return
}

// Path returns the path for this dependency
// searches for the appropriate directory in each part of the GOPATH (delimited by ':')
// if not found return the path using the first port of GOPATH
func (d *Dependency) Path() (p string) {
	parts := strings.Split(os.Getenv("GOPATH"), ":")

	for _, path := range parts {
		p = filepath.Join(path, "src")
		if d.Alias == "" {
			p = filepath.Join(p, d.Repo)
		} else {
			p = filepath.Join(p, d.Alias)
		}

		if util.Exists(p) {
			return
		}
	}

	// didn't find a directory, use the first part of gopath
	p = filepath.Join(parts[0], "src")
	if d.Alias == "" {
		p = filepath.Join(p, d.Repo)
	} else {
		p = filepath.Join(p, d.Alias)
	}

	return

}

//GetPath processes p and returns a clean path ending in deps.json
func GetPath(p string) (result string) {
	if !strings.HasSuffix(p, DepsFile) {
		result = p + "/" + DepsFile
	}
	result = filepath.Clean(result)
	return
}
<commit_msg>Display warning for aliased dependency not of type git-clone<commit_after>// Package dep provides a  Dependency struct, a DependencyMap from nicknames (strings) to Dependencies,
// and functions to read and write a DependencyMap to a deps.json file
package dep

// Copyright 2013 Vubeology, Inc.

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/vube/depman/colors"
	"github.com/vube/depman/util"
)

// Dependency Types
const (
	TypeGit      = "git"
	TypeHg       = "hg"
	TypeBzr      = "bzr"
	TypeGitClone = "git-clone"
)

var (
	ErrUnknownType  = errors.New("unknown dependency type")
	ErrMissingAlias = errors.New("dependency type git-clone requires alias field")
)

// The name of the dependency file
const DepsFile string = "deps.json"

// Dependency defines a single dependency
type Dependency struct {
	Repo      string         `json:"repo"`
	Version   string         `json:"version"`
	Type      string         `json:"type"`
	Alias     string         `json:"alias,omitempty"`
	SkipCache bool           `json:"skip-cache,omitempty"`
	VCS       VersionControl `json:"-"`
}

type VersionControl interface {
	Clone(d *Dependency) (err error)

	// Get changes from the server
	Fetch(d *Dependency) (err error)

	// Pull/Merge/Update this branch
	Update(d *Dependency) (err error)

	Checkout(d *Dependency) (err error)

	LastCommit(d *Dependency, branch string) (hash string, err error)
	GetHead(d *Dependency) (to_return string, err error)

	Clean(d *Dependency)
}

// DependencyMap defines a set of dependencies
type DependencyMap struct {
	Map  map[string]*Dependency
	Path string
}

// New returns a newly constructed DependencyMap
func New() (d DependencyMap) {
	d.Map = make(map[string]*Dependency)
	return
}

// Read reads filename and parses the content into a DependencyMap
func Read(filename string) (deps DependencyMap, err error) {
	deps.Map = make(map[string]*Dependency)
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	err = json.Unmarshal(data, &deps.Map)
	if err != nil {
		return
	}

	// traverse map and look for empty version fields - provide a default if such found
	for key, _ := range deps.Map {
		val := deps.Map[key]
		if val.Version == "" {
			switch val.Type {
			case TypeGit, TypeGitClone:
				val.Version = "master"
			case TypeHg:
				val.Version = "tip"
			case TypeBzr:
				val.Version = "trunk"
			default:
				val.Version = ""
			}
			deps.Map[key] = val
		}
	}

	for name, d := range deps.Map {
		err := d.SetupVCS(name)
		if err != nil {
			delete(deps.Map, name)
		}

	}

	deps.Path = filename

	return
}

// Write the dependencyMap back into to the file it was read from
func (d *DependencyMap) Write() (err error) {

	var buf bytes.Buffer
	str, err := json.Marshal(d.Map)
	json.Indent(&buf, str, "", "    ")

	if err == nil {
		data := []byte(buf.String() + "\n")
		ioutil.WriteFile(d.Path, data, 0644)
	}
	return
}

// Configures the VCS depending on the type
func (d *Dependency) SetupVCS(name string) (err error) {
	switch d.Type {
	case TypeGitClone:
		if d.Alias == "" {
			util.PrintIndent(colors.Red("Error: Dependency " + name + ": Repo '" + d.Repo + "' Type '" + d.Type + "' requires 'alias' field"))
			err = ErrMissingAlias
			return
		}

		d.VCS = new(Git)
	case TypeGit:
		d.VCS = new(Git)
	case TypeBzr:
		d.VCS = new(Bzr)
	case TypeHg:
		d.VCS = new(Hg)
	default:
		util.PrintIndent(colors.Red(d.Repo + ": Unknown repository type (" + d.Type + "), skipping..."))
		util.PrintIndent(colors.Red("Valid Repository types: " + TypeGit + ", " + TypeHg + ", " + TypeBzr + ", " + TypeGitClone))
		err = ErrUnknownType
	}

	if d.Type != TypeGitClone && d.Alias != "" {
		util.Print(colors.Yellow("Warning: " + d.Repo + ": 'alias' field only allowed in dependencies with type 'git-clone', skipping..."))
		d.Alias = ""
	}

	return
}

// Path returns the path for this dependency
// searches for the appropriate directory in each part of the GOPATH (delimited by ':')
// if not found return the path using the first port of GOPATH
func (d *Dependency) Path() (p string) {
	parts := strings.Split(os.Getenv("GOPATH"), ":")

	for _, path := range parts {
		p = filepath.Join(path, "src")
		if d.Alias == "" {
			p = filepath.Join(p, d.Repo)
		} else {
			p = filepath.Join(p, d.Alias)
		}

		if util.Exists(p) {
			return
		}
	}

	// didn't find a directory, use the first part of gopath
	p = filepath.Join(parts[0], "src")
	if d.Alias == "" {
		p = filepath.Join(p, d.Repo)
	} else {
		p = filepath.Join(p, d.Alias)
	}

	return

}

//GetPath processes p and returns a clean path ending in deps.json
func GetPath(p string) (result string) {
	if !strings.HasSuffix(p, DepsFile) {
		result = p + "/" + DepsFile
	}
	result = filepath.Clean(result)
	return
}
<|endoftext|>


<commit_before>//
//
// File generated from our OpenAPI spec
//
//

package stripe

import "encoding/json"

// DisputeReason is the list of allowed values for a discount's reason.
type DisputeReason string

// List of values that DisputeReason can take.
const (
	DisputeReasonCreditNotProcessed   DisputeReason = "credit_not_processed"
	DisputeReasonDuplicate            DisputeReason = "duplicate"
	DisputeReasonFraudulent           DisputeReason = "fraudulent"
	DisputeReasonGeneral              DisputeReason = "general"
	DisputeReasonProductNotReceived   DisputeReason = "product_not_received"
	DisputeReasonProductUnacceptable  DisputeReason = "product_unacceptable"
	DisputeReasonSubscriptionCanceled DisputeReason = "subscription_canceled"
	DisputeReasonUnrecognized         DisputeReason = "unrecognized"
)

// DisputeStatus is the list of allowed values for a discount's status.
type DisputeStatus string

// List of values that DisputeStatus can take.
const (
	DisputeStatusChargeRefunded       DisputeStatus = "charge_refunded"
	DisputeStatusLost                 DisputeStatus = "lost"
	DisputeStatusNeedsResponse        DisputeStatus = "needs_response"
	DisputeStatusUnderReview          DisputeStatus = "under_review"
	DisputeStatusWarningClosed        DisputeStatus = "warning_closed"
	DisputeStatusWarningNeedsResponse DisputeStatus = "warning_needs_response"
	DisputeStatusWarningUnderReview   DisputeStatus = "warning_under_review"
	DisputeStatusWon                  DisputeStatus = "won"
)

// DisputeParams is the set of parameters that can be used when updating a dispute.
// For more details see https://stripe.com/docs/api#update_dispute.
type DisputeParams struct {
	Params   `form:"*"`
	Evidence *DisputeEvidenceParams `form:"evidence"`
	Submit   *bool                  `form:"submit"`
}

// DisputeEvidenceParams is the set of parameters that can be used when submitting
// evidence for disputes.
type DisputeEvidenceParams struct {
	AccessActivityLog            *string `form:"access_activity_log"`
	BillingAddress               *string `form:"billing_address"`
	CancellationPolicy           *string `form:"cancellation_policy"`
	CancellationPolicyDisclosure *string `form:"cancellation_policy_disclosure"`
	CancellationRebuttal         *string `form:"cancellation_rebuttal"`
	CustomerCommunication        *string `form:"customer_communication"`
	CustomerEmailAddress         *string `form:"customer_email_address"`
	CustomerName                 *string `form:"customer_name"`
	CustomerPurchaseIP           *string `form:"customer_purchase_ip"`
	CustomerSignature            *string `form:"customer_signature"`
	DuplicateChargeDocumentation *string `form:"duplicate_charge_documentation"`
	DuplicateChargeExplanation   *string `form:"duplicate_charge_explanation"`
	DuplicateChargeID            *string `form:"duplicate_charge_id"`
	ProductDescription           *string `form:"product_description"`
	Receipt                      *string `form:"receipt"`
	RefundPolicy                 *string `form:"refund_policy"`
	RefundPolicyDisclosure       *string `form:"refund_policy_disclosure"`
	RefundRefusalExplanation     *string `form:"refund_refusal_explanation"`
	ServiceDate                  *string `form:"service_date"`
	ServiceDocumentation         *string `form:"service_documentation"`
	ShippingAddress              *string `form:"shipping_address"`
	ShippingCarrier              *string `form:"shipping_carrier"`
	ShippingDate                 *string `form:"shipping_date"`
	ShippingDocumentation        *string `form:"shipping_documentation"`
	ShippingTrackingNumber       *string `form:"shipping_tracking_number"`
	UncategorizedFile            *string `form:"uncategorized_file"`
	UncategorizedText            *string `form:"uncategorized_text"`
}

// DisputeListParams is the set of parameters that can be used when listing disputes.
// For more details see https://stripe.com/docs/api#list_disputes.
type DisputeListParams struct {
	ListParams    `form:"*"`
	Charge        *string           `form:"charge"`
	Created       *int64            `form:"created"`
	CreatedRange  *RangeQueryParams `form:"created"`
	PaymentIntent *string           `form:"payment_intent"`
}

// Dispute is the resource representing a Stripe dispute.
// For more details see https://stripe.com/docs/api#disputes.
type Dispute struct {
	APIResource
	Amount              int64                 `json:"amount"`
	BalanceTransactions []*BalanceTransaction `json:"balance_transactions"`
	Charge              *Charge               `json:"charge"`
	Created             int64                 `json:"created"`
	Currency            Currency              `json:"currency"`
	Evidence            *DisputeEvidence      `json:"evidence"`
	EvidenceDetails     *EvidenceDetails      `json:"evidence_details"`
	ID                  string                `json:"id"`
	IsChargeRefundable  bool                  `json:"is_charge_refundable"`
	Livemode            bool                  `json:"livemode"`
	Metadata            map[string]string     `json:"metadata"`
	NetworkReasonCode   string                `json:"network_reason_code"`
	Object              string                `json:"object"`
	PaymentIntent       *PaymentIntent        `json:"payment_intent"`
	Reason              DisputeReason         `json:"reason"`
	Status              DisputeStatus         `json:"status"`
}

// EvidenceDetails is the structure representing more details about
// the dispute.
type EvidenceDetails struct {
	DueBy           int64 `json:"due_by"`
	HasEvidence     bool  `json:"has_evidence"`
	PastDue         bool  `json:"past_due"`
	SubmissionCount int64 `json:"submission_count"`
}

// DisputeEvidence is the structure that contains various details about
// the evidence submitted for the dispute.
// Almost all fields are strings since there structures (i.e. address)
// do not typically get parsed by anyone and are thus presented as-received.
type DisputeEvidence struct {
	AccessActivityLog            string `json:"access_activity_log"`
	BillingAddress               string `json:"billing_address"`
	CancellationPolicy           *File  `json:"cancellation_policy"`
	CancellationPolicyDisclosure string `json:"cancellation_policy_disclosure"`
	CancellationRebuttal         string `json:"cancellation_rebuttal"`
	CustomerCommunication        *File  `json:"customer_communication"`
	CustomerEmailAddress         string `json:"customer_email_address"`
	CustomerName                 string `json:"customer_name"`
	CustomerPurchaseIP           string `json:"customer_purchase_ip"`
	CustomerSignature            *File  `json:"customer_signature"`
	DuplicateChargeDocumentation *File  `json:"duplicate_charge_documentation"`
	DuplicateChargeExplanation   string `json:"duplicate_charge_explanation"`
	DuplicateChargeID            string `json:"duplicate_charge_id"`
	ProductDescription           string `json:"product_description"`
	Receipt                      *File  `json:"receipt"`
	RefundPolicy                 *File  `json:"refund_policy"`
	RefundPolicyDisclosure       string `json:"refund_policy_disclosure"`
	RefundRefusalExplanation     string `json:"refund_refusal_explanation"`
	ServiceDate                  string `json:"service_date"`
	ServiceDocumentation         *File  `json:"service_documentation"`
	ShippingAddress              string `json:"shipping_address"`
	ShippingCarrier              string `json:"shipping_carrier"`
	ShippingDate                 string `json:"shipping_date"`
	ShippingDocumentation        *File  `json:"shipping_documentation"`
	ShippingTrackingNumber       string `json:"shipping_tracking_number"`
	UncategorizedFile            *File  `json:"uncategorized_file"`
	UncategorizedText            string `json:"uncategorized_text"`
}

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

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

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

	*d = Dispute(v)
	return nil
}
<commit_msg>Adding missing dispute reasons following official documentation (https://stripe.com/docs/api/disputes/object#dispute_object-reason). (#1336)<commit_after>//
//
// File generated from our OpenAPI spec
//
//

package stripe

import "encoding/json"

// DisputeReason is the list of allowed values for a discount's reason.
type DisputeReason string

// List of values that DisputeReason can take.
const (
	DisputeReasonBankCannotProcess       DisputeReason = "bank_cannot_process"
	DisputeReasonCheckReturned           DisputeReason = "check_returned"
	DisputeReasonCreditNotProcessed      DisputeReason = "credit_not_processed"
	DisputeReasonCustomerInitiated       DisputeReason = "customer_initiated"
	DisputeReasonDebitNotAuthorized      DisputeReason = "debit_not_authorized"
	DisputeReasonDuplicate               DisputeReason = "duplicate"
	DisputeReasonFraudulent              DisputeReason = "fraudulent"
	DisputeReasonGeneral                 DisputeReason = "general"
	DisputeReasonIncorrectAccountDetails DisputeReason = "incorrect_account_details"
	DisputeReasonInsufficientFunds       DisputeReason = "insufficient_funds"
	DisputeReasonProductNotReceived      DisputeReason = "product_not_received"
	DisputeReasonProductUnacceptable     DisputeReason = "product_unacceptable"
	DisputeReasonSubscriptionCanceled    DisputeReason = "subscription_canceled"
	DisputeReasonUnrecognized            DisputeReason = "unrecognized"
)

// DisputeStatus is the list of allowed values for a discount's status.
type DisputeStatus string

// List of values that DisputeStatus can take.
const (
	DisputeStatusChargeRefunded       DisputeStatus = "charge_refunded"
	DisputeStatusLost                 DisputeStatus = "lost"
	DisputeStatusNeedsResponse        DisputeStatus = "needs_response"
	DisputeStatusUnderReview          DisputeStatus = "under_review"
	DisputeStatusWarningClosed        DisputeStatus = "warning_closed"
	DisputeStatusWarningNeedsResponse DisputeStatus = "warning_needs_response"
	DisputeStatusWarningUnderReview   DisputeStatus = "warning_under_review"
	DisputeStatusWon                  DisputeStatus = "won"
)

// DisputeParams is the set of parameters that can be used when updating a dispute.
// For more details see https://stripe.com/docs/api#update_dispute.
type DisputeParams struct {
	Params   `form:"*"`
	Evidence *DisputeEvidenceParams `form:"evidence"`
	Submit   *bool                  `form:"submit"`
}

// DisputeEvidenceParams is the set of parameters that can be used when submitting
// evidence for disputes.
type DisputeEvidenceParams struct {
	AccessActivityLog            *string `form:"access_activity_log"`
	BillingAddress               *string `form:"billing_address"`
	CancellationPolicy           *string `form:"cancellation_policy"`
	CancellationPolicyDisclosure *string `form:"cancellation_policy_disclosure"`
	CancellationRebuttal         *string `form:"cancellation_rebuttal"`
	CustomerCommunication        *string `form:"customer_communication"`
	CustomerEmailAddress         *string `form:"customer_email_address"`
	CustomerName                 *string `form:"customer_name"`
	CustomerPurchaseIP           *string `form:"customer_purchase_ip"`
	CustomerSignature            *string `form:"customer_signature"`
	DuplicateChargeDocumentation *string `form:"duplicate_charge_documentation"`
	DuplicateChargeExplanation   *string `form:"duplicate_charge_explanation"`
	DuplicateChargeID            *string `form:"duplicate_charge_id"`
	ProductDescription           *string `form:"product_description"`
	Receipt                      *string `form:"receipt"`
	RefundPolicy                 *string `form:"refund_policy"`
	RefundPolicyDisclosure       *string `form:"refund_policy_disclosure"`
	RefundRefusalExplanation     *string `form:"refund_refusal_explanation"`
	ServiceDate                  *string `form:"service_date"`
	ServiceDocumentation         *string `form:"service_documentation"`
	ShippingAddress              *string `form:"shipping_address"`
	ShippingCarrier              *string `form:"shipping_carrier"`
	ShippingDate                 *string `form:"shipping_date"`
	ShippingDocumentation        *string `form:"shipping_documentation"`
	ShippingTrackingNumber       *string `form:"shipping_tracking_number"`
	UncategorizedFile            *string `form:"uncategorized_file"`
	UncategorizedText            *string `form:"uncategorized_text"`
}

// DisputeListParams is the set of parameters that can be used when listing disputes.
// For more details see https://stripe.com/docs/api#list_disputes.
type DisputeListParams struct {
	ListParams    `form:"*"`
	Charge        *string           `form:"charge"`
	Created       *int64            `form:"created"`
	CreatedRange  *RangeQueryParams `form:"created"`
	PaymentIntent *string           `form:"payment_intent"`
}

// Dispute is the resource representing a Stripe dispute.
// For more details see https://stripe.com/docs/api#disputes.
type Dispute struct {
	APIResource
	Amount              int64                 `json:"amount"`
	BalanceTransactions []*BalanceTransaction `json:"balance_transactions"`
	Charge              *Charge               `json:"charge"`
	Created             int64                 `json:"created"`
	Currency            Currency              `json:"currency"`
	Evidence            *DisputeEvidence      `json:"evidence"`
	EvidenceDetails     *EvidenceDetails      `json:"evidence_details"`
	ID                  string                `json:"id"`
	IsChargeRefundable  bool                  `json:"is_charge_refundable"`
	Livemode            bool                  `json:"livemode"`
	Metadata            map[string]string     `json:"metadata"`
	NetworkReasonCode   string                `json:"network_reason_code"`
	Object              string                `json:"object"`
	PaymentIntent       *PaymentIntent        `json:"payment_intent"`
	Reason              DisputeReason         `json:"reason"`
	Status              DisputeStatus         `json:"status"`
}

// EvidenceDetails is the structure representing more details about
// the dispute.
type EvidenceDetails struct {
	DueBy           int64 `json:"due_by"`
	HasEvidence     bool  `json:"has_evidence"`
	PastDue         bool  `json:"past_due"`
	SubmissionCount int64 `json:"submission_count"`
}

// DisputeEvidence is the structure that contains various details about
// the evidence submitted for the dispute.
// Almost all fields are strings since there structures (i.e. address)
// do not typically get parsed by anyone and are thus presented as-received.
type DisputeEvidence struct {
	AccessActivityLog            string `json:"access_activity_log"`
	BillingAddress               string `json:"billing_address"`
	CancellationPolicy           *File  `json:"cancellation_policy"`
	CancellationPolicyDisclosure string `json:"cancellation_policy_disclosure"`
	CancellationRebuttal         string `json:"cancellation_rebuttal"`
	CustomerCommunication        *File  `json:"customer_communication"`
	CustomerEmailAddress         string `json:"customer_email_address"`
	CustomerName                 string `json:"customer_name"`
	CustomerPurchaseIP           string `json:"customer_purchase_ip"`
	CustomerSignature            *File  `json:"customer_signature"`
	DuplicateChargeDocumentation *File  `json:"duplicate_charge_documentation"`
	DuplicateChargeExplanation   string `json:"duplicate_charge_explanation"`
	DuplicateChargeID            string `json:"duplicate_charge_id"`
	ProductDescription           string `json:"product_description"`
	Receipt                      *File  `json:"receipt"`
	RefundPolicy                 *File  `json:"refund_policy"`
	RefundPolicyDisclosure       string `json:"refund_policy_disclosure"`
	RefundRefusalExplanation     string `json:"refund_refusal_explanation"`
	ServiceDate                  string `json:"service_date"`
	ServiceDocumentation         *File  `json:"service_documentation"`
	ShippingAddress              string `json:"shipping_address"`
	ShippingCarrier              string `json:"shipping_carrier"`
	ShippingDate                 string `json:"shipping_date"`
	ShippingDocumentation        *File  `json:"shipping_documentation"`
	ShippingTrackingNumber       string `json:"shipping_tracking_number"`
	UncategorizedFile            *File  `json:"uncategorized_file"`
	UncategorizedText            string `json:"uncategorized_text"`
}

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

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

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

	*d = Dispute(v)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/go-ini/ini"
)

var (
	regions = []string{
		"us-east-1",
		"us-west-1",
		"us-west-2",
		"eu-west-1",
		"ap-southeast-1",
		"ap-southeast-2",
		"ap-northeast-1",
		"sa-east-1",
	}
)

type InstanceInfo struct {
	Name, Profile string
	*ec2.Instance
}

func (i *InstanceInfo) LowerName() string {
	return strings.ToLower(i.Name)
}

func (i *InstanceInfo) String() string {
	return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
		i.Name,
		p2s(i.InstanceId),
		p2s(i.PublicIpAddress),
		p2s(i.PrivateIpAddress),
		i.Profile,
		p2s(i.Placement.AvailabilityZone),
		p2s(i.InstanceType),
	)
}

type EC2List struct {
	sync.RWMutex
	list []InstanceInfo
}

func (l *EC2List) Add(infos ...InstanceInfo) {
	l.Lock()
	defer l.Unlock()
	l.list = append(l.list, infos...)
}

func (l *EC2List) Sort() {
	sort.Sort(l)
}

func (l *EC2List) Output(w io.Writer) {
	l.Sort()
	for _, info := range l.list {
		fmt.Fprintf(w, info.String())
	}
}

func (l *EC2List) Len() int {
	return len(l.list)
}

func (l *EC2List) Swap(i, j int) {
	l.list[i], l.list[j] = l.list[j], l.list[i]
}

func (l *EC2List) Less(i, j int) bool {
	return l.list[i].LowerName() < l.list[j].LowerName()
}

//p2s return string value from pointer of string.
//if the pointer is nil, p2s returns empty string.
func p2s(ps *string) string {
	if ps == nil {
		return ""
	}
	return *ps
}

func nameTag(tags []*ec2.Tag) string {
	var name string
	for _, tag := range tags {
		if *tag.Key == "Name" {
			name = *tag.Value
		}
	}
	return name
}

func getCredentialFile() (string, error) {
	var provider credentials.SharedCredentialsProvider
	_, err := provider.Retrieve()
	if err != nil {
		return "", err
	}
	return provider.Filename, nil
}

func getProfileNames(filePath string) ([]string, error) {
	cfg, err := ini.Load(filePath)
	if err != nil {
		return nil, err
	}
	sections := cfg.SectionStrings()
	return sections, nil
}

func validateCredential(creds *credentials.Credentials) bool {
	_, err := creds.Get()
	if err != nil {
		return false
	}
	return true
}

func retrieve(cfg *aws.Config, profile, region string) ([]InstanceInfo, error) {
	svc := ec2.New(session.New(cfg), &aws.Config{Region: aws.String(region)})
	c := make(chan bool, 1)
	var resp *ec2.DescribeInstancesOutput
	var err error
	go func() {
		resp, err = svc.DescribeInstances(nil)
		if err != nil {
			log.Fatalf("profile=%s region=%s err=%v\n", profile, region, err)
		}
		c <- true
	}()

	select {
	case _ = <-c:
	case <-time.After(time.Second * 10):
		log.Fatalf("timeout error. profile=%s region=%s\n", profile, region)
	}

	var infos []InstanceInfo

	for idx := range resp.Reservations {
		for _, inst := range resp.Reservations[idx].Instances {
			name := nameTag(inst.Tags)
			info := InstanceInfo{
				Name:     name,
				Profile:  profile,
				Instance: inst,
			}
			infos = append(infos, info)
		}
	}

	return infos, nil
}

func main() {
	credfile, err := getCredentialFile()
	if err != nil {
		return
	}

	profiles, err := getProfileNames(credfile)
	if err != nil {
		return
	}

	var list EC2List
	var wg sync.WaitGroup

	for _, profile := range profiles {
		profile := profile
		creds := credentials.NewSharedCredentials(credfile, profile)
		if ok := validateCredential(creds); !ok {
			continue
		}

		cfg := aws.NewConfig().WithCredentials(creds)

		for _, region := range regions {
			region := region
			wg.Add(1)
			go func() {
				defer wg.Done()
				infos, err := retrieve(cfg, profile, region)
				if err != nil {
					log.Fatal(err)
				}
				list.Add(infos...)
			}()
		}
	}

	wg.Wait()
	list.Output(os.Stdout)
}
<commit_msg>Stop sort automatically inside Ouput.<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/go-ini/ini"
)

var (
	regions = []string{
		"us-east-1",
		"us-west-1",
		"us-west-2",
		"eu-west-1",
		"ap-southeast-1",
		"ap-southeast-2",
		"ap-northeast-1",
		"sa-east-1",
	}
)

type InstanceInfo struct {
	Name, Profile string
	*ec2.Instance
}

func (i *InstanceInfo) LowerName() string {
	return strings.ToLower(i.Name)
}

func (i *InstanceInfo) String() string {
	return fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
		i.Name,
		p2s(i.InstanceId),
		p2s(i.PublicIpAddress),
		p2s(i.PrivateIpAddress),
		i.Profile,
		p2s(i.Placement.AvailabilityZone),
		p2s(i.InstanceType),
	)
}

type EC2List struct {
	sync.RWMutex
	list []InstanceInfo
}

func (l *EC2List) Add(infos ...InstanceInfo) {
	l.Lock()
	defer l.Unlock()
	l.list = append(l.list, infos...)
}

func (l *EC2List) Sort() {
	sort.Sort(l)
}

func (l *EC2List) Output(w io.Writer) {
	for _, info := range l.list {
		fmt.Fprintf(w, info.String())
	}
}

func (l *EC2List) Len() int {
	return len(l.list)
}

func (l *EC2List) Swap(i, j int) {
	l.list[i], l.list[j] = l.list[j], l.list[i]
}

func (l *EC2List) Less(i, j int) bool {
	return l.list[i].LowerName() < l.list[j].LowerName()
}

//p2s return string value from pointer of string.
//if the pointer is nil, p2s returns empty string.
func p2s(ps *string) string {
	if ps == nil {
		return ""
	}
	return *ps
}

func nameTag(tags []*ec2.Tag) string {
	var name string
	for _, tag := range tags {
		if *tag.Key == "Name" {
			name = *tag.Value
		}
	}
	return name
}

func getCredentialFile() (string, error) {
	var provider credentials.SharedCredentialsProvider
	_, err := provider.Retrieve()
	if err != nil {
		return "", err
	}
	return provider.Filename, nil
}

func getProfileNames(filePath string) ([]string, error) {
	cfg, err := ini.Load(filePath)
	if err != nil {
		return nil, err
	}
	sections := cfg.SectionStrings()
	return sections, nil
}

func validateCredential(creds *credentials.Credentials) bool {
	_, err := creds.Get()
	if err != nil {
		return false
	}
	return true
}

func retrieve(cfg *aws.Config, profile, region string) ([]InstanceInfo, error) {
	svc := ec2.New(session.New(cfg), &aws.Config{Region: aws.String(region)})
	c := make(chan bool, 1)
	var resp *ec2.DescribeInstancesOutput
	var err error
	go func() {
		resp, err = svc.DescribeInstances(nil)
		if err != nil {
			log.Fatalf("profile=%s region=%s err=%v\n", profile, region, err)
		}
		c <- true
	}()

	select {
	case _ = <-c:
	case <-time.After(time.Second * 10):
		log.Fatalf("timeout error. profile=%s region=%s\n", profile, region)
	}

	var infos []InstanceInfo

	for idx := range resp.Reservations {
		for _, inst := range resp.Reservations[idx].Instances {
			name := nameTag(inst.Tags)
			info := InstanceInfo{
				Name:     name,
				Profile:  profile,
				Instance: inst,
			}
			infos = append(infos, info)
		}
	}

	return infos, nil
}

func main() {
	credfile, err := getCredentialFile()
	if err != nil {
		return
	}

	profiles, err := getProfileNames(credfile)
	if err != nil {
		return
	}

	var list EC2List
	var wg sync.WaitGroup

	for _, profile := range profiles {
		profile := profile
		creds := credentials.NewSharedCredentials(credfile, profile)
		if ok := validateCredential(creds); !ok {
			continue
		}

		cfg := aws.NewConfig().WithCredentials(creds)

		for _, region := range regions {
			region := region
			wg.Add(1)
			go func() {
				defer wg.Done()
				infos, err := retrieve(cfg, profile, region)
				if err != nil {
					log.Fatal(err)
				}
				list.Add(infos...)
			}()
		}
	}

	wg.Wait()
	list.Sort()
	list.Output(os.Stdout)
}
<|endoftext|>


<commit_before>package main

import (
	"io"
)

func Start(stop chan int) {
	for _, in := range Plugins.Inputs {
		go CopyMulty(in, Plugins.Outputs...)
	}

	select {
	case <-stop:
		return
	}
}

// Copy from 1 reader to multiple writers
func CopyMulty(src io.Reader, writers ...io.Writer) (err error) {
	buf := make([]byte, 32*1024)
	wIndex := 0

	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			Debug("Sending", src, ": ", string(buf[0:nr]))

			if Settings.splitOutput {
				// Simple round robin
				writers[wIndex].Write(buf[0:nr])

				wIndex++

				if wIndex >= len(writers) {
					wIndex = 0
				}
			} else {
				for _, dst := range writers {
					dst.Write(buf[0:nr])
				}
			}

		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}
<commit_msg>overflow fix<commit_after>package main

import (
	"io"
)

func Start(stop chan int) {
	for _, in := range Plugins.Inputs {
		go CopyMulty(in, Plugins.Outputs...)
	}

	select {
	case <-stop:
		return
	}
}

// Copy from 1 reader to multiple writers
func CopyMulty(src io.Reader, writers ...io.Writer) (err error) {
	buf := make([]byte, 32*1024)
	wIndex := 0

	for {
		nr, er := src.Read(buf)
		if nr > 0 && len(buf) > nr{
			Debug("Sending", src, ": ", string(buf[0:nr]))

			if Settings.splitOutput {
				// Simple round robin
				writers[wIndex].Write(buf[0:nr])

				wIndex++

				if wIndex >= len(writers) {
					wIndex = 0
				}
			} else {
				for _, dst := range writers {
					dst.Write(buf[0:nr])
				}
			}

		}
		if er == io.EOF {
			break
		}
		if er != nil {
			err = er
			break
		}
	}
	return err
}
<|endoftext|>


<commit_before>// Copyright 2015 LinkedIn Corp. 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.Copyright [201X] LinkedIn Corp. 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.

package goavro

import (
	"fmt"
	"io"
	"math"
)

// ErrEncoder is returned when the encoder encounters an error.
type ErrEncoder struct {
	Message string
	Err     error
}

func (e ErrEncoder) Error() string {
	if e.Err == nil {
		return "cannot encode " + e.Message
	}
	return "cannot encode " + e.Message + ": " + e.Err.Error()
}

func newEncoderError(dataType string, a ...interface{}) *ErrEncoder {
	var err error
	var format, message string
	var ok bool
	if len(a) == 0 {
		return &ErrEncoder{dataType + ": no reason given", nil}
	}
	// if last item is error: save it
	if err, ok = a[len(a)-1].(error); ok {
		a = a[:len(a)-1] // pop it
	}
	// if items left, first ought to be format string
	if len(a) > 0 {
		if format, ok = a[0].(string); ok {
			a = a[1:] // unshift
			message = fmt.Sprintf(format, a...)
		}
	}
	if message != "" {
		message = ": " + message
	}
	return &ErrEncoder{dataType + message, err}
}

func nullEncoder(_ io.Writer, _ interface{}) error {
	return nil
}

func booleanEncoder(w io.Writer, datum interface{}) error {
	someBoolean, ok := datum.(bool)
	if !ok {
		return newEncoderError("boolean", "expected: bool; received: %T", datum)
	}
	bb := make([]byte, 1)
	if someBoolean {
		bb[0] = byte(1)
	}
	if _, err := w.Write(bb); err != nil {
		return newEncoderError("boolean", err)
	}
	return nil
}

func intEncoder(w io.Writer, datum interface{}) error {
	downShift := uint32(31)
	someInt, ok := datum.(int32)
	if !ok {
		return newEncoderError("int", "expected: int32; received: %T", datum)
	}
	encoded := int64((someInt << 1) ^ (someInt >> downShift))
	bb := make([]byte, 0)
	if encoded == 0 {
		bb = append(bb, byte(0))
	} else {
		for encoded > 0 {
			b := byte(encoded & 127)
			encoded = encoded >> 7
			if !(encoded == 0) {
				b |= 128
			}
			bb = append(bb, b)
		}
	}
	_, err := w.Write(bb)
	return err
}

func longEncoder(w io.Writer, datum interface{}) error {
	downShift := uint32(63)
	someInt, ok := datum.(int64)
	if !ok {
		return newEncoderError("long", "expected: int64; received: %T", datum)
	}
	encoded := int64((someInt << 1) ^ (someInt >> downShift))
	bb := make([]byte, 0)
	if encoded == 0 {
		bb = append(bb, byte(0))
	} else {
		for encoded > 0 {
			b := byte(encoded & 127)
			encoded = encoded >> 7
			if !(encoded == 0) {
				b |= 128
			}
			bb = append(bb, b)
		}
	}
	_, err := w.Write(bb)
	return err
}

func floatEncoder(w io.Writer, datum interface{}) error {
	someFloat, ok := datum.(float32)
	if !ok {
		return newEncoderError("float", "expected: float32; received: %T", datum)
	}
	bits := uint64(math.Float32bits(someFloat))
	const byteCount = 4
	buf := make([]byte, byteCount)
	for i := 0; i < byteCount; i++ {
		buf[i] = byte(bits & 255)
		bits = bits >> 8
	}
	_, err := w.Write(buf)
	return err
}

func doubleEncoder(w io.Writer, datum interface{}) error {
	someFloat, ok := datum.(float64)
	if !ok {
		return newEncoderError("double", "expected: float64; received: %T", datum)
	}
	bits := uint64(math.Float64bits(someFloat))
	const byteCount = 8
	buf := make([]byte, byteCount)
	for i := 0; i < byteCount; i++ {
		buf[i] = byte(bits & 255)
		bits = bits >> 8
	}
	_, err := w.Write(buf)
	return err
}

func bytesEncoder(w io.Writer, datum interface{}) error {
	someBytes, ok := datum.([]byte)
	if !ok {
		return newEncoderError("bytes", "expected: []byte; received: %T", datum)
	}
	err := longEncoder(w, int64(len(someBytes)))
	if err != nil {
		return newEncoderError("bytes", err)
	}
	_, err = w.Write(someBytes)
	return err
}

func stringEncoder(w io.Writer, datum interface{}) error {
	someString, ok := datum.(string)
	if !ok {
		return newEncoderError("string", "expected: string; received: %T", datum)
	}
	err := longEncoder(w, int64(len(someString)))
	if err != nil {
		return newEncoderError("string", err)
	}
	_, err = w.Write([]byte(someString))
	return err
}
<commit_msg>Try to cast and use WriteString and WriteByte to avoid making slices<commit_after>// Copyright 2015 LinkedIn Corp. 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.Copyright [201X] LinkedIn Corp. 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.

package goavro

import (
	"fmt"
	"io"
	"math"
)

type ByteWriter interface {
	Grow(int)
	WriteByte(byte) error
}

type StringWriter interface {
	WriteString(string) (int, error)
}

// ErrEncoder is returned when the encoder encounters an error.
type ErrEncoder struct {
	Message string
	Err     error
}

func (e ErrEncoder) Error() string {
	if e.Err == nil {
		return "cannot encode " + e.Message
	}
	return "cannot encode " + e.Message + ": " + e.Err.Error()
}

func newEncoderError(dataType string, a ...interface{}) *ErrEncoder {
	var err error
	var format, message string
	var ok bool
	if len(a) == 0 {
		return &ErrEncoder{dataType + ": no reason given", nil}
	}
	// if last item is error: save it
	if err, ok = a[len(a)-1].(error); ok {
		a = a[:len(a)-1] // pop it
	}
	// if items left, first ought to be format string
	if len(a) > 0 {
		if format, ok = a[0].(string); ok {
			a = a[1:] // unshift
			message = fmt.Sprintf(format, a...)
		}
	}
	if message != "" {
		message = ": " + message
	}
	return &ErrEncoder{dataType + message, err}
}

func nullEncoder(_ io.Writer, _ interface{}) error {
	return nil
}

func booleanEncoder(w io.Writer, datum interface{}) error {
	someBoolean, ok := datum.(bool)
	if !ok {
		return newEncoderError("boolean", "expected: bool; received: %T", datum)
	}

	var b byte
	if someBoolean {
		b = byte(1)
	}

	var err error
	if bw, ok := w.(ByteWriter); ok {
		err = bw.WriteByte(b)
	} else {
		bb := make([]byte, 1)
		bb[0] = b
		_, err = w.Write(bb)
	}
	if err != nil {
		return newEncoderError("boolean", err)
	}
	return nil
}

func writeInt(w io.Writer, byteCount int, encoded int64) error {
	var err error
	var bb []byte
	bw, ok := w.(ByteWriter)
	// To avoid reallocations, grow capacity to the largest possible size
	// for this integer
	if ok {
		bw.Grow(byteCount)
	} else {
		bb = make([]byte, 0, byteCount)
	}

	if encoded == 0 {
		if bw != nil {
			err = bw.WriteByte(0)
			if err != nil {
				return err
			}
		} else {
			bb = append(bb, byte(0))
		}
	} else {
		for encoded > 0 {
			b := byte(encoded & 127)
			encoded = encoded >> 7
			if !(encoded == 0) {
				b |= 128
			}
			if bw != nil {
				err = bw.WriteByte(b)
				if err != nil {
					return err
				}
			} else {
				bb = append(bb, b)
			}
		}
	}
	if bw == nil {
		_, err := w.Write(bb)
		return err
	}
	return nil

}

func intEncoder(w io.Writer, datum interface{}) error {
	downShift := uint32(31)
	someInt, ok := datum.(int32)
	if !ok {
		return newEncoderError("int", "expected: int32; received: %T", datum)
	}
	encoded := int64((someInt << 1) ^ (someInt >> downShift))
	const maxByteSize = 5
	return writeInt(w, maxByteSize, encoded)
}

func longEncoder(w io.Writer, datum interface{}) error {
	downShift := uint32(63)
	someInt, ok := datum.(int64)
	if !ok {
		return newEncoderError("long", "expected: int64; received: %T", datum)
	}
	encoded := int64((someInt << 1) ^ (someInt >> downShift))
	const maxByteSize = 10
	return writeInt(w, maxByteSize, encoded)
}

func writeFloat(w io.Writer, byteCount int, bits uint64) error {
	var err error
	var bb []byte
	bw, ok := w.(ByteWriter)
	if ok {
		bw.Grow(byteCount)
	} else {
		bb = make([]byte, 0, byteCount)
	}
	for i := 0; i < byteCount; i++ {
		if bw != nil {
			err = bw.WriteByte(byte(bits & 255))
			if err != nil {
				return err
			}
		} else {
			bb = append(bb, byte(bits&255))
		}
		bits = bits >> 8
	}
	if bw == nil {
		_, err = w.Write(bb)
		return err
	}
	return nil
}

func floatEncoder(w io.Writer, datum interface{}) error {
	someFloat, ok := datum.(float32)
	if !ok {
		return newEncoderError("float", "expected: float32; received: %T", datum)
	}
	bits := uint64(math.Float32bits(someFloat))
	const byteCount = 4
	return writeFloat(w, byteCount, bits)
}

func doubleEncoder(w io.Writer, datum interface{}) error {
	someFloat, ok := datum.(float64)
	if !ok {
		return newEncoderError("double", "expected: float64; received: %T", datum)
	}
	bits := uint64(math.Float64bits(someFloat))
	const byteCount = 8
	return writeFloat(w, byteCount, bits)
}

func bytesEncoder(w io.Writer, datum interface{}) error {
	someBytes, ok := datum.([]byte)
	if !ok {
		return newEncoderError("bytes", "expected: []byte; received: %T", datum)
	}
	err := longEncoder(w, int64(len(someBytes)))
	if err != nil {
		return newEncoderError("bytes", err)
	}
	_, err = w.Write(someBytes)
	return err
}

func stringEncoder(w io.Writer, datum interface{}) error {
	someString, ok := datum.(string)
	if !ok {
		return newEncoderError("string", "expected: string; received: %T", datum)
	}
	err := longEncoder(w, int64(len(someString)))
	if err != nil {
		return newEncoderError("string", err)
	}
	if sw, ok := w.(StringWriter); ok {
		_, err = sw.WriteString(someString)
	} else {
		_, err = w.Write([]byte(someString))
	}
	return err
}
<|endoftext|>


<commit_before>package toolbox

import (
	"encoding/json"
	"fmt"
	"io"
)

//Encoder writes an instance to output stream
type Encoder interface {
	//Encode encodes  an instance to output stream
	Encode(object interface{}) error
}

//Marshaler represents byte to object converter
type Marshaler interface {
	//Marshal converts bytes to attributes of owner struct
	Marshal() (data []byte, err error)
}

//EncoderFactory create an encoder for an output stream
type EncoderFactory interface {
	//Create creates an encoder for an output stream
	Create(writer io.Writer) Encoder
}

type jsonEncoderFactory struct{}

func (e jsonEncoderFactory) Create(writer io.Writer) Encoder {
	return json.NewEncoder(writer)
}

//NewJSONEncoderFactory creates new NewJSONEncoderFactory
func NewJSONEncoderFactory() EncoderFactory {
	return &jsonEncoderFactory{}
}

type marshalerEncoderFactory struct {
}

func (f *marshalerEncoderFactory) Create(writer io.Writer) Encoder {
	return &marshalerEncoder{writer: writer}
}

type marshalerEncoder struct {
	writer io.Writer
}

func (e *marshalerEncoder) Encode(v interface{}) error {
	result, casted := v.(Marshaler)
	if !casted {
		return fmt.Errorf("Failed to decode - unable cast %T to %s", v, (*Marshaler)(nil))
	}
	bytes, err := result.Marshal()
	if err != nil {
		return err
	}

	for i := 0; i < len(bytes); i++ {
		count, err := e.writer.Write(bytes)
		if err != nil {
			return err
		}
		if count == len(bytes) {
			break
		}
		bytes = bytes[count:]
	}
	return nil
}

//NewMarshalerEncoderFactory create a new encoder factory for marsheler struct
func NewMarshalerEncoderFactory() EncoderFactory {
	return &marshalerEncoderFactory{}
}
<commit_msg>added decoder and encoder for marshaler<commit_after>package toolbox

import (
	"encoding/json"
	"fmt"
	"io"
)

//Encoder writes an instance to output stream
type Encoder interface {
	//Encode encodes  an instance to output stream
	Encode(object interface{}) error
}

//Marshaler represents byte to object converter
type Marshaler interface {
	//Marshal converts bytes to attributes of owner struct
	Marshal() (data []byte, err error)
}

//EncoderFactory create an encoder for an output stream
type EncoderFactory interface {
	//Create creates an encoder for an output stream
	Create(writer io.Writer) Encoder
}

type jsonEncoderFactory struct{}

func (e jsonEncoderFactory) Create(writer io.Writer) Encoder {
	return json.NewEncoder(writer)
}

//NewJSONEncoderFactory creates new NewJSONEncoderFactory
func NewJSONEncoderFactory() EncoderFactory {
	return &jsonEncoderFactory{}
}

type marshalerEncoderFactory struct {
}

func (f *marshalerEncoderFactory) Create(writer io.Writer) Encoder {
	return &marshalerEncoder{writer: writer}
}

type marshalerEncoder struct {
	writer io.Writer
}

func (e *marshalerEncoder) Encode(v interface{}) error {
	result, casted := v.(Marshaler)
	if !casted {
		return fmt.Errorf("Failed to decode - unable cast %T to %s", v, (*Marshaler)(nil))
	}
	bytes, err := result.Marshal()
	if err != nil {
		return err
	}
	var totalByteWritten int = 0
	var bytesLen = len(bytes)
	for i := 0; i < bytesLen; i++ {
		bytesWritten, err := e.writer.Write(bytes[totalByteWritten:])
		if err != nil {
			return fmt.Errorf("Failed to write data %v", err)
		}
		totalByteWritten = totalByteWritten + bytesWritten
		if totalByteWritten == bytesLen {
			break
		}
	}
	if totalByteWritten != bytesLen {
		return fmt.Errorf("Failed to write all data, written %v, expected: %v", totalByteWritten, bytesLen)
	}
	return nil
}

//NewMarshalerEncoderFactory create a new encoder factory for marsheler struct
func NewMarshalerEncoderFactory() EncoderFactory {
	return &marshalerEncoderFactory{}
}
<|endoftext|>


<commit_before>package encoder

// Original code borrowed from https://github.com/PuerkitoBio/martini-api-example
// TextEncoder and XmlEncoder has been removed. If someone really needs it, let me know.

// Supported tags:
// 	 - "out" if it sets to "false", value won't be set to field
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"reflect"
	"time"
)

// An Encoder implements an encoding format of values to be sent as response to
// requests on the API endpoints.
type Encoder interface {
	Encode(v ...interface{}) ([]byte, error)
}

// Because `panic`s are caught by martini's Recovery handler, it can be used
// to return server-side errors (500). Some helpful text message should probably
// be sent, although not the technical error (which is printed in the log).
func Must(data []byte, err error) []byte {
	if err != nil {
		panic(err)
	}
	return data
}

type JsonEncoder struct {
	PrettyPrint bool
}

// @todo test for slice of structure support
func (self JsonEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var result interface{}

	if v == nil {
		// So that empty results produces `[]` and not `null`
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	t := reflect.TypeOf(data)
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	switch t.Kind() {
	case reflect.Slice:
		result = iterateSlice(reflect.ValueOf(data)).Interface()

	case reflect.Struct:
		result = copyStruct(reflect.ValueOf(data)).Interface()

	default:
		result = data
	}

	if self.PrettyPrint {
		return json.MarshalIndent(result, "", "	")
	} else {
		return json.Marshal(result)
	}
}

type XmlEncoder struct{}

// Since we don't use xml as a binding source, we don't need to use
// copyStruct here. Just Marshal.
func (_ XmlEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var buffer bytes.Buffer

	if v == nil {
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	if _, err := buffer.Write([]byte(xml.Header)); err != nil {
		return []byte{}, err
	}

	b, err := xml.Marshal(data)
	if err != nil {
		return []byte{}, err
	}

	buffer.Write(b)

	return buffer.Bytes(), nil
}

func copyStruct(v reflect.Value) reflect.Value {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	result := reflect.New(v.Type()).Elem()

	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		vfield := v.Field(i)

		if tag := t.Field(i).Tag.Get("out"); tag == "false" {
			continue
		}

		if vfield.Type() == reflect.TypeOf(time.Time{}) {
			result.Field(i).Set(vfield)
			continue
		}

		if vfield.Kind() == reflect.Interface && vfield.Interface() != nil {
			vfield = vfield.Elem()

			for vfield.Kind() == reflect.Ptr {
				vfield = vfield.Elem()
			}

			result.Field(i).Set(copyStruct(vfield))
			continue
		}

		if vfield.Kind() == reflect.Struct || vfield.Kind() == reflect.Ptr {
			r := copyStruct(vfield)

			if result.Field(i).Kind() == reflect.Ptr {
				result.Field(i).Set(reflect.New(r.Type()))
			} else {
				result.Field(i).Set(r)
			}

			continue
		}

		if vfield.Kind() == reflect.Array || vfield.Kind() == reflect.Slice {
			result.Field(i).Set(iterateSlice(vfield))
			continue
		}

		if result.Field(i).CanSet() {
			result.Field(i).Set(vfield)
		}
	}

	return result
}

func iterateSlice(v reflect.Value) reflect.Value {
	result := reflect.MakeSlice(v.Type(), 0, v.Len())

	for i := 0; i < v.Len(); i++ {
		value := v.Index(i)

		if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
			result = reflect.Append(result, iterateSlice(value))
			continue
		}

		vi := copyStruct(value)
		if value.Kind() == reflect.Ptr {
			result = reflect.Append(result, vi.Addr())
		} else {
			result = reflect.Append(result, vi)
		}
	}

	return result
}
<commit_msg>Support slices of non-structs (strings, ints, etc.)<commit_after>package encoder

// Original code borrowed from https://github.com/PuerkitoBio/martini-api-example
// TextEncoder and XmlEncoder has been removed. If someone really needs it, let me know.

// Supported tags:
// 	 - "out" if it sets to "false", value won't be set to field
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"reflect"
	"time"
)

// An Encoder implements an encoding format of values to be sent as response to
// requests on the API endpoints.
type Encoder interface {
	Encode(v ...interface{}) ([]byte, error)
}

// Because `panic`s are caught by martini's Recovery handler, it can be used
// to return server-side errors (500). Some helpful text message should probably
// be sent, although not the technical error (which is printed in the log).
func Must(data []byte, err error) []byte {
	if err != nil {
		panic(err)
	}
	return data
}

type JsonEncoder struct {
	PrettyPrint bool
}

// @todo test for slice of structure support
func (self JsonEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var result interface{}

	if v == nil {
		// So that empty results produces `[]` and not `null`
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	t := reflect.TypeOf(data)
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	switch t.Kind() {
	case reflect.Slice:
		result = iterateSlice(reflect.ValueOf(data)).Interface()

	case reflect.Struct:
		result = copyStruct(reflect.ValueOf(data)).Interface()

	default:
		result = data
	}

	if self.PrettyPrint {
		return json.MarshalIndent(result, "", "	")
	} else {
		return json.Marshal(result)
	}
}

type XmlEncoder struct{}

// Since we don't use xml as a binding source, we don't need to use
// copyStruct here. Just Marshal.
func (_ XmlEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var buffer bytes.Buffer

	if v == nil {
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	if _, err := buffer.Write([]byte(xml.Header)); err != nil {
		return []byte{}, err
	}

	b, err := xml.Marshal(data)
	if err != nil {
		return []byte{}, err
	}

	buffer.Write(b)

	return buffer.Bytes(), nil
}

func copyStruct(v reflect.Value) reflect.Value {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	result := reflect.New(v.Type()).Elem()

	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		vfield := v.Field(i)

		if tag := t.Field(i).Tag.Get("out"); tag == "false" {
			continue
		}

		if vfield.Type() == reflect.TypeOf(time.Time{}) {
			result.Field(i).Set(vfield)
			continue
		}

		if vfield.Kind() == reflect.Interface && vfield.Interface() != nil {
			vfield = vfield.Elem()

			for vfield.Kind() == reflect.Ptr {
				vfield = vfield.Elem()
			}

			result.Field(i).Set(copyStruct(vfield))
			continue
		}

		if vfield.Kind() == reflect.Struct || vfield.Kind() == reflect.Ptr {
			r := copyStruct(vfield)

			if result.Field(i).Kind() == reflect.Ptr {
				result.Field(i).Set(reflect.New(r.Type()))
			} else {
				result.Field(i).Set(r)
			}

			continue
		}

		if vfield.Kind() == reflect.Array || vfield.Kind() == reflect.Slice {
			result.Field(i).Set(iterateSlice(vfield))
			continue
		}

		if result.Field(i).CanSet() {
			result.Field(i).Set(vfield)
		}
	}

	return result
}

func iterateSlice(v reflect.Value) reflect.Value {
	result := reflect.MakeSlice(v.Type(), 0, v.Len())

	for i := 0; i < v.Len(); i++ {
		value := v.Index(i)

		if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
			result = reflect.Append(result, iterateSlice(value))
			continue
		}

		vi := value
		if value.Kind() == reflect.Struct {
			vi = copyStruct(value)
		}

		if value.Kind() == reflect.Ptr {
			result = reflect.Append(result, vi.Addr())
		} else {
			result = reflect.Append(result, vi)
		}
	}

	return result
}
<|endoftext|>