<commit_before>// Package tpm supports direct communication with a tpm device under Linux.
package tpm

import (
	"bytes"
	"encoding/binary"
	"errors"
	"os"
)

// Supported TPM commands.
const (
	tagRQUCommand uint16 = 0x00C1
	tagRSPCommand uint16 = 0x00C4
)

// Supported TPM operations.
const (
	ordOSAP      uint32 = 0x0000000B
	ordOIAP      uint32 = 0x0000000A
	ordPCRExtend uint32 = 0x00000014
	ordPCRRead   uint32 = 0x00000015
	ordGetRandom uint32 = 0x00000046
)

// Each PCR has a fixed size of 20 bytes.
const PCRSize int = 20

// A CommandHeader is the header for a TPM command.
type CommandHeader struct {
	Tag  uint16
	Size uint32
	Cmd  uint32
}

// PackedSize computes the size of a sequence of types that can be passed to
// binary.Read or binary.Write.
func PackedSize(elts []interface{}) int {
	// Add the total size to the header.
	var size int
	for i := range elts {
		s := binary.Size(elts[i])
		if s == -1 {
			return -1
		}

		size += s
	}

	return size
}

// Pack takes a sequence of elements that are either of fixed length or slices
// of fixed-length types and packs them into a single byte array using
// binary.Write.
func Pack(ch CommandHeader, cmd []interface{}) ([]byte, error) {
	hdrSize := binary.Size(ch)
	bodySize := PackedSize(cmd)
	if bodySize <= 0 {
		return nil, errors.New("can't compute the size of the command")
	}

	size := hdrSize + bodySize
	ch.Size = uint32(size)
	buf := bytes.NewBuffer(make([]byte, 0, size))

	// The header goes first, unsurprisingly.
	if err := binary.Write(buf, binary.BigEndian, ch); err != nil {
		return nil, err
	}

	for _, c := range cmd {
		if err := binary.Write(buf, binary.BigEndian, c); err != nil {
			return nil, err
		}
	}

	return buf.Bytes(), nil
}

// A ResponseHeader is a header for TPM responses.
type ResponseHeader struct {
	Tag  uint16
	Size uint32
	Res  uint32
}

// A SliceSize is used to detect incoming variable-sized array responses.
type SliceSize uint32

// Unpack decodes from a byte array a sequence of elements that are either
// pointers to fixed length types or slices of fixed-length types. It uses
// binary.Read to do the decoding.
func Unpack(b []byte, resp []interface{}) error {
	buf := bytes.NewBuffer(b)
	var nextSliceSize SliceSize
	for _, r := range resp {
		if nextSliceSize > 0 {
			// This must be a byte slice to resize.
			bs, ok := r.([]byte)
			if !ok {
				return errors.New("a *SliceSize must be followed by a []byte")
			}

			if int(nextSliceSize) > len(b) {
				return errors.New("the TPM returned more bytes than can fit in the supplied slice")
			}

			// Resize the slice to match the number of bytes the TPM says it
			// returned for this value.
			r = bs[:nextSliceSize]
			nextSliceSize = 0
		}

		// Note that this only makes sense if the elements of resp are either
		// pointers or slices, since otherwise the decoded values just get
		// thrown away.
		if err := binary.Read(buf, binary.BigEndian, r); err != nil {
			return err
		}

		if ss, ok := r.(*SliceSize); ok {
			nextSliceSize = *ss
		}
	}

	if buf.Len() > 0 {
		return errors.New("unread bytes in the TPM response")
	}

	return nil
}

// submitTPMRequest sends a structure to the TPM device file and gets results
// back, interpreting them as a new provided structure.
func submitTPMRequest(f *os.File, tag uint16, ord uint32, in []interface{}, out []interface{}) error {
	ch := CommandHeader{tag, 0, ord}
	inb, err := Pack(ch, in)
	if err != nil {
		return err
	}

	if _, err := f.Write(inb); err != nil {
		return err
	}

	// Try to read the whole thing, but handle the case where it's just a
	// ResponseHeader and not the body, since that's what happens in the error
	// case.
	var rh ResponseHeader
	outSize := PackedSize(out)
	if outSize < 0 {
		return errors.New("invalid out arguments")
	}

	rhSize := binary.Size(rh)
	outb := make([]byte, rhSize+outSize)
	if _, err := f.Read(outb); err != nil {
		return err
	}

	if err := Unpack(outb[:rhSize], []interface{}{&rh}); err != nil {
		return err
	}

	// Check success before trying to read the rest of the result.
	if rh.Tag != tagRSPCommand {
		return errors.New("inconsistent tag returned by TPM")
	}

	if rh.Res != 0 {
		return tpmError(rh.Res)
	}

	if rh.Size > uint32(rhSize) {
		if err := Unpack(outb[rhSize:], out); err != nil {
			return err
		}
	}

	return nil
}

// ReadPCR reads a PCR value from the TPM.
func ReadPCR(f *os.File, pcr uint32) ([]byte, error) {
	in := []interface{}{pcr}
	v := make([]byte, PCRSize)
	out := []interface{}{v}
	if err := submitTPMRequest(f, tagRQUCommand, ordPCRRead, in, out); err != nil {
		return nil, err
	}

	return v, nil
}

// An OIAPResponse is a response to an OIAPCommand.
type OIAPResponse struct {
	Auth      uint32
	NonceEven [20]byte
}

// OIAP sends an OIAP command to the TPM and gets back an auth value and a
// nonce.
func OIAP(f *os.File) (*OIAPResponse, error) {
	var resp OIAPResponse
	out := []interface{}{&resp}
	if err := submitTPMRequest(f, tagRQUCommand, ordOIAP, nil, out); err != nil {
		return nil, err
	}

	return &resp, nil
}

// GetRandom gets random bytes from the TPM.
func GetRandom(f *os.File, size uint32) ([]byte, error) {
	in := []interface{}{size}

	var outSize SliceSize
	b := make([]byte, int(size))
	out := []interface{}{&outSize, b}

	if err := submitTPMRequest(f, tagRQUCommand, ordGetRandom, in, out); err != nil {
		return nil, err
	}

	return b[:outSize], nil
}

// An OSAPCommand is a command sent for OSAP authentication.
type OSAPCommand struct {
	EntityType  uint16
	EntityValue uint32
	OddOSAP     [20]byte
}

// An OSAPResponse is a TPM reply to an OSAPCommand.
type OSAPResponse struct {
	Auth      uint32
	NonceEven [20]byte
	EvenOSAP  [20]byte
}

// OSAP sends an OSAPCommand to the TPM and gets back authentication
// information in an OSAPResponse.
func OSAP(f *os.File, entityType uint16, entityValue uint32, oddOSAP [20]byte) (*OSAPResponse, error) {
	in := []interface{}{OSAPCommand{entityType, entityValue, oddOSAP}}
	var resp OSAPResponse
	out := []interface{}{&resp}
	if err := submitTPMRequest(f, tagRQUCommand, ordOSAP, in, out); err != nil {
		return nil, err
	}

	return &resp, nil
}
<commit_msg>Fixed bug in slice resizing<commit_after>// Package tpm supports direct communication with a tpm device under Linux.
package tpm

import (
	"bytes"
	"encoding/binary"
	"errors"
	"os"
)

// Supported TPM commands.
const (
	tagRQUCommand uint16 = 0x00C1
	tagRSPCommand uint16 = 0x00C4
)

// Supported TPM operations.
const (
	ordOSAP      uint32 = 0x0000000B
	ordOIAP      uint32 = 0x0000000A
	ordPCRExtend uint32 = 0x00000014
	ordPCRRead   uint32 = 0x00000015
	ordGetRandom uint32 = 0x00000046
)

// Each PCR has a fixed size of 20 bytes.
const PCRSize int = 20

// A CommandHeader is the header for a TPM command.
type CommandHeader struct {
	Tag  uint16
	Size uint32
	Cmd  uint32
}

// PackedSize computes the size of a sequence of types that can be passed to
// binary.Read or binary.Write.
func PackedSize(elts []interface{}) int {
	// Add the total size to the header.
	var size int
	for i := range elts {
		s := binary.Size(elts[i])
		if s == -1 {
			return -1
		}

		size += s
	}

	return size
}

// Pack takes a sequence of elements that are either of fixed length or slices
// of fixed-length types and packs them into a single byte array using
// binary.Write.
func Pack(ch CommandHeader, cmd []interface{}) ([]byte, error) {
	hdrSize := binary.Size(ch)
	bodySize := PackedSize(cmd)
	if bodySize <= 0 {
		return nil, errors.New("can't compute the size of the command")
	}

	size := hdrSize + bodySize
	ch.Size = uint32(size)
	buf := bytes.NewBuffer(make([]byte, 0, size))

	// The header goes first, unsurprisingly.
	if err := binary.Write(buf, binary.BigEndian, ch); err != nil {
		return nil, err
	}

	for _, c := range cmd {
		if err := binary.Write(buf, binary.BigEndian, c); err != nil {
			return nil, err
		}
	}

	return buf.Bytes(), nil
}

// A ResponseHeader is a header for TPM responses.
type ResponseHeader struct {
	Tag  uint16
	Size uint32
	Res  uint32
}

// A SliceSize is used to detect incoming variable-sized array responses. Note
// that any time there is a SliceSize followed by a slice in a respones, this
// slice must be resized to match its preceeding SliceSize after
// submitTPMRequest, since the Unpack code doesn't resize the underlying slice.
type SliceSize uint32

// Unpack decodes from a byte array a sequence of elements that are either
// pointers to fixed length types or slices of fixed-length types. It uses
// binary.Read to do the decoding.
func Unpack(b []byte, resp []interface{}) error {
	buf := bytes.NewBuffer(b)
	var nextSliceSize SliceSize
	var resizeNext bool
	for _, r := range resp {
		if resizeNext {
			// This must be a byte slice to resize.
			bs, ok := r.([]byte)
			if !ok {
				return errors.New("a *SliceSize must be followed by a []byte")
			}

			if int(nextSliceSize) > len(b) {
				return errors.New("the TPM returned more bytes than can fit in the supplied slice")
			}

			// Resize the slice to match the number of bytes the TPM says it
			// returned for this value.
			r = bs[:nextSliceSize]
			nextSliceSize = 0
			resizeNext = false
		}

		// Note that this only makes sense if the elements of resp are either
		// pointers or slices, since otherwise the decoded values just get
		// thrown away.
		if err := binary.Read(buf, binary.BigEndian, r); err != nil {
			return err
		}

		if ss, ok := r.(*SliceSize); ok {
			nextSliceSize = *ss
			resizeNext = true
		}
	}

	if buf.Len() > 0 {
		return errors.New("unread bytes in the TPM response")
	}

	return nil
}

// submitTPMRequest sends a structure to the TPM device file and gets results
// back, interpreting them as a new provided structure.
func submitTPMRequest(f *os.File, tag uint16, ord uint32, in []interface{}, out []interface{}) error {
	ch := CommandHeader{tag, 0, ord}
	inb, err := Pack(ch, in)
	if err != nil {
		return err
	}

	if _, err := f.Write(inb); err != nil {
		return err
	}

	// Try to read the whole thing, but handle the case where it's just a
	// ResponseHeader and not the body, since that's what happens in the error
	// case.
	var rh ResponseHeader
	outSize := PackedSize(out)
	if outSize < 0 {
		return errors.New("invalid out arguments")
	}

	rhSize := binary.Size(rh)
	outb := make([]byte, rhSize+outSize)
	if _, err := f.Read(outb); err != nil {
		return err
	}

	if err := Unpack(outb[:rhSize], []interface{}{&rh}); err != nil {
		return err
	}

	// Check success before trying to read the rest of the result.
	if rh.Tag != tagRSPCommand {
		return errors.New("inconsistent tag returned by TPM")
	}

	if rh.Res != 0 {
		return tpmError(rh.Res)
	}

	if rh.Size > uint32(rhSize) {
		if err := Unpack(outb[rhSize:], out); err != nil {
			return err
		}
	}

	return nil
}

// ReadPCR reads a PCR value from the TPM.
func ReadPCR(f *os.File, pcr uint32) ([]byte, error) {
	in := []interface{}{pcr}
	v := make([]byte, PCRSize)
	out := []interface{}{v}
	if err := submitTPMRequest(f, tagRQUCommand, ordPCRRead, in, out); err != nil {
		return nil, err
	}

	return v, nil
}

// An OIAPResponse is a response to an OIAPCommand.
type OIAPResponse struct {
	Auth      uint32
	NonceEven [20]byte
}

// OIAP sends an OIAP command to the TPM and gets back an auth value and a
// nonce.
func OIAP(f *os.File) (*OIAPResponse, error) {
	var resp OIAPResponse
	out := []interface{}{&resp}
	if err := submitTPMRequest(f, tagRQUCommand, ordOIAP, nil, out); err != nil {
		return nil, err
	}

	return &resp, nil
}

// GetRandom gets random bytes from the TPM.
func GetRandom(f *os.File, size uint32) ([]byte, error) {
	in := []interface{}{size}

	var outSize SliceSize
	b := make([]byte, int(size))
	out := []interface{}{&outSize, b}

	if err := submitTPMRequest(f, tagRQUCommand, ordGetRandom, in, out); err != nil {
		return nil, err
	}

	return b[:outSize], nil
}

// An OSAPCommand is a command sent for OSAP authentication.
type OSAPCommand struct {
	EntityType  uint16
	EntityValue uint32
	OddOSAP     [20]byte
}

// An OSAPResponse is a TPM reply to an OSAPCommand.
type OSAPResponse struct {
	Auth      uint32
	NonceEven [20]byte
	EvenOSAP  [20]byte
}

// OSAP sends an OSAPCommand to the TPM and gets back authentication
// information in an OSAPResponse.
func OSAP(f *os.File, entityType uint16, entityValue uint32, oddOSAP [20]byte) (*OSAPResponse, error) {
	in := []interface{}{OSAPCommand{entityType, entityValue, oddOSAP}}
	var resp OSAPResponse
	out := []interface{}{&resp}
	if err := submitTPMRequest(f, tagRQUCommand, ordOSAP, in, out); err != nil {
		return nil, err
	}

	return &resp, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Serulian Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package typeconstructor

import (
	"fmt"
	"strings"

	"github.com/streamrail/concurrent-map"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/graphs/typegraph"
	"github.com/serulian/compiler/webidl"
)

// GLOBAL_CONTEXT_ANNOTATIONS are the annotations that mark an interface as being a global context
// (e.g. Window) in WebIDL.
var GLOBAL_CONTEXT_ANNOTATIONS = []interface{}{"Global", "PrimaryGlobal"}

// CONSTRUCTOR_ANNOTATION is an annotation that describes support for a constructor on a WebIDL
// type. This translates to being able to do "new Type(...)" in ECMAScript.
const CONSTRUCTOR_ANNOTATION = "Constructor"

// NATIVE_OPERATOR_ANNOTATION is an annotation that marks an declaration as supporting the
// specified operator natively (i.e. not a custom defined operator).
const NATIVE_OPERATOR_ANNOTATION = "NativeOperator"

// SPECIALIZATION_NAMES maps WebIDL member specializations into Serulian typegraph names.
var SPECIALIZATION_NAMES = map[webidl.MemberSpecialization]string{
	webidl.GetterSpecialization: "index",
	webidl.SetterSpecialization: "setindex",
}

// SERIALIZABLE_OPS defines the WebIDL custom ops that mark a type as serializable.
var SERIALIZABLE_OPS = map[string]bool{
	"jsonifier":  true,
	"serializer": true,
}

// NATIVE_TYPES maps from the predefined WebIDL types to the type actually supported
// in ES. We lose some information by doing so, but it allows for compatibility
// with existing WebIDL specifications. In the future, we might find a way to
// have these types be used in a more specific manner.
var NATIVE_TYPES = map[string]string{
	"boolean":             "Boolean",
	"byte":                "Number",
	"octet":               "Number",
	"short":               "Number",
	"unsigned short":      "Number",
	"long":                "Number",
	"unsigned long":       "Number",
	"long long":           "Number",
	"float":               "Number",
	"double":              "Number",
	"unrestricted float":  "Number",
	"unrestricted double": "Number",
}

// GetConstructor returns a TypeGraph constructor for the given IRG.
func GetConstructor(irg *webidl.WebIRG) *irgTypeConstructor {
	return &irgTypeConstructor{
		irg:              irg,
		typesEncountered: cmap.New(),
	}
}

// irgTypeConstructor defines a type for populating a type graph from the IRG.
type irgTypeConstructor struct {
	irg              *webidl.WebIRG     // The IRG being transformed.
	typesEncountered cmap.ConcurrentMap // The types already encountered.
}

func (itc *irgTypeConstructor) DefineModules(builder typegraph.GetModuleBuilder) {
	for _, module := range itc.irg.GetModules() {
		builder().
			Name(module.Name()).
			Path(string(module.InputSource())).
			SourceNode(module.Node()).
			Define()
	}
}

func (itc *irgTypeConstructor) DefineTypes(builder typegraph.GetTypeBuilder) {
	for _, module := range itc.irg.GetModules() {
		for _, declaration := range module.Declarations() {
			// If the type is marked as [Global] then it defines an "interface" whose members
			// get added to the global context, and not a real type.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				continue
			}

			typeBuilder := builder(module.Node())

			for _, customop := range declaration.CustomOperations() {
				if _, ok := SERIALIZABLE_OPS[customop]; ok {
					typeBuilder.WithAttribute(typegraph.SERIALIZABLE_ATTRIBUTE)
				}
			}

			typeBuilder.Name(declaration.Name()).
				GlobalId(declaration.Name()).
				SourceNode(declaration.GraphNode).
				TypeKind(typegraph.ExternalInternalType).
				Define()
		}
	}
}

func (itc *irgTypeConstructor) DefineDependencies(annotator typegraph.Annotator, graph *typegraph.TypeGraph) {
	for _, module := range itc.irg.GetModules() {
		for _, declaration := range module.Declarations() {
			// If the type is marked as [Global] then it defines an "interface" whose members
			// get added to the global context, and not a real type.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				continue
			}

			// Ensure that we don't have duplicate types across modules. Intra-module is handled by the type
			// graph.
			existingModule, found := itc.typesEncountered.Get(declaration.Name())
			if found && existingModule != module {
				annotator.ReportError(declaration.GraphNode, "Redeclaration of WebIDL interface %v is not supported", declaration.Name())
			}

			itc.typesEncountered.Set(declaration.Name(), module)

			// Determine whether we have a parent type for inheritance.
			parentTypeString, hasParentType := declaration.ParentType()
			if !hasParentType {
				continue
			}

			parentType, err := itc.ResolveType(parentTypeString, graph)
			if err != nil {
				annotator.ReportError(declaration.GraphNode, "%v", err)
				continue
			}

			annotator.DefineParentType(declaration.GraphNode, parentType)
		}
	}
}

func (itc *irgTypeConstructor) DefineMembers(builder typegraph.GetMemberBuilder, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	for _, declaration := range itc.irg.Declarations() {
		// Global members get defined under their module, not their declaration.
		var parentNode = declaration.GraphNode
		if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
			parentNode = declaration.Module().GraphNode
		}

		// If the declaration has one (or more) constructors, add then as a "new".
		if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) {
			// Declare a "new" member which returns an instance of this type.
			builder(parentNode, false).
				Name("new").
				SourceNode(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode).
				Define()
		}

		// Add support for any native operators.
		if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) && declaration.HasAnnotation(NATIVE_OPERATOR_ANNOTATION) {
			reporter.ReportError(declaration.GraphNode, "[NativeOperator] not supported on declarations marked with [GlobalContext]")
			return
		}

		for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) {
			opName, hasOpName := nativeOp.Value()
			if !hasOpName {
				reporter.ReportError(nativeOp.GraphNode, "Missing operator name on [NativeOperator] annotation")
				continue
			}

			// Lookup the operator under the type graph.
			opDefinition, found := graph.GetOperatorDefinition(opName)
			if !found || !opDefinition.IsStatic {
				reporter.ReportError(nativeOp.GraphNode, "Unknown native operator '%v'", opName)
				continue
			}

			// Add the operator to the type.
			builder(parentNode, true).
				Name(opName).
				SourceNode(nativeOp.GraphNode).
				Define()
		}

		// Add the declared members and specializations.
		for _, member := range declaration.Members() {
			name, hasName := member.Name()
			if hasName {
				builder(parentNode, false).
					Name(name).
					SourceNode(member.GraphNode).
					Define()
			} else {
				// This is a specialization.
				specialization, _ := member.Specialization()
				builder(parentNode, true).
					Name(SPECIALIZATION_NAMES[specialization]).
					SourceNode(member.GraphNode).
					Define()
			}
		}
	}
}

func (itc *irgTypeConstructor) DecorateMembers(decorator typegraph.GetMemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	for _, declaration := range itc.irg.Declarations() {
		if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) {
			// Should never be allowed.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				reporter.ReportError(declaration.GraphNode, "[Global] interface `%v` cannot also have a [Constructor]", declaration.Name())
				continue
			}

			// For each constructor defined, create the intersection of their parameters.
			var parameters = make([]typegraph.TypeReference, 0)
			for constructorIndex, constructor := range declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION) {
				for index, parameter := range constructor.Parameters() {
					parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph)
					if err != nil {
						reporter.ReportError(parameter.GraphNode, "%v", err)
						continue
					}

					var resolvedParameterType = parameterType
					if parameter.IsOptional() {
						resolvedParameterType = resolvedParameterType.AsNullable()
					}

					if index >= len(parameters) {
						// If this is not the first constructor, then this parameter is implicitly optional
						// and therefore nullable.
						if constructorIndex > 0 {
							resolvedParameterType = resolvedParameterType.AsNullable()
						}

						parameters = append(parameters, resolvedParameterType)
					} else {
						parameters[index] = parameters[index].Intersect(resolvedParameterType)
					}
				}
			}

			// Define the construction function for the type.
			typeDecl, hasTypeDecl := graph.GetTypeForSourceNode(declaration.GraphNode)
			if !hasTypeDecl {
				panic(fmt.Sprintf("Missing type declaration for node %v", declaration.Name()))
			}

			var constructorFunction = graph.FunctionTypeReference(typeDecl.GetTypeReference())
			for _, parameterType := range parameters {
				constructorFunction = constructorFunction.WithParameter(parameterType)
			}

			decorator(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode).
				Exported(true).
				Static(true).
				ReadOnly(true).
				MemberKind(typegraph.NativeConstructorMemberSignature).
				MemberType(constructorFunction).
				Decorate()
		}

		for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) {
			// Should never be allowed.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				reporter.ReportError(declaration.GraphNode, "[Global] interface `%v` cannot also have a [NativeOperator]", declaration.Name())
				continue
			}

			opName, hasOpName := nativeOp.Value()
			if !hasOpName {
				continue
			}

			opDefinition, found := graph.GetOperatorDefinition(opName)
			if !found {
				continue
			}

			// Define the operator's member type based on the definition.
			typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode)

			var expectedReturnType = opDefinition.ExpectedReturnType(typeDecl.GetTypeReference())
			if expectedReturnType.HasReferredType(graph.BoolType()) {
				expectedReturnType, _ = itc.ResolveType("Boolean", graph)
			}

			var operatorType = graph.FunctionTypeReference(expectedReturnType)
			for _, parameter := range opDefinition.Parameters {
				operatorType = operatorType.WithParameter(parameter.ExpectedType(typeDecl.GetTypeReference()))
			}

			// Add the operator to the type.
			decorator(nativeOp.GraphNode).
				Native(true).
				Exported(true).
				SkipOperatorChecking(true).
				MemberType(operatorType).
				MemberKind(typegraph.NativeOperatorMemberSignature).
				Decorate()
		}

		// Add the declared members.
		for _, member := range declaration.Members() {
			declaredType, err := itc.ResolveType(member.DeclaredType(), graph)
			if err != nil {
				reporter.ReportError(member.GraphNode, "%v", err)
				continue
			}

			var memberType = declaredType
			var memberKind = typegraph.CustomMemberSignature
			var isReadonly = member.IsReadonly()

			switch member.Kind() {
			case webidl.FunctionMember:
				isReadonly = true
				memberKind = typegraph.NativeFunctionMemberSignature
				memberType = graph.FunctionTypeReference(memberType)

				// Add the parameter types.
				var markOptional = false
				for _, parameter := range member.Parameters() {
					if parameter.IsOptional() {
						markOptional = true
					}

					parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph)
					if err != nil {
						reporter.ReportError(member.GraphNode, "%v", err)
						continue
					}

					// All optional parameters get marked as nullable, which means we can skip
					// passing them on function calls.
					if markOptional {
						memberType = memberType.WithParameter(parameterType.AsNullable())
					} else {
						memberType = memberType.WithParameter(parameterType)
					}
				}

			case webidl.AttributeMember:
				memberKind = typegraph.NativePropertyMemberSignature

				if len(member.Parameters()) > 0 {
					reporter.ReportError(member.GraphNode, "Attributes cannot have parameters")
				}

			default:
				panic("Unknown WebIDL member kind")
			}

			decorator := decorator(member.GraphNode)
			if _, hasName := member.Name(); !hasName {
				decorator.Native(true)
			}

			decorator.Exported(true).
				Static(member.IsStatic()).
				ReadOnly(isReadonly).
				MemberKind(memberKind).
				MemberType(memberType).
				Decorate()
		}
	}
}

func (itc *irgTypeConstructor) Validate(reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
}

func (itc *irgTypeConstructor) GetLocation(sourceNodeId compilergraph.GraphNodeId) (compilercommon.SourceAndLocation, bool) {
	layerNode, found := itc.irg.TryGetNode(sourceNodeId)
	if !found {
		return compilercommon.SourceAndLocation{}, false
	}

	return itc.irg.NodeLocation(layerNode), true
}

// ResolveType attempts to resolve the given type string.
func (itc *irgTypeConstructor) ResolveType(typeString string, graph *typegraph.TypeGraph) (typegraph.TypeReference, error) {
	if typeString == "any" {
		return graph.AnyTypeReference(), nil
	}

	if typeString == "void" {
		return graph.VoidTypeReference(), nil
	}

	var nullable = false
	if strings.HasSuffix(typeString, "?") {
		nullable = true
		typeString = typeString[0 : len(typeString)-1]
	}

	// Perform native type mapping.
	if found, ok := NATIVE_TYPES[typeString]; ok {
		typeString = found
	}

	declaration, hasDeclaration := itc.irg.FindDeclaration(typeString)
	if !hasDeclaration {
		return graph.AnyTypeReference(), fmt.Errorf("Could not find WebIDL type %v", typeString)
	}

	typeDecl, hasType := graph.GetTypeForSourceNode(declaration.GraphNode)
	if !hasType {
		panic("Type not found for WebIDL type declaration")
	}

	typeRef := typeDecl.GetTypeReference()
	if nullable {
		return typeRef.AsNullable(), nil
	}

	return typeRef, nil
}
<commit_msg>Fix typo<commit_after>// Copyright 2015 The Serulian Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package typeconstructor

import (
	"fmt"
	"strings"

	"github.com/streamrail/concurrent-map"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/graphs/typegraph"
	"github.com/serulian/compiler/webidl"
)

// GLOBAL_CONTEXT_ANNOTATIONS are the annotations that mark an interface as being a global context
// (e.g. Window) in WebIDL.
var GLOBAL_CONTEXT_ANNOTATIONS = []interface{}{"Global", "PrimaryGlobal"}

// CONSTRUCTOR_ANNOTATION is an annotation that describes support for a constructor on a WebIDL
// type. This translates to being able to do "new Type(...)" in ECMAScript.
const CONSTRUCTOR_ANNOTATION = "Constructor"

// NATIVE_OPERATOR_ANNOTATION is an annotation that marks an declaration as supporting the
// specified operator natively (i.e. not a custom defined operator).
const NATIVE_OPERATOR_ANNOTATION = "NativeOperator"

// SPECIALIZATION_NAMES maps WebIDL member specializations into Serulian typegraph names.
var SPECIALIZATION_NAMES = map[webidl.MemberSpecialization]string{
	webidl.GetterSpecialization: "index",
	webidl.SetterSpecialization: "setindex",
}

// SERIALIZABLE_OPS defines the WebIDL custom ops that mark a type as serializable.
var SERIALIZABLE_OPS = map[string]bool{
	"jsonifier":  true,
	"serializer": true,
}

// NATIVE_TYPES maps from the predefined WebIDL types to the type actually supported
// in ES. We lose some information by doing so, but it allows for compatibility
// with existing WebIDL specifications. In the future, we might find a way to
// have these types be used in a more specific manner.
var NATIVE_TYPES = map[string]string{
	"boolean":             "Boolean",
	"byte":                "Number",
	"octet":               "Number",
	"short":               "Number",
	"unsigned short":      "Number",
	"long":                "Number",
	"unsigned long":       "Number",
	"long long":           "Number",
	"float":               "Number",
	"double":              "Number",
	"unrestricted float":  "Number",
	"unrestricted double": "Number",
}

// GetConstructor returns a TypeGraph constructor for the given IRG.
func GetConstructor(irg *webidl.WebIRG) *irgTypeConstructor {
	return &irgTypeConstructor{
		irg:              irg,
		typesEncountered: cmap.New(),
	}
}

// irgTypeConstructor defines a type for populating a type graph from the IRG.
type irgTypeConstructor struct {
	irg              *webidl.WebIRG     // The IRG being transformed.
	typesEncountered cmap.ConcurrentMap // The types already encountered.
}

func (itc *irgTypeConstructor) DefineModules(builder typegraph.GetModuleBuilder) {
	for _, module := range itc.irg.GetModules() {
		builder().
			Name(module.Name()).
			Path(string(module.InputSource())).
			SourceNode(module.Node()).
			Define()
	}
}

func (itc *irgTypeConstructor) DefineTypes(builder typegraph.GetTypeBuilder) {
	for _, module := range itc.irg.GetModules() {
		for _, declaration := range module.Declarations() {
			// If the type is marked as [Global] then it defines an "interface" whose members
			// get added to the global context, and not a real type.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				continue
			}

			typeBuilder := builder(module.Node())

			for _, customop := range declaration.CustomOperations() {
				if _, ok := SERIALIZABLE_OPS[customop]; ok {
					typeBuilder.WithAttribute(typegraph.SERIALIZABLE_ATTRIBUTE)
				}
			}

			typeBuilder.Name(declaration.Name()).
				GlobalId(declaration.Name()).
				SourceNode(declaration.GraphNode).
				TypeKind(typegraph.ExternalInternalType).
				Define()
		}
	}
}

func (itc *irgTypeConstructor) DefineDependencies(annotator typegraph.Annotator, graph *typegraph.TypeGraph) {
	for _, module := range itc.irg.GetModules() {
		for _, declaration := range module.Declarations() {
			// If the type is marked as [Global] then it defines an "interface" whose members
			// get added to the global context, and not a real type.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				continue
			}

			// Ensure that we don't have duplicate types across modules. Intra-module is handled by the type
			// graph.
			existingModule, found := itc.typesEncountered.Get(declaration.Name())
			if found && existingModule != module {
				annotator.ReportError(declaration.GraphNode, "Redeclaration of WebIDL interface %v is not supported", declaration.Name())
			}

			itc.typesEncountered.Set(declaration.Name(), module)

			// Determine whether we have a parent type for inheritance.
			parentTypeString, hasParentType := declaration.ParentType()
			if !hasParentType {
				continue
			}

			parentType, err := itc.ResolveType(parentTypeString, graph)
			if err != nil {
				annotator.ReportError(declaration.GraphNode, "%v", err)
				continue
			}

			annotator.DefineParentType(declaration.GraphNode, parentType)
		}
	}
}

func (itc *irgTypeConstructor) DefineMembers(builder typegraph.GetMemberBuilder, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	for _, declaration := range itc.irg.Declarations() {
		// Global members get defined under their module, not their declaration.
		var parentNode = declaration.GraphNode
		if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
			parentNode = declaration.Module().GraphNode
		}

		// If the declaration has one (or more) constructors, add them as a "new".
		if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) {
			// Declare a "new" member which returns an instance of this type.
			builder(parentNode, false).
				Name("new").
				SourceNode(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode).
				Define()
		}

		// Add support for any native operators.
		if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) && declaration.HasAnnotation(NATIVE_OPERATOR_ANNOTATION) {
			reporter.ReportError(declaration.GraphNode, "[NativeOperator] not supported on declarations marked with [GlobalContext]")
			return
		}

		for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) {
			opName, hasOpName := nativeOp.Value()
			if !hasOpName {
				reporter.ReportError(nativeOp.GraphNode, "Missing operator name on [NativeOperator] annotation")
				continue
			}

			// Lookup the operator under the type graph.
			opDefinition, found := graph.GetOperatorDefinition(opName)
			if !found || !opDefinition.IsStatic {
				reporter.ReportError(nativeOp.GraphNode, "Unknown native operator '%v'", opName)
				continue
			}

			// Add the operator to the type.
			builder(parentNode, true).
				Name(opName).
				SourceNode(nativeOp.GraphNode).
				Define()
		}

		// Add the declared members and specializations.
		for _, member := range declaration.Members() {
			name, hasName := member.Name()
			if hasName {
				builder(parentNode, false).
					Name(name).
					SourceNode(member.GraphNode).
					Define()
			} else {
				// This is a specialization.
				specialization, _ := member.Specialization()
				builder(parentNode, true).
					Name(SPECIALIZATION_NAMES[specialization]).
					SourceNode(member.GraphNode).
					Define()
			}
		}
	}
}

func (itc *irgTypeConstructor) DecorateMembers(decorator typegraph.GetMemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	for _, declaration := range itc.irg.Declarations() {
		if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) {
			// Should never be allowed.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				reporter.ReportError(declaration.GraphNode, "[Global] interface `%v` cannot also have a [Constructor]", declaration.Name())
				continue
			}

			// For each constructor defined, create the intersection of their parameters.
			var parameters = make([]typegraph.TypeReference, 0)
			for constructorIndex, constructor := range declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION) {
				for index, parameter := range constructor.Parameters() {
					parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph)
					if err != nil {
						reporter.ReportError(parameter.GraphNode, "%v", err)
						continue
					}

					var resolvedParameterType = parameterType
					if parameter.IsOptional() {
						resolvedParameterType = resolvedParameterType.AsNullable()
					}

					if index >= len(parameters) {
						// If this is not the first constructor, then this parameter is implicitly optional
						// and therefore nullable.
						if constructorIndex > 0 {
							resolvedParameterType = resolvedParameterType.AsNullable()
						}

						parameters = append(parameters, resolvedParameterType)
					} else {
						parameters[index] = parameters[index].Intersect(resolvedParameterType)
					}
				}
			}

			// Define the construction function for the type.
			typeDecl, hasTypeDecl := graph.GetTypeForSourceNode(declaration.GraphNode)
			if !hasTypeDecl {
				panic(fmt.Sprintf("Missing type declaration for node %v", declaration.Name()))
			}

			var constructorFunction = graph.FunctionTypeReference(typeDecl.GetTypeReference())
			for _, parameterType := range parameters {
				constructorFunction = constructorFunction.WithParameter(parameterType)
			}

			decorator(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode).
				Exported(true).
				Static(true).
				ReadOnly(true).
				MemberKind(typegraph.NativeConstructorMemberSignature).
				MemberType(constructorFunction).
				Decorate()
		}

		for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) {
			// Should never be allowed.
			if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) {
				reporter.ReportError(declaration.GraphNode, "[Global] interface `%v` cannot also have a [NativeOperator]", declaration.Name())
				continue
			}

			opName, hasOpName := nativeOp.Value()
			if !hasOpName {
				continue
			}

			opDefinition, found := graph.GetOperatorDefinition(opName)
			if !found {
				continue
			}

			// Define the operator's member type based on the definition.
			typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode)

			var expectedReturnType = opDefinition.ExpectedReturnType(typeDecl.GetTypeReference())
			if expectedReturnType.HasReferredType(graph.BoolType()) {
				expectedReturnType, _ = itc.ResolveType("Boolean", graph)
			}

			var operatorType = graph.FunctionTypeReference(expectedReturnType)
			for _, parameter := range opDefinition.Parameters {
				operatorType = operatorType.WithParameter(parameter.ExpectedType(typeDecl.GetTypeReference()))
			}

			// Add the operator to the type.
			decorator(nativeOp.GraphNode).
				Native(true).
				Exported(true).
				SkipOperatorChecking(true).
				MemberType(operatorType).
				MemberKind(typegraph.NativeOperatorMemberSignature).
				Decorate()
		}

		// Add the declared members.
		for _, member := range declaration.Members() {
			declaredType, err := itc.ResolveType(member.DeclaredType(), graph)
			if err != nil {
				reporter.ReportError(member.GraphNode, "%v", err)
				continue
			}

			var memberType = declaredType
			var memberKind = typegraph.CustomMemberSignature
			var isReadonly = member.IsReadonly()

			switch member.Kind() {
			case webidl.FunctionMember:
				isReadonly = true
				memberKind = typegraph.NativeFunctionMemberSignature
				memberType = graph.FunctionTypeReference(memberType)

				// Add the parameter types.
				var markOptional = false
				for _, parameter := range member.Parameters() {
					if parameter.IsOptional() {
						markOptional = true
					}

					parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph)
					if err != nil {
						reporter.ReportError(member.GraphNode, "%v", err)
						continue
					}

					// All optional parameters get marked as nullable, which means we can skip
					// passing them on function calls.
					if markOptional {
						memberType = memberType.WithParameter(parameterType.AsNullable())
					} else {
						memberType = memberType.WithParameter(parameterType)
					}
				}

			case webidl.AttributeMember:
				memberKind = typegraph.NativePropertyMemberSignature

				if len(member.Parameters()) > 0 {
					reporter.ReportError(member.GraphNode, "Attributes cannot have parameters")
				}

			default:
				panic("Unknown WebIDL member kind")
			}

			decorator := decorator(member.GraphNode)
			if _, hasName := member.Name(); !hasName {
				decorator.Native(true)
			}

			decorator.Exported(true).
				Static(member.IsStatic()).
				ReadOnly(isReadonly).
				MemberKind(memberKind).
				MemberType(memberType).
				Decorate()
		}
	}
}

func (itc *irgTypeConstructor) Validate(reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
}

func (itc *irgTypeConstructor) GetLocation(sourceNodeId compilergraph.GraphNodeId) (compilercommon.SourceAndLocation, bool) {
	layerNode, found := itc.irg.TryGetNode(sourceNodeId)
	if !found {
		return compilercommon.SourceAndLocation{}, false
	}

	return itc.irg.NodeLocation(layerNode), true
}

// ResolveType attempts to resolve the given type string.
func (itc *irgTypeConstructor) ResolveType(typeString string, graph *typegraph.TypeGraph) (typegraph.TypeReference, error) {
	if typeString == "any" {
		return graph.AnyTypeReference(), nil
	}

	if typeString == "void" {
		return graph.VoidTypeReference(), nil
	}

	var nullable = false
	if strings.HasSuffix(typeString, "?") {
		nullable = true
		typeString = typeString[0 : len(typeString)-1]
	}

	// Perform native type mapping.
	if found, ok := NATIVE_TYPES[typeString]; ok {
		typeString = found
	}

	declaration, hasDeclaration := itc.irg.FindDeclaration(typeString)
	if !hasDeclaration {
		return graph.AnyTypeReference(), fmt.Errorf("Could not find WebIDL type %v", typeString)
	}

	typeDecl, hasType := graph.GetTypeForSourceNode(declaration.GraphNode)
	if !hasType {
		panic("Type not found for WebIDL type declaration")
	}

	typeRef := typeDecl.GetTypeReference()
	if nullable {
		return typeRef.AsNullable(), nil
	}

	return typeRef, nil
}
<|endoftext|>


<commit_before>package sparta

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/Sirupsen/logrus"
	gocf "github.com/crewjam/go-cloudformation"
)

var cloudformationTypeMapDiscoveryOutputs = map[string][]string{
	"AWS::S3::Bucket": []string{"DomainName", "WebsiteURL"},
}

// cloudFormationAPIGatewayResource is the CustomResource type used to
// provision an APIGateway
type cloudFormationAPIGatewayResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	API          interface{}
}

type cloudFormationS3PermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Permission   interface{}
	LambdaTarget *gocf.StringExpr
	BucketArn    *gocf.StringExpr
}

type cloudFormationSNSPermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Mode         string
	TopicArn     *gocf.StringExpr
	LambdaTarget *gocf.StringExpr
}

type cloudFormationSESPermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Rules        interface{}
}

type cloudformationS3SiteManager struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	TargetBucket *gocf.StringExpr
	SourceKey    *gocf.StringExpr
	SourceBucket *gocf.StringExpr
	APIGateway   map[string]*gocf.Output
}

func customTypeProvider(resourceType string) gocf.ResourceProperties {
	switch resourceType {
	case "Custom::SpartaAPIGateway":
		{
			return &cloudFormationAPIGatewayResource{}
		}
	case "Custom::SpartaS3Permission":
		{
			return &cloudFormationS3PermissionResource{}
		}
	case "Custom::SpartaSNSPermission":
		{
			return &cloudFormationSNSPermissionResource{}
		}
	case "Custom::SpartaSESPermission":
		{
			return &cloudFormationSESPermissionResource{}
		}
	case "Custom::SpartaS3SiteManager":
		{
			return &cloudformationS3SiteManager{}
		}
	default:
		return nil
	}
}

func init() {
	gocf.RegisterCustomResourceProvider(customTypeProvider)
}

func newCloudFormationResource(resourceType string, logger *logrus.Logger) (gocf.ResourceProperties, error) {
	resProps := gocf.NewResourceByType(resourceType)
	if nil == resProps {
		logger.WithFields(logrus.Fields{
			"Type": resourceType,
		}).Fatal("Failed to create CloudFormation CustomResource!")
		return nil, fmt.Errorf("Unsupported CustomResourceType: %s", resourceType)
	}
	return resProps, nil
}

func outputsForResource(template *gocf.Template, logicalResourceName string, logger *logrus.Logger) (map[string]interface{}, error) {
	item, ok := template.Resources[logicalResourceName]
	if !ok {
		return nil, nil
	}

	outputs := make(map[string]interface{}, 0)
	attrs, exists := cloudformationTypeMapDiscoveryOutputs[item.Properties.ResourceType()]
	if exists {
		outputs["Ref"] = gocf.Ref(logicalResourceName).String()
		outputs["Type"] = gocf.String("AWS::S3::Bucket")
		for _, eachAttr := range attrs {
			outputs[eachAttr] = gocf.GetAtt(logicalResourceName, eachAttr)
		}

		// Any tags?
		r := reflect.ValueOf(item.Properties)
		tagsField := reflect.Indirect(r).FieldByName("Tags")
		if tagsField.IsValid() {
			outputs["Tags"] = tagsField.Interface()
		}
	}
	return outputs, nil
}
func safeAppendDependency(resource *gocf.Resource, dependencyName string) {
	if nil == resource.DependsOn {
		resource.DependsOn = []string{}
	}
	resource.DependsOn = append(resource.DependsOn, dependencyName)
}
func safeMetadataInsert(resource *gocf.Resource, key string, value interface{}) {
	if nil == resource.Metadata {
		resource.Metadata = make(map[string]interface{}, 0)
	}
	resource.Metadata[key] = value
}

func safeMergeTemplates(sourceTemplate *gocf.Template, destTemplate *gocf.Template, logger *logrus.Logger) error {
	var mergeErrors []string

	// Append the custom resources
	for eachKey, eachLambdaResource := range sourceTemplate.Resources {
		_, exists := destTemplate.Resources[eachKey]
		if exists {
			errorMsg := fmt.Sprintf("Duplicate CloudFormation resource name: %s", eachKey)
			mergeErrors = append(mergeErrors, errorMsg)
		} else {
			destTemplate.Resources[eachKey] = eachLambdaResource
		}
	}
	// Append the custom outputs
	for eachKey, eachLambdaOutput := range sourceTemplate.Outputs {
		_, exists := destTemplate.Outputs[eachKey]
		if exists {
			errorMsg := fmt.Sprintf("Duplicate CloudFormation output key name: %s", eachKey)
			mergeErrors = append(mergeErrors, errorMsg)
		} else {
			destTemplate.Outputs[eachKey] = eachLambdaOutput
		}
	}
	if len(mergeErrors) > 0 {
		logger.Error("Failed to update template. The following collisions were found:")
		for _, eachError := range mergeErrors {
			logger.Error("\t" + eachError)
		}
		return errors.New("Template merge failed")
	}
	return nil
}
<commit_msg>Check for `nil` Tags prior to assigning<commit_after>package sparta

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/Sirupsen/logrus"
	gocf "github.com/crewjam/go-cloudformation"
)

var cloudformationTypeMapDiscoveryOutputs = map[string][]string{
	"AWS::S3::Bucket": []string{"DomainName", "WebsiteURL"},
}

// cloudFormationAPIGatewayResource is the CustomResource type used to
// provision an APIGateway
type cloudFormationAPIGatewayResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	API          interface{}
}

type cloudFormationS3PermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Permission   interface{}
	LambdaTarget *gocf.StringExpr
	BucketArn    *gocf.StringExpr
}

type cloudFormationSNSPermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Mode         string
	TopicArn     *gocf.StringExpr
	LambdaTarget *gocf.StringExpr
}

type cloudFormationSESPermissionResource struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	Rules        interface{}
}

type cloudformationS3SiteManager struct {
	gocf.CloudFormationCustomResource
	ServiceToken *gocf.StringExpr
	TargetBucket *gocf.StringExpr
	SourceKey    *gocf.StringExpr
	SourceBucket *gocf.StringExpr
	APIGateway   map[string]*gocf.Output
}

func customTypeProvider(resourceType string) gocf.ResourceProperties {
	switch resourceType {
	case "Custom::SpartaAPIGateway":
		{
			return &cloudFormationAPIGatewayResource{}
		}
	case "Custom::SpartaS3Permission":
		{
			return &cloudFormationS3PermissionResource{}
		}
	case "Custom::SpartaSNSPermission":
		{
			return &cloudFormationSNSPermissionResource{}
		}
	case "Custom::SpartaSESPermission":
		{
			return &cloudFormationSESPermissionResource{}
		}
	case "Custom::SpartaS3SiteManager":
		{
			return &cloudformationS3SiteManager{}
		}
	default:
		return nil
	}
}

func init() {
	gocf.RegisterCustomResourceProvider(customTypeProvider)
}

func newCloudFormationResource(resourceType string, logger *logrus.Logger) (gocf.ResourceProperties, error) {
	resProps := gocf.NewResourceByType(resourceType)
	if nil == resProps {
		logger.WithFields(logrus.Fields{
			"Type": resourceType,
		}).Fatal("Failed to create CloudFormation CustomResource!")
		return nil, fmt.Errorf("Unsupported CustomResourceType: %s", resourceType)
	}
	return resProps, nil
}

func outputsForResource(template *gocf.Template,
	logicalResourceName string,
	logger *logrus.Logger) (map[string]interface{}, error) {
	item, ok := template.Resources[logicalResourceName]
	if !ok {
		return nil, nil
	}

	outputs := make(map[string]interface{}, 0)
	attrs, exists := cloudformationTypeMapDiscoveryOutputs[item.Properties.ResourceType()]
	if exists {
		outputs["Ref"] = gocf.Ref(logicalResourceName).String()
		outputs["Type"] = gocf.String("AWS::S3::Bucket")
		for _, eachAttr := range attrs {
			outputs[eachAttr] = gocf.GetAtt(logicalResourceName, eachAttr)
		}

		// Any tags?
		r := reflect.ValueOf(item.Properties)
		tagsField := reflect.Indirect(r).FieldByName("Tags")
		if tagsField.IsValid() && !tagsField.IsNil() {
			outputs["Tags"] = tagsField.Interface()
		}
	}

	if len(outputs) != 0 {
		logger.WithFields(logrus.Fields{
			"ResourceName": logicalResourceName,
			"Outputs":      outputs,
		}).Debug("Resource Outputs")
	}

	return outputs, nil
}
func safeAppendDependency(resource *gocf.Resource, dependencyName string) {
	if nil == resource.DependsOn {
		resource.DependsOn = []string{}
	}
	resource.DependsOn = append(resource.DependsOn, dependencyName)
}
func safeMetadataInsert(resource *gocf.Resource, key string, value interface{}) {
	if nil == resource.Metadata {
		resource.Metadata = make(map[string]interface{}, 0)
	}
	resource.Metadata[key] = value
}

func safeMergeTemplates(sourceTemplate *gocf.Template, destTemplate *gocf.Template, logger *logrus.Logger) error {
	var mergeErrors []string

	// Append the custom resources
	for eachKey, eachLambdaResource := range sourceTemplate.Resources {
		_, exists := destTemplate.Resources[eachKey]
		if exists {
			errorMsg := fmt.Sprintf("Duplicate CloudFormation resource name: %s", eachKey)
			mergeErrors = append(mergeErrors, errorMsg)
		} else {
			destTemplate.Resources[eachKey] = eachLambdaResource
		}
	}
	// Append the custom outputs
	for eachKey, eachLambdaOutput := range sourceTemplate.Outputs {
		_, exists := destTemplate.Outputs[eachKey]
		if exists {
			errorMsg := fmt.Sprintf("Duplicate CloudFormation output key name: %s", eachKey)
			mergeErrors = append(mergeErrors, errorMsg)
		} else {
			destTemplate.Outputs[eachKey] = eachLambdaOutput
		}
	}
	if len(mergeErrors) > 0 {
		logger.Error("Failed to update template. The following collisions were found:")
		for _, eachError := range mergeErrors {
			logger.Error("\t" + eachError)
		}
		return errors.New("Template merge failed")
	}
	return nil
}
<|endoftext|>


<commit_before>package glplus

import "math"

// VBOOptions ...
type VBOOptions struct {
	Vertex  int
	Normals int
	UV      int
	IsStrip bool
	Quads   int
}

func DefaultVBOOptions() VBOOptions {
	return VBOOptions{
		Vertex: 3,
		UV:     2,
	}
}

// VBO ...
type VBO struct {
	vao        *ENGOGLVertexArray
	vboVerts   *ENGOGLBuffer
	vboIndices *ENGOGLBuffer
	numElem    int
	isShort    bool

	options VBOOptions
}

// DeleteVBO ...
func (v *VBO) DeleteVBO() {
	if v.vboVerts != nil {
		Gl.DeleteBuffer(v.vboVerts)
	}
	if v.vboIndices != nil {
		Gl.DeleteBuffer(v.vboIndices)
	}
	if v.vao != nil {
		Gl.DeleteVertexArray(v.vao)
	}
}

// Bind ...
func (v *VBO) Bind() {
	Gl.BindVertexArray(v.vao)
	if v.options.Vertex != 0 {
		Gl.EnableVertexAttribArray(gPositionAttr)
	}
	if v.options.UV != 0 {
		Gl.EnableVertexAttribArray(gUVsAttr)
	}
	if v.options.Normals != 0 {
		Gl.EnableVertexAttribArray(gNormalsAttr)
	}
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, v.vboIndices)
	} else {
		Gl.BindBuffer(Gl.ARRAY_BUFFER, v.vboVerts)
	}
}

// Unbind ...
func (v *VBO) Unbind() {
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, nil)
	} else {
		Gl.BindBuffer(Gl.ARRAY_BUFFER, nil)
	}
	if v.options.Vertex != 0 {
		Gl.DisableVertexAttribArray(gPositionAttr)
	}
	if v.options.UV != 0 {
		Gl.DisableVertexAttribArray(gUVsAttr)
	}
	if v.options.Normals != 0 {
		Gl.DisableVertexAttribArray(gNormalsAttr)
	}
	Gl.BindVertexArray(nil)
}

func (v *VBO) elemType() int {
	if v.isShort {
		return Gl.UNSIGNED_SHORT
	}

	return Gl.UNSIGNED_INT
}

// Draw ...
func (v *VBO) Draw() {
	if v.vboIndices != nil {
		if v.options.Quads != 0 {
			Gl.DrawElements(Gl.TRIANGLES, v.options.Quads*6, v.elemType(), 0)
		} else if v.options.IsStrip {
			Gl.DrawElements(Gl.TRIANGLE_STRIP, v.numElem, v.elemType(), 0)
		} else {
			Gl.DrawElements(Gl.TRIANGLES, v.numElem, v.elemType(), 0)
		}
	} else {
		if v.options.Quads != 0 {
			Gl.DrawArrays(Gl.TRIANGLES, 0, v.options.Quads*6)
		} else if v.options.IsStrip {
			Gl.DrawArrays(Gl.TRIANGLE_STRIP, 0, v.numElem)
		} else {
			Gl.DrawArrays(Gl.TRIANGLES, 0, v.numElem)
		}
	}
}

// Load ...
func (v *VBO) load(verts []float32, indices []uint32) {
	Gl.BindVertexArray(v.vao)
	Gl.BindBuffer(Gl.ARRAY_BUFFER, v.vboVerts)
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, v.vboIndices)
	}

	// load our data up and bind it to the 'position' shader attribute
	Gl.BufferData(Gl.ARRAY_BUFFER, verts, Gl.STATIC_DRAW)

	if v.vboIndices != nil {
		if len(indices) < math.MaxUint16 {
			v.isShort = true
			uindices := make([]uint16, len(indices))
			for i, ind := range indices {
				uindices[i] = uint16(ind)
			}
			Gl.BufferData(Gl.ELEMENT_ARRAY_BUFFER, uindices, Gl.STATIC_DRAW)
		} else {
			Gl.BufferData(Gl.ELEMENT_ARRAY_BUFFER, indices, Gl.STATIC_DRAW)
		}
	}

	var numElemsPerVertex = v.options.Vertex + v.options.UV + v.options.Normals
	var totalSize = numElemsPerVertex * 4
	var offset int
	if v.options.Vertex != 0 {
		Gl.VertexAttribPointer(gPositionAttr, v.options.Vertex, Gl.FLOAT, false, totalSize, offset)
		offset += v.options.Vertex * 4
	}
	if v.options.UV != 0 {
		Gl.VertexAttribPointer(gUVsAttr, v.options.UV, Gl.FLOAT, false, totalSize, offset)
		offset += v.options.UV * 4
	}
	if v.options.Normals != 0 {
		Gl.VertexAttribPointer(gNormalsAttr, v.options.Normals, Gl.FLOAT, false, totalSize, offset)
	}

	Gl.BindBuffer(Gl.ARRAY_BUFFER, nil)
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, nil)
	}
	Gl.BindVertexArray(nil)

	if v.vboIndices != nil {
		v.numElem = len(indices)
	} else {
		v.numElem = len(verts) / numElemsPerVertex
	}
}

// NewVBO ...
func NewVBO(options VBOOptions, verts []float32, indices []uint32) (vbo *VBO) {
	// create and bind the required VAO object
	var vao *ENGOGLVertexArray
	vao = Gl.CreateVertexArray()
	Gl.BindVertexArray(vao)

	// create a VBO to hold the vertex data
	var vboVerts *ENGOGLBuffer
	var vboIndices *ENGOGLBuffer
	vboVerts = Gl.CreateBuffer()
	if indices != nil {
		vboIndices = Gl.CreateBuffer()
	}

	vbo = &VBO{vao: vao,
		vboVerts:   vboVerts,
		vboIndices: vboIndices,
		numElem:    0,
		options:    options,
	}
	Gl.BindVertexArray(nil)

	vbo.load(verts, indices)

	return vbo
}

// NewVBOQuad ...
func NewVBOQuad(x float32, y float32, w float32, h float32) (vbo *VBO) {

	verts := [...]float32{
		x, y, 0.0, 0, 0,
		x + w, y, 0.0, 1, 0,
		x + w, y + h, 0.0, 1, 1,
		x, y + h, 0.0, 0, 1,
	}

	indices := [...]uint32{
		0, 1, 2,
		2, 3, 0,
	}

	vbo = NewVBO(DefaultVBOOptions(), verts[:], indices[:])
	return vbo
}

// NewVBOCube ...
func NewVBOCube(x float32, y float32, z float32, u float32, v float32, w float32) (vbo *VBO) {
	verts := [...]float32{
		// front
		-1.0, -1.0, 1.0, 0, 0,
		1.0, -1.0, 1.0, 0, 0,
		1.0, 1.0, 1.0, 0, 0,
		-1.0, 1.0, 1.0, 0, 0,
		// back
		-1.0, -1.0, -1.0, 0, 0,
		1.0, -1.0, -1.0, 0, 0,
		1.0, 1.0, -1.0, 0, 0,
		-1.0, 1.0, -1.0, 0, 0,
	}

	var i uint32
	for i = 0; i < 8; i++ {
		var ind = i * 5
		verts[ind+0] = verts[ind+0]*u + x
		verts[ind+1] = verts[ind+1]*v + y
		verts[ind+2] = verts[ind+2]*w + z
	}

	indices := [...]uint32{
		// front
		0, 1, 2,
		2, 3, 0,
		// top
		1, 5, 6,
		6, 2, 1,
		// back
		7, 6, 5,
		5, 4, 7,
		// bottom
		4, 0, 3,
		3, 7, 4,
		// left
		4, 5, 1,
		1, 0, 4,
		// right
		3, 2, 6,
		6, 7, 3,
	}

	vbo = NewVBO(DefaultVBOOptions(), verts[:], indices[:])
	return vbo
}

// NewVBOCubeNormal ...
func NewVBOCubeNormal(x float32, y float32, z float32, u float32, v float32, w float32) (vbo *VBO) {
	verts := [...]float32{
		// Vertex data for face 0
		-1.0, -1.0, 1.0, 0.0, 0.0, 0, 0, 1, // v0
		1.0, -1.0, 1.0, 0.33, 0.0, 0, 0, 1, // v1
		-1.0, 1.0, 1.0, 0.0, 0.5, 0, 0, 1, // v2
		1.0, 1.0, 1.0, 0.33, 0.5, 0, 0, 1, // v3

		// Vertex data for face 1
		1.0, -1.0, 1.0, 0.0, 0.5, 1, 0, 0, // v4
		1.0, -1.0, -1.0, 0.33, 0.5, 1, 0, 0, // v5
		1.0, 1.0, 1.0, 0.0, 1.0, 1, 0, 0, // v6
		1.0, 1.0, -1.0, 0.33, 1.0, 1, 0, 0, // v7

		// Vertex data for face 2
		1.0, -1.0, -1.0, 0.66, 0.5, 0, 0, -1, // v8
		-1.0, -1.0, -1.0, 1.0, 0.5, 0, 0, -1, // v9
		1.0, 1.0, -1.0, 0.66, 1.0, 0, 0, -1, // v10
		-1.0, 1.0, -1.0, 1.0, 1.0, 0, 0, -1, // v11

		// Vertex data for face 3
		-1.0, -1.0, -1.0, 0.66, 0.0, -1, 0, 0, // v12
		-1.0, -1.0, 1.0, 1.0, 0.0, -1, 0, 0, // v13
		-1.0, 1.0, -1.0, 0.66, 0.5, -1, 0, 0, // v14
		-1.0, 1.0, 1.0, 1.0, 0.5, -1, 0, 0, // v15

		// Vertex data for face 4
		-1.0, -1.0, -1.0, 0.33, 0.0, 0, -1, 0, // v16
		1.0, -1.0, -1.0, 0.66, 0.0, 0, -1, 0, // v17
		-1.0, -1.0, 1.0, 0.33, 0.5, 0, -1, 0, // v18
		1.0, -1.0, 1.0, 0.66, 0.5, 0, -1, 0, // v19

		// Vertex data for face 5
		-1.0, 1.0, 1.0, 0.33, 0.5, 0, 1, 0, // v20
		1.0, 1.0, 1.0, 0.66, 0.5, 0, 1, 0, // v21
		-1.0, 1.0, -1.0, 0.33, 1.0, 0, 1, 0, // v22
		1.0, 1.0, -1.0, 0.66, 1.0, 0, 1, 0, // v23
	}

	var i uint32
	for i = 0; i < 24; i++ {
		var ind = i * 8
		verts[ind+0] = verts[ind+0]*u + x
		verts[ind+1] = verts[ind+1]*v + y
		verts[ind+2] = verts[ind+2]*w + z
	}

	indices := [...]uint32{
		0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0,  v1,  v2,  v3)
		4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4,  v5,  v6,  v7)
		8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8,  v9, v10, v11)
		12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15)
		16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19)
		20, 20, 21, 22, 23, // Face 5 - triangle strip (v20, v21, v22, v23)
	}

	opt := DefaultVBOOptions()
	opt.IsStrip = true
	opt.Normals = 3
	vbo = NewVBO(opt, verts[:], indices[:])

	return vbo
}
<commit_msg>cosmetic<commit_after>package glplus

import "math"

// VBOOptions ...
type VBOOptions struct {
	Vertex  int
	Normals int
	UV      int
	IsStrip bool
	Quads   int
}

// DefaultVBOOptions ...
func DefaultVBOOptions() VBOOptions {
	return VBOOptions{
		Vertex: 3,
		UV:     2,
	}
}

// VBO ...
type VBO struct {
	vao        *ENGOGLVertexArray
	vboVerts   *ENGOGLBuffer
	vboIndices *ENGOGLBuffer
	numElem    int
	isShort    bool

	options VBOOptions
}

// DeleteVBO ...
func (v *VBO) DeleteVBO() {
	if v.vboVerts != nil {
		Gl.DeleteBuffer(v.vboVerts)
	}
	if v.vboIndices != nil {
		Gl.DeleteBuffer(v.vboIndices)
	}
	if v.vao != nil {
		Gl.DeleteVertexArray(v.vao)
	}
}

// Bind ...
func (v *VBO) Bind() {
	Gl.BindVertexArray(v.vao)
	if v.options.Vertex != 0 {
		Gl.EnableVertexAttribArray(gPositionAttr)
	}
	if v.options.UV != 0 {
		Gl.EnableVertexAttribArray(gUVsAttr)
	}
	if v.options.Normals != 0 {
		Gl.EnableVertexAttribArray(gNormalsAttr)
	}
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, v.vboIndices)
	} else {
		Gl.BindBuffer(Gl.ARRAY_BUFFER, v.vboVerts)
	}
}

// Unbind ...
func (v *VBO) Unbind() {
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, nil)
	} else {
		Gl.BindBuffer(Gl.ARRAY_BUFFER, nil)
	}
	if v.options.Vertex != 0 {
		Gl.DisableVertexAttribArray(gPositionAttr)
	}
	if v.options.UV != 0 {
		Gl.DisableVertexAttribArray(gUVsAttr)
	}
	if v.options.Normals != 0 {
		Gl.DisableVertexAttribArray(gNormalsAttr)
	}
	Gl.BindVertexArray(nil)
}

func (v *VBO) elemType() int {
	if v.isShort {
		return Gl.UNSIGNED_SHORT
	}

	return Gl.UNSIGNED_INT
}

// Draw ...
func (v *VBO) Draw() {
	if v.vboIndices != nil {
		if v.options.Quads != 0 {
			Gl.DrawElements(Gl.TRIANGLES, v.options.Quads*6, v.elemType(), 0)
		} else if v.options.IsStrip {
			Gl.DrawElements(Gl.TRIANGLE_STRIP, v.numElem, v.elemType(), 0)
		} else {
			Gl.DrawElements(Gl.TRIANGLES, v.numElem, v.elemType(), 0)
		}
	} else {
		if v.options.Quads != 0 {
			Gl.DrawArrays(Gl.TRIANGLES, 0, v.options.Quads*6)
		} else if v.options.IsStrip {
			Gl.DrawArrays(Gl.TRIANGLE_STRIP, 0, v.numElem)
		} else {
			Gl.DrawArrays(Gl.TRIANGLES, 0, v.numElem)
		}
	}
}

// Load ...
func (v *VBO) load(verts []float32, indices []uint32) {
	Gl.BindVertexArray(v.vao)
	Gl.BindBuffer(Gl.ARRAY_BUFFER, v.vboVerts)
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, v.vboIndices)
	}

	// load our data up and bind it to the 'position' shader attribute
	Gl.BufferData(Gl.ARRAY_BUFFER, verts, Gl.STATIC_DRAW)

	if v.vboIndices != nil {
		if len(indices) < math.MaxUint16 {
			v.isShort = true
			uindices := make([]uint16, len(indices))
			for i, ind := range indices {
				uindices[i] = uint16(ind)
			}
			Gl.BufferData(Gl.ELEMENT_ARRAY_BUFFER, uindices, Gl.STATIC_DRAW)
		} else {
			Gl.BufferData(Gl.ELEMENT_ARRAY_BUFFER, indices, Gl.STATIC_DRAW)
		}
	}

	var numElemsPerVertex = v.options.Vertex + v.options.UV + v.options.Normals
	var totalSize = numElemsPerVertex * 4
	var offset int
	if v.options.Vertex != 0 {
		Gl.VertexAttribPointer(gPositionAttr, v.options.Vertex, Gl.FLOAT, false, totalSize, offset)
		offset += v.options.Vertex * 4
	}
	if v.options.UV != 0 {
		Gl.VertexAttribPointer(gUVsAttr, v.options.UV, Gl.FLOAT, false, totalSize, offset)
		offset += v.options.UV * 4
	}
	if v.options.Normals != 0 {
		Gl.VertexAttribPointer(gNormalsAttr, v.options.Normals, Gl.FLOAT, false, totalSize, offset)
	}

	Gl.BindBuffer(Gl.ARRAY_BUFFER, nil)
	if v.vboIndices != nil {
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, nil)
	}
	Gl.BindVertexArray(nil)

	if v.vboIndices != nil {
		v.numElem = len(indices)
	} else {
		v.numElem = len(verts) / numElemsPerVertex
	}
}

// NewVBO ...
func NewVBO(options VBOOptions, verts []float32, indices []uint32) (vbo *VBO) {
	// create and bind the required VAO object
	var vao *ENGOGLVertexArray
	vao = Gl.CreateVertexArray()
	Gl.BindVertexArray(vao)

	// create a VBO to hold the vertex data
	var vboVerts *ENGOGLBuffer
	var vboIndices *ENGOGLBuffer
	vboVerts = Gl.CreateBuffer()
	if indices != nil {
		vboIndices = Gl.CreateBuffer()
	}

	vbo = &VBO{vao: vao,
		vboVerts:   vboVerts,
		vboIndices: vboIndices,
		numElem:    0,
		options:    options,
	}
	Gl.BindVertexArray(nil)

	vbo.load(verts, indices)

	return vbo
}

// NewVBOQuad ...
func NewVBOQuad(x float32, y float32, w float32, h float32) (vbo *VBO) {

	verts := [...]float32{
		x, y, 0.0, 0, 0,
		x + w, y, 0.0, 1, 0,
		x + w, y + h, 0.0, 1, 1,
		x, y + h, 0.0, 0, 1,
	}

	indices := [...]uint32{
		0, 1, 2,
		2, 3, 0,
	}

	vbo = NewVBO(DefaultVBOOptions(), verts[:], indices[:])
	return vbo
}

// NewVBOCube ...
func NewVBOCube(x float32, y float32, z float32, u float32, v float32, w float32) (vbo *VBO) {
	verts := [...]float32{
		// front
		-1.0, -1.0, 1.0, 0, 0,
		1.0, -1.0, 1.0, 0, 0,
		1.0, 1.0, 1.0, 0, 0,
		-1.0, 1.0, 1.0, 0, 0,
		// back
		-1.0, -1.0, -1.0, 0, 0,
		1.0, -1.0, -1.0, 0, 0,
		1.0, 1.0, -1.0, 0, 0,
		-1.0, 1.0, -1.0, 0, 0,
	}

	var i uint32
	for i = 0; i < 8; i++ {
		var ind = i * 5
		verts[ind+0] = verts[ind+0]*u + x
		verts[ind+1] = verts[ind+1]*v + y
		verts[ind+2] = verts[ind+2]*w + z
	}

	indices := [...]uint32{
		// front
		0, 1, 2,
		2, 3, 0,
		// top
		1, 5, 6,
		6, 2, 1,
		// back
		7, 6, 5,
		5, 4, 7,
		// bottom
		4, 0, 3,
		3, 7, 4,
		// left
		4, 5, 1,
		1, 0, 4,
		// right
		3, 2, 6,
		6, 7, 3,
	}

	vbo = NewVBO(DefaultVBOOptions(), verts[:], indices[:])
	return vbo
}

// NewVBOCubeNormal ...
func NewVBOCubeNormal(x float32, y float32, z float32, u float32, v float32, w float32) (vbo *VBO) {
	verts := [...]float32{
		// Vertex data for face 0
		-1.0, -1.0, 1.0, 0.0, 0.0, 0, 0, 1, // v0
		1.0, -1.0, 1.0, 0.33, 0.0, 0, 0, 1, // v1
		-1.0, 1.0, 1.0, 0.0, 0.5, 0, 0, 1, // v2
		1.0, 1.0, 1.0, 0.33, 0.5, 0, 0, 1, // v3

		// Vertex data for face 1
		1.0, -1.0, 1.0, 0.0, 0.5, 1, 0, 0, // v4
		1.0, -1.0, -1.0, 0.33, 0.5, 1, 0, 0, // v5
		1.0, 1.0, 1.0, 0.0, 1.0, 1, 0, 0, // v6
		1.0, 1.0, -1.0, 0.33, 1.0, 1, 0, 0, // v7

		// Vertex data for face 2
		1.0, -1.0, -1.0, 0.66, 0.5, 0, 0, -1, // v8
		-1.0, -1.0, -1.0, 1.0, 0.5, 0, 0, -1, // v9
		1.0, 1.0, -1.0, 0.66, 1.0, 0, 0, -1, // v10
		-1.0, 1.0, -1.0, 1.0, 1.0, 0, 0, -1, // v11

		// Vertex data for face 3
		-1.0, -1.0, -1.0, 0.66, 0.0, -1, 0, 0, // v12
		-1.0, -1.0, 1.0, 1.0, 0.0, -1, 0, 0, // v13
		-1.0, 1.0, -1.0, 0.66, 0.5, -1, 0, 0, // v14
		-1.0, 1.0, 1.0, 1.0, 0.5, -1, 0, 0, // v15

		// Vertex data for face 4
		-1.0, -1.0, -1.0, 0.33, 0.0, 0, -1, 0, // v16
		1.0, -1.0, -1.0, 0.66, 0.0, 0, -1, 0, // v17
		-1.0, -1.0, 1.0, 0.33, 0.5, 0, -1, 0, // v18
		1.0, -1.0, 1.0, 0.66, 0.5, 0, -1, 0, // v19

		// Vertex data for face 5
		-1.0, 1.0, 1.0, 0.33, 0.5, 0, 1, 0, // v20
		1.0, 1.0, 1.0, 0.66, 0.5, 0, 1, 0, // v21
		-1.0, 1.0, -1.0, 0.33, 1.0, 0, 1, 0, // v22
		1.0, 1.0, -1.0, 0.66, 1.0, 0, 1, 0, // v23
	}

	var i uint32
	for i = 0; i < 24; i++ {
		var ind = i * 8
		verts[ind+0] = verts[ind+0]*u + x
		verts[ind+1] = verts[ind+1]*v + y
		verts[ind+2] = verts[ind+2]*w + z
	}

	indices := [...]uint32{
		0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0,  v1,  v2,  v3)
		4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4,  v5,  v6,  v7)
		8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8,  v9, v10, v11)
		12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15)
		16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19)
		20, 20, 21, 22, 23, // Face 5 - triangle strip (v20, v21, v22, v23)
	}

	opt := DefaultVBOOptions()
	opt.IsStrip = true
	opt.Normals = 3
	vbo = NewVBO(opt, verts[:], indices[:])

	return vbo
}
<|endoftext|>


<commit_before>// Package fibvec provides a vector that can store unsigned integers by first
// converting them to their fibonacci encoded values before saving to a bit
// array. This can save memory space (especially for small values) in exchange
// for slower operations.
package fibvec

import (
	"bytes"
	"encoding/gob"
	"unsafe"

	"github.com/robskie/bit"
)

const (
	// These variables affects the size and
	// speed of the vector. Lower values means
	// larger size but faster Gets and vice versa.

	// sr is the rank sampling block size.
	// This represents the number of bits in
	// each rank sampling block.
	sr = 1024

	// ss is the number of 1s in each select
	// sampling block. Note that the number of
	// bits in each block varies.
	ss = 256
)

// Vector represents a container for unsigned integers.
type Vector struct {
	bits *bit.Array

	// ranks[i] is the number of 11s
	// from 0 to index (i*sr)-1
	ranks []int

	// indices[i] points to the
	// beginning of the uint64 (LSB)
	// that contains the (i*ss)+1th
	// pair of bits.
	indices []int

	popcount int

	length      int
	initialized bool
}

// Initialize vector
func (v *Vector) init() {
	v.bits = bit.NewArray(0)
	v.ranks = make([]int, 1)
	v.indices = make([]int, 1)

	// Add terminating bits
	v.bits.Add(0x3, 3)

	v.initialized = true
}

// NewVector creates a new vector.
func NewVector() *Vector {
	vec := &Vector{}
	vec.init()
	return vec
}

// Add adds an integer to the vector.
func (v *Vector) Add(n int) {
	if n > MaxValue || n < MinValue {
		panic("fibvec: input is not in the range of encodable values")
	} else if !v.initialized {
		v.init()
	}

	// Convert to sign-magnitude representation
	// so that "small" negative numbers such as
	// -1, -2, -3... can be encoded
	nn := toSignMagnitude(n)

	v.length++
	idx := v.bits.Len() - 3
	fc, lfc := fibencode(nn)
	size := lfc

	if lfc > 64 {
		v.bits.Insert(idx, fc[0], 64)
		lfc -= 64

		for _, f := range fc[1 : len(fc)-1] {
			v.bits.Add(f, 64)
			lfc -= 64
		}
		v.bits.Add(fc[len(fc)-1], lfc)
	} else {
		v.bits.Insert(idx, fc[0], lfc)
	}

	// Add bit padding so that pairs
	// of 1 (11s) don't get separated
	// by array boundaries.
	if (v.bits.Len()-1)&63 == 62 {
		v.bits.Add(0x3, 2)
	}

	v.popcount++
	vlen := v.bits.Len()

	lenranks := len(v.ranks)
	overflow := vlen - (lenranks * sr)
	if overflow > 0 {
		v.ranks = append(v.ranks, 0)
		v.ranks[lenranks] = v.popcount
		if size <= overflow {
			v.ranks[lenranks]--
		}
	}

	lenidx := len(v.indices)
	if v.popcount-(lenidx*ss) > 0 {
		v.indices = append(v.indices, 0)
		v.indices[lenidx] = idx ^ 0x3F
	}

	// Add terminating bits so that
	// the last value can be decoded
	v.bits.Add(0x3, 3)
}

// Get returns the value at index i.
func (v *Vector) Get(i int) int {
	if i >= v.length {
		panic("fibvec: index out of bounds")
	} else if i < 0 {
		panic("fibvec: invalid index")
	}

	idx := v.select11(i + 1)
	bits := v.bits.Bits()

	// Temporary store and
	// zero out extra bits
	aidx := idx >> 6
	bidx := idx & 63
	temp := bits[aidx]
	bits[aidx] &= ^((1 << uint(bidx)) - 1)

	// Transform to bytes
	bytes := byteSliceFromUint64Slice(bits)
	bytes = bytes[idx>>3:]

	// This makes sure that the last number is decoded
	if len(bytes) < 16 {
		bytes = append(bytes, []byte{0, 0}...)
	}
	result := fibdecode(bytes, 1)

	// Restore bits
	bits[aidx] = temp

	return result[0]
}

// GetValues returns the values from start to end-1.
func (v *Vector) GetValues(start, end int) []int {
	if end-start <= 0 {
		panic("fibvec: end must be greater than start")
	} else if start < 0 || end < 0 {
		panic("fibvec: invalid index")
	} else if end > v.length {
		panic("fibvec: index out of bounds")
	}

	idx := v.select11(start + 1)
	bits := v.bits.Bits()

	// Temporary store and
	// zero out extra bits
	aidx := idx >> 6
	bidx := idx & 63
	temp := bits[aidx]
	bits[aidx] &= ^((1 << uint(bidx)) - 1)

	// Transform to bytes
	bytes := byteSliceFromUint64Slice(bits)
	bytes = bytes[idx>>3:]

	// This makes sure that the last number is decoded
	if len(bytes) < 16 {
		bytes = append(bytes, []byte{0, 0}...)
	}
	results := fibdecode(bytes, end-start)

	// Restore bits
	bits[aidx] = temp

	return results
}

// Size returns the vector size in bytes.
func (v *Vector) Size() int {
	sizeofInt := int(unsafe.Sizeof(int(0)))

	size := v.bits.Size()
	size += len(v.ranks) * sizeofInt
	size += len(v.indices) * sizeofInt

	return size
}

// Len returns the number of values stored.
func (v *Vector) Len() int {
	return v.length
}

// GobEncode encodes this vector into gob streams.
func (v *Vector) GobEncode() ([]byte, error) {
	buf := &bytes.Buffer{}
	enc := gob.NewEncoder(buf)

	enc.Encode(v.bits)
	enc.Encode(v.ranks)
	enc.Encode(v.indices)
	enc.Encode(v.popcount)
	enc.Encode(v.length)
	enc.Encode(v.initialized)

	return buf.Bytes(), nil
}

// GobDecode populates this vector from gob streams.
func (v *Vector) GobDecode(data []byte) error {
	buf := bytes.NewReader(data)
	dec := gob.NewDecoder(buf)

	dec.Decode(v.bits)
	dec.Decode(&v.ranks)
	dec.Decode(&v.indices)
	dec.Decode(&v.popcount)
	dec.Decode(&v.length)
	dec.Decode(&v.initialized)

	return nil
}

// select11 selects the ith 11 pair.
//
// Taken from "Fast, Small, Simple Rank/Select
// on Bitmaps" by Navarro et al., with some minor
// modifications.
func (v *Vector) select11(i int) int {
	const m = 0xC000000000000000

	j := (i - 1) / ss
	q := v.indices[j] / sr

	k := 0
	r := 0
	rq := v.ranks[q:]
	for k, r = range rq {
		if r >= i {
			k--
			break
		}
	}

	idx := 0
	rank := rq[k]
	vbits := v.bits.Bits()
	aidx := ((q + k) * sr) >> 6

	vbits = vbits[aidx:]
	for ii, b := range vbits {
		rank += popcount11_64(b)

		// If b ends with 11 and the next bits
		// starts with 1, then the 11 in b is
		// not the beginning of an encoded value,
		// but popcount11_64 has already counted
		// it so we need to subtract 1 to rank
		if b&m == m && vbits[ii+1]&1 == 1 {
			rank--
		}

		if rank >= i {
			idx = (aidx + ii) << 6
			overflow := rank - i
			popcnt := popcount11_64(b)
			if b&m == m && vbits[ii+1]&1 == 1 {
				popcnt--
			}

			idx += select11_64(b, popcnt-overflow)

			break
		}
	}

	return idx
}

// popcount11 counts the number of 11 pairs
// in v. This assumes that v doesn't contain
// more than 3 consecutive 1s. This assumption
// is satisfied since the minimum encoded value
// is 011.
func popcount11_64(v uint64) int {
	// Reduce cluster of 1s by 1.
	// This makes 11 to 01, 111 to 011,
	// and unsets all 1s.
	v &= v >> 1

	// Reduces all 11s to 10s
	// while maintaining all lone 1s.
	v &= ^(v >> 1)

	// Proceed to regular bit counting
	return bit.PopCount(v)
}

// select11 returns the index of the ith 11 pair.
func select11_64(v uint64, i int) int {
	// Same with popcount11
	v &= v >> 1
	v &= ^(v >> 1)

	// Perform regular select
	return bit.Select(v, i)
}
<commit_msg>Fixed GobDecode method<commit_after>// Package fibvec provides a vector that can store unsigned integers by first
// converting them to their fibonacci encoded values before saving to a bit
// array. This can save memory space (especially for small values) in exchange
// for slower operations.
package fibvec

import (
	"bytes"
	"encoding/gob"
	"unsafe"

	"github.com/robskie/bit"
)

const (
	// These variables affects the size and
	// speed of the vector. Lower values means
	// larger size but faster Gets and vice versa.

	// sr is the rank sampling block size.
	// This represents the number of bits in
	// each rank sampling block.
	sr = 1024

	// ss is the number of 1s in each select
	// sampling block. Note that the number of
	// bits in each block varies.
	ss = 256
)

// Vector represents a container for unsigned integers.
type Vector struct {
	bits *bit.Array

	// ranks[i] is the number of 11s
	// from 0 to index (i*sr)-1
	ranks []int

	// indices[i] points to the
	// beginning of the uint64 (LSB)
	// that contains the (i*ss)+1th
	// pair of bits.
	indices []int

	popcount int

	length      int
	initialized bool
}

// Initialize vector
func (v *Vector) init() {
	v.bits = bit.NewArray(0)
	v.ranks = make([]int, 1)
	v.indices = make([]int, 1)

	// Add terminating bits
	v.bits.Add(0x3, 3)

	v.initialized = true
}

// NewVector creates a new vector.
func NewVector() *Vector {
	vec := &Vector{}
	vec.init()
	return vec
}

// Add adds an integer to the vector.
func (v *Vector) Add(n int) {
	if n > MaxValue || n < MinValue {
		panic("fibvec: input is not in the range of encodable values")
	} else if !v.initialized {
		v.init()
	}

	// Convert to sign-magnitude representation
	// so that "small" negative numbers such as
	// -1, -2, -3... can be encoded
	nn := toSignMagnitude(n)

	v.length++
	idx := v.bits.Len() - 3
	fc, lfc := fibencode(nn)
	size := lfc

	if lfc > 64 {
		v.bits.Insert(idx, fc[0], 64)
		lfc -= 64

		for _, f := range fc[1 : len(fc)-1] {
			v.bits.Add(f, 64)
			lfc -= 64
		}
		v.bits.Add(fc[len(fc)-1], lfc)
	} else {
		v.bits.Insert(idx, fc[0], lfc)
	}

	// Add bit padding so that pairs
	// of 1 (11s) don't get separated
	// by array boundaries.
	if (v.bits.Len()-1)&63 == 62 {
		v.bits.Add(0x3, 2)
	}

	v.popcount++
	vlen := v.bits.Len()

	lenranks := len(v.ranks)
	overflow := vlen - (lenranks * sr)
	if overflow > 0 {
		v.ranks = append(v.ranks, 0)
		v.ranks[lenranks] = v.popcount
		if size <= overflow {
			v.ranks[lenranks]--
		}
	}

	lenidx := len(v.indices)
	if v.popcount-(lenidx*ss) > 0 {
		v.indices = append(v.indices, 0)
		v.indices[lenidx] = idx ^ 0x3F
	}

	// Add terminating bits so that
	// the last value can be decoded
	v.bits.Add(0x3, 3)
}

// Get returns the value at index i.
func (v *Vector) Get(i int) int {
	if i >= v.length {
		panic("fibvec: index out of bounds")
	} else if i < 0 {
		panic("fibvec: invalid index")
	}

	idx := v.select11(i + 1)
	bits := v.bits.Bits()

	// Temporary store and
	// zero out extra bits
	aidx := idx >> 6
	bidx := idx & 63
	temp := bits[aidx]
	bits[aidx] &= ^((1 << uint(bidx)) - 1)

	// Transform to bytes
	bytes := byteSliceFromUint64Slice(bits)
	bytes = bytes[idx>>3:]

	// This makes sure that the last number is decoded
	if len(bytes) < 16 {
		bytes = append(bytes, []byte{0, 0}...)
	}
	result := fibdecode(bytes, 1)

	// Restore bits
	bits[aidx] = temp

	return result[0]
}

// GetValues returns the values from start to end-1.
func (v *Vector) GetValues(start, end int) []int {
	if end-start <= 0 {
		panic("fibvec: end must be greater than start")
	} else if start < 0 || end < 0 {
		panic("fibvec: invalid index")
	} else if end > v.length {
		panic("fibvec: index out of bounds")
	}

	idx := v.select11(start + 1)
	bits := v.bits.Bits()

	// Temporary store and
	// zero out extra bits
	aidx := idx >> 6
	bidx := idx & 63
	temp := bits[aidx]
	bits[aidx] &= ^((1 << uint(bidx)) - 1)

	// Transform to bytes
	bytes := byteSliceFromUint64Slice(bits)
	bytes = bytes[idx>>3:]

	// This makes sure that the last number is decoded
	if len(bytes) < 16 {
		bytes = append(bytes, []byte{0, 0}...)
	}
	results := fibdecode(bytes, end-start)

	// Restore bits
	bits[aidx] = temp

	return results
}

// Size returns the vector size in bytes.
func (v *Vector) Size() int {
	sizeofInt := int(unsafe.Sizeof(int(0)))

	size := v.bits.Size()
	size += len(v.ranks) * sizeofInt
	size += len(v.indices) * sizeofInt

	return size
}

// Len returns the number of values stored.
func (v *Vector) Len() int {
	return v.length
}

// GobEncode encodes this vector into gob streams.
func (v *Vector) GobEncode() ([]byte, error) {
	buf := &bytes.Buffer{}
	enc := gob.NewEncoder(buf)

	enc.Encode(v.bits)
	enc.Encode(v.ranks)
	enc.Encode(v.indices)
	enc.Encode(v.popcount)
	enc.Encode(v.length)
	enc.Encode(v.initialized)

	return buf.Bytes(), nil
}

// GobDecode populates this vector from gob streams.
func (v *Vector) GobDecode(data []byte) error {
	buf := bytes.NewReader(data)
	dec := gob.NewDecoder(buf)

	if v.bits == nil {
		v.bits = bit.NewArray(0)
	}

	dec.Decode(v.bits)
	dec.Decode(&v.ranks)
	dec.Decode(&v.indices)
	dec.Decode(&v.popcount)
	dec.Decode(&v.length)
	dec.Decode(&v.initialized)

	return nil
}

// select11 selects the ith 11 pair.
//
// Taken from "Fast, Small, Simple Rank/Select
// on Bitmaps" by Navarro et al., with some minor
// modifications.
func (v *Vector) select11(i int) int {
	const m = 0xC000000000000000

	j := (i - 1) / ss
	q := v.indices[j] / sr

	k := 0
	r := 0
	rq := v.ranks[q:]
	for k, r = range rq {
		if r >= i {
			k--
			break
		}
	}

	idx := 0
	rank := rq[k]
	vbits := v.bits.Bits()
	aidx := ((q + k) * sr) >> 6

	vbits = vbits[aidx:]
	for ii, b := range vbits {
		rank += popcount11_64(b)

		// If b ends with 11 and the next bits
		// starts with 1, then the 11 in b is
		// not the beginning of an encoded value,
		// but popcount11_64 has already counted
		// it so we need to subtract 1 to rank
		if b&m == m && vbits[ii+1]&1 == 1 {
			rank--
		}

		if rank >= i {
			idx = (aidx + ii) << 6
			overflow := rank - i
			popcnt := popcount11_64(b)
			if b&m == m && vbits[ii+1]&1 == 1 {
				popcnt--
			}

			idx += select11_64(b, popcnt-overflow)

			break
		}
	}

	return idx
}

// popcount11 counts the number of 11 pairs
// in v. This assumes that v doesn't contain
// more than 3 consecutive 1s. This assumption
// is satisfied since the minimum encoded value
// is 011.
func popcount11_64(v uint64) int {
	// Reduce cluster of 1s by 1.
	// This makes 11 to 01, 111 to 011,
	// and unsets all 1s.
	v &= v >> 1

	// Reduces all 11s to 10s
	// while maintaining all lone 1s.
	v &= ^(v >> 1)

	// Proceed to regular bit counting
	return bit.PopCount(v)
}

// select11 returns the index of the ith 11 pair.
func select11_64(v uint64, i int) int {
	// Same with popcount11
	v &= v >> 1
	v &= ^(v >> 1)

	// Perform regular select
	return bit.Select(v, i)
}
<|endoftext|>


<commit_before>package goarmorapi

const (
	CtxKeyConfig CtxKey = iota
	CtxKeyLogger
)

type CtxKey int
<commit_msg>minor<commit_after>package goarmorapi

const (
	CtxKeyConfig CtxKey = iota
	CtxKeyLogger
	CtxKeyRandSrc
)

type CtxKey int
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"net/http"
	"reflect"
	"strings"
)

type Handler struct {
	methods map[string]*Method
}

type Method struct {
	api               reflect.Value
	reqType, respType reflect.Type
	name              string
	fn                reflect.Value
}

var errorType = reflect.TypeOf((*error)(nil)).Elem()

func NewHandler() *Handler {
	return &Handler{
		methods: make(map[string]*Method),
	}
}

func (h *Handler) Register(o interface{}) {
	objType := reflect.TypeOf(o)
	nMethods := objType.NumMethod()
	apiValue := reflect.ValueOf(o)
	for i := 0; i < nMethods; i++ {
		method := objType.Method(i)
		methodType := method.Type
		nArgs := methodType.NumIn()
		if nArgs != 3 {
			continue
		}
		nReturns := methodType.NumOut()
		if nReturns != 1 {
			continue
		}
		if methodType.Out(0) != errorType {
			continue
		}
		m := &Method{
			api:      apiValue,
			reqType:  methodType.In(1).Elem(),
			respType: methodType.In(2).Elem(),
			name:     method.Name,
			fn:       method.Func,
		}
		h.methods[m.name] = m
	}
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// allow cross origin
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Credentials", "true")
	// requested method
	what := strings.Split(r.URL.Path, "/")[2]
	var method *Method
	var ok bool
	if method, ok = h.methods[what]; !ok { // no method
		http.NotFound(w, r)
		return
	}
	// decode request data
	reqData := reflect.New(method.reqType)
	de := json.NewDecoder(r.Body)
	ce(de.Decode(reqData.Interface()), "decode")
	// call method
	respData := reflect.New(method.respType)
	method.fn.Call([]reflect.Value{
		method.api, reqData, respData,
	})[0].Interface()
	// encode response data
	en := json.NewEncoder(w)
	ce(en.Encode(respData.Interface()), "encode")
}
<commit_msg>fix golang api server<commit_after>package main

import (
	"encoding/json"
	"net/http"
	"reflect"
	"strings"
)

type Handler struct {
	methods map[string]*Method
}

type Method struct {
	api               reflect.Value
	reqType, respType reflect.Type
	name              string
	fn                reflect.Value
}

var errorType = reflect.TypeOf((*error)(nil)).Elem()

func NewHandler() *Handler {
	return &Handler{
		methods: make(map[string]*Method),
	}
}

func (h *Handler) Register(o interface{}) {
	objType := reflect.TypeOf(o)
	nMethods := objType.NumMethod()
	apiValue := reflect.ValueOf(o)
	for i := 0; i < nMethods; i++ {
		method := objType.Method(i)
		methodType := method.Type
		nArgs := methodType.NumIn()
		if nArgs != 3 {
			continue
		}
		nReturns := methodType.NumOut()
		if nReturns != 1 {
			continue
		}
		if methodType.Out(0) != errorType {
			continue
		}
		m := &Method{
			api:      apiValue,
			reqType:  methodType.In(1).Elem(),
			respType: methodType.In(2).Elem(),
			name:     method.Name,
			fn:       method.Func,
		}
		h.methods[m.name] = m
	}
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// allow cross origin
	w.Header().Add("Access-Control-Allow-Origin", "*")
	// requested method
	what := strings.Split(r.URL.Path, "/")[2]
	var method *Method
	var ok bool
	if method, ok = h.methods[what]; !ok { // no method
		http.NotFound(w, r)
		return
	}
	// decode request data
	reqData := reflect.New(method.reqType)
	de := json.NewDecoder(r.Body)
	ce(de.Decode(reqData.Interface()), "decode")
	// call method
	respData := reflect.New(method.respType)
	method.fn.Call([]reflect.Value{
		method.api, reqData, respData,
	})[0].Interface()
	// encode response data
	en := json.NewEncoder(w)
	ce(en.Encode(respData.Interface()), "encode")
}
<|endoftext|>


<commit_before>/*
Package golibwireshark use libwireshark library to decode pcap file.
*/
package golibwireshark

/*
#cgo pkg-config: glib-2.0
#cgo LDFLAGS: -lwiretap -lwsutil -lwireshark
#cgo CFLAGS: -I.
#cgo CFLAGS: -I/usr/include/glib-2.0
#cgo CFLAGS: -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
#cgo CFLAGS: -I/usr/include/wireshark
#cgo CFLAGS: -I/usr/include/wireshark/wiretap
#cgo CFLAGS: -I./include

#include "./include/lib.h"

*/
import "C"
import (
	"fmt"
	"unsafe"
)

//Packet data index after dissection
type Packet struct {
	Edt   *C.struct_epan_dissect //packet data index after dissected
	Field *C.struct__proto_node  //packet field index
}

//Init initializing the dissection. If open inputfile or savefile fail,
//return err. After dissection finish, should use Clean() to end the dissection.
//Do it before GetPacket().
func Init(inputfile, savefile string) error {
	var err C.int

	if savefile == "" {
		err = C.init(C.CString(inputfile), nil)
	} else {
		err = C.init(C.CString(inputfile), C.CString(savefile))
	}

	if err != 0 {
		return fmt.Errorf("can't open file")
	}
	return nil
}

//Clean to end the dissection.
func Clean() {

	C.clean()
}

//Iskey find a key in packet dissection data. If key exists, return value,
//otherwise return "".
func (p Packet) Iskey(key string) (value string) {
	buf := C.get_field_value(p.Edt, C.CString(key))
	defer C.free(unsafe.Pointer(buf))

	value = C.GoString(buf)
	return value
}

//GetPacket get one packet data index which has been dissected. If no more
//packet to be dissected, Edt return nil.
//After analysing packet data, should use FreePacket() to free packet
//data.
func (p *Packet) GetPacket() {
	var edt *C.struct_epan_dissect
	edt = C.next_packet()
	if edt == nil {
		p.Edt = nil
	}
	p.Edt = edt
}

//FreePacket to release packet memory
func (p *Packet) FreePacket() {
	C.free_packet(p.Edt)
}

//GetField get field index by key. If key exists, return true, Field item equal index,
//otherwise return false and Field item equal nil.
func (p *Packet) GetField(key string) bool {
	p.Field = C.get_field(p.Edt, C.CString(key))
	if p.Field != nil {
		return true
	}
	return false
}

//String do human readable printout. If Field equal nil, print out the packet.
//If Field doesn't equal nil, print out the Field.
func (p Packet) String() string {
	var node *C.struct__proto_node
	var buf string

	if p.Field != nil {
		node = p.Field
		cbuf := C.print_node(node)
		defer C.free(unsafe.Pointer(cbuf))
		buf = C.GoString(cbuf)
	} else {
		node = (p.Edt).tree
		cbuf := C.print_packet(node)
		defer C.free(unsafe.Pointer(cbuf))
		buf = C.GoString(cbuf)
	}

	return buf
}

//WriteToFile write a packet to file. If savefile aren't be initialized,
//return error.
func (p *Packet) WriteToFile() error {
	if i := C.write_to_file(); i == 0 {
		return nil
	} else if i == 1 {
		return fmt.Errorf("output file isn't opened")
	}
	return nil
}
<commit_msg>comments change<commit_after>/*
Package golibwireshark use libwireshark library to decode pcap file.
*/
package golibwireshark

/*
#cgo pkg-config: glib-2.0
#cgo LDFLAGS: -lwiretap -lwsutil -lwireshark
#cgo CFLAGS: -I.
#cgo CFLAGS: -I/usr/include/glib-2.0
#cgo CFLAGS: -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
#cgo CFLAGS: -I/usr/include/wireshark
#cgo CFLAGS: -I/usr/include/wireshark/wiretap
#cgo CFLAGS: -I./include

#include "./include/lib.h"

*/
import "C"
import (
	"fmt"
	"unsafe"
)

//Packet data index after dissection
type Packet struct {
	Edt   *C.struct_epan_dissect //packet data index after dissected
	Field *C.struct__proto_node  //packet field index
}

//Init initializing the dissection. If opening inputfile or savefile fail,
//return err. After dissection finish, should use Clean() to end the dissection.
func Init(inputfile, savefile string) error {
	var err C.int

	if savefile == "" {
		err = C.init(C.CString(inputfile), nil)
	} else {
		err = C.init(C.CString(inputfile), C.CString(savefile))
	}

	if err != 0 {
		return fmt.Errorf("can't open file")
	}
	return nil
}

//Clean to end the dissection.
func Clean() {

	C.clean()
}

//Iskey find a key in packet dissection data. If key exists, return value,
//otherwise return "".
func (p Packet) Iskey(key string) (value string) {
	buf := C.get_field_value(p.Edt, C.CString(key))
	defer C.free(unsafe.Pointer(buf))

	value = C.GoString(buf)
	return value
}

//GetPacket get one packet data index which has been dissected. If no more
//packet to be dissected, Edt return nil.
//After analysing packet data, should use FreePacket() to free packet
//data.
func (p *Packet) GetPacket() {
	var edt *C.struct_epan_dissect
	edt = C.next_packet()
	if edt == nil {
		p.Edt = nil
	}
	p.Edt = edt
}

//FreePacket to release packet memory
func (p *Packet) FreePacket() {
	C.free_packet(p.Edt)
}

//GetField get field index by key. If key exists, return true, Field item equal index,
//otherwise return false and Field item equal nil.
func (p *Packet) GetField(key string) bool {
	p.Field = C.get_field(p.Edt, C.CString(key))
	if p.Field != nil {
		return true
	}
	return false
}

//String do human readable printout. If Field equal nil, print out the packet.
//If Field doesn't equal nil, print out the Field.
func (p Packet) String() string {
	var node *C.struct__proto_node
	var buf string

	if p.Field != nil {
		node = p.Field
		cbuf := C.print_node(node)
		defer C.free(unsafe.Pointer(cbuf))
		buf = C.GoString(cbuf)
	} else {
		node = (p.Edt).tree
		cbuf := C.print_packet(node)
		defer C.free(unsafe.Pointer(cbuf))
		buf = C.GoString(cbuf)
	}

	return buf
}

//WriteToFile write a packet to file. If savefile aren't be initialized,
//return error.
func (p *Packet) WriteToFile() error {
	if i := C.write_to_file(); i == 0 {
		return nil
	} else if i == 1 {
		return fmt.Errorf("output file isn't opened")
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goplay

import (
	"fmt"
	"io"
	"net/http"

	"appengine"
	"appengine/urlfetch"
)

const runUrl = "http://127.0.0.1/compile?output=json"

func init() {
	http.HandleFunc("/compile", compile)
}

func compile(w http.ResponseWriter, r *http.Request) {
	if err := passThru(w, r); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, "Compile server error.")
	}
}

func passThru(w io.Writer, req *http.Request) error {
	c := appengine.NewContext(req)
	client := urlfetch.Client(c)
	defer req.Body.Close()
	r, err := client.Post(runUrl, req.Header.Get("Content-type"), req.Body)
	if err != nil {
		c.Errorf("making POST request:", err)
		return err
	}
	defer r.Body.Close()
	if _, err := io.Copy(w, r.Body); err != nil {
		c.Errorf("copying response Body:", err)
		return err
	}
	return nil
}
<commit_msg>Route the programs to the 1337 localhost port.<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goplay

import (
	"fmt"
	"io"
	"net/http"

	"appengine"
	"appengine/urlfetch"
)

const runUrl = "http://127.0.0.1:1337/compile?output=json"

func init() {
	http.HandleFunc("/compile", compile)
}

func compile(w http.ResponseWriter, r *http.Request) {
	if err := passThru(w, r); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, "Compile server error.")
	}
}

func passThru(w io.Writer, req *http.Request) error {
	c := appengine.NewContext(req)
	client := urlfetch.Client(c)
	defer req.Body.Close()
	r, err := client.Post(runUrl, req.Header.Get("Content-type"), req.Body)
	if err != nil {
		c.Errorf("making POST request:", err)
		return err
	}
	defer r.Body.Close()
	if _, err := io.Copy(w, r.Body); err != nil {
		c.Errorf("copying response Body:", err)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package coder

import (
	"bytes"
	"testing"
	"time"

	"github.com/apache/beam/sdks/go/pkg/beam/core/typex"
)

func TestEncodeDecodeEventTime(t *testing.T) {
	tests := []struct {
		time        time.Time
		errExpected bool
	}{
		{time: time.Unix(0, 0)},
		{time: time.Unix(10, 0)},
		{time: time.Unix(1257894000, 0)},
		{time: time.Unix(0, 1257894000000000000)},
		{time: time.Time{}, errExpected: true},
	}

	for _, test := range tests {
		var buf bytes.Buffer
		err := EncodeEventTime(typex.EventTime(test.time), &buf)
		if test.errExpected {
			if err != nil {
				continue
			}
			t.Fatalf("EncodeEventTime(%v) failed: got nil error", test.time)
		}
		if err != nil {
			t.Fatalf("EncodeEventTime(%v) failed: %v", test.time, err)
		}
		t.Logf("Encoded %v to %v", test.time, buf.Bytes())

		if len(buf.Bytes()) != 8 {
			t.Errorf("EncodeEventTime(%v) = %v, want %v", test.time, len(buf.Bytes()), 8)
		}

		actual, err := DecodeEventTime(&buf)
		if err != nil {
			t.Fatalf("DecodeEventTime(<%v>) failed: %v", test.time, err)
		}
		if (time.Time)(actual) != test.time {
			t.Errorf("DecodeEventTime(<%v>) = %v, want %v", test.time, actual, test.time)
		}
	}
}
<commit_msg>Fix missing license header in test.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 coder

import (
	"bytes"
	"testing"
	"time"

	"github.com/apache/beam/sdks/go/pkg/beam/core/typex"
)

func TestEncodeDecodeEventTime(t *testing.T) {
	tests := []struct {
		time        time.Time
		errExpected bool
	}{
		{time: time.Unix(0, 0)},
		{time: time.Unix(10, 0)},
		{time: time.Unix(1257894000, 0)},
		{time: time.Unix(0, 1257894000000000000)},
		{time: time.Time{}, errExpected: true},
	}

	for _, test := range tests {
		var buf bytes.Buffer
		err := EncodeEventTime(typex.EventTime(test.time), &buf)
		if test.errExpected {
			if err != nil {
				continue
			}
			t.Fatalf("EncodeEventTime(%v) failed: got nil error", test.time)
		}
		if err != nil {
			t.Fatalf("EncodeEventTime(%v) failed: %v", test.time, err)
		}
		t.Logf("Encoded %v to %v", test.time, buf.Bytes())

		if len(buf.Bytes()) != 8 {
			t.Errorf("EncodeEventTime(%v) = %v, want %v", test.time, len(buf.Bytes()), 8)
		}

		actual, err := DecodeEventTime(&buf)
		if err != nil {
			t.Fatalf("DecodeEventTime(<%v>) failed: %v", test.time, err)
		}
		if (time.Time)(actual) != test.time {
			t.Errorf("DecodeEventTime(<%v>) = %v, want %v", test.time, actual, test.time)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	// "log"
	// "os"
	"path"
	// "strings"
	"wpst.me/calf/storage"
)

var cmdExport = &Command{
	UsageLine: "export -s roof -o direcotry",
	Short:     "export data to local file",
	Long: `
export to local system
`,
}

var (
	eroof  string
	edir   string
	eid    string
	etotal int
	elimit int
)

const (
	max_limit = 50
)

func init() {
	cmdExport.Run = runExport
	cmdExport.Flag.StringVar(&eroof, "s", "", "config section name")
	cmdExport.Flag.StringVar(&edir, "o", "", "a local direcotry to export into.")
	cmdExport.Flag.StringVar(&eid, "id", "", "only export a special id.")
	cmdExport.Flag.IntVar(&etotal, "total", 0, "export total count.")
	cmdExport.Flag.IntVar(&elimit, "limit", 10, "export total count.")
}

func runExport(args []string) bool {

	if eroof == "" || edir == "" {
		return false
	}

	mw := storage.NewMetaWrapper(eroof)
	if eid != "" {
		id, err := storage.NewEntryId(eid)
		if err != nil {
			fmt.Printf("error id: %s, %s", eid, err)
			return false
		}
		entry, err := mw.GetEntry(*id)
		if err != nil {
			fmt.Printf("get entry error: %s", err)
			return false
		}
		return _save_export(entry, edir)
	}
	total, err := mw.Count()
	if err != nil {
		fmt.Println(err)
		return false
	}
	fmt.Printf("total: %d\n", total)

	if total == 0 {
		return true
	}

	var (
		limit = elimit
		skip  = 0
	)
	if total < max_limit {
		limit = total
	}

	for skip < total {
		fmt.Printf("start %d/%d\n", skip, total)
		a, err := mw.Browse(limit, skip, map[string]int{"created": storage.DESCENDING})
		if err != nil {
			fmt.Println(err)
			return false
		}

		for _, entry := range a {
			if !_save_export(entry, edir) {
				return false
			}
		}
		skip += limit
	}

	return true
}

func _save_export(entry *storage.Entry, edir string) bool {
	filename := path.Join(edir, entry.Path)
	fmt.Printf("save to: %s ", filename)
	err := storage.Dump(entry, eroof, filename)
	if err != nil {
		fmt.Println(err)
		return false
	} else {
		fmt.Print("ok\n")
	}
	return true
}
<commit_msg>fixes export: do not replace exist file<commit_after>package main

import (
	"fmt"
	// "log"
	"os"
	"path"
	// "strings"
	"wpst.me/calf/storage"
)

var cmdExport = &Command{
	UsageLine: "export -s roof -o direcotry",
	Short:     "export data to local file",
	Long: `
export to local system
`,
}

var (
	eroof  string
	edir   string
	eid    string
	etotal int
	elimit int
)

const (
	max_limit = 50
)

func init() {
	cmdExport.Run = runExport
	cmdExport.Flag.StringVar(&eroof, "s", "", "config section name")
	cmdExport.Flag.StringVar(&edir, "o", "", "a local direcotry to export into.")
	cmdExport.Flag.StringVar(&eid, "id", "", "only export a special id.")
	cmdExport.Flag.IntVar(&etotal, "total", 0, "export total count.")
	cmdExport.Flag.IntVar(&elimit, "limit", 10, "export total count.")
}

func runExport(args []string) bool {

	if eroof == "" || edir == "" {
		return false
	}

	mw := storage.NewMetaWrapper(eroof)
	if eid != "" {
		id, err := storage.NewEntryId(eid)
		if err != nil {
			fmt.Printf("error id: %s, %s", eid, err)
			return false
		}
		entry, err := mw.GetEntry(*id)
		if err != nil {
			fmt.Printf("get entry error: %s", err)
			return false
		}
		return _save_export(entry, edir)
	}
	total, err := mw.Count()
	if err != nil {
		fmt.Println(err)
		return false
	}
	fmt.Printf("total: %d\n", total)

	if total == 0 {
		return true
	}

	var (
		limit = elimit
		skip  = 0
	)
	if total < max_limit {
		limit = total
	}

	for skip < total {
		fmt.Printf("start %d/%d\n", skip, total)
		a, err := mw.Browse(limit, skip, map[string]int{"created": storage.DESCENDING})
		if err != nil {
			fmt.Println(err)
			return false
		}

		for _, entry := range a {
			if !_save_export(entry, edir) {
				return false
			}
		}
		skip += limit
	}

	return true
}

func _save_export(entry *storage.Entry, edir string) bool {
	name := path.Join(edir, entry.Path)
	fmt.Printf("save to: %s ", name)
	if fi, fe := os.Stat(name); fe == nil && fi.Size() == int64(entry.Size) {
		fmt.Println("exist")
		return true
	}
	err := storage.Dump(entry, eroof, name)
	if err != nil {
		fmt.Println(err)
		return false
	} else {
		fmt.Print("ok\n")
	}
	return true
}
<|endoftext|>