<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcs

import (
	"errors"
	"io"
	"net/http"
	"unicode/utf8"

	"golang.org/x/net/context"
	storagev1 "google.golang.org/api/storage/v1"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// A request to create an object, accepted by Bucket.CreateObject.
type CreateObjectRequest struct {
	// Attributes with which the object should be created. The Name field must be
	// set; other zero-valued fields are ignored.
	//
	// Object names must:
	//
	// *  be non-empty.
	// *  be no longer than 1024 bytes.
	// *  be valid UTF-8.
	// *  not contain the code point U+000A (line feed).
	// *  not contain the code point U+000D (carriage return).
	//
	// See here for authoritative documentation:
	//     https://cloud.google.com/storage/docs/bucket-naming#objectnames
	Attrs storage.ObjectAttrs

	// A reader from which to obtain the contents of the object. Must be non-nil.
	Contents io.Reader
}

// Bucket represents a GCS bucket, pre-bound with a bucket name and necessary
// authorization information.
//
// Each method that may block accepts a context object that is used for
// deadlines and cancellation. Users need not package authorization information
// into the context object (using cloud.WithContext or similar).
type Bucket interface {
	Name() string

	// List the objects in the bucket that meet the criteria defined by the
	// query, returning a result object that contains the results and potentially
	// a cursor for retrieving the next portion of the larger set of results.
	ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error)

	// Create a reader for the contents of the object with the given name. The
	// caller must arrange for the reader to be closed when it is no longer
	// needed.
	NewReader(ctx context.Context, objectName string) (io.ReadCloser, error)

	// Create or overwrite an object according to the supplied request. The new
	// object is guaranteed to exist immediately for the purposes of reading (and
	// eventually for listing) after this method returns a nil error. It is
	// guaranteed not to exist before req.Contents returns io.EOF.
	CreateObject(ctx context.Context, req *CreateObjectRequest) (*storage.Object, error)

	// Delete the object with the given name.
	DeleteObject(ctx context.Context, name string) error
}

type bucket struct {
	projID string
	client *http.Client
	name   string
}

func (b *bucket) Name() string {
	return b.name
}

func (b *bucket) ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.ListObjects(authContext, b.name, query)
}

func (b *bucket) NewReader(ctx context.Context, objectName string) (io.ReadCloser, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.NewReader(authContext, b.name, objectName)
}

func toRawAcls(in []storage.ACLRule) []*storagev1.ObjectAccessControl {
	out := make([]*storagev1.ObjectAccessControl, len(in))
	for i, rule := range in {
		out[i] = &storagev1.ObjectAccessControl{
			Entity: string(rule.Entity),
			Role:   string(rule.Role),
		}
	}

	return out
}

func fromRawAcls(in []*storagev1.ObjectAccessControl) []storage.ACLRule

func fromRawObject(bucketName string, in *storagev1.Object) *storage.Object {
	out := &storage.Object{
		Bucket:          bucketName,
		Name:            in.Name,
		ContentType:     in.ContentType,
		ContentLanguage: in.ContentLanguage,
		CacheControl:    in.CacheControl,
		ACL:             fromRawAcls(in.Acl),
		Owner:           in.Owner,
		ContentEncoding: in.ContentEncoding,
		Size:            in.Size,
		MD5:             in.MD5,
		CRC32C:          in.CRC32C,
		MediaLink:       in.MediaLink,
		Metadata:        in.Metadata,
		Generation:      in.Generation,
		MetaGeneration:  in.MetaGeneration,
		StorageClass:    in.StorageClass,
		Deleted:         in.TimeDeleted,
		Updated:         in.Updated,
	}

	return out
}

func getRawService(authContext context.Context) *storagev1.Service

func (b *bucket) CreateObject(
	ctx context.Context,
	req *CreateObjectRequest) (o *storage.Object, err error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	objectsService := getRawService(authContext).Objects

	// As of 2015-02, the wrapped storage package doesn't check this for us,
	// causing silently transformed names:
	//     https://github.com/GoogleCloudPlatform/gcloud-golang/issues/111
	if !utf8.ValidString(req.Attrs.Name) {
		err = errors.New("Invalid object name: not valid UTF-8")
		return
	}

	// Set up an object struct based on the supplied attributes.
	inputObj := &storagev1.Object{
		Name:            req.Attrs.Name,
		Bucket:          b.Name(),
		ContentType:     req.Attrs.ContentType,
		ContentLanguage: req.Attrs.ContentLanguage,
		ContentEncoding: req.Attrs.ContentEncoding,
		CacheControl:    req.Attrs.CacheControl,
		Acl:             toRawAcls(req.Attrs.ACL),
		Metadata:        req.Attrs.Metadata,
	}

	// Configure a 'call' object.
	call := objectsService.Insert(b.Name(), inputObj)
	call.Media(req.Contents)
	call.Projection("full")

	// Execute the call.
	rawObject, err := call.Do()
	if err != nil {
		return
	}

	// Convert the returned object.
	o = fromRawObject(b.Name(), rawObject)

	return
}

func (b *bucket) DeleteObject(ctx context.Context, name string) error {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.DeleteObject(authContext, b.name, name)
}
<commit_msg>Fixed some build errors.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcs

import (
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"net/http"
	"unicode/utf8"

	"golang.org/x/net/context"
	storagev1 "google.golang.org/api/storage/v1"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// A request to create an object, accepted by Bucket.CreateObject.
type CreateObjectRequest struct {
	// Attributes with which the object should be created. The Name field must be
	// set; other zero-valued fields are ignored.
	//
	// Object names must:
	//
	// *  be non-empty.
	// *  be no longer than 1024 bytes.
	// *  be valid UTF-8.
	// *  not contain the code point U+000A (line feed).
	// *  not contain the code point U+000D (carriage return).
	//
	// See here for authoritative documentation:
	//     https://cloud.google.com/storage/docs/bucket-naming#objectnames
	Attrs storage.ObjectAttrs

	// A reader from which to obtain the contents of the object. Must be non-nil.
	Contents io.Reader
}

// Bucket represents a GCS bucket, pre-bound with a bucket name and necessary
// authorization information.
//
// Each method that may block accepts a context object that is used for
// deadlines and cancellation. Users need not package authorization information
// into the context object (using cloud.WithContext or similar).
type Bucket interface {
	Name() string

	// List the objects in the bucket that meet the criteria defined by the
	// query, returning a result object that contains the results and potentially
	// a cursor for retrieving the next portion of the larger set of results.
	ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error)

	// Create a reader for the contents of the object with the given name. The
	// caller must arrange for the reader to be closed when it is no longer
	// needed.
	NewReader(ctx context.Context, objectName string) (io.ReadCloser, error)

	// Create or overwrite an object according to the supplied request. The new
	// object is guaranteed to exist immediately for the purposes of reading (and
	// eventually for listing) after this method returns a nil error. It is
	// guaranteed not to exist before req.Contents returns io.EOF.
	CreateObject(ctx context.Context, req *CreateObjectRequest) (*storage.Object, error)

	// Delete the object with the given name.
	DeleteObject(ctx context.Context, name string) error
}

type bucket struct {
	projID string
	client *http.Client
	name   string
}

func (b *bucket) Name() string {
	return b.name
}

func (b *bucket) ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.ListObjects(authContext, b.name, query)
}

func (b *bucket) NewReader(ctx context.Context, objectName string) (io.ReadCloser, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.NewReader(authContext, b.name, objectName)
}

func toRawAcls(in []storage.ACLRule) []*storagev1.ObjectAccessControl {
	out := make([]*storagev1.ObjectAccessControl, len(in))
	for i, rule := range in {
		out[i] = &storagev1.ObjectAccessControl{
			Entity: string(rule.Entity),
			Role:   string(rule.Role),
		}
	}

	return out
}

func fromRawAcls(in []*storagev1.ObjectAccessControl) []storage.ACLRule

func fromRawObject(
	bucketName string,
	in *storagev1.Object) (out *storage.Object, err error) {
	// Convert the easy fields.
	out = &storage.Object{
		Bucket:          bucketName,
		Name:            in.Name,
		ContentType:     in.ContentType,
		ContentLanguage: in.ContentLanguage,
		CacheControl:    in.CacheControl,
		ACL:             fromRawAcls(in.Acl),
		ContentEncoding: in.ContentEncoding,
		Size:            int64(in.Size),
		CRC32C:          in.CRC32C,
		MediaLink:       in.MediaLink,
		Metadata:        in.Metadata,
		Generation:      in.Generation,
		MetaGeneration:  in.MetaGeneration,
		StorageClass:    in.StorageClass,
		Deleted:         in.TimeDeleted,
		Updated:         in.Updated,
	}

	// Handle special cases.
	if in.Owner != nil {
		out.Owner = in.Owner.Entity
	}

	if out.MD5, err = base64.StdEncoding.DecodeString(in.Md5Hash); err != nil {
		err = fmt.Errorf("Decoding Md5Hash field: %v", err)
		return
	}

	return
}

func getRawService(authContext context.Context) *storagev1.Service

func (b *bucket) CreateObject(
	ctx context.Context,
	req *CreateObjectRequest) (o *storage.Object, err error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	objectsService := getRawService(authContext).Objects

	// As of 2015-02, the wrapped storage package doesn't check this for us,
	// causing silently transformed names:
	//     https://github.com/GoogleCloudPlatform/gcloud-golang/issues/111
	if !utf8.ValidString(req.Attrs.Name) {
		err = errors.New("Invalid object name: not valid UTF-8")
		return
	}

	// Set up an object struct based on the supplied attributes.
	inputObj := &storagev1.Object{
		Name:            req.Attrs.Name,
		Bucket:          b.Name(),
		ContentType:     req.Attrs.ContentType,
		ContentLanguage: req.Attrs.ContentLanguage,
		ContentEncoding: req.Attrs.ContentEncoding,
		CacheControl:    req.Attrs.CacheControl,
		Acl:             toRawAcls(req.Attrs.ACL),
		Metadata:        req.Attrs.Metadata,
	}

	// Configure a 'call' object.
	call := objectsService.Insert(b.Name(), inputObj)
	call.Media(req.Contents)
	call.Projection("full")

	// Execute the call.
	rawObject, err := call.Do()
	if err != nil {
		return
	}

	// Convert the returned object.
	o, err = fromRawObject(b.Name(), rawObject)
	if err != nil {
		return
	}

	return
}

func (b *bucket) DeleteObject(ctx context.Context, name string) error {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.DeleteObject(authContext, b.name, name)
}
<|endoftext|>


<commit_before>package gen

import (
	"go/ast"
	"go/token"
	"strings"
)

func AnotatedStructs(f *ast.File, anotation string) structs {

	structs := structs{}

	pkg := f.Name.Name
	ast.Inspect(f, func(n ast.Node) bool {

		g, ok := n.(*ast.GenDecl)

		if !ok || g.Tok != token.TYPE {
			return true
		}

		comments := findComments(g.Doc)
		if !isMarked(comments, anotation) {
			return true
		}

		st, ok := findStruct(g.Specs)
		if !ok {
			return true
		}

		st.Comments = comments
		st.Package = pkg

		structs = append(structs, st)
		return false
	})

	return structs
}

func StructFuncs(f *ast.File) map[string]funcs {

	structFuncs := map[string]funcs{}

	ast.Inspect(f, func(n ast.Node) bool {

		f, ok := n.(*ast.FuncDecl)

		if !ok {
			return true
		}

		recv, ok := findRecv(f.Recv)
		if !ok {
			return true
		}

		fn := funcType{
			Recv:     recv,
			Name:     f.Name.Name,
			Comments: findComments(f.Doc),
		}

		structFuncs[recv] = append(structFuncs[recv], fn)
		return false
	})

	return structFuncs
}

func findComments(cs *ast.CommentGroup) comments {
	result := comments{}
	if cs == nil {
		return result
	}
	for _, c := range cs.List {
		t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
		result = append(result, comment(t))
	}
	return result
}

func isMarked(comments comments, mark string) bool {
	for _, c := range comments {
		if strings.HasPrefix(string(c), mark) {
			return true
		}
	}
	return false
}

func findStruct(specs []ast.Spec) (*structType, bool) {
	st := &structType{}
	for _, spec := range specs {
		t := spec.(*ast.TypeSpec)
		s, ok := t.Type.(*ast.StructType)
		if !ok {
			return st, false
		}

		st.Name = t.Name.Name
		for _, f := range s.Fields.List {
			field := field{
				Name: f.Names[0].Name,
				Type: f.Type.(*ast.Ident).Name,
			}
			if f.Tag != nil {
				field.Tag = tag(f.Tag.Value)
			}
			st.Fields = append(st.Fields, field)
		}
	}
	return st, true
}

func findRecv(recv *ast.FieldList) (string, bool) {
	if recv == nil {
		return "", false
	}
	for _, r := range recv.List {
		f, ok := r.Type.(*ast.Ident)
		if !ok {
			return "", false
		}
		return f.Name, true
	}
	return "", false
}
<commit_msg>gen: support the case that field.Type is *ast.SelectorExpr.<commit_after>package gen

import (
	"go/ast"
	"go/token"
	"strings"
)

func AnotatedStructs(f *ast.File, anotation string) structs {

	structs := structs{}

	pkg := f.Name.Name
	ast.Inspect(f, func(n ast.Node) bool {

		g, ok := n.(*ast.GenDecl)

		if !ok || g.Tok != token.TYPE {
			return true
		}

		comments := findComments(g.Doc)
		if !isMarked(comments, anotation) {
			return true
		}

		st, ok := findStruct(g.Specs)
		if !ok {
			return true
		}

		st.Comments = comments
		st.Package = pkg

		structs = append(structs, st)
		return false
	})

	return structs
}

func StructFuncs(f *ast.File) map[string]funcs {

	structFuncs := map[string]funcs{}

	ast.Inspect(f, func(n ast.Node) bool {

		f, ok := n.(*ast.FuncDecl)

		if !ok {
			return true
		}

		recv, ok := findRecv(f.Recv)
		if !ok {
			return true
		}

		fn := funcType{
			Recv:     recv,
			Name:     f.Name.Name,
			Comments: findComments(f.Doc),
		}

		structFuncs[recv] = append(structFuncs[recv], fn)
		return false
	})

	return structFuncs
}

func findComments(cs *ast.CommentGroup) comments {
	result := comments{}
	if cs == nil {
		return result
	}
	for _, c := range cs.List {
		t := strings.TrimSpace(strings.TrimLeft(c.Text, "//"))
		result = append(result, comment(t))
	}
	return result
}

func isMarked(comments comments, mark string) bool {
	for _, c := range comments {
		if strings.HasPrefix(string(c), mark) {
			return true
		}
	}
	return false
}

func findStruct(specs []ast.Spec) (*structType, bool) {
	st := &structType{}
	for _, spec := range specs {
		t := spec.(*ast.TypeSpec)
		s, ok := t.Type.(*ast.StructType)
		if !ok {
			return st, false
		}

		st.Name = t.Name.Name
		for _, f := range s.Fields.List {
			var ident *ast.Ident
			switch f.Type.(type) {
			case *ast.Ident:
				ident = f.Type.(*ast.Ident)
			case *ast.SelectorExpr:
				ident = f.Type.(*ast.SelectorExpr).Sel
			}
			field := field{
				Name: f.Names[0].Name,
				Type: ident.Name,
			}
			if f.Tag != nil {
				field.Tag = tag(f.Tag.Value)
			}
			st.Fields = append(st.Fields, field)
		}
	}
	return st, true
}

func findRecv(recv *ast.FieldList) (string, bool) {
	if recv == nil {
		return "", false
	}
	for _, r := range recv.List {
		f, ok := r.Type.(*ast.Ident)
		if !ok {
			return "", false
		}
		return f.Name, true
	}
	return "", false
}
<|endoftext|>


<commit_before>// +build x
// +build !generated

// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

import (
	"bytes"
	"testing"

	gcbor "bitbucket.org/bodhisnarkva/cbor/go" // gcbor "code.google.com/p/cbor/go"
	"github.com/Sereal/Sereal/Go/sereal"
	xdr "github.com/davecgh/go-xdr/xdr2"
	jsoniter "github.com/json-iterator/go"
	"go.mongodb.org/mongo-driver/bson"         // "github.com/mongodb/mongo-go-driver/bson"
	mgobson "github.com/globalsign/mgo/bson"             //"labix.org/v2/mgo/bson"
	vmsgpack "github.com/vmihailenco/msgpack/v4" //"github.com/vmihailenco/msgpack"
	fxcbor "github.com/fxamacker/cbor/v2"
)

/*
 To update all these, use:
 go get -u github.com/tinylib/msgp/msgp github.com/tinylib/msgp \
           github.com/pquerna/ffjson/ffjson github.com/pquerna/ffjson \
           github.com/Sereal/Sereal/Go/sereal \
           bitbucket.org/bodhisnarkva/cbor/go \
           github.com/davecgh/go-xdr/xdr2 \
           github.com/globalsign/mgo/bson \
           github.com/vmihailenco/msgpack/v4 /
           github.com/json-iterator/go \
           github.com/fxamacker/cbor/v2 \
           github.com/mailru/easyjson/...

 Known Issues with external libraries:
 - msgp io.R/W support doesn't work. It throws error

*/

func init() {
	testPreInitFns = append(testPreInitFns, benchXPreInit)
	_ = bson.NewDecoder
}

func benchXPreInit() {
	benchCheckers = append(benchCheckers,
		benchChecker{"json-iter", fnJsonIterEncodeFn, fnJsonIterDecodeFn},
		benchChecker{"v-msgpack", fnVMsgpackEncodeFn, fnVMsgpackDecodeFn},
		benchChecker{"bson", fnBsonEncodeFn, fnBsonDecodeFn},
		benchChecker{"mgobson", fnMgobsonEncodeFn, fnMgobsonDecodeFn},
		benchChecker{"fxcbor", fnFxcborEncodeFn, fnFxcborDecodeFn},
		// place codecs with issues at the end, so as not to make results too ugly
		benchChecker{"gcbor", fnGcborEncodeFn, fnGcborDecodeFn}, // this logs fat ugly message, but we log.SetOutput(ioutil.Discard)
		benchChecker{"xdr", fnXdrEncodeFn, fnXdrDecodeFn},
		benchChecker{"sereal", fnSerealEncodeFn, fnSerealDecodeFn},
	)
}

func fnVMsgpackEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	if testUseIoEncDec >= 0 {
		buf := bytes.NewBuffer(bsIn[:0]) // new(bytes.Buffer)
		err := vmsgpack.NewEncoder(buf).Encode(ts)
		return buf.Bytes(), err
	}
	return vmsgpack.Marshal(ts)
}

func fnVMsgpackDecodeFn(buf []byte, ts interface{}) error {
	if testUseIoEncDec >= 0 {
		return vmsgpack.NewDecoder(bytes.NewReader(buf)).Decode(ts)
	}
	return vmsgpack.Unmarshal(buf, ts)
}

func fnBsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return bson.Marshal(ts)
}

func fnBsonDecodeFn(buf []byte, ts interface{}) error {
	return bson.Unmarshal(buf, ts)
}

func fnMgobsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return mgobson.Marshal(ts)
}

func fnMgobsonDecodeFn(buf []byte, ts interface{}) error {
	return mgobson.Unmarshal(buf, ts)
}

func fnJsonIterEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	if testUseIoEncDec >= 0 {
		buf := bytes.NewBuffer(bsIn[:0]) // new(bytes.Buffer)
		err := jsoniter.NewEncoder(buf).Encode(ts)
		return buf.Bytes(), err
	}
	return jsoniter.Marshal(ts)
}

func fnJsonIterDecodeFn(buf []byte, ts interface{}) error {
	if testUseIoEncDec >= 0 {
		return jsoniter.NewDecoder(bytes.NewReader(buf)).Decode(ts)
	}
	return jsoniter.Unmarshal(buf, ts)
}

func fnFxcborEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return fxcbor.Marshal(ts)
}

func fnFxcborDecodeFn(buf []byte, ts interface{}) error {
	return fxcbor.Unmarshal(buf, ts)
}

func fnXdrEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	buf := fnBenchmarkByteBuf(bsIn)
	i, err := xdr.Marshal(buf, ts)
	return buf.Bytes()[:i], err
}

func fnXdrDecodeFn(buf []byte, ts interface{}) error {
	_, err := xdr.Unmarshal(bytes.NewReader(buf), ts)
	return err
}

func fnSerealEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return sereal.Marshal(ts)
}

func fnSerealDecodeFn(buf []byte, ts interface{}) error {
	return sereal.Unmarshal(buf, ts)
}

func fnGcborEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
	buf := fnBenchmarkByteBuf(bsIn)
	err = gcbor.NewEncoder(buf).Encode(ts)
	return buf.Bytes(), err
}

func fnGcborDecodeFn(buf []byte, ts interface{}) error {
	return gcbor.NewDecoder(bytes.NewReader(buf)).Decode(ts)
}

func Benchmark__JsonIter___Encode(b *testing.B) {
	fnBenchmarkEncode(b, "jsoniter", benchTs, fnJsonIterEncodeFn)
}

func Benchmark__JsonIter___Decode(b *testing.B) {
	fnBenchmarkDecode(b, "jsoniter", benchTs, fnJsonIterEncodeFn, fnJsonIterDecodeFn, fnBenchNewTs)
}

func Benchmark__Fxcbor_____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "fxcbor", benchTs, fnFxcborEncodeFn)
}

func Benchmark__Fxcbor_____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "fxcbor", benchTs, fnFxcborEncodeFn, fnFxcborDecodeFn, fnBenchNewTs)
}

// Place codecs with issues at the bottom, so as not to make results look too ugly.

func Benchmark__Mgobson____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "mgobson", benchTs, fnMgobsonEncodeFn)
}

func Benchmark__Mgobson____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "mgobson", benchTs, fnMgobsonEncodeFn, fnMgobsonDecodeFn, fnBenchNewTs)
}

func Benchmark__Bson_______Encode(b *testing.B) {
	fnBenchmarkEncode(b, "bson", benchTs, fnBsonEncodeFn)
}

func Benchmark__Bson_______Decode(b *testing.B) {
	fnBenchmarkDecode(b, "bson", benchTs, fnBsonEncodeFn, fnBsonDecodeFn, fnBenchNewTs)
}

func Benchmark__VMsgpack___Encode(b *testing.B) {
	fnBenchmarkEncode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn)
}

func Benchmark__VMsgpack___Decode(b *testing.B) {
	fnBenchmarkDecode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn, fnVMsgpackDecodeFn, fnBenchNewTs)
}

func Benchmark__Gcbor______Encode(b *testing.B) {
	fnBenchmarkEncode(b, "gcbor", benchTs, fnGcborEncodeFn)
}

func Benchmark__Gcbor______Decode(b *testing.B) {
	fnBenchmarkDecode(b, "gcbor", benchTs, fnGcborEncodeFn, fnGcborDecodeFn, fnBenchNewTs)
}

func Benchmark__Xdr________Encode(b *testing.B) {
	fnBenchmarkEncode(b, "xdr", benchTs, fnXdrEncodeFn)
}

func Benchmark__Xdr________Decode(b *testing.B) {
	fnBenchmarkDecode(b, "xdr", benchTs, fnXdrEncodeFn, fnXdrDecodeFn, fnBenchNewTs)
}

func Benchmark__Sereal_____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "sereal", benchTs, fnSerealEncodeFn)
}

func Benchmark__Sereal_____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "sereal", benchTs, fnSerealEncodeFn, fnSerealDecodeFn, fnBenchNewTs)
}
<commit_msg>codec/bench: support IO interfaces for fxcbor benchmark run<commit_after>// +build x
// +build !generated

// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

import (
	"bytes"
	"testing"

	gcbor "bitbucket.org/bodhisnarkva/cbor/go" // gcbor "code.google.com/p/cbor/go"
	"github.com/Sereal/Sereal/Go/sereal"
	xdr "github.com/davecgh/go-xdr/xdr2"
	jsoniter "github.com/json-iterator/go"
	"go.mongodb.org/mongo-driver/bson"         // "github.com/mongodb/mongo-go-driver/bson"
	mgobson "github.com/globalsign/mgo/bson"             //"labix.org/v2/mgo/bson"
	vmsgpack "github.com/vmihailenco/msgpack/v4" //"github.com/vmihailenco/msgpack"
	fxcbor "github.com/fxamacker/cbor/v2"
)

/*
 To update all these, use:
 go get -u github.com/tinylib/msgp/msgp github.com/tinylib/msgp \
           github.com/pquerna/ffjson/ffjson github.com/pquerna/ffjson \
           github.com/Sereal/Sereal/Go/sereal \
           bitbucket.org/bodhisnarkva/cbor/go \
           github.com/davecgh/go-xdr/xdr2 \
           github.com/globalsign/mgo/bson \
           github.com/vmihailenco/msgpack/v4 /
           github.com/json-iterator/go \
           github.com/fxamacker/cbor/v2 \
           github.com/mailru/easyjson/...

 Known Issues with external libraries:
 - msgp io.R/W support doesn't work. It throws error

*/

func init() {
	testPreInitFns = append(testPreInitFns, benchXPreInit)
	_ = bson.NewDecoder
}

func benchXPreInit() {
	benchCheckers = append(benchCheckers,
		benchChecker{"json-iter", fnJsonIterEncodeFn, fnJsonIterDecodeFn},
		benchChecker{"v-msgpack", fnVMsgpackEncodeFn, fnVMsgpackDecodeFn},
		benchChecker{"bson", fnBsonEncodeFn, fnBsonDecodeFn},
		benchChecker{"mgobson", fnMgobsonEncodeFn, fnMgobsonDecodeFn},
		benchChecker{"fxcbor", fnFxcborEncodeFn, fnFxcborDecodeFn},
		// place codecs with issues at the end, so as not to make results too ugly
		benchChecker{"gcbor", fnGcborEncodeFn, fnGcborDecodeFn}, // this logs fat ugly message, but we log.SetOutput(ioutil.Discard)
		benchChecker{"xdr", fnXdrEncodeFn, fnXdrDecodeFn},
		benchChecker{"sereal", fnSerealEncodeFn, fnSerealDecodeFn},
	)
}

func fnVMsgpackEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	if testUseIoEncDec >= 0 {
		buf := bytes.NewBuffer(bsIn[:0]) // new(bytes.Buffer)
		err := vmsgpack.NewEncoder(buf).Encode(ts)
		return buf.Bytes(), err
	}
	return vmsgpack.Marshal(ts)
}

func fnVMsgpackDecodeFn(buf []byte, ts interface{}) error {
	if testUseIoEncDec >= 0 {
		return vmsgpack.NewDecoder(bytes.NewReader(buf)).Decode(ts)
	}
	return vmsgpack.Unmarshal(buf, ts)
}

func fnBsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return bson.Marshal(ts)
}

func fnBsonDecodeFn(buf []byte, ts interface{}) error {
	return bson.Unmarshal(buf, ts)
}

func fnMgobsonEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return mgobson.Marshal(ts)
}

func fnMgobsonDecodeFn(buf []byte, ts interface{}) error {
	return mgobson.Unmarshal(buf, ts)
}

func fnJsonIterEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	if testUseIoEncDec >= 0 {
		buf := bytes.NewBuffer(bsIn[:0]) // new(bytes.Buffer)
		err := jsoniter.NewEncoder(buf).Encode(ts)
		return buf.Bytes(), err
	}
	return jsoniter.Marshal(ts)
}

func fnJsonIterDecodeFn(buf []byte, ts interface{}) error {
	if testUseIoEncDec >= 0 {
		return jsoniter.NewDecoder(bytes.NewReader(buf)).Decode(ts)
	}
	return jsoniter.Unmarshal(buf, ts)
}

func fnFxcborEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	if testUseIoEncDec >= 0 {
		buf := bytes.NewBuffer(bsIn[:0])
		err := fxcbor.NewEncoder(buf).Encode(ts)
		return buf.Bytes(), err
	}
	return fxcbor.Marshal(ts)
}

func fnFxcborDecodeFn(buf []byte, ts interface{}) error {
	if testUseIoEncDec >= 0 {
		return fxcbor.NewDecoder(bytes.NewReader(buf)).Decode(ts)
	}
	return fxcbor.Unmarshal(buf, ts)
}

func fnXdrEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	buf := fnBenchmarkByteBuf(bsIn)
	i, err := xdr.Marshal(buf, ts)
	return buf.Bytes()[:i], err
}

func fnXdrDecodeFn(buf []byte, ts interface{}) error {
	_, err := xdr.Unmarshal(bytes.NewReader(buf), ts)
	return err
}

func fnSerealEncodeFn(ts interface{}, bsIn []byte) ([]byte, error) {
	return sereal.Marshal(ts)
}

func fnSerealDecodeFn(buf []byte, ts interface{}) error {
	return sereal.Unmarshal(buf, ts)
}

func fnGcborEncodeFn(ts interface{}, bsIn []byte) (bs []byte, err error) {
	buf := fnBenchmarkByteBuf(bsIn)
	err = gcbor.NewEncoder(buf).Encode(ts)
	return buf.Bytes(), err
}

func fnGcborDecodeFn(buf []byte, ts interface{}) error {
	return gcbor.NewDecoder(bytes.NewReader(buf)).Decode(ts)
}

func Benchmark__JsonIter___Encode(b *testing.B) {
	fnBenchmarkEncode(b, "jsoniter", benchTs, fnJsonIterEncodeFn)
}

func Benchmark__JsonIter___Decode(b *testing.B) {
	fnBenchmarkDecode(b, "jsoniter", benchTs, fnJsonIterEncodeFn, fnJsonIterDecodeFn, fnBenchNewTs)
}

func Benchmark__Fxcbor_____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "fxcbor", benchTs, fnFxcborEncodeFn)
}

func Benchmark__Fxcbor_____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "fxcbor", benchTs, fnFxcborEncodeFn, fnFxcborDecodeFn, fnBenchNewTs)
}

// Place codecs with issues at the bottom, so as not to make results look too ugly.

func Benchmark__Mgobson____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "mgobson", benchTs, fnMgobsonEncodeFn)
}

func Benchmark__Mgobson____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "mgobson", benchTs, fnMgobsonEncodeFn, fnMgobsonDecodeFn, fnBenchNewTs)
}

func Benchmark__Bson_______Encode(b *testing.B) {
	fnBenchmarkEncode(b, "bson", benchTs, fnBsonEncodeFn)
}

func Benchmark__Bson_______Decode(b *testing.B) {
	fnBenchmarkDecode(b, "bson", benchTs, fnBsonEncodeFn, fnBsonDecodeFn, fnBenchNewTs)
}

func Benchmark__VMsgpack___Encode(b *testing.B) {
	fnBenchmarkEncode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn)
}

func Benchmark__VMsgpack___Decode(b *testing.B) {
	fnBenchmarkDecode(b, "v-msgpack", benchTs, fnVMsgpackEncodeFn, fnVMsgpackDecodeFn, fnBenchNewTs)
}

func Benchmark__Gcbor______Encode(b *testing.B) {
	fnBenchmarkEncode(b, "gcbor", benchTs, fnGcborEncodeFn)
}

func Benchmark__Gcbor______Decode(b *testing.B) {
	fnBenchmarkDecode(b, "gcbor", benchTs, fnGcborEncodeFn, fnGcborDecodeFn, fnBenchNewTs)
}

func Benchmark__Xdr________Encode(b *testing.B) {
	fnBenchmarkEncode(b, "xdr", benchTs, fnXdrEncodeFn)
}

func Benchmark__Xdr________Decode(b *testing.B) {
	fnBenchmarkDecode(b, "xdr", benchTs, fnXdrEncodeFn, fnXdrDecodeFn, fnBenchNewTs)
}

func Benchmark__Sereal_____Encode(b *testing.B) {
	fnBenchmarkEncode(b, "sereal", benchTs, fnSerealEncodeFn)
}

func Benchmark__Sereal_____Decode(b *testing.B) {
	fnBenchmarkDecode(b, "sereal", benchTs, fnSerealEncodeFn, fnSerealDecodeFn, fnBenchNewTs)
}
<|endoftext|>


<commit_before>package window

/*
#cgo darwin CFLAGS:   -F/Library/Frameworks -D_GOSMF_OSX_
#cgo darwin LDFLAGS:  -F/Library/Frameworks -framework SDL2

#cgo linux CFLAGS:    -D_GOSMF_LINUX_
#cgo linux LDFLAGS:   -lSDL2main -lSDL2

#cgo windows CFLAGS:  -D_GOSMF_WINDOWS_
#cgo windows LDFLAGS: -lSDL2main -lSDL2
*/
import "C"
<commit_msg>Fix invalid CFLAG for golang v1.9.4<commit_after>package window

/*
#cgo darwin CFLAGS:   -D_GOSMF_OSX_
#cgo darwin LDFLAGS:  -F/Library/Frameworks -framework SDL2

#cgo linux CFLAGS:    -D_GOSMF_LINUX_
#cgo linux LDFLAGS:   -lSDL2main -lSDL2

#cgo windows CFLAGS:  -D_GOSMF_WINDOWS_
#cgo windows LDFLAGS: -lSDL2main -lSDL2
*/
import "C"
<|endoftext|>


<commit_before>package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
)

//define address
const (
	Xunlei   = "http://bt.box.n0808.com/%s/%s/%s.torrent"
	Torcache = "https://torcache.net/torrent/%s.torrent"
)

//define errors
var (
	ErrNotFound = errors.New("not found")
	LibUrls     = []string{
		// "http://www.torrent.org.cn/Home/torrent/download.html?hash=%s",
		// "http://torcache.net/torrent/%s.torrent",
		// "http://torrage.com/torrent/%s.torrent",
		// "http://zoink.it/torrent/%s.torrent",
		// "https://178.73.198.210/torrent/%s.torrent",
		// "http://d1.torrentkittycn.com/?infohash=%s",
		// "http://reflektor.karmorra.info/torrent/%s.torrent",
		"http://itorrents.org/torrent/%s.torrent",
	}
)

//DownloadXunlei torrent
func DownloadXunlei(hash string, client *http.Client) (mi MetaInfo, err error) {
	mi.InfoHash = hash
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}

	//从迅雷种子库查找
	address := fmt.Sprintf(Xunlei, hash[:2], hash[len(hash)-2:], hash)
	req0, err := http.NewRequest("GET", address, nil)
	if err != nil {
		return
	}
	req0.Header.Set("User-Agent", "Mozilla/5.0")
	resp, err := client.Do(req0)
	if err != nil {
		return
	}
	if resp != nil {
		defer func() {
			// io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}()

		if resp.StatusCode == 200 {
			//解析种子
			err = mi.Parse(resp.Body)
		} else if resp.StatusCode == 404 {
			err = ErrNotFound
		} else {
			err = errors.New("refuse error")
		}
	}
	return
}

//Download torrent
func DownloadTorrent(hash string, client *http.Client) (mi MetaInfo, err error) {
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}
	// mi, err = DownloadXunlei(hash, client)
	// //迅雷解析成功，不用再調用後面的種子庫
	// if err == nil {
	// 	return
	// }

	mi.InfoHash = hash
	//將來改用字典實現
	for _, lib_url := range LibUrls {
		address := fmt.Sprintf(lib_url, strings.ToUpper(hash))
		req0, err := http.NewRequest("GET", address, nil)
		if err != nil {
			continue
		}
		resp, err := client.Do(req0)
		if err != nil {
			continue
		}
		if resp != nil {
			defer func() {
				// io.Copy(ioutil.Discard, resp.Body)
				resp.Body.Close()
			}()

			if resp.StatusCode == 200 {
				//解析种子
				err = mi.Parse(resp.Body)
				return mi, err
			} else if resp.StatusCode == 404 {
				err = ErrNotFound
			} else {
				err = errors.New("refuse error")
			}
		}
	}
	return
}

func pretty(v interface{}) {
	b, _ := json.MarshalIndent(v, " ", "  ")
	fmt.Println(string(b))
}
<commit_msg>update 种子库<commit_after>package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
)

//define address
const (
	Xunlei   = "http://bt.box.n0808.com/%s/%s/%s.torrent"
	Torcache = "https://torcache.net/torrent/%s.torrent"
	Itorrent = "http://itorrents.org/torrent/%s.torrent"
)

//define errors
var (
	ErrNotFound = errors.New("not found")
	LibUrls     = []string{
		// "http://www.torrent.org.cn/Home/torrent/download.html?hash=%s",
		// "http://torcache.net/torrent/%s.torrent",
		// "http://torrage.com/torrent/%s.torrent",
		// "http://zoink.it/torrent/%s.torrent",
		// "https://178.73.198.210/torrent/%s.torrent",
		// "http://d1.torrentkittycn.com/?infohash=%s",
		// "http://reflektor.karmorra.info/torrent/%s.torrent",
		"http://itorrents.org/torrent/%s.torrent",
	}
)

//DownloadXunlei torrent
func DownloadXunlei(hash string, client *http.Client) (mi MetaInfo, err error) {
	mi.InfoHash = hash
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}

	//从迅雷种子库查找
	address := fmt.Sprintf(Xunlei, hash[:2], hash[len(hash)-2:], hash)
	req0, err := http.NewRequest("GET", address, nil)
	if err != nil {
		return
	}
	req0.Header.Set("User-Agent", "Mozilla/5.0")
	resp, err := client.Do(req0)
	if err != nil {
		return
	}
	if resp != nil {
		defer func() {
			// io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}()

		if resp.StatusCode == 200 {
			//解析种子
			err = mi.Parse(resp.Body)
		} else if resp.StatusCode == 404 {
			err = ErrNotFound
		} else {
			err = errors.New("refuse error")
		}
	}
	return
}

//DownloadTorrent
func DownloadTorrent(hash string, client *http.Client) (mi MetaInfo, err error) {
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}
	// mi, err = DownloadXunlei(hash, client)
	// //迅雷解析成功，不用再調用後面的種子庫
	// if err == nil {
	// 	return
	// }

	mi.InfoHash = hash
	//將來改用字典實現

	address := fmt.Sprintf(Itorrent, hash)
	req0, err := http.NewRequest("GET", address, nil)
	req0.Header.Set("User-Agent", "Mozilla/5.0")
	if err != nil {
		return
	}
	resp, err := client.Do(req0)
	if err != nil {
		return
	}
	if resp != nil {
		defer func() {
			// io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}()

		if resp.StatusCode == 200 {
			//解析种子
			err = mi.Parse(resp.Body)
			return mi, err
		} else if resp.StatusCode == 404 {
			err = ErrNotFound
		} else {
			err = errors.New("refuse error")
		}
	}
	return
}

func pretty(v interface{}) {
	b, _ := json.MarshalIndent(v, " ", "  ")
	fmt.Println(string(b))
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"os"

	"github.com/ark-lang/ark-go/util"
)

// IMPORTANT NOTE for setTypeHint():
// When implementing this function for an Expr, only set the Expr's Type if
// you are on a lowest-level Expr, ie. a literal. That means, if you Expr
// contains a pointer to another Expr(s), simple pass the type hint along to that
// Expr(s) then return.

type semanticAnalyzer struct {
	file     *File
	function *Function // the function we're in, or nil if we aren't
}

func (v *semanticAnalyzer) err(err string, stuff ...interface{}) {
	/*fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" [%s:%d:%d] %s\n",
	v.peek(0).Filename, v.peek(0).LineNumber, v.peek(0).CharNumber, fmt.Sprintf(err, stuff...))*/
	fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" %s\n",
		fmt.Sprintf(err, stuff...))
	os.Exit(2)
}

func (v *semanticAnalyzer) warn(err string, stuff ...interface{}) {
	/*fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" [%s:%d:%d] %s\n",
	v.peek(0).Filename, v.peek(0).LineNumber, v.peek(0).CharNumber, fmt.Sprintf(err, stuff...))*/
	fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic warning:"+util.TEXT_RESET+" %s\n",
		fmt.Sprintf(err, stuff...))
}

func (v *semanticAnalyzer) analyze() {
	for _, node := range v.file.nodes {
		node.analyze(v)
	}
}

func (v *Block) analyze(s *semanticAnalyzer) {
	for _, n := range v.Nodes {
		n.analyze(s)
	}
}

func (v *VariableDecl) analyze(s *semanticAnalyzer) {
	v.Variable.analyze(s)
	v.Assignment.setTypeHint(v.Variable.Type)
	v.Assignment.analyze(s)
	if v.Variable.Type == nil { // type is inferred
		v.Variable.Type = v.Assignment.GetType()
	} else if v.Variable.Type != v.Assignment.GetType() {
		s.err("Cannot assign expression of type `%s` to variable of type `%s`",
			v.Assignment.GetType().TypeName(), v.Variable.Type.TypeName())
	}
}

func (v *Variable) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid variable attribute key `%s`", attr.Key)
		}
	}
}

func (v *StructDecl) analyze(s *semanticAnalyzer) {
	v.Struct.analyze(s)
}

func (v *StructType) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "packed":
			if attr.Value != "" {
				s.err("Struct attribute `%s` doesn't expect value", attr.Key)
			}
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid struct attribute key `%s`", attr.Key)
		}
	}

	for _, decl := range v.Variables {
		decl.analyze(s)
	}
}

func (v *FunctionDecl) analyze(s *semanticAnalyzer) {
	v.Function.analyze(s)
}

func (v *Function) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid function attribute key `%s`", attr.Key)
		}
	}

	s.function = v
	if v.Body != nil {
		v.Body.analyze(s)
	}
	s.function = nil
}

func (v *semanticAnalyzer) checkDuplicateAttrs(attrs []*Attr) {
	encountered := make(map[string]bool)
	for _, attr := range attrs {
		if encountered[attr.Key] {
			v.err("Duplicate attribute `%s`", attr.Key)
		}
		encountered[attr.Key] = true
	}
}

func (v *ReturnStat) analyze(s *semanticAnalyzer) {
	if s.function == nil {
		s.err("Return statement must be in a function")
	}

	v.Value.setTypeHint(s.function.ReturnType)
	v.Value.analyze(s)
	if v.Value.GetType() != s.function.ReturnType {
		s.err("Cannot return expression of type `%s` from function `%s` of type `%s`",
			v.Value.GetType().TypeName(), s.function.Name, s.function.ReturnType.TypeName())
	}
}
func (v *UnaryExpr) analyze(s *semanticAnalyzer) {
	v.Expr.analyze(s)

	switch v.Op {
	case UNOP_LOG_NOT:
		if v.Expr.GetType() == PRIMITIVE_bool {
			v.Type = PRIMITIVE_bool
		} else {
			s.err("Used logical not on non-bool")
		}
	case UNOP_BIT_NOT:
		if v.Expr.GetType().IsIntegerType() || v.Expr.GetType().IsFloatingType() {
			v.Type = v.Expr.GetType()
		} else {
			s.err("Used bitwise not on non-numeric type")
		}
	case UNOP_ADDRESS:
		v.Type = pointerTo(v.Expr.GetType())
		// TODO make sure v.Expr is a variable! (can't take address of a literal)
	case UNOP_DEREF:
		if ptr, ok := v.Expr.GetType().(PointerType); ok {
			v.Type = ptr.Addressee
		} else {
			s.err("Used dereference operator on non-pointer")
		}
	default:
		panic("whoops")
	}
}

func (v *UnaryExpr) setTypeHint(t Type) {
	switch v.Op {
	case UNOP_LOG_NOT:
		v.Expr.setTypeHint(PRIMITIVE_bool)
	case UNOP_BIT_NOT:
		v.Expr.setTypeHint(t)
	case UNOP_ADDRESS, UNOP_DEREF:
		v.Expr.setTypeHint(nil)
	default:
		panic("whoops")
	}
}

func (v *BinaryExpr) analyze(s *semanticAnalyzer) {
	v.Lhand.analyze(s)
	v.Rhand.analyze(s)

	switch v.Op {
	case BINOP_ADD, BINOP_SUB, BINOP_MUL, BINOP_DIV, BINOP_MOD,
		BINOP_GREATER, BINOP_LESS, BINOP_GREATER_EQ, BINOP_LESS_EQ, BINOP_EQ, BINOP_NOT_EQ,
		BINOP_BIT_AND, BINOP_BIT_OR, BINOP_BIT_XOR:
		if v.Lhand.GetType() != v.Rhand.GetType() {
			s.err("Operands for binary operator `%s` must have the same type, have `%s` and `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName(), v.Rhand.GetType().TypeName())
		} else if lht := v.Lhand.GetType(); !(lht.IsIntegerType() || lht.IsFloatingType() || lht.LevelsOfIndirection() > 0) {
			s.err("Operands for binary operator `%s` must be numeric or pointers, have `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName())
		} else {
			switch v.Op.Category() {
			case OP_ARITHMETIC:
				v.Type = v.Lhand.GetType()
			case OP_COMPARISON:
				v.Type = PRIMITIVE_bool
			default:
				panic("shouldn't happenen ever")
			}
		}

	case BINOP_DOT: // TODO

	case BINOP_BIT_LEFT, BINOP_BIT_RIGHT:
		if lht := v.Lhand.GetType(); !(lht.IsFloatingType() || lht.IsIntegerType() || lht.LevelsOfIndirection() > 0) {
			s.err("Left-hand operand for bitshift operator `%s` must be numeric or a pointer, have `%s`",
				v.Op.OpString(), lht.TypeName())
		} else if !v.Rhand.GetType().IsIntegerType() {
			s.err("Right-hand operatnd for bitshift operator `%s` must be an integer, have `%s`",
				v.Op.OpString(), v.Rhand.GetType().TypeName())
		} else {
			v.Type = lht
		}

	case BINOP_LOG_AND, BINOP_LOG_OR:
		if v.Lhand.GetType() != PRIMITIVE_bool || v.Rhand.GetType() != PRIMITIVE_bool {
			s.err("Operands for logical operator `%s` must have the same type, have `%s` and `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName(), v.Rhand.GetType().TypeName())
		} else {
			v.Type = PRIMITIVE_bool
		}

	case BINOP_ASSIGN:

	default:
		panic("unimplemented bin operation")
	}
}

func (v *BinaryExpr) setTypeHint(t Type) {
	switch v.Op.Category() {
	case OP_ARITHMETIC:
		v.Lhand.setTypeHint(t)
		v.Rhand.setTypeHint(t)
	case OP_COMPARISON:
		v.Lhand.setTypeHint(nil)
		v.Rhand.setTypeHint(nil)
	case OP_BITWISE:
		v.Lhand.setTypeHint(t)
		v.Rhand.setTypeHint(t)
	case OP_LOGICAL:
		v.Lhand.setTypeHint(PRIMITIVE_bool)
		v.Rhand.setTypeHint(PRIMITIVE_bool)
	case OP_ACCESS:
		// TODO
	case OP_ASSIGN:
		// TODO
	default:
		panic("missing opcategory")
	}
}

func (v *IntegerLiteral) analyze(s *semanticAnalyzer) {}

func (v *IntegerLiteral) setTypeHint(t Type) {
	switch t {
	case PRIMITIVE_int, PRIMITIVE_uint,
		PRIMITIVE_i8, PRIMITIVE_i16, PRIMITIVE_i32, PRIMITIVE_i64, PRIMITIVE_i128,
		PRIMITIVE_u8, PRIMITIVE_u16, PRIMITIVE_u32, PRIMITIVE_u64, PRIMITIVE_u128:
		v.Type = t
	default:
		v.Type = PRIMITIVE_int // TODO check overflow
	}
}

func (v *FloatingLiteral) analyze(s *semanticAnalyzer) {}

func (v *FloatingLiteral) setTypeHint(t Type) {
	switch t {
	case PRIMITIVE_f64, PRIMITIVE_f32, PRIMITIVE_f128:
		v.Type = t
	default:
		v.Type = PRIMITIVE_f64
	}
}

func (v *StringLiteral) analyze(s *semanticAnalyzer) {}
func (v *StringLiteral) setTypeHint(t Type)          {}

func (v *RuneLiteral) analyze(s *semanticAnalyzer) {}
func (v *RuneLiteral) setTypeHint(t Type)          {}

func (v *CastExpr) analyze(s *semanticAnalyzer) {
	v.Expr.analyze(s)
	if v.Type == v.Expr.GetType() {
		s.warn("Casting expression of type `%s` to the same type",
			v.Type.TypeName())
	} else if !v.Expr.GetType().CanCastTo(v.Type) {
		s.err("Cannot cast expression of type `%s` to type `%s`",
			v.Expr.GetType().TypeName(), v.Type.TypeName())
	}
}

func (v *CastExpr) setTypeHint(t Type) {
	v.Expr.setTypeHint(nil)
}

func (v *CallExpr) analyze(s *semanticAnalyzer) {
	if len(v.Arguments) != len(v.Function.Parameters) {
		s.err("Call to `%s` expects %d arguments, have %d",
			v.Function.Name, len(v.Function.Parameters), len(v.Arguments))
	}

	for i, arg := range v.Arguments {
		arg.setTypeHint(v.Function.Parameters[i].Variable.Type)
		arg.analyze(s)
	}
}

func (v *CallExpr) setTypeHint(t Type) {}

func (v *CallStat) analyze(s *semanticAnalyzer) {
	v.Call.analyze(s)
}

func (v *CallStat) setTypeHint(t Type) {}
<commit_msg>cleanup semantic.go<commit_after>package parser

import (
	"fmt"
	"os"

	"github.com/ark-lang/ark-go/util"
)

// IMPORTANT NOTE for setTypeHint():
// When implementing this function for an Expr, only set the Expr's Type if
// you are on a lowest-level Expr, ie. a literal. That means, if you Expr
// contains a pointer to another Expr(s), simple pass the type hint along to that
// Expr(s) then return.

type semanticAnalyzer struct {
	file     *File
	function *Function // the function we're in, or nil if we aren't
}

func (v *semanticAnalyzer) err(err string, stuff ...interface{}) {
	/*fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" [%s:%d:%d] %s\n",
	v.peek(0).Filename, v.peek(0).LineNumber, v.peek(0).CharNumber, fmt.Sprintf(err, stuff...))*/
	fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" %s\n",
		fmt.Sprintf(err, stuff...))
	os.Exit(2)
}

func (v *semanticAnalyzer) warn(err string, stuff ...interface{}) {
	/*fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic error:"+util.TEXT_RESET+" [%s:%d:%d] %s\n",
	v.peek(0).Filename, v.peek(0).LineNumber, v.peek(0).CharNumber, fmt.Sprintf(err, stuff...))*/
	fmt.Printf(util.TEXT_RED+util.TEXT_BOLD+"Semantic warning:"+util.TEXT_RESET+" %s\n",
		fmt.Sprintf(err, stuff...))
}

func (v *semanticAnalyzer) checkDuplicateAttrs(attrs []*Attr) {
	encountered := make(map[string]bool)
	for _, attr := range attrs {
		if encountered[attr.Key] {
			v.err("Duplicate attribute `%s`", attr.Key)
		}
		encountered[attr.Key] = true
	}
}

func (v *semanticAnalyzer) analyze() {
	for _, node := range v.file.nodes {
		node.analyze(v)
	}
}

func (v *Block) analyze(s *semanticAnalyzer) {
	for _, n := range v.Nodes {
		n.analyze(s)
	}
}

func (v *Function) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid function attribute key `%s`", attr.Key)
		}
	}

	s.function = v
	if v.Body != nil {
		v.Body.analyze(s)
	}
	s.function = nil
}

func (v *StructType) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "packed":
			if attr.Value != "" {
				s.err("Struct attribute `%s` doesn't expect value", attr.Key)
			}
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid struct attribute key `%s`", attr.Key)
		}
	}

	for _, decl := range v.Variables {
		decl.analyze(s)
	}
}

func (v *Variable) analyze(s *semanticAnalyzer) {
	// make sure there are no illegal attributes
	s.checkDuplicateAttrs(v.Attrs)
	for _, attr := range v.Attrs {
		switch attr.Key {
		case "deprecated":
			// value is optional, nothing to check
		default:
			s.err("Invalid variable attribute key `%s`", attr.Key)
		}
	}
}

/**
 * Declarations
 */

func (v *VariableDecl) analyze(s *semanticAnalyzer) {
	v.Variable.analyze(s)
	v.Assignment.setTypeHint(v.Variable.Type)
	v.Assignment.analyze(s)

	if v.Variable.Type == nil { // type is inferred
		v.Variable.Type = v.Assignment.GetType()
	} else if v.Variable.Type != v.Assignment.GetType() {
		s.err("Cannot assign expression of type `%s` to variable of type `%s`",
			v.Assignment.GetType().TypeName(), v.Variable.Type.TypeName())
	}
}

func (v *StructDecl) analyze(s *semanticAnalyzer) {
	v.Struct.analyze(s)
}

func (v *FunctionDecl) analyze(s *semanticAnalyzer) {
	v.Function.analyze(s)
}

/*
 * Statements
 */

func (v *ReturnStat) analyze(s *semanticAnalyzer) {
	if s.function == nil {
		s.err("Return statement must be in a function")
	}

	v.Value.setTypeHint(s.function.ReturnType)
	v.Value.analyze(s)
	if v.Value.GetType() != s.function.ReturnType {
		s.err("Cannot return expression of type `%s` from function `%s` of type `%s`",
			v.Value.GetType().TypeName(), s.function.Name, s.function.ReturnType.TypeName())
	}
}

func (v *CallStat) analyze(s *semanticAnalyzer) {
	v.Call.analyze(s)
}

/*
 * Expressions
 */

// UnaryExpr

func (v *UnaryExpr) analyze(s *semanticAnalyzer) {
	v.Expr.analyze(s)

	switch v.Op {
	case UNOP_LOG_NOT:
		if v.Expr.GetType() == PRIMITIVE_bool {
			v.Type = PRIMITIVE_bool
		} else {
			s.err("Used logical not on non-bool")
		}
	case UNOP_BIT_NOT:
		if v.Expr.GetType().IsIntegerType() || v.Expr.GetType().IsFloatingType() {
			v.Type = v.Expr.GetType()
		} else {
			s.err("Used bitwise not on non-numeric type")
		}
	case UNOP_ADDRESS:
		v.Type = pointerTo(v.Expr.GetType())
		// TODO make sure v.Expr is a variable! (can't take address of a literal)
	case UNOP_DEREF:
		if ptr, ok := v.Expr.GetType().(PointerType); ok {
			v.Type = ptr.Addressee
		} else {
			s.err("Used dereference operator on non-pointer")
		}
	default:
		panic("whoops")
	}
}

func (v *UnaryExpr) setTypeHint(t Type) {
	switch v.Op {
	case UNOP_LOG_NOT:
		v.Expr.setTypeHint(PRIMITIVE_bool)
	case UNOP_BIT_NOT:
		v.Expr.setTypeHint(t)
	case UNOP_ADDRESS, UNOP_DEREF:
		v.Expr.setTypeHint(nil)
	default:
		panic("whoops")
	}
}

// BinaryExpr

func (v *BinaryExpr) analyze(s *semanticAnalyzer) {
	v.Lhand.analyze(s)
	v.Rhand.analyze(s)

	switch v.Op {
	case BINOP_ADD, BINOP_SUB, BINOP_MUL, BINOP_DIV, BINOP_MOD,
		BINOP_GREATER, BINOP_LESS, BINOP_GREATER_EQ, BINOP_LESS_EQ, BINOP_EQ, BINOP_NOT_EQ,
		BINOP_BIT_AND, BINOP_BIT_OR, BINOP_BIT_XOR:
		if v.Lhand.GetType() != v.Rhand.GetType() {
			s.err("Operands for binary operator `%s` must have the same type, have `%s` and `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName(), v.Rhand.GetType().TypeName())
		} else if lht := v.Lhand.GetType(); !(lht.IsIntegerType() || lht.IsFloatingType() || lht.LevelsOfIndirection() > 0) {
			s.err("Operands for binary operator `%s` must be numeric or pointers, have `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName())
		} else {
			switch v.Op.Category() {
			case OP_ARITHMETIC:
				v.Type = v.Lhand.GetType()
			case OP_COMPARISON:
				v.Type = PRIMITIVE_bool
			default:
				panic("shouldn't happenen ever")
			}
		}

	case BINOP_DOT: // TODO

	case BINOP_BIT_LEFT, BINOP_BIT_RIGHT:
		if lht := v.Lhand.GetType(); !(lht.IsFloatingType() || lht.IsIntegerType() || lht.LevelsOfIndirection() > 0) {
			s.err("Left-hand operand for bitshift operator `%s` must be numeric or a pointer, have `%s`",
				v.Op.OpString(), lht.TypeName())
		} else if !v.Rhand.GetType().IsIntegerType() {
			s.err("Right-hand operatnd for bitshift operator `%s` must be an integer, have `%s`",
				v.Op.OpString(), v.Rhand.GetType().TypeName())
		} else {
			v.Type = lht
		}

	case BINOP_LOG_AND, BINOP_LOG_OR:
		if v.Lhand.GetType() != PRIMITIVE_bool || v.Rhand.GetType() != PRIMITIVE_bool {
			s.err("Operands for logical operator `%s` must have the same type, have `%s` and `%s`",
				v.Op.OpString(), v.Lhand.GetType().TypeName(), v.Rhand.GetType().TypeName())
		} else {
			v.Type = PRIMITIVE_bool
		}

	case BINOP_ASSIGN:

	default:
		panic("unimplemented bin operation")
	}
}

func (v *BinaryExpr) setTypeHint(t Type) {
	switch v.Op.Category() {
	case OP_ARITHMETIC:
		v.Lhand.setTypeHint(t)
		v.Rhand.setTypeHint(t)
	case OP_COMPARISON:
		v.Lhand.setTypeHint(nil)
		v.Rhand.setTypeHint(nil)
	case OP_BITWISE:
		v.Lhand.setTypeHint(t)
		v.Rhand.setTypeHint(t)
	case OP_LOGICAL:
		v.Lhand.setTypeHint(PRIMITIVE_bool)
		v.Rhand.setTypeHint(PRIMITIVE_bool)
	case OP_ACCESS:
		// TODO
	case OP_ASSIGN:
		// TODO
	default:
		panic("missing opcategory")
	}
}

// IntegerLiteral

func (v *IntegerLiteral) analyze(s *semanticAnalyzer) {}

func (v *IntegerLiteral) setTypeHint(t Type) {
	switch t {
	case PRIMITIVE_int, PRIMITIVE_uint,
		PRIMITIVE_i8, PRIMITIVE_i16, PRIMITIVE_i32, PRIMITIVE_i64, PRIMITIVE_i128,
		PRIMITIVE_u8, PRIMITIVE_u16, PRIMITIVE_u32, PRIMITIVE_u64, PRIMITIVE_u128:
		v.Type = t
	default:
		v.Type = PRIMITIVE_int // TODO check overflow
	}
}

// FloatingLiteral

func (v *FloatingLiteral) analyze(s *semanticAnalyzer) {}

func (v *FloatingLiteral) setTypeHint(t Type) {
	switch t {
	case PRIMITIVE_f64, PRIMITIVE_f32, PRIMITIVE_f128:
		v.Type = t
	default:
		v.Type = PRIMITIVE_f64
	}
}

// StringLiteral

func (v *StringLiteral) analyze(s *semanticAnalyzer) {}
func (v *StringLiteral) setTypeHint(t Type)          {}

// RuneLiteral

func (v *RuneLiteral) analyze(s *semanticAnalyzer) {}
func (v *RuneLiteral) setTypeHint(t Type)          {}

// CastExpr

func (v *CastExpr) analyze(s *semanticAnalyzer) {
	v.Expr.analyze(s)
	if v.Type == v.Expr.GetType() {
		s.warn("Casting expression of type `%s` to the same type",
			v.Type.TypeName())
	} else if !v.Expr.GetType().CanCastTo(v.Type) {
		s.err("Cannot cast expression of type `%s` to type `%s`",
			v.Expr.GetType().TypeName(), v.Type.TypeName())
	}
}

func (v *CastExpr) setTypeHint(t Type) {
	v.Expr.setTypeHint(nil)
}

// CallExpr

func (v *CallExpr) analyze(s *semanticAnalyzer) {
	if len(v.Arguments) != len(v.Function.Parameters) {
		s.err("Call to `%s` expects %d arguments, have %d",
			v.Function.Name, len(v.Function.Parameters), len(v.Arguments))
	}

	for i, arg := range v.Arguments {
		arg.setTypeHint(v.Function.Parameters[i].Variable.Type)
		arg.analyze(s)
	}
}

func (v *CallExpr) setTypeHint(t Type) {}
<|endoftext|>


<commit_before>package steam

import (
	"encoding/json"
	"net/http"
	"strconv"
)

type upToDateCheckResponse struct {
	Response *UpToDateCheckResponse `json:"response"`
}

type UpToDateCheckResponse struct {
	Success           bool   `json:"success"`
	UpToDate          bool   `json:"up_to_date"`
	VersionIsListable bool   `json:"version_is_listable"`
	Message           string `json:"message"`
}

func UpToDateCheck(appid, version int) (*UpToDateCheckResponse, error) {
	url := "http://api.steampowered.com/ISteamApps/UpToDateCheck/v0001/?appid=" + strconv.Itoa(appid) + "&version=" + strconv.Itoa(version)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	var utdcResp upToDateCheckResponse
	dec := json.NewDecoder(resp.Body)
	dec.Decode(&utdcResp)
	return utdcResp.Response, nil
}
<commit_msg>Add UpToDateCheck.RequiredVersion field<commit_after>package steam

import (
	"encoding/json"
	"net/http"
	"strconv"
)

type upToDateCheckResponse struct {
	Response *UpToDateCheckResponse `json:"response"`
}

type UpToDateCheckResponse struct {
	Success           bool   `json:"success"`
	UpToDate          bool   `json:"up_to_date"`
	RequiredVersion   int    `json:"required_version"`
	VersionIsListable bool   `json:"version_is_listable"`
	Message           string `json:"message"`
}

func UpToDateCheck(appid, version int) (*UpToDateCheckResponse, error) {
	// http://api.steampowered.com/ISteamApps/UpToDateCheck/v0001/?appid=570&version=36
	url := "http://api.steampowered.com/ISteamApps/UpToDateCheck/v0001/?appid=" + strconv.Itoa(appid) + "&version=" + strconv.Itoa(version)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	var utdcResp upToDateCheckResponse
	dec := json.NewDecoder(resp.Body)
	dec.Decode(&utdcResp)
	return utdcResp.Response, nil
}
<|endoftext|>


<commit_before>// PLAYER OBJECT STRUCT AND METHODS
package main

import (
	"io"
	"os/exec"
	"syscall"
)

var command_list = map[string]string{"pause": "p", "up": "\x1b[A", "down": "\x1b[B", "left": "\x1b[D", "right": "\x1b[C"}

type Player struct {
	Playing  bool
	Paused   string
	FilmName string
	Film     *exec.Cmd
	PipeIn   io.WriteCloser
}

func (p *Player) StartFilm(name string) error {
	var err error
	p.FilmName = name
	p.Paused = "Pause"
	p.Playing = true
	p.Film = exec.Command("omxplayer", "-o", "hdmi", name)
	p.Film.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	p.PipeIn, err = p.Film.StdinPipe()
	if err == nil {
		err = p.Film.Start()
	}
	return err
}

func (p *Player) PauseFilm() {
	if p.Paused == "Pause" {
		p.Paused = "Play"
	} else {
		p.Paused = "Pause"
	}
}

func (p *Player) EndFilm() error {
	pgid, err := syscall.Getpgid(p.Film.Process.Pid)
	if err == nil {
		syscall.Kill(-pgid, 15)
		p.FilmName = ""
		pageData.CurrentFilm = ""
		p.Playing = false
	} else {
		return err
	}
}

func (p *Player) SendCommandToFilm(command string) error {
	if command == "pause" {
		p.PauseFilm()
	}
	_, err := p.PipeIn.Write([]byte(command_list[command]))
	return err
}
<commit_msg>ensured there is always return in EndFilm() function<commit_after>// PLAYER OBJECT STRUCT AND METHODS
package main

import (
	"io"
	"os/exec"
	"syscall"
)

var command_list = map[string]string{"pause": "p", "up": "\x1b[A", "down": "\x1b[B", "left": "\x1b[D", "right": "\x1b[C"}

type Player struct {
	Playing  bool
	Paused   string
	FilmName string
	Film     *exec.Cmd
	PipeIn   io.WriteCloser
}

func (p *Player) StartFilm(name string) error {
	var err error
	p.FilmName = name
	p.Paused = "Pause"
	p.Playing = true
	p.Film = exec.Command("omxplayer", "-o", "hdmi", name)
	p.Film.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	p.PipeIn, err = p.Film.StdinPipe()
	if err == nil {
		err = p.Film.Start()
	}
	return err
}

func (p *Player) PauseFilm() {
	if p.Paused == "Pause" {
		p.Paused = "Play"
	} else {
		p.Paused = "Pause"
	}
}

func (p *Player) EndFilm() error {
	pgid, err := syscall.Getpgid(p.Film.Process.Pid)
	if err == nil {
		syscall.Kill(-pgid, 15)
		p.FilmName = ""
		pageData.CurrentFilm = ""
		p.Playing = false
	}
	return err
}

func (p *Player) SendCommandToFilm(command string) error {
	if command == "pause" {
		p.PauseFilm()
	}
	_, err := p.PipeIn.Write([]byte(command_list[command]))
	return err
}
<|endoftext|>


<commit_before>package vollocal

import (
	"bufio"
	"encoding/json"
	"fmt"
	"path"
	"strings"

	"net/url"

	"code.cloudfoundry.org/goshims/osshim"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/voldriver"
	"code.cloudfoundry.org/voldriver/driverhttp"
)

//go:generate counterfeiter -o ../volmanfakes/fake_driver_factory.go . DriverFactory

// DriverFactories are responsible for instantiating remote client implementations of the voldriver.Driver interface.
type DriverFactory interface {
	// Given a driver id, path and config filename returns a remote client implementation of the voldriver.Driver interface
	Driver(logger lager.Logger, driverId string, driverPath, driverFileName string, existing map[string]voldriver.Driver) (voldriver.Driver, error)
}

type realDriverFactory struct {
	Factory         driverhttp.RemoteClientFactory
	useOs           osshim.Os
	DriversRegistry map[string]voldriver.Driver
}

func NewDriverFactory() DriverFactory {
	remoteClientFactory := driverhttp.NewRemoteClientFactory()
	return NewDriverFactoryWithRemoteClientFactory(remoteClientFactory)
}

func NewDriverFactoryWithRemoteClientFactory(remoteClientFactory driverhttp.RemoteClientFactory) DriverFactory {
	return &realDriverFactory{remoteClientFactory, &osshim.OsShim{}, nil}
}

func NewDriverFactoryWithOs(useOs osshim.Os) DriverFactory {
	remoteClientFactory := driverhttp.NewRemoteClientFactory()
	return &realDriverFactory{remoteClientFactory, useOs, nil}
}

func (r *realDriverFactory) Driver(logger lager.Logger, driverId string, driverPath string, driverFileName string, existing map[string]voldriver.Driver) (voldriver.Driver, error) {
	logger = logger.Session("driver", lager.Data{"driverId": driverId, "driverFileName": driverFileName})
	logger.Info("start")
	defer logger.Info("end")

	var driver voldriver.Driver

	var address string
	var tls *voldriver.TLSConfig
	if strings.Contains(driverFileName, ".") {
		extension := strings.Split(driverFileName, ".")[1]
		switch extension {
		case "sock":
			address = path.Join(driverPath, driverFileName)
		case "spec":
			configFile, err := r.useOs.Open(path.Join(driverPath, driverFileName))
			if err != nil {
				logger.Error(fmt.Sprintf("error-opening-config-%s", driverFileName), err)
				return nil, err
			}
			reader := bufio.NewReader(configFile)
			addressBytes, _, err := reader.ReadLine()
			if err != nil { // no real value in faking this as bigger problems exist when this fails
				logger.Error(fmt.Sprintf("error-reading-%s", driverFileName), err)
				return nil, err
			}
			address = string(addressBytes)
		case "json":
			// extract url from json file
			var driverJsonSpec voldriver.DriverSpec
			configFile, err := r.useOs.Open(path.Join(driverPath, driverFileName))
			if err != nil {
				logger.Error(fmt.Sprintf("error-opening-config-%s", driverFileName), err)
				return nil, err
			}
			jsonParser := json.NewDecoder(configFile)
			if err = jsonParser.Decode(&driverJsonSpec); err != nil {
				logger.Error("parsing-config-file-error", err)
				return nil, err
			}
			address = driverJsonSpec.Address
			tls = driverJsonSpec.TLSConfig
		default:
			err := fmt.Errorf("unknown-driver-extension: %s", extension)
			logger.Error("driver", err)
			return nil, err

		}
		var err error

		address, err = r.canonicalize(logger, address)
		if err != nil {
			logger.Error(fmt.Sprintf("invalid-address: %s", address), err)
			return nil, err
		}

		logger.Info("checking-existing-drivers")
		var ok bool
		driver, ok = existing[driverId]
		if ok {
			matchable, ok := driver.(voldriver.MatchableDriver)
			if !ok || !matchable.Matches(logger, address, tls) {
				driver = nil
			}
			logger.Info("existing-driver-matches")
		}

		if driver == nil {
			logger.Info("getting-driver", lager.Data{"address": address})
			driver, err = r.Factory.NewRemoteClient(address, tls)
			if err != nil {
				logger.Error(fmt.Sprintf("error-building-driver-attached-to-%s", address), err)
				return nil, err
			}
		}

		return driver, nil
	}

	return nil, fmt.Errorf("Driver '%s' not found in list of known drivers", driverId)
}

func (r *realDriverFactory) canonicalize(logger lager.Logger, address string) (string, error) {
	logger = logger.Session("canonicalize", lager.Data{"address": address})
	logger.Debug("start")
	defer logger.Debug("end")

	url, err := url.Parse(address)
	if err != nil {
		return address, err
	}

	switch url.Scheme {
	case "http", "https":
		return address, nil
	case "tcp":
		return fmt.Sprintf("http://%s%s", url.Host, url.Path), nil
	case "unix":
		return address, nil
	default:
		if strings.HasSuffix(url.Path, ".sock") {
			return fmt.Sprintf("%s%s", url.Host, url.Path), nil
		}
	}
	return fmt.Sprintf("http://%s", address), nil
}

func driverImplements(protocol string, activateResponseProtocols []string) bool {
	for _, nextProtocol := range activateResponseProtocols {
		if protocol == nextProtocol {
			return true
		}
	}
	return false
}
<commit_msg>additional logging messages [#137800871](https://www.pivotaltracker.com/story/show/137800871)<commit_after>package vollocal

import (
	"bufio"
	"encoding/json"
	"fmt"
	"path"
	"strings"

	"net/url"

	"code.cloudfoundry.org/goshims/osshim"
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/voldriver"
	"code.cloudfoundry.org/voldriver/driverhttp"
)

//go:generate counterfeiter -o ../volmanfakes/fake_driver_factory.go . DriverFactory

// DriverFactories are responsible for instantiating remote client implementations of the voldriver.Driver interface.
type DriverFactory interface {
	// Given a driver id, path and config filename returns a remote client implementation of the voldriver.Driver interface
	Driver(logger lager.Logger, driverId string, driverPath, driverFileName string, existing map[string]voldriver.Driver) (voldriver.Driver, error)
}

type realDriverFactory struct {
	Factory         driverhttp.RemoteClientFactory
	useOs           osshim.Os
	DriversRegistry map[string]voldriver.Driver
}

func NewDriverFactory() DriverFactory {
	remoteClientFactory := driverhttp.NewRemoteClientFactory()
	return NewDriverFactoryWithRemoteClientFactory(remoteClientFactory)
}

func NewDriverFactoryWithRemoteClientFactory(remoteClientFactory driverhttp.RemoteClientFactory) DriverFactory {
	return &realDriverFactory{remoteClientFactory, &osshim.OsShim{}, nil}
}

func NewDriverFactoryWithOs(useOs osshim.Os) DriverFactory {
	remoteClientFactory := driverhttp.NewRemoteClientFactory()
	return &realDriverFactory{remoteClientFactory, useOs, nil}
}

func (r *realDriverFactory) Driver(logger lager.Logger, driverId string, driverPath string, driverFileName string, existing map[string]voldriver.Driver) (voldriver.Driver, error) {
	logger = logger.Session("driver", lager.Data{"driverId": driverId, "driverFileName": driverFileName})
	logger.Info("start")
	defer logger.Info("end")

	var driver voldriver.Driver

	var address string
	var tls *voldriver.TLSConfig
	if strings.Contains(driverFileName, ".") {
		extension := strings.Split(driverFileName, ".")[1]
		switch extension {
		case "sock":
			address = path.Join(driverPath, driverFileName)
		case "spec":
			configFile, err := r.useOs.Open(path.Join(driverPath, driverFileName))
			if err != nil {
				logger.Error(fmt.Sprintf("error-opening-config-%s", driverFileName), err)
				return nil, err
			}
			reader := bufio.NewReader(configFile)
			addressBytes, _, err := reader.ReadLine()
			if err != nil { // no real value in faking this as bigger problems exist when this fails
				logger.Error(fmt.Sprintf("error-reading-%s", driverFileName), err)
				return nil, err
			}
			address = string(addressBytes)
		case "json":
			// extract url from json file
			var driverJsonSpec voldriver.DriverSpec
			configFile, err := r.useOs.Open(path.Join(driverPath, driverFileName))
			if err != nil {
				logger.Error(fmt.Sprintf("error-opening-config-%s", driverFileName), err)
				return nil, err
			}
			jsonParser := json.NewDecoder(configFile)
			if err = jsonParser.Decode(&driverJsonSpec); err != nil {
				logger.Error("parsing-config-file-error", err)
				return nil, err
			}
			address = driverJsonSpec.Address
			tls = driverJsonSpec.TLSConfig
		default:
			err := fmt.Errorf("unknown-driver-extension: %s", extension)
			logger.Error("driver", err)
			return nil, err

		}
		var err error

		address, err = r.canonicalize(logger, address)
		if err != nil {
			logger.Error(fmt.Sprintf("invalid-address: %s", address), err)
			return nil, err
		}

		logger.Info("checking-existing-drivers", lager.Data{"driverId": driverId})
		var ok bool
		driver, ok = existing[driverId]
		if ok {
			logger.Info("existing-driver-found", lager.Data{"driverId": driverId})
			matchable, ok := driver.(voldriver.MatchableDriver)
			if !ok || !matchable.Matches(logger, address, tls) {
				logger.Info("existing-driver-mismatch", lager.Data{"driverId": driverId, "address": address, "tls": tls})
				driver = nil
			}
			logger.Info("existing-driver-matches", lager.Data{"driverId": driverId})
		}

		if driver == nil {
			logger.Info("getting-driver", lager.Data{"address": address})
			driver, err = r.Factory.NewRemoteClient(address, tls)
			if err != nil {
				logger.Error(fmt.Sprintf("error-building-driver-attached-to-%s", address), err)
				return nil, err
			}
		}

		return driver, nil
	}

	return nil, fmt.Errorf("Driver '%s' not found in list of known drivers", driverId)
}

func (r *realDriverFactory) canonicalize(logger lager.Logger, address string) (string, error) {
	logger = logger.Session("canonicalize", lager.Data{"address": address})
	logger.Debug("start")
	defer logger.Debug("end")

	url, err := url.Parse(address)
	if err != nil {
		return address, err
	}

	switch url.Scheme {
	case "http", "https":
		return address, nil
	case "tcp":
		return fmt.Sprintf("http://%s%s", url.Host, url.Path), nil
	case "unix":
		return address, nil
	default:
		if strings.HasSuffix(url.Path, ".sock") {
			return fmt.Sprintf("%s%s", url.Host, url.Path), nil
		}
	}
	return fmt.Sprintf("http://%s", address), nil
}

func driverImplements(protocol string, activateResponseProtocols []string) bool {
	for _, nextProtocol := range activateResponseProtocols {
		if protocol == nextProtocol {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package opentsdb

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type Logger interface {
	Debug(i ...interface{})
}

type DefaultLogger struct {
}

func (logger *DefaultLogger) Debug(i ...interface{}) {
	return
}

var logger Logger

func init() {
	logger = &DefaultLogger{}
}

// OpenTSDB request parameters.
type RequestParams struct {
	Host    string                 // Host to query.
	Start   string                 // Time point when to start query.
	End     string                 // Time point to end query (optional).
	Metrics []*MetricConfiguration // Configuration of the metrics to request.
}

// OpenTSDB metric query parameters and configuration for result
// interpration.
type MetricConfiguration struct {
	Unit      string                // TODO: required?
	Filter    func(float64) float64 // Function used to map metric values.
	Aggregate string                // Aggregation of matching metrics
	Rate      string                // Mark metric as rate or downsample.
	Metric    string                // Metric to query for.
	TagFilter string                // Filter on tags (comma separated string with <tag>=<value> pairs.
}

// Mapping from the metric identifier to the according configuration
// used to parse and handle the results.
type MetricConfigurations map[string]*MetricConfiguration

// Parse a single line of the result returned by OpenTSDB in ASCII mode.
func parseLogEventLine(line string, mCfg MetricConfigurations) (*MetricValue, error) {
	parts := strings.SplitN(line, " ", 4)
	if len(parts) != 4 {
		logger.Debug("failed to parse line:", line)
		return nil, errors.New("failed to parse line")
	}

	key, tags := parts[0], parts[3]

	timestamp, err := strconv.ParseInt(parts[1], 10, 64)
	if err != nil {
		logger.Debug("failed to parse timestamp:", parts[1])
		return nil, err
	}

	value, err := strconv.ParseFloat(parts[2], 64)
	if err != nil {
		logger.Debug("failed to parse value:", parts[2])
		return nil, err
	}

	if mCfg[key].Filter != nil {
		value = mCfg[key].Filter(value)
	}

	return &MetricValue{
		Key:   key,
		Value: value,
		Time:  time.Unix(timestamp, 0),
		Tags:  tags,
	}, nil
}

// Parse the content of the ASCII based OpenTSDB response.
func parseResponse(content io.ReadCloser, mCfg MetricConfigurations) (MetricsTree, error) {
	scanner := bufio.NewScanner(content)
	mt := NewMetricsTree()
	for scanner.Scan() {
		if mv, e := parseLogEventLine(scanner.Text(), mCfg); e == nil {
			if e = mt.AddMetricValue(mv); e != nil {
				return nil, e
			}
		} else {
			return nil, e
		}
	}
	return mt, nil
}

func createQueryURL(attrs *RequestParams) string {
	values := url.Values{}
	values.Add("start", attrs.Start)
	if attrs.End != "" {
		values.Add("end", attrs.End)
	}

	for _, m := range attrs.Metrics {
		metric := m.Aggregate
		if m.Rate != "" {
			metric += ":" + m.Rate
		}
		metric += ":" + m.Metric
		metric += "{" + m.TagFilter + "}"
		values.Add("m", metric)
	}

	return "http://" + attrs.Host + ":4242/q?ascii&" + values.Encode()
}

func createMetricConfigurations(attrs *RequestParams) (MetricConfigurations, error) {
	mCfg := make(MetricConfigurations)

	for _, m := range attrs.Metrics {
		if _, ok := mCfg[m.Metric]; ok {
			return nil, errors.New("Each metric only allowed once!")
		}
		mCfg[m.Metric] = m
	}
	return mCfg, nil
}

// Request data from OpenTSDB in ASCII format.
func GetData(attrs *RequestParams) (MetricsTree, error) {
	url := createQueryURL(attrs)
	logger.Debug("Request URL is ", url)

	mCfg, err := createMetricConfigurations(attrs)
	if err != nil {
		return nil, err
	}

	logger.Debug("Starting request to OpenTSDB: " + url)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		b, _ := ioutil.ReadAll(resp.Body)
		return nil, errors.New(fmt.Sprintf("Request to OpenTSDB failed with %s (%s)", resp.Status, string(b)))
	}
	logger.Debug("Finished request to OpenTSDB")

	logger.Debug("Starting to parse the response from OpenTSDB")
	mt, e := parseResponse(resp.Body, mCfg)
	logger.Debug("Finsihed parsing the response from OpenTSDB")

	return mt, e
}
<commit_msg>add method to set opentsdb logger<commit_after>package opentsdb

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type Logger interface {
	Debug(i ...interface{})
}

type DefaultLogger struct {
}

func (logger *DefaultLogger) Debug(i ...interface{}) {
	return
}

func SetLogger(newLogger Logger) {
	logger = newLogger
}

var logger Logger

func init() {
	logger = &DefaultLogger{}
}

// OpenTSDB request parameters.
type RequestParams struct {
	Host    string                 // Host to query.
	Start   string                 // Time point when to start query.
	End     string                 // Time point to end query (optional).
	Metrics []*MetricConfiguration // Configuration of the metrics to request.
}

// OpenTSDB metric query parameters and configuration for result
// interpration.
type MetricConfiguration struct {
	Unit      string                // TODO: required?
	Filter    func(float64) float64 // Function used to map metric values.
	Aggregate string                // Aggregation of matching metrics
	Rate      string                // Mark metric as rate or downsample.
	Metric    string                // Metric to query for.
	TagFilter string                // Filter on tags (comma separated string with <tag>=<value> pairs.
}

// Mapping from the metric identifier to the according configuration
// used to parse and handle the results.
type MetricConfigurations map[string]*MetricConfiguration

// Parse a single line of the result returned by OpenTSDB in ASCII mode.
func parseLogEventLine(line string, mCfg MetricConfigurations) (*MetricValue, error) {
	parts := strings.SplitN(line, " ", 4)
	if len(parts) != 4 {
		logger.Debug("failed to parse line:", line)
		return nil, errors.New("failed to parse line")
	}

	key, tags := parts[0], parts[3]

	timestamp, err := strconv.ParseInt(parts[1], 10, 64)
	if err != nil {
		logger.Debug("failed to parse timestamp:", parts[1])
		return nil, err
	}

	value, err := strconv.ParseFloat(parts[2], 64)
	if err != nil {
		logger.Debug("failed to parse value:", parts[2])
		return nil, err
	}

	if mCfg[key].Filter != nil {
		value = mCfg[key].Filter(value)
	}

	return &MetricValue{
		Key:   key,
		Value: value,
		Time:  time.Unix(timestamp, 0),
		Tags:  tags,
	}, nil
}

// Parse the content of the ASCII based OpenTSDB response.
func parseResponse(content io.ReadCloser, mCfg MetricConfigurations) (MetricsTree, error) {
	scanner := bufio.NewScanner(content)
	mt := NewMetricsTree()
	for scanner.Scan() {
		if mv, e := parseLogEventLine(scanner.Text(), mCfg); e == nil {
			if e = mt.AddMetricValue(mv); e != nil {
				return nil, e
			}
		} else {
			return nil, e
		}
	}
	return mt, nil
}

func createQueryURL(attrs *RequestParams) string {
	values := url.Values{}
	values.Add("start", attrs.Start)
	if attrs.End != "" {
		values.Add("end", attrs.End)
	}

	for _, m := range attrs.Metrics {
		metric := m.Aggregate
		if m.Rate != "" {
			metric += ":" + m.Rate
		}
		metric += ":" + m.Metric
		metric += "{" + m.TagFilter + "}"
		values.Add("m", metric)
	}

	return "http://" + attrs.Host + ":4242/q?ascii&" + values.Encode()
}

func createMetricConfigurations(attrs *RequestParams) (MetricConfigurations, error) {
	mCfg := make(MetricConfigurations)

	for _, m := range attrs.Metrics {
		if _, ok := mCfg[m.Metric]; ok {
			return nil, errors.New("Each metric only allowed once!")
		}
		mCfg[m.Metric] = m
	}
	return mCfg, nil
}

// Request data from OpenTSDB in ASCII format.
func GetData(attrs *RequestParams) (MetricsTree, error) {
	url := createQueryURL(attrs)
	logger.Debug("Request URL is ", url)

	mCfg, err := createMetricConfigurations(attrs)
	if err != nil {
		return nil, err
	}

	logger.Debug("Starting request to OpenTSDB: " + url)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		b, _ := ioutil.ReadAll(resp.Body)
		return nil, errors.New(fmt.Sprintf("Request to OpenTSDB failed with %s (%s)", resp.Status, string(b)))
	}
	logger.Debug("Finished request to OpenTSDB")

	logger.Debug("Starting to parse the response from OpenTSDB")
	mt, e := parseResponse(resp.Body, mCfg)
	logger.Debug("Finsihed parsing the response from OpenTSDB")

	return mt, e
}
<|endoftext|>


<commit_before>package variantproxy

import (
	"crypto/tls"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/foomo/variant-balancer/config"
)

// Node of a variant
type Node struct {
	Server            string
	URL               *url.URL
	SessionCookieName string
	ID                string
	openConnections   int
	maxConnections    int
	Hits              int64
	ReverseProxy      *httputil.ReverseProxy
	channelOpenConn   chan int
	channelCloseConn  chan int
	user              string
	password          string
}

var CloseIdleProxyTransportConnectionsAfter = time.Second * 60

func NewNode(nodeConfig *config.Node) *Node {
	url, err := url.Parse(nodeConfig.Server)
	if err != nil {
		panic(err)
	}
	reverseProxy := httputil.NewSingleHostReverseProxy(url)
	if nodeConfig.InsecureSkipVerify {
		reverseProxy.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	}
	password := ""
	user := ""
	if url.User != nil {
		password, _ = url.User.Password()
		if len(password) > 0 {
			user = url.User.Username()
		}
	}
	n := &Node{
		Server:            nodeConfig.Server,
		URL:               url,
		Hits:              0,
		ID:                nodeConfig.Id,
		ReverseProxy:      reverseProxy,
		SessionCookieName: nodeConfig.Cookie,
		openConnections:   0,
		maxConnections:    nodeConfig.MaxConnections,
		channelOpenConn:   make(chan int),
		channelCloseConn:  make(chan int),
		user:              user,
		password:          password,
	}
	go func() {
		debugConn := func(msg string) {
			if Debug {
				debug(msg, n.ID, "================================> open", n.openConnections, "hits", n.Hits, "load", n.Load())
			}
		}
		for {
			select {
			case <-time.After(CloseIdleProxyTransportConnectionsAfter):
				// idle connection maintenance
				// this should become obsolete:
				// https://github.com/golang/go/issues/6785 and others ...
				proxyTransport := n.ReverseProxy.Transport.(*http.Transport)
				if proxyTransport != nil {
					debugConn("closing idle connections")
					proxyTransport.CloseIdleConnections()
				} else {
					debugConn("can not close idle connections")
				}
			case <-n.channelCloseConn:
				debugConn("node close conn")
				n.openConnections--
			case <-n.channelOpenConn:
				n.Hits++
				n.openConnections++
				debugConn("node open conn")
			}
		}
	}()
	return n
}

// Load calculate current load
func (n *Node) Load() float64 {
	if n.openConnections > 0 {
		l := float64(n.openConnections) / float64(n.maxConnections)
		return l
	}
	return 0.0
}

func (n *Node) closeConn() {
	n.channelCloseConn <- 1
}

func (n *Node) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
	n.channelOpenConn <- 1
	defer func() {
		if err := recover(); err != nil {
			n.closeConn()
		}
	}()
	if len(n.user) > 0 && incomingRequest.URL.User == nil {
		incomingRequest.SetBasicAuth(n.user, n.password)
	}
	n.ReverseProxy.ServeHTTP(w, incomingRequest)
	n.closeConn()
}
<commit_msg>copied http.DefaultTransport, when using the InsecureSkipVerify option<commit_after>package variantproxy

import (
	"crypto/tls"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/foomo/variant-balancer/config"
)

// Node of a variant
type Node struct {
	Server            string
	URL               *url.URL
	SessionCookieName string
	ID                string
	openConnections   int
	maxConnections    int
	Hits              int64
	ReverseProxy      *httputil.ReverseProxy
	channelOpenConn   chan int
	channelCloseConn  chan int
	user              string
	password          string
}

var CloseIdleProxyTransportConnectionsAfter = time.Second * 60

func NewNode(nodeConfig *config.Node) *Node {
	url, err := url.Parse(nodeConfig.Server)
	if err != nil {
		panic(err)
	}
	reverseProxy := httputil.NewSingleHostReverseProxy(url)
	if nodeConfig.InsecureSkipVerify {
		// unfourtunately there is no method to construct a default transport in the net/http package
		// there this is a copy of http.DefaultTransport
		myDefaultTransportInstance := &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).DialContext,
			MaxIdleConns:          100,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
		}
		// our magnificent change
		myDefaultTransportInstance.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
		reverseProxy.Transport = myDefaultTransportInstance
	}
	password := ""
	user := ""
	if url.User != nil {
		password, _ = url.User.Password()
		if len(password) > 0 {
			user = url.User.Username()
		}
	}
	n := &Node{
		Server:            nodeConfig.Server,
		URL:               url,
		Hits:              0,
		ID:                nodeConfig.Id,
		ReverseProxy:      reverseProxy,
		SessionCookieName: nodeConfig.Cookie,
		openConnections:   0,
		maxConnections:    nodeConfig.MaxConnections,
		channelOpenConn:   make(chan int),
		channelCloseConn:  make(chan int),
		user:              user,
		password:          password,
	}
	go func() {
		debugConn := func(msg string) {
			if Debug {
				debug(msg, n.ID, "================================> open", n.openConnections, "hits", n.Hits, "load", n.Load())
			}
		}
		for {
			select {
			case <-time.After(CloseIdleProxyTransportConnectionsAfter):
				// idle connection maintenance
				// this should become obsolete:
				// https://github.com/golang/go/issues/6785 and others ...
				proxyTransport := n.ReverseProxy.Transport.(*http.Transport)
				if proxyTransport != nil {
					debugConn("closing idle connections")
					proxyTransport.CloseIdleConnections()
				} else {
					debugConn("can not close idle connections")
				}
			case <-n.channelCloseConn:
				debugConn("node close conn")
				n.openConnections--
			case <-n.channelOpenConn:
				n.Hits++
				n.openConnections++
				debugConn("node open conn")
			}
		}
	}()
	return n
}

// Load calculate current load
func (n *Node) Load() float64 {
	if n.openConnections > 0 {
		l := float64(n.openConnections) / float64(n.maxConnections)
		return l
	}
	return 0.0
}

func (n *Node) closeConn() {
	n.channelCloseConn <- 1
}

func (n *Node) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
	n.channelOpenConn <- 1
	defer func() {
		if err := recover(); err != nil {
			n.closeConn()
		}
	}()
	if len(n.user) > 0 && incomingRequest.URL.User == nil {
		incomingRequest.SetBasicAuth(n.user, n.password)
	}
	n.ReverseProxy.ServeHTTP(w, incomingRequest)
	n.closeConn()
}
<|endoftext|>


<commit_before>// Copyright © 2017 ben dewan <benj.dewan@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package config

import "fmt"

var validRoles = map[string]struct{}{
	"admin":     {},
	"developer": {},
	"manager":   {},
}

var validTypes = map[string]struct{}{
	"mongodb":        {},
	"rethinkdb":      {},
	"elastic_search": {},
	"redis":          {},
	"postgresql":     {},
	"rabbitmq":       {},
	"etcd":           {},
	"mysql":          {},
	"janusgraph":     {},
}

func validateType(deploymentType string, errs []string) []string {
	if len(deploymentType) == 0 {
		errs = append(errs, "The 'type' field is required\n")
	} else if _, ok := validTypes[deploymentType]; !ok {
		errs = append(errs,
			fmt.Sprintf("'%s' is not a valid deployment type.", deploymentType))
	}
	return errs
}

func validateName(name string, errs []string) []string {
	if len(name) == 0 {
		errs = append(errs, "The 'name' field is required\n")
	}
	return errs
}

func validateScaling(scaling *int, errs []string) []string {
	if scaling != nil && *scaling < 1 {
		errs = append(errs, "The 'scaling' field must be an integer >= 1\n")
	}
	return errs
}

func validateTeams(teams []*TeamV1, errs []string) []string {
	if teams == nil {
		return errs
	}
	for _, team := range teams {
		if len(team.ID) == 0 {
			errs = append(errs, "Every team entry requires an ID\n")
		}
		if _, ok := validRoles[team.Role]; ok {
			continue
		}
		errs = append(errs,
			fmt.Sprintf("'%s' is not a valid team role\n", team.Role))
	}
	return errs
}

func validateWiredTiger(wiredTiger bool, deploymentType string, errs []string) []string {
	if wiredTiger && deploymentType != "mongodb" {
		errs = append(errs,
			"The 'wired_tiger' field is only valid for the 'mongodb' deployment type\n")
	}
	return errs
}
<commit_msg>Add support for the 'disque' deployment type<commit_after>// Copyright © 2017 ben dewan <benj.dewan@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package config

import "fmt"

var validRoles = map[string]struct{}{
	"admin":     {},
	"developer": {},
	"manager":   {},
}

var validTypes = map[string]struct{}{
	"mongodb":        {},
	"rethinkdb":      {},
	"elastic_search": {},
	"redis":          {},
	"postgresql":     {},
	"rabbitmq":       {},
	"etcd":           {},
	"mysql":          {},
	"janusgraph":     {},
	"disque":         {},
}

func validateType(deploymentType string, errs []string) []string {
	if len(deploymentType) == 0 {
		errs = append(errs, "The 'type' field is required\n")
	} else if _, ok := validTypes[deploymentType]; !ok {
		errs = append(errs,
			fmt.Sprintf("'%s' is not a valid deployment type.", deploymentType))
	}
	return errs
}

func validateName(name string, errs []string) []string {
	if len(name) == 0 {
		errs = append(errs, "The 'name' field is required\n")
	}
	return errs
}

func validateScaling(scaling *int, errs []string) []string {
	if scaling != nil && *scaling < 1 {
		errs = append(errs, "The 'scaling' field must be an integer >= 1\n")
	}
	return errs
}

func validateTeams(teams []*TeamV1, errs []string) []string {
	if teams == nil {
		return errs
	}
	for _, team := range teams {
		if len(team.ID) == 0 {
			errs = append(errs, "Every team entry requires an ID\n")
		}
		if _, ok := validRoles[team.Role]; ok {
			continue
		}
		errs = append(errs,
			fmt.Sprintf("'%s' is not a valid team role\n", team.Role))
	}
	return errs
}

func validateWiredTiger(wiredTiger bool, deploymentType string, errs []string) []string {
	if wiredTiger && deploymentType != "mongodb" {
		errs = append(errs,
			"The 'wired_tiger' field is only valid for the 'mongodb' deployment type\n")
	}
	return errs
}
<|endoftext|>