<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
	"time"

	"github.com/surma-dump/gouuid"
)

type LocalContainerManager struct {
	Root       string
	m          *sync.Mutex
	containers map[ContainerId]*localContainer
}

type localContainer struct {
	Id        ContainerId
	Root      string
	Cmd       *exec.Cmd
	Done      chan bool
	destroyed chan bool
	Logs      *bytes.Buffer
	Port      int
}

func NewLocalContainerManager() *LocalContainerManager {
	r := &LocalContainerManager{
		m:          &sync.Mutex{},
		containers: map[ContainerId]*localContainer{},
		Root:       filepath.Join(os.TempDir(), "pixelpixel"),
	}
	return r
}

func (lcm *LocalContainerManager) NewContainer(fs *tar.Reader, envInjections []string) (ContainerId, error) {
	id := ContainerId(gouuid.New().String())
	dir := filepath.Join(lcm.Root, id.String())
	err := os.MkdirAll(dir, os.FileMode(0755))
	if err != nil {
		return id, err
	}
	purge := true
	defer func() {
		if purge {
			os.RemoveAll(dir)
		}
	}()

	ctr := &localContainer{
		Id:        id,
		Root:      dir,
		Logs:      &bytes.Buffer{},
		Done:      make(chan bool),
		destroyed: make(chan bool),
	}

	err = ctr.extractFileSystem(fs)
	if err != nil {
		return id, err
	}

	files, err := filepath.Glob(filepath.Join(dir, "*.go"))
	if err != nil {
		return id, err
	}
	ctr.Cmd = exec.Command("go", stringList("run", files)...)
	ctr.Cmd.Dir = dir
	ctr.Cmd.Stdout = ctr.Logs
	ctr.Cmd.Stderr = ctr.Logs
	ctr.Port = <-portGenerator
	ctr.Cmd.Env = stringList(os.Environ(), envInjections, fmt.Sprintf("PORT=%d", ctr.Port))
	err = ctr.Cmd.Start()
	if err != nil {
		return id, err
	}

	go func(ctr *localContainer) {
		err := ctr.Cmd.Wait()
		if ee, ok := err.(*exec.ExitError); !ok || ee.ProcessState.Exited() {
			close(ctr.Done)
		}
	}(ctr)

	lcm.m.Lock()
	lcm.containers[id] = ctr
	lcm.m.Unlock()

	purge = false
	return id, nil
}

func (lcm *LocalContainerManager) AllContainers() []ContainerId {
	r := make([]ContainerId, 0, len(lcm.containers))
	for cid := range lcm.containers {
		r = append(r, cid)
	}
	return r
}

func (lcm *LocalContainerManager) DestroyContainer(id ContainerId, purge bool) error {
	ctr, ok := lcm.containers[id]
	if !ok {
		return os.ErrNotExist
	}

	ctr.Cmd.Process.Signal(os.Interrupt)
	select {
	case <-ctr.Done:
		// Nop
	case <-time.After(1 * time.Second):
		ctr.Cmd.Process.Kill()
		close(ctr.Done)
	}

	lcm.m.Lock()
	delete(lcm.containers, id)
	lcm.m.Unlock()

	if purge {
		os.RemoveAll(ctr.Root)
	}
	close(ctr.destroyed)
	return nil
}

func (lcm *LocalContainerManager) WaitFor(id ContainerId) chan bool {
	ctr, ok := lcm.containers[id]
	if !ok {
		// Since the original channel is gone, return a new one
		// that is closed to signal a finished container.
		// FIXME: This is kind of stupid, isn't it?
		c := make(chan bool)
		close(c)
		return c
	}
	return ctr.Done
}

func (lcm *LocalContainerManager) Logs(id ContainerId) ([]byte, error) {
	ctr, ok := lcm.containers[id]
	if !ok {
		return nil, os.ErrNotExist
	}
	return ctr.Logs.Bytes(), nil
}

func (lcm *LocalContainerManager) SocketAddress(id ContainerId) (string, error) {
	ctr, ok := lcm.containers[id]
	if !ok {
		return "", os.ErrNotExist
	}
	return fmt.Sprintf("localhost:%d", ctr.Port), nil
}

func (lc *localContainer) extractFileSystem(fs *tar.Reader) error {
	hdr, err := fs.Next()
	for err != io.EOF {
		if err != nil {
			return err
		}
		file := filepath.Join(lc.Root, hdr.Name)
		switch hdr.Typeflag {
		case tar.TypeDir:
			err := os.MkdirAll(file, os.FileMode(0755))
			if err != nil {
				return err
			}
		case tar.TypeReg:
			err := lc.writeFile(file, fs)
			if err != nil {
				return err
			}
		default:
			log.Printf("Encountered unknown file type 0x%02x, skipping", hdr.Typeflag)
		}

		hdr, err = fs.Next()
	}
	return nil
}

func (lc *localContainer) writeFile(file string, ff io.Reader) error {
	f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(f, ff)
	return err
}

// Stolen from $GOROOT/src/cmd/go/main.go
// stringList's arguments should be a sequence of string or []string values.
// stringList flattens them into a single []string.
func stringList(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("stringList: invalid argument")
		}
	}
	return x
}

var (
	portGenerator <-chan int
)

func init() {
	c := make(chan int)
	portGenerator = c
	go func() {
		for {
			for i := 49000; i < 65535; i++ {
				c <- i
			}
		}
	}()
}
<commit_msg>Don't use go run because of termination problems<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
	"time"

	"github.com/surma-dump/gouuid"
)

type LocalContainerManager struct {
	Root       string
	m          *sync.Mutex
	containers map[ContainerId]*localContainer
}

type localContainer struct {
	Id        ContainerId
	Root      string
	Cmd       *exec.Cmd
	Done      chan bool
	destroyed chan bool
	Logs      *bytes.Buffer
	Port      int
}

func NewLocalContainerManager() *LocalContainerManager {
	r := &LocalContainerManager{
		m:          &sync.Mutex{},
		containers: map[ContainerId]*localContainer{},
		Root:       filepath.Join(os.TempDir(), "pixelpixel"),
	}
	return r
}

func (lcm *LocalContainerManager) NewContainer(fs *tar.Reader, envInjections []string) (ContainerId, error) {
	id := ContainerId(gouuid.New().String())
	dir := filepath.Join(lcm.Root, id.String())
	err := os.MkdirAll(dir, os.FileMode(0755))
	if err != nil {
		return id, err
	}
	purge := true
	defer func() {
		if purge {
			os.RemoveAll(dir)
		}
	}()

	ctr := &localContainer{
		Id:        id,
		Root:      dir,
		Logs:      &bytes.Buffer{},
		Done:      make(chan bool),
		destroyed: make(chan bool),
	}

	err = ctr.extractFileSystem(fs)
	if err != nil {
		return id, err
	}

	files, err := filepath.Glob(filepath.Join(dir, "*.go"))
	if err != nil {
		return id, err
	}
	ctr.Cmd = exec.Command("go", stringList("build", "-o", "pixel", files)...)
	ctr.Cmd.Dir = dir
	ctr.Cmd.Stdout = ctr.Logs
	ctr.Cmd.Stderr = ctr.Logs
	err = ctr.Cmd.Run()
	if err != nil {
		return id, err
	}

	ctr.Cmd = exec.Command(filepath.Join(dir, "pixel"))
	ctr.Cmd.Dir = dir
	ctr.Cmd.Stdout = ctr.Logs
	ctr.Cmd.Stderr = ctr.Logs
	ctr.Port = <-portGenerator
	ctr.Cmd.Env = stringList(os.Environ(), envInjections, fmt.Sprintf("PORT=%d", ctr.Port))
	err = ctr.Cmd.Start()
	if err != nil {
		return id, err
	}

	go func(ctr *localContainer) {
		err := ctr.Cmd.Wait()
		if ee, ok := err.(*exec.ExitError); !ok || ee.ProcessState.Exited() {
			close(ctr.Done)
		}
	}(ctr)

	lcm.m.Lock()
	lcm.containers[id] = ctr
	lcm.m.Unlock()

	purge = false
	return id, nil
}

func (lcm *LocalContainerManager) AllContainers() []ContainerId {
	r := make([]ContainerId, 0, len(lcm.containers))
	for cid := range lcm.containers {
		r = append(r, cid)
	}
	return r
}

func (lcm *LocalContainerManager) DestroyContainer(id ContainerId, purge bool) error {
	ctr, ok := lcm.containers[id]
	if !ok {
		return os.ErrNotExist
	}

	ctr.Cmd.Process.Signal(os.Interrupt)
	select {
	case <-ctr.Done:
		// Nop
	case <-time.After(1 * time.Second):
		ctr.Cmd.Process.Kill()
		close(ctr.Done)
	}

	lcm.m.Lock()
	delete(lcm.containers, id)
	lcm.m.Unlock()

	if purge {
		os.RemoveAll(ctr.Root)
	}
	close(ctr.destroyed)
	return nil
}

func (lcm *LocalContainerManager) WaitFor(id ContainerId) chan bool {
	ctr, ok := lcm.containers[id]
	if !ok {
		// Since the original channel is gone, return a new one
		// that is closed to signal a finished container.
		// FIXME: This is kind of stupid, isn't it?
		c := make(chan bool)
		close(c)
		return c
	}
	return ctr.Done
}

func (lcm *LocalContainerManager) Logs(id ContainerId) ([]byte, error) {
	ctr, ok := lcm.containers[id]
	if !ok {
		return nil, os.ErrNotExist
	}
	return ctr.Logs.Bytes(), nil
}

func (lcm *LocalContainerManager) SocketAddress(id ContainerId) (string, error) {
	ctr, ok := lcm.containers[id]
	if !ok {
		return "", os.ErrNotExist
	}
	return fmt.Sprintf("localhost:%d", ctr.Port), nil
}

func (lc *localContainer) extractFileSystem(fs *tar.Reader) error {
	hdr, err := fs.Next()
	for err != io.EOF {
		if err != nil {
			return err
		}
		file := filepath.Join(lc.Root, hdr.Name)
		switch hdr.Typeflag {
		case tar.TypeDir:
			err := os.MkdirAll(file, os.FileMode(0755))
			if err != nil {
				return err
			}
		case tar.TypeReg:
			err := lc.writeFile(file, fs)
			if err != nil {
				return err
			}
		default:
			log.Printf("Encountered unknown file type 0x%02x, skipping", hdr.Typeflag)
		}

		hdr, err = fs.Next()
	}
	return nil
}

func (lc *localContainer) writeFile(file string, ff io.Reader) error {
	f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(f, ff)
	return err
}

// Stolen from $GOROOT/src/cmd/go/main.go
// stringList's arguments should be a sequence of string or []string values.
// stringList flattens them into a single []string.
func stringList(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("stringList: invalid argument")
		}
	}
	return x
}

var (
	portGenerator <-chan int
)

func init() {
	c := make(chan int)
	portGenerator = c
	go func() {
		for {
			for i := 49000; i < 65535; i++ {
				c <- i
			}
		}
	}()
}
<|endoftext|>


<commit_before>package device

import (
	"fmt"

	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/validate"
)

// nicValidationRules returns config validation rules for nic devices.
func nicValidationRules(requiredFields []string, optionalFields []string, instConf instance.ConfigReader) map[string]func(value string) error {
	// Define a set of default validators for each field name.
	defaultValidators := map[string]func(value string) error{
		"name":                    validate.Optional(validate.IsInterfaceName, func(_ string) error { return nicCheckNamesUnique(instConf) }),
		"parent":                  validate.IsAny,
		"network":                 validate.IsAny,
		"mtu":                     validate.Optional(validate.IsNetworkMTU),
		"vlan":                    validate.IsNetworkVLAN,
		"gvrp":                    validate.Optional(validate.IsBool),
		"hwaddr":                  validate.IsNetworkMAC,
		"host_name":               validate.IsAny,
		"limits.ingress":          validate.IsAny,
		"limits.egress":           validate.IsAny,
		"limits.max":              validate.IsAny,
		"security.mac_filtering":  validate.IsAny,
		"security.ipv4_filtering": validate.IsAny,
		"security.ipv6_filtering": validate.IsAny,
		"security.port_isolation": validate.Optional(validate.IsBool),
		"maas.subnet.ipv4":        validate.IsAny,
		"maas.subnet.ipv6":        validate.IsAny,
		"ipv4.address":            validate.Optional(validate.IsNetworkAddressV4),
		"ipv6.address":            validate.Optional(validate.IsNetworkAddressV6),
		"ipv4.routes":             validate.Optional(validate.IsNetworkV4List),
		"ipv6.routes":             validate.Optional(validate.IsNetworkV6List),
		"boot.priority":           validate.Optional(validate.IsUint32),
		"ipv4.gateway":            networkValidGateway,
		"ipv6.gateway":            networkValidGateway,
		"ipv4.host_address":       validate.Optional(validate.IsNetworkAddressV4),
		"ipv6.host_address":       validate.Optional(validate.IsNetworkAddressV6),
		"ipv4.host_table":         validate.Optional(validate.IsUint32),
		"ipv6.host_table":         validate.Optional(validate.IsUint32),
		"ipv4.routes.external":    validate.Optional(validate.IsNetworkV4List),
		"ipv6.routes.external":    validate.Optional(validate.IsNetworkV6List),
		"security.acls":           validate.IsAny,
	}

	validators := map[string]func(value string) error{}

	for _, k := range optionalFields {
		defaultValidator := defaultValidators[k]

		// If field doesn't have a known validator, it is an unknown field, skip.
		if defaultValidator == nil {
			continue
		}

		// Wrap the default validator in an empty check as field is optional.
		validators[k] = func(value string) error {
			if value == "" {
				return nil
			}

			return defaultValidator(value)
		}
	}

	// Add required fields last, that way if they are specified in both required and optional
	// field sets, the required one will overwrite the optional validators.
	for _, k := range requiredFields {
		defaultValidator := defaultValidators[k]

		// If field doesn't have a known validator, it is an unknown field, skip.
		if defaultValidator == nil {
			continue
		}

		// Wrap the default validator in a not empty check as field is required.
		validators[k] = func(value string) error {
			err := validate.IsNotEmpty(value)
			if err != nil {
				return err
			}

			return defaultValidator(value)
		}
	}

	return validators
}

// nicHasAutoGateway takes the value of the "ipv4.gateway" or "ipv6.gateway" config keys and returns whether they
// specify whether the gateway mode is automatic or not
func nicHasAutoGateway(value string) bool {
	if value == "" || value == "auto" {
		return true
	}

	return false
}

// nicCheckNamesUnique checks that all the NICs in the instConf's expanded devices have a unique (or unset) name.
func nicCheckNamesUnique(instConf instance.ConfigReader) error {
	seenNICNames := []string{}

	for _, devConfig := range instConf.ExpandedDevices() {
		if devConfig["type"] != "nic" || devConfig["name"] == "" {
			continue
		}

		if shared.StringInSlice(devConfig["name"], seenNICNames) {
			return fmt.Errorf("Duplicate NIC name detected %q", devConfig["name"])
		}

		seenNICNames = append(seenNICNames, devConfig["name"])
	}

	return nil
}
<commit_msg>lxd/device/nic: Add support for validating security.acls.default.{in,e}gress.{action,logged} config keys<commit_after>package device

import (
	"fmt"

	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/network/acl"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/validate"
)

// nicValidationRules returns config validation rules for nic devices.
func nicValidationRules(requiredFields []string, optionalFields []string, instConf instance.ConfigReader) map[string]func(value string) error {
	// Define a set of default validators for each field name.
	defaultValidators := map[string]func(value string) error{
		"name":                    validate.Optional(validate.IsInterfaceName, func(_ string) error { return nicCheckNamesUnique(instConf) }),
		"parent":                  validate.IsAny,
		"network":                 validate.IsAny,
		"mtu":                     validate.Optional(validate.IsNetworkMTU),
		"vlan":                    validate.IsNetworkVLAN,
		"gvrp":                    validate.Optional(validate.IsBool),
		"hwaddr":                  validate.IsNetworkMAC,
		"host_name":               validate.IsAny,
		"limits.ingress":          validate.IsAny,
		"limits.egress":           validate.IsAny,
		"limits.max":              validate.IsAny,
		"security.mac_filtering":  validate.IsAny,
		"security.ipv4_filtering": validate.IsAny,
		"security.ipv6_filtering": validate.IsAny,
		"security.port_isolation": validate.Optional(validate.IsBool),
		"maas.subnet.ipv4":        validate.IsAny,
		"maas.subnet.ipv6":        validate.IsAny,
		"ipv4.address":            validate.Optional(validate.IsNetworkAddressV4),
		"ipv6.address":            validate.Optional(validate.IsNetworkAddressV6),
		"ipv4.routes":             validate.Optional(validate.IsNetworkV4List),
		"ipv6.routes":             validate.Optional(validate.IsNetworkV6List),
		"boot.priority":           validate.Optional(validate.IsUint32),
		"ipv4.gateway":            networkValidGateway,
		"ipv6.gateway":            networkValidGateway,
		"ipv4.host_address":       validate.Optional(validate.IsNetworkAddressV4),
		"ipv6.host_address":       validate.Optional(validate.IsNetworkAddressV6),
		"ipv4.host_table":         validate.Optional(validate.IsUint32),
		"ipv6.host_table":         validate.Optional(validate.IsUint32),
		"ipv4.routes.external":    validate.Optional(validate.IsNetworkV4List),
		"ipv6.routes.external":    validate.Optional(validate.IsNetworkV6List),
		"security.acls":           validate.IsAny,
		"security.acls.default.ingress.action": validate.Optional(func(value string) error {
			return validate.IsOneOf(value, acl.ValidActions)
		}),
		"security.acls.default.egress.action": validate.Optional(func(value string) error {
			return validate.IsOneOf(value, acl.ValidActions)
		}),
		"security.acls.default.ingress.logged": validate.Optional(validate.IsBool),
		"security.acls.default.egress.logged":  validate.Optional(validate.IsBool),
	}

	validators := map[string]func(value string) error{}

	for _, k := range optionalFields {
		defaultValidator := defaultValidators[k]

		// If field doesn't have a known validator, it is an unknown field, skip.
		if defaultValidator == nil {
			continue
		}

		// Wrap the default validator in an empty check as field is optional.
		validators[k] = func(value string) error {
			if value == "" {
				return nil
			}

			return defaultValidator(value)
		}
	}

	// Add required fields last, that way if they are specified in both required and optional
	// field sets, the required one will overwrite the optional validators.
	for _, k := range requiredFields {
		defaultValidator := defaultValidators[k]

		// If field doesn't have a known validator, it is an unknown field, skip.
		if defaultValidator == nil {
			continue
		}

		// Wrap the default validator in a not empty check as field is required.
		validators[k] = func(value string) error {
			err := validate.IsNotEmpty(value)
			if err != nil {
				return err
			}

			return defaultValidator(value)
		}
	}

	return validators
}

// nicHasAutoGateway takes the value of the "ipv4.gateway" or "ipv6.gateway" config keys and returns whether they
// specify whether the gateway mode is automatic or not
func nicHasAutoGateway(value string) bool {
	if value == "" || value == "auto" {
		return true
	}

	return false
}

// nicCheckNamesUnique checks that all the NICs in the instConf's expanded devices have a unique (or unset) name.
func nicCheckNamesUnique(instConf instance.ConfigReader) error {
	seenNICNames := []string{}

	for _, devConfig := range instConf.ExpandedDevices() {
		if devConfig["type"] != "nic" || devConfig["name"] == "" {
			continue
		}

		if shared.StringInSlice(devConfig["name"], seenNICNames) {
			return fmt.Errorf("Duplicate NIC name detected %q", devConfig["name"])
		}

		seenNICNames = append(seenNICNames, devConfig["name"])
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"github.com/codegangsta/cli"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"syscall"
)

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
	log.SetPrefix("magellan-proxy: ")

	app := cli.NewApp()
	app.Name = "magellan-proxy"
	app.Version = Version
	app.Usage = "bypass request to HTTP port"
	app.Author = "Groovenauts,Inc."
	app.Email = "tech@groovenauts.jp"
	app.Action = doMain
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "port, p",
			Value: 80,
			Usage: "Port to foward HTTP request",
		},
		cli.IntFlag{
			Name:  "num, n",
			Value: 1,
			Usage: "Maximum number concurrent HTTP request",
		},
		cli.StringFlag{
			Name: "publish",
			Value: "/publish",
			Usage: "Specify URL path to Post Publish message from MQTT",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:   "run",
			Usage:  "fork and exec command",
			Action: doRun,
		},
	}

	app.Run(os.Args)
}

func doMain(c *cli.Context) {
	doRun(c)
}

func spawn(args []string) (*os.Process, error) {
	if len(args) == 0 {
		log.Println("Please specify command")
		return nil, errors.New("Please specify command")
	}

	arg0 := args[0]
	if arg0 == filepath.Base(arg0) {
		if lp, err := exec.LookPath(arg0); err != nil {
			msg := "command " + arg0 + " not found"
			log.Println(msg)
			return nil, errors.New(msg)
		} else {
			arg0 = lp
		}
	}
	var attr os.ProcAttr
	attr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
	child, err := os.StartProcess(arg0, args, &attr)
	if err != nil {
		log.Printf("fail to os.StartProcess: %s", err.Error())
		return nil, err
	}
	return child, nil
}

func watchChild(child *os.Process, sigchan chan os.Signal) {
	_, _ = child.Wait()
	sigchan <- os.Interrupt
}

func processSignal(sigchan chan os.Signal, child *os.Process, req_ch chan *RequestMessage, exitQueue chan bool) {
	sig := <-sigchan
	_ = child.Signal(sig)
	close(req_ch)
	exitQueue <- true
	close(exitQueue)
}

func processRequest(mq *MessageQueue, req_ch chan *RequestMessage) {
	for req := range req_ch {
		log.Println(req.Request.Env.Method + " " + req.Request.Env.Url)

		res, err := ProcessHttpRequest(&req.Request)
		if err != nil {
			log.Printf("ProcessHttpRequest fail: %s", err.Error())
			res = &Response{
				Headers:      map[string]string{"Content-Type": "text/plain"},
				Status:       "200",
				Body:         []byte("magellan-proxy: ProcessHttpRequest fail: " + err.Error()),
				BodyEncoding: "plain",
			}
		}
		if res != nil {
			mq.Publish(req, res)
		}
	}
}

func doRun(c *cli.Context) {
	mq, err := SetupMessageQueue()
	if err != nil {
		log.Printf("fail to setup MQ: %s", err.Error())
		return
	}
	defer mq.Close()

	req_ch, err := mq.Consume()
	if err != nil {
		log.Printf("fail to get message: %s", err.Error())
		return
	}

	child, err := spawn(c.Args())
	if err != nil {
		return
	}

	sigchan := make(chan os.Signal)
	signal.Notify(sigchan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

	go watchChild(child, sigchan)

	exitQueue := make(chan bool)

	go processSignal(sigchan, child, req_ch, exitQueue)

	jobNum := c.Int("num")
	InitHttpTransport(c.Int("port"), jobNum, c.String("publish"))

	for i := 0; i < jobNum; i++ {
		go processRequest(mq, req_ch)
	}

	for exit_p := range exitQueue {
		if exit_p {
			break
		}
	}
}

// vim:set noexpandtab ts=2:
<commit_msg>wait until backend application server start to listen socket.<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/codegangsta/cli"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"
)

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
	log.SetPrefix("magellan-proxy: ")

	app := cli.NewApp()
	app.Name = "magellan-proxy"
	app.Version = Version
	app.Usage = "bypass request to HTTP port"
	app.Author = "Groovenauts,Inc."
	app.Email = "tech@groovenauts.jp"
	app.Action = doMain
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "port, p",
			Value: 80,
			Usage: "Port to foward HTTP request",
		},
		cli.IntFlag{
			Name:  "num, n",
			Value: 1,
			Usage: "Maximum number concurrent HTTP request",
		},
		cli.StringFlag{
			Name:  "publish",
			Value: "/publish",
			Usage: "Specify URL path to Post Publish message from MQTT",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:   "run",
			Usage:  "fork and exec command",
			Action: doRun,
		},
	}

	app.Run(os.Args)
}

func doMain(c *cli.Context) {
	doRun(c)
}

func spawn(args []string) (*os.Process, error) {
	if len(args) == 0 {
		log.Println("Please specify command")
		return nil, errors.New("Please specify command")
	}

	arg0 := args[0]
	if arg0 == filepath.Base(arg0) {
		if lp, err := exec.LookPath(arg0); err != nil {
			msg := "command " + arg0 + " not found"
			log.Println(msg)
			return nil, errors.New(msg)
		} else {
			arg0 = lp
		}
	}
	var attr os.ProcAttr
	attr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
	child, err := os.StartProcess(arg0, args, &attr)
	if err != nil {
		log.Printf("fail to os.StartProcess: %s", err.Error())
		return nil, err
	}
	return child, nil
}

func watchChild(child *os.Process, sigchan chan os.Signal) {
	_, _ = child.Wait()
	sigchan <- os.Interrupt
}

func processSignal(sigchan chan os.Signal, child *os.Process, req_ch chan *RequestMessage, exitQueue chan bool) {
	sig := <-sigchan
	_ = child.Signal(sig)
	close(req_ch)
	exitQueue <- true
	close(exitQueue)
}

func processRequest(mq *MessageQueue, req_ch chan *RequestMessage) {
	for req := range req_ch {
		log.Println(req.Request.Env.Method + " " + req.Request.Env.Url)

		res, err := ProcessHttpRequest(&req.Request)
		if err != nil {
			log.Printf("ProcessHttpRequest fail: %s", err.Error())
			res = &Response{
				Headers:      map[string]string{"Content-Type": "text/plain"},
				Status:       "200",
				Body:         []byte("magellan-proxy: ProcessHttpRequest fail: " + err.Error()),
				BodyEncoding: "plain",
			}
		}
		if res != nil {
			mq.Publish(req, res)
		}
	}
}

func doRun(c *cli.Context) {
	mq, err := SetupMessageQueue()
	if err != nil {
		log.Printf("fail to setup MQ: %s", err.Error())
		return
	}
	defer mq.Close()

	req_ch, err := mq.Consume()
	if err != nil {
		log.Printf("fail to get message: %s", err.Error())
		return
	}

	child, err := spawn(c.Args())
	if err != nil {
		return
	}

	sigchan := make(chan os.Signal)
	signal.Notify(sigchan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

	go watchChild(child, sigchan)

	exitQueue := make(chan bool)

	go processSignal(sigchan, child, req_ch, exitQueue)

	jobNum := c.Int("num")
	portNo := c.Int("port")
	InitHttpTransport(portNo, jobNum, c.String("publish"))

	// wait until backend application server start to listen socket
	maxWait := 60
	ready := false
	for i := 0; i < maxWait; i++ {
		conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", portNo))
		if err != nil {
			if i == maxWait-1 {
				log.Printf("timeout waiting for application server start to listen socket port:%d, err=%s",
					portNo, err.Error())
				sigchan <- os.Interrupt
			}
			time.Sleep(1000000000) // 1 sec
		} else {
			log.Printf("Confirmed application server listen to 127.0.0.1:#{portNo}")
			conn.Close()
			ready = true
			break
		}
	}

	if ready {
		for i := 0; i < jobNum; i++ {
			go processRequest(mq, req_ch)
		}
	}

	for exit_p := range exitQueue {
		if exit_p {
			break
		}
	}
}

// vim:set noexpandtab ts=2:
<|endoftext|>


<commit_before>package market

import (
	"fmt"

	"github.com/nzai/stockrecorder/db"
	"gopkg.in/mgo.v2/bson"
)

const (
	companiesFileName = "companies.txt"
)

//	公司
type Company struct {
	Market string
	Name   string
	Code   string
}

//	公司列表
type CompanyList []Company

func (l CompanyList) Len() int {
	return len(l)
}
func (l CompanyList) Swap(i, j int) {
	l[i], l[j] = l[j], l[i]
}
func (l CompanyList) Less(i, j int) bool {
	return l[i].Code < l[j].Code
}

//	保存上市公司列表到文件
func (l CompanyList) Save(market Market) error {

	//	连接数据库
	session, err := db.Get()
	if err != nil {
		return fmt.Errorf("[DB]\t获取数据库连接失败:%s", err.Error())
	}
	defer session.Close()

	companies := ([]Company)(l)
	list := make([]interface{}, 0)
	for _, company := range companies {
		list = append(list, company)
	}

	collection := session.DB("stock").C("Company")

	//	删除原有记录
	_, err = collection.RemoveAll(bson.M{"market": market.Name()})
	if err != nil {
		return fmt.Errorf("[DB]\t删除原有上市公司发生错误: %s", err.Error())
	}

	return collection.Insert(list...)
}

//	从存档读取上市公司列表
func (l *CompanyList) Load(market Market) error {
	//	连接数据库
	session, err := db.Get()
	if err != nil {
		return fmt.Errorf("[DB]\t获取数据库连接失败:%s", err.Error())
	}
	defer session.Close()

	var companies []Company
	err = session.DB("stock").C("Company").Find(bson.M{"market": market.Name()}).Sort("code").All(&companies)
	if err != nil {
		return fmt.Errorf("[DB]\t查询上市公司发生错误: %s", err.Error())
	}

	cl := CompanyList(companies)
	l = &cl

	return nil
}
<commit_msg>上市公司列表保存到磁盘文件中<commit_after>package market

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/nzai/stockrecorder/config"
	"github.com/nzai/stockrecorder/io"
)

const (
	companiesFileName = "companies.txt"
)

//	公司
type Company struct {
	Market string
	Name   string
	Code   string
}

//	公司列表
type CompanyList []Company

func (l CompanyList) Len() int {
	return len(l)
}
func (l CompanyList) Swap(i, j int) {
	l[i], l[j] = l[j], l[i]
}
func (l CompanyList) Less(i, j int) bool {
	return l[i].Code < l[j].Code
}

//	保存上市公司列表到文件
func (l CompanyList) Save(market Market) error {

	lines := make([]string, 0)
	companies := ([]Company)(l)
	for _, company := range companies {
		lines = append(lines, fmt.Sprintf("%s\t%s", company.Code, company.Name))
	}

	return io.WriteLines(filepath.Join(config.Get().DataDir, market.Name(), companiesFileName), lines)
}

//	从存档读取上市公司列表
func (l *CompanyList) Load(market Market) error {

	lines, err := io.ReadLines(filepath.Join(config.Get().DataDir, market.Name(), companiesFileName))
	if err != nil {
		return err
	}

	companies := make([]Company, 0)
	for _, line := range lines {
		parts := strings.Split(line, "\t")
		if len(parts) != 2 {
			return fmt.Errorf("[%s]\t上市公司文件格式有错误: %s", market.Name(), line)
		}

		companies = append(companies, Company{
			Market: market.Name(),
			Code:   parts[0],
			Name:   parts[1]})
	}

	cl := CompanyList(companies)
	l = &cl

	return nil
}
<|endoftext|>


<commit_before>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on the CholeskyDecomposition class from Jama 1.0.3.

package mat64

import (
	"math"

	"github.com/gonum/blas"
	"github.com/gonum/blas/blas64"
	"github.com/gonum/lapack/lapack64"
	"github.com/gonum/matrix"
)

const badTriangle = "mat64: invalid triangle"

// Cholesky is a type for creating and using the Cholesky factorization of a
// symmetric positive definite matrix.
type Cholesky struct {
	chol *TriDense
	cond float64
}

// updateCond updates the condition number of the Cholesky decomposition. If
// norm > 0, then that norm is used as the norm of the original matrix A, otherwise
// the norm is estimated from the decomposition.
func (c *Cholesky) updateCond(norm float64) {
	n := c.chol.mat.N
	work := make([]float64, 3*n)
	if norm < 0 {
		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||.
		// Here, A = U^T * U.
		// The condition number is ||A|| || A^-1||, so this will underestimate
		// the condition number somewhat.
		// The norm of the original factorized matrix cannot be stored because of
		// update possibilities.
		unorm := lapack64.Lantr(matrix.CondNorm, c.chol.mat, work)
		lnorm := lapack64.Lantr(matrix.CondNormTrans, c.chol.mat, work)
		norm = unorm * lnorm
	}
	sym := c.chol.asSymBlas()
	iwork := make([]int, n)
	v := lapack64.Pocon(sym, norm, work, iwork)
	c.cond = 1 / v
}

// Factorize calculates the Cholesky decomposition of the matrix A and returns
// whether the matrix is positive definite.
func (c *Cholesky) Factorize(a Symmetric) (ok bool) {
	n := a.Symmetric()
	if c.chol == nil {
		c.chol = NewTriDense(n, matrix.Upper, nil)
	} else {
		c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n))
	}
	copySymIntoTriangle(c.chol, a)

	sym := c.chol.asSymBlas()
	work := make([]float64, c.chol.mat.N)
	norm := lapack64.Lansy(matrix.CondNorm, sym, work)
	_, ok = lapack64.Potrf(sym)
	if ok {
		c.updateCond(norm)
	} else {
		c.cond = math.Inf(1)
	}
	return ok
}

// Det returns the determinant of the matrix that has been factorized.
func (c *Cholesky) Det() float64 {
	return math.Exp(c.LogDet())
}

// Size returns the dimension of the factorized matrix.
func (c *Cholesky) Size() int {
	return c.chol.mat.N
}

// LogDet returns the log of the determinant of the matrix that has been factorized.
func (c *Cholesky) LogDet() float64 {
	var det float64
	for i := 0; i < c.chol.mat.N; i++ {
		det += 2 * math.Log(c.chol.mat.Data[i*c.chol.mat.Stride+i])
	}
	return det
}

// SolveCholesky finds the matrix m that solves A * m = b where A is represented
// by the Cholesky decomposition, placing the result in the receiver.
func (m *Dense) SolveCholesky(chol *Cholesky, b Matrix) error {
	n := chol.chol.mat.N
	bm, bn := b.Dims()
	if n != bm {
		panic(matrix.ErrShape)
	}

	m.reuseAs(bm, bn)
	if b != m {
		m.Copy(b)
	}
	blas64.Trsm(blas.Left, blas.Trans, 1, chol.chol.mat, m.mat)
	blas64.Trsm(blas.Left, blas.NoTrans, 1, chol.chol.mat, m.mat)
	if chol.cond > matrix.ConditionTolerance {
		return matrix.Condition(chol.cond)
	}
	return nil
}

// SolveCholeskyVec finds the vector v that solves A * v = b where A is represented
// by the Cholesky decomposition, placing the result in the receiver.
func (v *Vector) SolveCholeskyVec(chol *Cholesky, b *Vector) error {
	n := chol.chol.mat.N
	vn := b.Len()
	if vn != n {
		panic(matrix.ErrShape)
	}
	if v != b {
		v.checkOverlap(b.mat)
	}
	v.reuseAs(n)
	if v != b {
		v.CopyVec(b)
	}
	blas64.Trsv(blas.Trans, chol.chol.mat, v.mat)
	blas64.Trsv(blas.NoTrans, chol.chol.mat, v.mat)
	if chol.cond > matrix.ConditionTolerance {
		return matrix.Condition(chol.cond)
	}
	return nil

}

// UFromCholesky extracts the n×n upper triangular matrix U from a Cholesky
// decomposition
//  A = U^T * U.
func (t *TriDense) UFromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	t.reuseAs(n, matrix.Upper)
	t.Copy(chol.chol)
}

// LFromCholesky extracts the n×n lower triangular matrix L from a Cholesky
// decomposition
//  A = L * L^T.
func (t *TriDense) LFromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	t.reuseAs(n, matrix.Lower)
	t.Copy(chol.chol.TTri())
}

// FromCholesky reconstructs the original positive definite matrix given its
// Cholesky decomposition.
func (s *SymDense) FromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	s.reuseAs(n)
	s.SymOuterK(1, chol.chol.T())
}

// InverseCholesky computes the inverse of the matrix represented by its Cholesky
// factorization and stores the result into the receiver. If the factorized
// matrix is ill-conditioned, a Condition error will be returned.
// Note that matrix inversion is numerically unstable, and should generally be
// avoided where possible, for example by using the Solve routines.
func (s *SymDense) InverseCholesky(chol *Cholesky) error {
	// TODO(btracey): Replace this code with a direct call to Dpotri when it
	// is available.
	s.reuseAs(chol.chol.mat.N)
	// If:
	//  chol(A) = U^T * U
	// Then:
	//  chol(A^-1) = S * S^T
	// where S = U^-1
	var t TriDense
	err := t.InverseTri(chol.chol)
	s.SymOuterK(1, &t)
	return err
}
<commit_msg>mat64: add Cholesky.SymRankOne<commit_after>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on the CholeskyDecomposition class from Jama 1.0.3.

package mat64

import (
	"math"

	"github.com/gonum/blas"
	"github.com/gonum/blas/blas64"
	"github.com/gonum/lapack/lapack64"
	"github.com/gonum/matrix"
)

const badTriangle = "mat64: invalid triangle"

// Cholesky is a type for creating and using the Cholesky factorization of a
// symmetric positive definite matrix.
type Cholesky struct {
	chol *TriDense
	cond float64
}

// updateCond updates the condition number of the Cholesky decomposition. If
// norm > 0, then that norm is used as the norm of the original matrix A, otherwise
// the norm is estimated from the decomposition.
func (c *Cholesky) updateCond(norm float64) {
	n := c.chol.mat.N
	work := make([]float64, 3*n)
	if norm < 0 {
		// This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||.
		// Here, A = U^T * U.
		// The condition number is ||A|| || A^-1||, so this will underestimate
		// the condition number somewhat.
		// The norm of the original factorized matrix cannot be stored because of
		// update possibilities.
		unorm := lapack64.Lantr(matrix.CondNorm, c.chol.mat, work)
		lnorm := lapack64.Lantr(matrix.CondNormTrans, c.chol.mat, work)
		norm = unorm * lnorm
	}
	sym := c.chol.asSymBlas()
	iwork := make([]int, n)
	v := lapack64.Pocon(sym, norm, work, iwork)
	c.cond = 1 / v
}

// Factorize calculates the Cholesky decomposition of the matrix A and returns
// whether the matrix is positive definite.
func (c *Cholesky) Factorize(a Symmetric) (ok bool) {
	n := a.Symmetric()
	if c.isZero() {
		c.chol = NewTriDense(n, matrix.Upper, nil)
	} else {
		c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n))
	}
	copySymIntoTriangle(c.chol, a)

	sym := c.chol.asSymBlas()
	work := make([]float64, c.chol.mat.N)
	norm := lapack64.Lansy(matrix.CondNorm, sym, work)
	_, ok = lapack64.Potrf(sym)
	if ok {
		c.updateCond(norm)
	} else {
		c.cond = math.Inf(1)
	}
	return ok
}

// Det returns the determinant of the matrix that has been factorized.
func (c *Cholesky) Det() float64 {
	return math.Exp(c.LogDet())
}

// Size returns the dimension of the factorized matrix.
func (c *Cholesky) Size() int {
	return c.chol.mat.N
}

// LogDet returns the log of the determinant of the matrix that has been factorized.
func (c *Cholesky) LogDet() float64 {
	var det float64
	for i := 0; i < c.chol.mat.N; i++ {
		det += 2 * math.Log(c.chol.mat.Data[i*c.chol.mat.Stride+i])
	}
	return det
}

// SolveCholesky finds the matrix m that solves A * m = b where A is represented
// by the Cholesky decomposition, placing the result in the receiver.
func (m *Dense) SolveCholesky(chol *Cholesky, b Matrix) error {
	n := chol.chol.mat.N
	bm, bn := b.Dims()
	if n != bm {
		panic(matrix.ErrShape)
	}

	m.reuseAs(bm, bn)
	if b != m {
		m.Copy(b)
	}
	blas64.Trsm(blas.Left, blas.Trans, 1, chol.chol.mat, m.mat)
	blas64.Trsm(blas.Left, blas.NoTrans, 1, chol.chol.mat, m.mat)
	if chol.cond > matrix.ConditionTolerance {
		return matrix.Condition(chol.cond)
	}
	return nil
}

// SolveCholeskyVec finds the vector v that solves A * v = b where A is represented
// by the Cholesky decomposition, placing the result in the receiver.
func (v *Vector) SolveCholeskyVec(chol *Cholesky, b *Vector) error {
	n := chol.chol.mat.N
	vn := b.Len()
	if vn != n {
		panic(matrix.ErrShape)
	}
	if v != b {
		v.checkOverlap(b.mat)
	}
	v.reuseAs(n)
	if v != b {
		v.CopyVec(b)
	}
	blas64.Trsv(blas.Trans, chol.chol.mat, v.mat)
	blas64.Trsv(blas.NoTrans, chol.chol.mat, v.mat)
	if chol.cond > matrix.ConditionTolerance {
		return matrix.Condition(chol.cond)
	}
	return nil

}

// UFromCholesky extracts the n×n upper triangular matrix U from a Cholesky
// decomposition
//  A = U^T * U.
func (t *TriDense) UFromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	t.reuseAs(n, matrix.Upper)
	t.Copy(chol.chol)
}

// LFromCholesky extracts the n×n lower triangular matrix L from a Cholesky
// decomposition
//  A = L * L^T.
func (t *TriDense) LFromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	t.reuseAs(n, matrix.Lower)
	t.Copy(chol.chol.TTri())
}

// FromCholesky reconstructs the original positive definite matrix given its
// Cholesky decomposition.
func (s *SymDense) FromCholesky(chol *Cholesky) {
	n := chol.chol.mat.N
	s.reuseAs(n)
	s.SymOuterK(1, chol.chol.T())
}

// InverseCholesky computes the inverse of the matrix represented by its Cholesky
// factorization and stores the result into the receiver. If the factorized
// matrix is ill-conditioned, a Condition error will be returned.
// Note that matrix inversion is numerically unstable, and should generally be
// avoided where possible, for example by using the Solve routines.
func (s *SymDense) InverseCholesky(chol *Cholesky) error {
	// TODO(btracey): Replace this code with a direct call to Dpotri when it
	// is available.
	s.reuseAs(chol.chol.mat.N)
	// If:
	//  chol(A) = U^T * U
	// Then:
	//  chol(A^-1) = S * S^T
	// where S = U^-1
	var t TriDense
	err := t.InverseTri(chol.chol)
	s.SymOuterK(1, &t)
	return err
}

// SymRankOne performs a rank-1 update of the original matrix A and refactorizes
// its Cholesky factorization, storing the result into the reciever. That is, if
// in the original Cholesky factorization
//  U^T * U = A,
// in the updated factorization
//  U'^T * U' = A + alpha * x * x^T = A'.
//
// Note that when alpha is negative, the updating problem may be ill-conditioned
// and the results may be inaccurate, or the updated matrix A' may not be
// positive definite and not have a Cholesky factorization. SymRankOne returns
// whether the updated matrix A' is positive definite.
//
// SymRankOne updates a Cholesky factorization in O(n²) time. The Cholesky
// factorization computation from scratch is O(n³).
func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x *Vector) (ok bool) {
	n := orig.Size()
	if x.Len() != n {
		panic(matrix.ErrShape)
	}
	if orig != c {
		if c.isZero() {
			c.chol = NewTriDense(n, matrix.Upper, nil)
		} else if c.chol.mat.N != n {
			panic(matrix.ErrShape)
		}
		c.chol.Copy(orig.chol)
	}

	if alpha == 0 {
		return true
	}

	// Algorithms for updating and downdating the Cholesky factorization are
	// described, for example, in
	// - J. J. Dongarra, J. R. Bunch, C. B. Moler, G. W. Stewart: LINPACK
	//   Users' Guide. SIAM (1979), pages 10.10--10.14
	// or
	// - P. E. Gill, G. H. Golub, W. Murray, and M. A. Saunders: Methods for
	//   modifying matrix factorizations. Mathematics of Computation 28(126)
	//   (1974), Method C3 on page 521
	//
	// The implementation is based on LINPACK code
	// http://www.netlib.org/linpack/dchud.f
	// http://www.netlib.org/linpack/dchdd.f
	// and
	// https://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=2646
	//
	// According to http://icl.cs.utk.edu/lapack-forum/archives/lapack/msg00301.html
	// LINPACK is released under BSD license.
	//
	// See also:
	// - M. A. Saunders: Large-scale Linear Programming Using the Cholesky
	//   Factorization. Technical Report Stanford University (1972)
	//   http://i.stanford.edu/pub/cstr/reports/cs/tr/72/252/CS-TR-72-252.pdf
	// - Matthias Seeger: Low rank updates for the Cholesky decomposition.
	//   EPFL Technical Report 161468 (2004)
	//   http://infoscience.epfl.ch/record/161468

	work := make([]float64, n)
	blas64.Copy(n, x.RawVector(), blas64.Vector{1, work})

	if alpha > 0 {
		// Compute rank-1 update.
		if alpha != 1 {
			blas64.Scal(n, math.Sqrt(alpha), blas64.Vector{1, work})
		}
		umat := c.chol.mat
		stride := umat.Stride
		for i := 0; i < n; i++ {
			// Compute parameters of the Givens matrix that zeroes
			// the i-th element of x.
			c, s, r, _ := blas64.Rotg(umat.Data[i*stride+i], work[i])
			if r < 0 {
				// Multiply by -1 to have positive diagonal
				// elemnts.
				r *= -1
				c *= -1
				s *= -1
			}
			umat.Data[i*stride+i] = r
			if i < n-1 {
				// Multiply the extended factorization matrix by
				// the Givens matrix from the left. Only
				// the i-th row and x are modified.
				blas64.Rot(n-i-1,
					blas64.Vector{1, umat.Data[i*stride+i+1 : i*stride+n]},
					blas64.Vector{1, work[i+1 : n]},
					c, s)
			}
		}
		c.updateCond(-1)
		return true
	}

	// Compute rank-1 downdate.
	alpha = math.Sqrt(-alpha)
	if alpha != 1 {
		blas64.Scal(n, alpha, blas64.Vector{1, work})
	}
	// Solve U^T * p = x storing the result into work.
	ok = lapack64.Trtrs(blas.Trans, c.chol.RawTriangular(), blas64.General{
		Rows:   n,
		Cols:   1,
		Stride: 1,
		Data:   work,
	})
	if !ok {
		// The original matrix is singular.
		return false
	}
	norm := blas64.Nrm2(n, blas64.Vector{1, work})
	if norm >= 1 {
		// The updated matrix is not positive definite.
		return false
	}
	norm = math.Sqrt((1 + norm) * (1 - norm))
	cos := make([]float64, n)
	sin := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		// Compute parameters of Givens matrices that zero elements of p
		// backwards.
		cos[i], sin[i], norm, _ = blas64.Rotg(norm, work[i])
		if norm < 0 {
			norm *= -1
			cos[i] *= -1
			sin[i] *= -1
		}
	}
	umat := c.chol.mat
	stride := umat.Stride
	ok = true
	for i := n - 1; i >= 0; i-- {
		// Apply Givens matrices to U.
		blas64.Rot(n-i, blas64.Vector{1, work[i:n]}, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]}, cos[i], sin[i])
		if umat.Data[i*stride+i] == 0 {
			// The matrix is singular (may rarely happen due to
			// floating-point effects?).
			ok = false
		} else if umat.Data[i*stride+i] < 0 {
			// Diagonal elements should be positive. If it happens
			// that on the i-th row the diagonal is negative,
			// multiply U from the left by an identity matrix that
			// has -1 on the i-th row.
			blas64.Scal(n-i, -1, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]})
		}
	}
	if ok {
		c.updateCond(-1)
	} else {
		c.cond = math.Inf(1)
	}
	return ok
}

func (c *Cholesky) isZero() bool {
	return c.chol == nil
}
<|endoftext|>


<commit_before>package matchers

var (
	TypeMp4  = newType("mp4", "video/mp4")
	TypeM4v  = newType("m4v", "video/x-m4v")
	TypeMkv  = newType("mkv", "video/x-matroska")
	TypeWebm = newType("webm", "video/webm")
	TypeMov  = newType("mov", "video/quicktime")
	TypeAvi  = newType("avi", "video/x-msvideo")
	TypeWmv  = newType("wmv", "video/x-ms-wmv")
	TypeMpeg = newType("mpg", "video/mpeg")
	TypeFlv  = newType("flv", "video/x-flv")
)

var Video = Map{
	TypeMp4:  Mp4,
	TypeM4v:  M4v,
	TypeMkv:  Mkv,
	TypeWebm: Webm,
	TypeMov:  Mov,
	TypeAvi:  Avi,
	TypeWmv:  Wmv,
	TypeMpeg: Mpeg,
	TypeFlv:  Flv,
}

func M4v(buf []byte) bool {
	return len(buf) > 10 &&
		buf[4] == 0x66 && buf[5] == 0x74 &&
		buf[6] == 0x79 && buf[7] == 0x70 &&
		buf[8] == 0x4D && buf[9] == 0x34 &&
		buf[10] == 0x56
}

func Mkv(buf []byte) bool {
	return (len(buf) > 15 &&
		buf[0] == 0x1A && buf[1] == 0x45 &&
		buf[2] == 0xDF && buf[3] == 0xA3 &&
		buf[4] == 0x93 && buf[5] == 0x42 &&
		buf[6] == 0x82 && buf[7] == 0x88 &&
		buf[8] == 0x6D && buf[9] == 0x61 &&
		buf[10] == 0x74 && buf[11] == 0x72 &&
		buf[12] == 0x6F && buf[13] == 0x73 &&
		buf[14] == 0x6B && buf[15] == 0x61) ||
		(len(buf) > 38 &&
			buf[31] == 0x6D && buf[32] == 0x61 &&
			buf[33] == 0x74 && buf[34] == 0x72 &&
			buf[35] == 0x6f && buf[36] == 0x73 &&
			buf[37] == 0x6B && buf[38] == 0x61)
}

func Webm(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x1A && buf[1] == 0x45 &&
		buf[2] == 0xDF && buf[3] == 0xA3
}

func Mov(buf []byte) bool {
	return len(buf) > 15 && ((buf[0] == 0x0 && buf[1] == 0x0 &&
		buf[2] == 0x0 && buf[3] == 0x14 &&
		buf[4] == 0x66 && buf[5] == 0x74 &&
		buf[6] == 0x79 && buf[7] == 0x70) ||
		(buf[4] == 0x6d && buf[5] == 0x6f && buf[6] == 0x6f && buf[7] == 0x76) ||
		(buf[4] == 0x6d && buf[5] == 0x64 && buf[6] == 0x61 && buf[7] == 0x74) ||
		(buf[12] == 0x6d && buf[13] == 0x64 && buf[14] == 0x61 && buf[15] == 0x74))
}

func Avi(buf []byte) bool {
	return len(buf) > 10 &&
		buf[0] == 0x52 && buf[1] == 0x49 &&
		buf[2] == 0x46 && buf[3] == 0x46 &&
		buf[8] == 0x41 && buf[9] == 0x56 &&
		buf[10] == 0x49
}

func Wmv(buf []byte) bool {
	return len(buf) > 9 &&
		buf[0] == 0x30 && buf[1] == 0x26 &&
		buf[2] == 0xB2 && buf[3] == 0x75 &&
		buf[4] == 0x8E && buf[5] == 0x66 &&
		buf[6] == 0xCF && buf[7] == 0x11 &&
		buf[8] == 0xA6 && buf[9] == 0xD9
}

func Mpeg(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x0 && buf[1] == 0x0 &&
		buf[2] == 0x1 && buf[3] >= 0xb0 &&
		buf[3] <= 0xbf
}

func Flv(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x46 && buf[1] == 0x4C &&
		buf[2] == 0x56 && buf[3] == 0x01
}

func Mp4(buf []byte) bool {
	return len(buf) > 11 &&
		(buf[4] == 'f' && buf[5] == 't' && buf[6] == 'y' && buf[7] == 'p') &&
		((buf[8] == 'a' && buf[9] == 'v' && buf[10] == 'c' && buf[11] == '1') ||
			(buf[8] == 'd' && buf[9] == 'a' && buf[10] == 's' && buf[11] == 'h') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '2') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '3') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '4') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '5') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '6') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == 'm') ||
			(buf[8] == 'm' && buf[9] == 'm' && buf[10] == 'p' && buf[11] == '4') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '1') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '2') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '7' && buf[11] == '1') ||
			(buf[8] == 'M' && buf[9] == 'S' && buf[10] == 'N' && buf[11] == 'V') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'A' && buf[11] == 'S') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'S' && buf[10] == 'D' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'H') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'M') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'P') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'S') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'H') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'M') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'P') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'S') ||
			(buf[8] == 'F' && buf[9] == '4' && buf[10] == 'V' && buf[11] == ' ') ||
			(buf[8] == 'F' && buf[9] == '4' && buf[10] == 'P' && buf[11] == ' '))
}
<commit_msg>Added ftypmp4v to MP4 matcher<commit_after>package matchers

var (
	TypeMp4  = newType("mp4", "video/mp4")
	TypeM4v  = newType("m4v", "video/x-m4v")
	TypeMkv  = newType("mkv", "video/x-matroska")
	TypeWebm = newType("webm", "video/webm")
	TypeMov  = newType("mov", "video/quicktime")
	TypeAvi  = newType("avi", "video/x-msvideo")
	TypeWmv  = newType("wmv", "video/x-ms-wmv")
	TypeMpeg = newType("mpg", "video/mpeg")
	TypeFlv  = newType("flv", "video/x-flv")
)

var Video = Map{
	TypeMp4:  Mp4,
	TypeM4v:  M4v,
	TypeMkv:  Mkv,
	TypeWebm: Webm,
	TypeMov:  Mov,
	TypeAvi:  Avi,
	TypeWmv:  Wmv,
	TypeMpeg: Mpeg,
	TypeFlv:  Flv,
}

func M4v(buf []byte) bool {
	return len(buf) > 10 &&
		buf[4] == 0x66 && buf[5] == 0x74 &&
		buf[6] == 0x79 && buf[7] == 0x70 &&
		buf[8] == 0x4D && buf[9] == 0x34 &&
		buf[10] == 0x56
}

func Mkv(buf []byte) bool {
	return (len(buf) > 15 &&
		buf[0] == 0x1A && buf[1] == 0x45 &&
		buf[2] == 0xDF && buf[3] == 0xA3 &&
		buf[4] == 0x93 && buf[5] == 0x42 &&
		buf[6] == 0x82 && buf[7] == 0x88 &&
		buf[8] == 0x6D && buf[9] == 0x61 &&
		buf[10] == 0x74 && buf[11] == 0x72 &&
		buf[12] == 0x6F && buf[13] == 0x73 &&
		buf[14] == 0x6B && buf[15] == 0x61) ||
		(len(buf) > 38 &&
			buf[31] == 0x6D && buf[32] == 0x61 &&
			buf[33] == 0x74 && buf[34] == 0x72 &&
			buf[35] == 0x6f && buf[36] == 0x73 &&
			buf[37] == 0x6B && buf[38] == 0x61)
}

func Webm(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x1A && buf[1] == 0x45 &&
		buf[2] == 0xDF && buf[3] == 0xA3
}

func Mov(buf []byte) bool {
	return len(buf) > 15 && ((buf[0] == 0x0 && buf[1] == 0x0 &&
		buf[2] == 0x0 && buf[3] == 0x14 &&
		buf[4] == 0x66 && buf[5] == 0x74 &&
		buf[6] == 0x79 && buf[7] == 0x70) ||
		(buf[4] == 0x6d && buf[5] == 0x6f && buf[6] == 0x6f && buf[7] == 0x76) ||
		(buf[4] == 0x6d && buf[5] == 0x64 && buf[6] == 0x61 && buf[7] == 0x74) ||
		(buf[12] == 0x6d && buf[13] == 0x64 && buf[14] == 0x61 && buf[15] == 0x74))
}

func Avi(buf []byte) bool {
	return len(buf) > 10 &&
		buf[0] == 0x52 && buf[1] == 0x49 &&
		buf[2] == 0x46 && buf[3] == 0x46 &&
		buf[8] == 0x41 && buf[9] == 0x56 &&
		buf[10] == 0x49
}

func Wmv(buf []byte) bool {
	return len(buf) > 9 &&
		buf[0] == 0x30 && buf[1] == 0x26 &&
		buf[2] == 0xB2 && buf[3] == 0x75 &&
		buf[4] == 0x8E && buf[5] == 0x66 &&
		buf[6] == 0xCF && buf[7] == 0x11 &&
		buf[8] == 0xA6 && buf[9] == 0xD9
}

func Mpeg(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x0 && buf[1] == 0x0 &&
		buf[2] == 0x1 && buf[3] >= 0xb0 &&
		buf[3] <= 0xbf
}

func Flv(buf []byte) bool {
	return len(buf) > 3 &&
		buf[0] == 0x46 && buf[1] == 0x4C &&
		buf[2] == 0x56 && buf[3] == 0x01
}

func Mp4(buf []byte) bool {
	return len(buf) > 11 &&
		(buf[4] == 'f' && buf[5] == 't' && buf[6] == 'y' && buf[7] == 'p') &&
		((buf[8] == 'a' && buf[9] == 'v' && buf[10] == 'c' && buf[11] == '1') ||
			(buf[8] == 'd' && buf[9] == 'a' && buf[10] == 's' && buf[11] == 'h') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '2') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '3') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '4') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '5') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '6') ||
			(buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == 'm') ||
			(buf[8] == 'm' && buf[9] == 'm' && buf[10] == 'p' && buf[11] == '4') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '1') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '2') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == 'v') ||
			(buf[8] == 'm' && buf[9] == 'p' && buf[10] == '7' && buf[11] == '1') ||
			(buf[8] == 'M' && buf[9] == 'S' && buf[10] == 'N' && buf[11] == 'V') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'A' && buf[11] == 'S') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'S' && buf[10] == 'D' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'H') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'M') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'P') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'S') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'C') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'H') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'M') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'P') ||
			(buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'S') ||
			(buf[8] == 'F' && buf[9] == '4' && buf[10] == 'V' && buf[11] == ' ') ||
			(buf[8] == 'F' && buf[9] == '4' && buf[10] == 'P' && buf[11] == ' '))
}
<|endoftext|>


<commit_before>package math

import (
	"unsafe"
)

// Transform is a utility type used to aggregate transformations. Transform
// concatenation, like matrix multiplication, is not commutative.
type Transform Mat4

// NewTransform returns a new, initialized transform.
func NewTransform() Transform {
	return Transform(Ident4())
}

// Iden sets this transform to the identity transform. You NEED to call this
// EXCEPT IF:
// - You get your transform from NewTransform
// - You're gonna call Set* BEFORE Translate* or Rotate*
func (t *Transform) Iden() {
	*t = Transform(Ident4())
}

// Translate3f concatenates a translation to this transform of {x, y, z}.
func (t *Transform) Translate3f(x, y, z float32) {
	tran := Translate3D(x, y, z)
	((*Mat4)(t)).Mul4With(&tran)
}

// TranslateVec3 concatenates a translation to this transform of v.
func (t *Transform) TranslateVec3(v *Vec3) {
	tran := Translate3D(v[0], v[1], v[2])
	((*Mat4)(t)).Mul4With(&tran)
}

// SetTranslate3f sets the transform to a translate transform of {x, y, z}.
func (t *Transform) SetTranslate3f(x, y, z float32) {
	*t = Transform(Translate3D(x, y, z))
}

// SetTranslateVec3 sets the transform to a translate transform of v.
func (t *Transform) SetTranslateVec3(v *Vec3) {
	*t = Transform(Translate3D(v[0], v[1], v[2]))
}

// RotateQuat rotates this transform by q.
func (t *Transform) RotateQuat(q *Quaternion) {
	m := q.Mat4()
	((*Mat4)(t)).Mul4With(&m)
}

// SetRotateQuat rotates this transform by q.
func (t *Transform) SetRotateQuat(q *Quaternion) {
	*t = Transform(q.Mat4())
}

// Concatenate Transform t2 into t.
func (t *Transform) Concatenate(t2 *Transform) {
	((*Mat4)(t)).Mul4With((*Mat4)(t2))
}

// Scale3f scales this transform by {x, y, z}.
func (t *Transform) Scale3f(x, y, z float32) {
	tran := Scale3D(x, y, z)
	((*Mat4)(t)).Mul4With(&tran)
}

// ScaleVec3 scales this transform by v.
func (t *Transform) ScaleVec3(v *Vec3) {
	tran := Scale3D(v[0], v[1], v[2])
	((*Mat4)(t)).Mul4With(&tran)
}

// SetScale3f sets the transform to a scaling operation by {x, y, z}.
func (t *Transform) SetScale3f(x, y, z float32) {
	*t = Transform(Scale3D(x, y, z))
}

// SetScaleVec3 sets the transform to a scaling operation by v.
func (t *Transform) SetScaleVec3(v *Vec3) {
	*t = Transform(Scale3D(v[0], v[1], v[2]))
}

// LocalToWorld transforms a given point and returns the world point that this
// transform generates.
func (t *Transform) LocalToWorld(v *Vec3) Vec3 {
	v4 := v.Vec4(1)
	v4 = (*Mat4)(t).Mul4x1(&v4)
	return v4.Vec3()
}

// WorldToLocal transform a given point and returns the local point that this
// transform generates.
func (t *Transform) WorldToLocal(v *Vec3) Vec3 {
	// BUG(hydroflame): the current implementation currently inverse the matrix
	// on every call ... that may not be the most efficient.
	inv := (*Mat4)(t).Inverse()
	v4 := v.Vec4(1)
	v4 = inv.Mul4x1(&v4)
	return v4.Vec3()
}

// Normal returns the normal matrix of this transform, this is used in most
// light shading algorithms.
func (t *Transform) Normal() Mat3 {
	// Since we prevent scaling we are guaranteed that the upper 3x3 matrix is
	// orthogonal and (TODO(hydroflame): find the word for when a matrix has all
	// unit vectors), we can just throw it back and it's the correct transform
	// matrix.
	return ((*Mat4)(t)).Mat3()
}

// Mat4 simply returns the Mat4 associated with this Transform. This effectively
// makes a copy.
func (t *Transform) Mat4() Mat4 {
	return *((*Mat4)(t))
}

// Pointer returns the pointer to the first element of the underlying 4x4
// matrix. This is can be passed directly to OpenGL function.
func (t *Transform) Pointer() unsafe.Pointer {
	return unsafe.Pointer(t)
}

// String return a string that represents this transform (a mat4).
func (t *Transform) String() string {
	return (*Mat4)(t).String()
}

// Transform2D is a utility type used to aggregate transformations. Transform
// concatenation, like matrix multiplication, is not commutative.
type Transform2D Mat3

// NewTransform2D returns a new, initialized transform.
func NewTransform2D() Transform2D {
	return Transform2D(Ident3())
}

// Iden sets this transform to the identity transform. You NEED to call this
// EXCEPT IF:
// - You get your transform from NewTransform
// - You're gonna call Set* BEFORE Translate* or Rotate*
func (t *Transform2D) Iden() {
	*t = Transform2D(Ident3())
}

// Translate2f concatenates a translation to this transform of {x, y, z}.
func (t *Transform2D) Translate2f(x, y float32) {
	tran := Translate2D(x, y)
	((*Mat3)(t)).Mul3With(&tran)
}

// TranslateVec2 concatenates a translation to this transform of v.
func (t *Transform2D) TranslateVec2(v *Vec2) {
	tran := Translate2D(v[0], v[1])
	((*Mat3)(t)).Mul3With(&tran)
}

// SetTranslate2f sets the transform to a translate transform of {x, y, z}.
func (t *Transform2D) SetTranslate2f(x, y float32) {
	*t = Transform2D(Translate2D(x, y))
}

// SetTranslateVec2 sets the transform to a translate transform of v.
func (t *Transform2D) SetTranslateVec2(v *Vec2) {
	*t = Transform2D(Translate2D(v[0], v[1]))
}

// Rotate concatenates a rotation of angle (radian).
func (t *Transform2D) Rotate(angle float32) {
	rot := HomogRotate2D(angle)
	((*Mat3)(t)).Mul3With(&rot)
}

// SetRotate sets the transform to a rotate transform of angle (radian).
func (t *Transform2D) SetRotate(angle float32) {
	*t = Transform2D(HomogRotate2D(angle))
}

// LocalToWorld transform a given point and returns the world point that this
// transform generates.
func (t *Transform2D) LocalToWorld(v *Vec2) Vec2 {
	v3 := v.Vec3(1)
	v3 = (*Mat3)(t).Mul3x1(&v3)
	return v3.Vec2()
}

// WorldToLocal transform a given point and returns the local point that this
// transform generates.
func (t *Transform2D) WorldToLocal(v *Vec2) Vec2 {
	// BUG(hydroflame): the current implementation currently inverse the matrix
	// on every call ... that may not be the most efficient.
	inv := (*Mat3)(t).Inverse()
	v3 := v.Vec3(1)
	v3 = inv.Mul3x1(&v3)
	return v3.Vec2()
}

// Concatenate Transform t2 into t.
func (t *Transform2D) Concatenate(t2 *Transform2D) {
	((*Mat3)(t)).Mul3With((*Mat3)(t2))
}

// Mat3 simply returns the Mat3 associated with this Transform. This effectively
// makes a copy.
func (t *Transform2D) Mat3() Mat3 {
	return *((*Mat3)(t))
}

// Pointer returns the pointer to the first element of the underlying 4x4
// matrix. This is can be passed directly to OpenGL function.
func (t *Transform2D) Pointer() unsafe.Pointer {
	return unsafe.Pointer(t)
}

// String return a string that represents this transform (a mat4).
func (t *Transform2D) String() string {
	return (*Mat3)(t).String()
}
<commit_msg>transform: Add a convenience function to retrieve a *Mat4<commit_after>package math

import (
	"unsafe"
)

// Transform is a utility type used to aggregate transformations. Transform
// concatenation, like matrix multiplication, is not commutative.
type Transform Mat4

// NewTransform returns a new, initialized transform.
func NewTransform() Transform {
	return Transform(Ident4())
}

// Iden sets this transform to the identity transform. You NEED to call this
// EXCEPT IF:
// - You get your transform from NewTransform
// - You're gonna call Set* BEFORE Translate* or Rotate*
func (t *Transform) Iden() {
	*t = Transform(Ident4())
}

// Translate3f concatenates a translation to this transform of {x, y, z}.
func (t *Transform) Translate3f(x, y, z float32) {
	tran := Translate3D(x, y, z)
	((*Mat4)(t)).Mul4With(&tran)
}

// TranslateVec3 concatenates a translation to this transform of v.
func (t *Transform) TranslateVec3(v *Vec3) {
	tran := Translate3D(v[0], v[1], v[2])
	((*Mat4)(t)).Mul4With(&tran)
}

// SetTranslate3f sets the transform to a translate transform of {x, y, z}.
func (t *Transform) SetTranslate3f(x, y, z float32) {
	*t = Transform(Translate3D(x, y, z))
}

// SetTranslateVec3 sets the transform to a translate transform of v.
func (t *Transform) SetTranslateVec3(v *Vec3) {
	*t = Transform(Translate3D(v[0], v[1], v[2]))
}

// RotateQuat rotates this transform by q.
func (t *Transform) RotateQuat(q *Quaternion) {
	m := q.Mat4()
	((*Mat4)(t)).Mul4With(&m)
}

// SetRotateQuat rotates this transform by q.
func (t *Transform) SetRotateQuat(q *Quaternion) {
	*t = Transform(q.Mat4())
}

// Concatenate Transform t2 into t.
func (t *Transform) Concatenate(t2 *Transform) {
	((*Mat4)(t)).Mul4With((*Mat4)(t2))
}

// Scale3f scales this transform by {x, y, z}.
func (t *Transform) Scale3f(x, y, z float32) {
	tran := Scale3D(x, y, z)
	((*Mat4)(t)).Mul4With(&tran)
}

// ScaleVec3 scales this transform by v.
func (t *Transform) ScaleVec3(v *Vec3) {
	tran := Scale3D(v[0], v[1], v[2])
	((*Mat4)(t)).Mul4With(&tran)
}

// SetScale3f sets the transform to a scaling operation by {x, y, z}.
func (t *Transform) SetScale3f(x, y, z float32) {
	*t = Transform(Scale3D(x, y, z))
}

// SetScaleVec3 sets the transform to a scaling operation by v.
func (t *Transform) SetScaleVec3(v *Vec3) {
	*t = Transform(Scale3D(v[0], v[1], v[2]))
}

// LocalToWorld transforms a given point and returns the world point that this
// transform generates.
func (t *Transform) LocalToWorld(v *Vec3) Vec3 {
	v4 := v.Vec4(1)
	v4 = (*Mat4)(t).Mul4x1(&v4)
	return v4.Vec3()
}

// WorldToLocal transform a given point and returns the local point that this
// transform generates.
func (t *Transform) WorldToLocal(v *Vec3) Vec3 {
	// BUG(hydroflame): the current implementation currently inverse the matrix
	// on every call ... that may not be the most efficient.
	inv := (*Mat4)(t).Inverse()
	v4 := v.Vec4(1)
	v4 = inv.Mul4x1(&v4)
	return v4.Vec3()
}

// Normal returns the normal matrix of this transform, this is used in most
// light shading algorithms.
func (t *Transform) Normal() Mat3 {
	// Since we prevent scaling we are guaranteed that the upper 3x3 matrix is
	// orthogonal and (TODO(hydroflame): find the word for when a matrix has all
	// unit vectors), we can just throw it back and it's the correct transform
	// matrix.
	return ((*Mat4)(t)).Mat3()
}

// Mat4 simply returns the Mat4 associated with this Transform. This effectively
// makes a copy.
func (t *Transform) Mat4() Mat4 {
	return *((*Mat4)(t))
}

// Mat4 simply returns a pointer to the Mat4 associated with this Transform.
func (t *Transform) AsMat4() *Mat4 {
	return (*Mat4)(t)
}

// Pointer returns the pointer to the first element of the underlying 4x4
// matrix. This is can be passed directly to OpenGL function.
func (t *Transform) Pointer() unsafe.Pointer {
	return unsafe.Pointer(t)
}

// String return a string that represents this transform (a mat4).
func (t *Transform) String() string {
	return (*Mat4)(t).String()
}

// Transform2D is a utility type used to aggregate transformations. Transform
// concatenation, like matrix multiplication, is not commutative.
type Transform2D Mat3

// NewTransform2D returns a new, initialized transform.
func NewTransform2D() Transform2D {
	return Transform2D(Ident3())
}

// Iden sets this transform to the identity transform. You NEED to call this
// EXCEPT IF:
// - You get your transform from NewTransform
// - You're gonna call Set* BEFORE Translate* or Rotate*
func (t *Transform2D) Iden() {
	*t = Transform2D(Ident3())
}

// Translate2f concatenates a translation to this transform of {x, y, z}.
func (t *Transform2D) Translate2f(x, y float32) {
	tran := Translate2D(x, y)
	((*Mat3)(t)).Mul3With(&tran)
}

// TranslateVec2 concatenates a translation to this transform of v.
func (t *Transform2D) TranslateVec2(v *Vec2) {
	tran := Translate2D(v[0], v[1])
	((*Mat3)(t)).Mul3With(&tran)
}

// SetTranslate2f sets the transform to a translate transform of {x, y, z}.
func (t *Transform2D) SetTranslate2f(x, y float32) {
	*t = Transform2D(Translate2D(x, y))
}

// SetTranslateVec2 sets the transform to a translate transform of v.
func (t *Transform2D) SetTranslateVec2(v *Vec2) {
	*t = Transform2D(Translate2D(v[0], v[1]))
}

// Rotate concatenates a rotation of angle (radian).
func (t *Transform2D) Rotate(angle float32) {
	rot := HomogRotate2D(angle)
	((*Mat3)(t)).Mul3With(&rot)
}

// SetRotate sets the transform to a rotate transform of angle (radian).
func (t *Transform2D) SetRotate(angle float32) {
	*t = Transform2D(HomogRotate2D(angle))
}

// LocalToWorld transform a given point and returns the world point that this
// transform generates.
func (t *Transform2D) LocalToWorld(v *Vec2) Vec2 {
	v3 := v.Vec3(1)
	v3 = (*Mat3)(t).Mul3x1(&v3)
	return v3.Vec2()
}

// WorldToLocal transform a given point and returns the local point that this
// transform generates.
func (t *Transform2D) WorldToLocal(v *Vec2) Vec2 {
	// BUG(hydroflame): the current implementation currently inverse the matrix
	// on every call ... that may not be the most efficient.
	inv := (*Mat3)(t).Inverse()
	v3 := v.Vec3(1)
	v3 = inv.Mul3x1(&v3)
	return v3.Vec2()
}

// Concatenate Transform t2 into t.
func (t *Transform2D) Concatenate(t2 *Transform2D) {
	((*Mat3)(t)).Mul3With((*Mat3)(t2))
}

// Mat3 simply returns the Mat3 associated with this Transform. This effectively
// makes a copy.
func (t *Transform2D) Mat3() Mat3 {
	return *((*Mat3)(t))
}

// Pointer returns the pointer to the first element of the underlying 4x4
// matrix. This is can be passed directly to OpenGL function.
func (t *Transform2D) Pointer() unsafe.Pointer {
	return unsafe.Pointer(t)
}

// String return a string that represents this transform (a mat4).
func (t *Transform2D) String() string {
	return (*Mat3)(t).String()
}
<|endoftext|>


<commit_before><commit_msg>Separate readTrailer() into a separate function and perform minor cleanup.<commit_after><|endoftext|>


<commit_before>package minify

import (
	"bytes"
	"io"
)

type Mapping struct {
	src             int32
	srcLine, srcCol int32
	dstLine, dstCol int32
}

type SourceMap struct {
	sources  [][]byte
	names    [][]byte
	mappings []Mapping
}

func NewSourceMap(sources [][]byte) *SourceMap {
	return &SourceMap{
		sources: sources,
	}
}

func (sm *SourceMap) Add(src, srcLine, srcCol, dstLine, dstCol int, name []byte) {
	sm.mappings = append(sm.mappings, Mapping{
		src:     int32(src),
		srcLine: int32(srcLine),
		srcCol:  int32(srcCol),
		dstLine: int32(dstLine),
		dstCol:  int32(dstCol),
	})
	sm.names = append(sm.names, name)
}

func (sm *SourceMap) Write(w io.Writer) error {
	w.Write([]byte(`{"version":3,"sources":["`))
	for i, source := range sm.sources {
		if i != 0 {
			w.Write([]byte(`","`))
		}
		w.Write(source)
	}
	w.Write([]byte(`"],"names":["`))
	for i, name := range sm.names {
		if i != 0 {
			w.Write([]byte(`","`))
		}
		w.Write(name)
	}
	w.Write([]byte(`"],"mappings":"`))
	var prevSrc, prevSrcLine, prevSrcCol, prevDstLine int32
	for i, mapping := range sm.mappings {
		if prevDstLine != mapping.dstLine {
			w.Write(bytes.Repeat([]byte(`;`), int(mapping.dstLine-prevDstLine)))
			prevDstLine = mapping.dstLine
		} else if i != 0 {
			w.Write([]byte(`,`))
		}
		sm.WriteVLQ(mapping.dstCol)
		if prevSrc != mapping.src {
			sm.WriteVLQ(mapping.src - prevSrc)
			prevSrc = mapping.src
		}
		if prevSrcLine != mapping.srcLine {
			sm.WriteVLQ(mapping.srcLine - prevSrcLine)
			prevSrcLine = mapping.srcLine
		}
		if prevSrcCol != mapping.srcCol {
			sm.WriteVLQ(mapping.srcCol - prevSrcCol)
			prevSrcCol = mapping.srcCol
		}
	}
	_, err := w.Write([]byte(`"}`))
	return err
}

func (sm *SourceMap) WriteVLQ(val int32) {
	// TODO
}
<commit_msg>Remove sourcemap.go<commit_after><|endoftext|>


<commit_before><commit_msg>Decode HTTP/JSON response<commit_after><|endoftext|>


<commit_before>package wfhost

import (
	"sync"

	"github.com/zmj/sfslack/log"
	"github.com/zmj/sfslack/slack"
	"github.com/zmj/sfslack/workflow"
)

type replier struct {
	mu          *sync.Mutex
	waiting     []redirectCb
	useCurrent  bool
	current     reply
	firstReply  chan slack.Message
	repliesSent int
	cmd         slack.Command
	wf          workflow.Workflow
	log         *log.Logger

	done    chan struct{}
	replies chan reply
}

func (r *replier) Reply(msg slack.Message) bool {
	c := make(chan bool, 1)
	r.replies <- reply{msg, "", nil, c}
	return <-c
}

func (r *replier) RedirectOrReply(url string, msg slack.Message) bool {
	c := make(chan bool, 1)
	r.replies <- reply{msg, url, nil, c}
	return <-c
}

func (r *replier) ReplyErr(err error) bool {
	c := make(chan bool, 1)
	r.replies <- reply{errorMessage(err), "", err, c}
	return <-c
}

func (r *replier) sendReplies() {
	for {
		select {
		case re := <-r.replies:
			if r.repliesSent > slack.MaxDelayedReplies {
				re.accepted <- false
				continue
			}
			re.accepted <- true
			r.replyInner(re)
		case <-r.done:
			return
		}
	}
}

type reply struct {
	msg      slack.Message
	url      string
	err      error
	accepted chan bool
}

func (r *replier) replyInner(re reply) {
	r.mu.Lock()
	cbs := r.waiting
	r.waiting = nil
	r.current = re
	r.useCurrent = true
	r.mu.Unlock()

	var accepted bool
	for _, cb := range cbs {
		accepted = cb(re.url, re.err) || accepted
	}
	if re.url == "" || !accepted {
		r.sendMsg(re.msg)
	}
}

func (r *replier) sendMsg(msg slack.Message) {
	if r.firstReply != nil {
		r.firstReply <- msg
		r.firstReply = nil
		return
	}

	err := msg.RespondTo(r.cmd)
	if err != nil {
		r.log.Err(err)
		return
	}
	r.repliesSent++
}

type redirectCb func(string, error) bool

func (r *replier) NextRedirect(cb redirectCb) {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.useCurrent {
		go cb(r.current.url, r.current.err)
	} else {
		r.waiting = append(r.waiting, cb)
	}
}
<commit_msg>save upload url as last redirectable response<commit_after>package wfhost

import (
	"sync"

	"github.com/zmj/sfslack/log"
	"github.com/zmj/sfslack/slack"
	"github.com/zmj/sfslack/workflow"
)

type replier struct {
	mu          *sync.Mutex
	waiting     []redirectCb
	useCurrent  bool
	current     reply
	firstReply  chan slack.Message
	repliesSent int
	cmd         slack.Command
	wf          workflow.Workflow
	log         *log.Logger

	done    chan struct{}
	replies chan reply
}

func (r *replier) Reply(msg slack.Message) bool {
	c := make(chan bool, 1)
	r.replies <- reply{msg, "", nil, c}
	return <-c
}

func (r *replier) RedirectOrReply(url string, msg slack.Message) bool {
	c := make(chan bool, 1)
	r.replies <- reply{msg, url, nil, c}
	return <-c
}

func (r *replier) ReplyErr(err error) bool {
	c := make(chan bool, 1)
	r.replies <- reply{errorMessage(err), "", err, c}
	return <-c
}

func (r *replier) sendReplies() {
	for {
		select {
		case re := <-r.replies:
			if r.repliesSent > slack.MaxDelayedReplies {
				re.accepted <- false
				continue
			}
			re.accepted <- true
			r.replyInner(re)
		case <-r.done:
			return
		}
	}
}

type reply struct {
	msg      slack.Message
	url      string
	err      error
	accepted chan bool
}

func (r *replier) replyInner(re reply) {
	r.mu.Lock()
	cbs := r.waiting
	if re.msg.ResponseType == slack.ResponseTypeEphemeral {
		r.waiting = nil
		r.current = re
		r.useCurrent = true
	}
	r.mu.Unlock()

	var accepted bool
	for _, cb := range cbs {
		accepted = cb(re.url, re.err) || accepted
	}
	if re.url == "" || !accepted {
		r.sendMsg(re.msg)
	}
}

func (r *replier) sendMsg(msg slack.Message) {
	if r.firstReply != nil {
		r.firstReply <- msg
		r.firstReply = nil
		return
	}

	err := msg.RespondTo(r.cmd)
	if err != nil {
		r.log.Err(err)
		return
	}
	r.repliesSent++
}

type redirectCb func(string, error) bool

func (r *replier) NextRedirect(cb redirectCb) {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.useCurrent {
		go cb(r.current.url, r.current.err)
	} else {
		r.waiting = append(r.waiting, cb)
	}
}
<|endoftext|>


<commit_before>package origin

import (
	"io"

	"github.com/tsavola/gate/service"
)

const (
	Name    = "origin"
	Version = 0

	packetHeaderSize = 8
)

type Factory struct {
	R io.Reader
	W io.Writer
}

func (f *Factory) Register(r *service.Registry) {
	service.Register(r, Name, Version, f)
}

func (f *Factory) New() service.Instance {
	return &origin{f.R, f.W}
}

var Default = new(Factory)

func Register(r *service.Registry) {
	Default.Register(r)
}

func CloneRegistryWith(r *service.Registry, origIn io.Reader, origOut io.Writer) *service.Registry {
	clone := service.Clone(r)
	(&Factory{R: origIn, W: origOut}).Register(clone)
	return clone
}

type origin struct {
	r io.Reader
	w io.Writer
}

func (o *origin) Handle(buf []byte, replies chan<- []byte) {
	if o.w != nil {
		if _, err := o.w.Write(buf[packetHeaderSize:]); err != nil {
			// assume that the error is EOF, broken pipe or such
			o.w = nil
		}
	}
}

func (o *origin) Shutdown() {
}
<commit_msg>service: origin: implement input<commit_after>package origin

import (
	"io"

	"github.com/tsavola/gate/service"
)

const (
	Name    = "origin"
	Version = 0

	packetHeaderSize = 8

	maxPacketSize = 0x10000 // TODO: move this elsewhere
)

type Factory struct {
	R io.Reader
	W io.Writer
}

func (f *Factory) Register(r *service.Registry) {
	service.Register(r, Name, Version, f)
}

func (f *Factory) New() service.Instance {
	return &origin{r: f.R, w: f.W}
}

var Default = new(Factory)

func Register(r *service.Registry) {
	Default.Register(r)
}

func CloneRegistryWith(r *service.Registry, origIn io.Reader, origOut io.Writer) *service.Registry {
	clone := service.Clone(r)
	(&Factory{R: origIn, W: origOut}).Register(clone)
	return clone
}

type origin struct {
	r io.Reader
	w io.Writer

	reading chan struct{}
}

func (o *origin) Handle(buf []byte, replies chan<- []byte) {
	if o.r != nil && o.reading == nil {
		o.reading = make(chan struct{})
		go o.readLoop(buf[6:8], replies)
	}

	if o.w != nil {
		if _, err := o.w.Write(buf[packetHeaderSize:]); err != nil {
			// assume that the error is EOF, broken pipe or such
			o.w = nil
		}
	}
}

func (o *origin) Shutdown() {
	if o.reading != nil {
		close(o.reading)
	}
}

func (o *origin) readLoop(code []byte, replies chan<- []byte) {
	for {
		buf := make([]byte, maxPacketSize) // TODO: smaller buffer?
		copy(buf[6:8], code)

		n, err := o.r.Read(buf[packetHeaderSize:])
		if err != nil {
			o.r = nil
			return
		}

		select {
		case replies <- buf[:packetHeaderSize+n]:
			// ok

		case <-o.reading:
			return
		}
	}
}
<|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 binary

// This file implements "varint" encoding of 64-bit integers.
// The encoding is:
// - unsigned integers are serialized 7 bits at a time, starting with the
//   least significant bits
// - the most significant bit (msb) in each output byte indicates if there
//   is a continuation byte (msb = 1)
// - signed integers are mapped to unsigned integers using "zig-zag"
//   encoding: Positive values x are written as 2*x + 0, negative values
//   are written as 2*(^x) + 1; that is, negative numbers are complemented
//   and whether to complement is encoded in bit 0.
//
// Design note:
// At most 10 bytes are needed for 64-bit values. The encoding could
// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
// Instead, the msb of the previous byte could be used to hold bit 63 since we
// know there can't be more than 64 bits. This is a trivial improvement and
// would reduce the maximum encoding length to 9 bytes. However, it breaks the
// invariant that the msb is always the "continuation bit" and thus makes the
// format incompatible with a varint encoding for larger numbers (say 128-bit).

import (
	"errors"
	"io"
)

// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
const (
	MaxVarintLen16 = 3
	MaxVarintLen32 = 5
	MaxVarintLen64 = 10
)

// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
// If the buffer is too small, PutUvarint will panic.
func PutUvarint(buf []byte, x uint64) int {
	i := 0
	for x >= 0x80 {
		buf[i] = byte(x) | 0x80
		x >>= 7
		i++
	}
	buf[i] = byte(x)
	return i + 1
}

// Uvarint decodes a uint64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 meaning:
//
//	n == 0: buf too small
//	n  < 0: value larger than 64 bits (overflow)
//              and -n is the number of bytes read
//
func Uvarint(buf []byte) (uint64, int) {
	var x uint64
	var s uint
	for i, b := range buf {
		if b < 0x80 {
			if i > 9 || i == 9 && b > 1 {
				return 0, -(i + 1) // overflow
			}
			return x | uint64(b)<<s, i + 1
		}
		x |= uint64(b&0x7f) << s
		s += 7
	}
	return 0, 0
}

// PutVarint encodes an int64 into buf and returns the number of bytes written.
// If the buffer is too small, PutVarint will panic.
func PutVarint(buf []byte, x int64) int {
	ux := uint64(x) << 1
	if x < 0 {
		ux = ^ux
	}
	return PutUvarint(buf, ux)
}

// Varint decodes an int64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 with the following meaning:
//
//	n == 0: buf too small
//	n  < 0: value larger than 64 bits (overflow)
//              and -n is the number of bytes read
//
func Varint(buf []byte) (int64, int) {
	ux, n := Uvarint(buf) // ok to continue in presence of error
	x := int64(ux >> 1)
	if ux&1 != 0 {
		x = ^x
	}
	return x, n
}

var overflow = errors.New("binary: varint overflows a 64-bit integer")

// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
func ReadUvarint(r io.ByteReader) (uint64, error) {
	var x uint64
	var s uint
	for i := 0; ; i++ {
		b, err := r.ReadByte()
		if err != nil {
			return x, err
		}
		if b < 0x80 {
			if i > 9 || i == 9 && b > 1 {
				return x, overflow
			}
			return x | uint64(b)<<s, nil
		}
		x |= uint64(b&0x7f) << s
		s += 7
	}
	panic("unreachable")
}

// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
func ReadVarint(r io.ByteReader) (int64, error) {
	ux, err := ReadUvarint(r) // ok to continue in presence of error
	x := int64(ux >> 1)
	if ux&1 != 0 {
		x = ^x
	}
	return x, err
}
<commit_msg>encoding/binary: fix typo: ReadVarint returns an int64, not a uint64.<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 binary

// This file implements "varint" encoding of 64-bit integers.
// The encoding is:
// - unsigned integers are serialized 7 bits at a time, starting with the
//   least significant bits
// - the most significant bit (msb) in each output byte indicates if there
//   is a continuation byte (msb = 1)
// - signed integers are mapped to unsigned integers using "zig-zag"
//   encoding: Positive values x are written as 2*x + 0, negative values
//   are written as 2*(^x) + 1; that is, negative numbers are complemented
//   and whether to complement is encoded in bit 0.
//
// Design note:
// At most 10 bytes are needed for 64-bit values. The encoding could
// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
// Instead, the msb of the previous byte could be used to hold bit 63 since we
// know there can't be more than 64 bits. This is a trivial improvement and
// would reduce the maximum encoding length to 9 bytes. However, it breaks the
// invariant that the msb is always the "continuation bit" and thus makes the
// format incompatible with a varint encoding for larger numbers (say 128-bit).

import (
	"errors"
	"io"
)

// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
const (
	MaxVarintLen16 = 3
	MaxVarintLen32 = 5
	MaxVarintLen64 = 10
)

// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
// If the buffer is too small, PutUvarint will panic.
func PutUvarint(buf []byte, x uint64) int {
	i := 0
	for x >= 0x80 {
		buf[i] = byte(x) | 0x80
		x >>= 7
		i++
	}
	buf[i] = byte(x)
	return i + 1
}

// Uvarint decodes a uint64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 meaning:
//
//	n == 0: buf too small
//	n  < 0: value larger than 64 bits (overflow)
//              and -n is the number of bytes read
//
func Uvarint(buf []byte) (uint64, int) {
	var x uint64
	var s uint
	for i, b := range buf {
		if b < 0x80 {
			if i > 9 || i == 9 && b > 1 {
				return 0, -(i + 1) // overflow
			}
			return x | uint64(b)<<s, i + 1
		}
		x |= uint64(b&0x7f) << s
		s += 7
	}
	return 0, 0
}

// PutVarint encodes an int64 into buf and returns the number of bytes written.
// If the buffer is too small, PutVarint will panic.
func PutVarint(buf []byte, x int64) int {
	ux := uint64(x) << 1
	if x < 0 {
		ux = ^ux
	}
	return PutUvarint(buf, ux)
}

// Varint decodes an int64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 with the following meaning:
//
//	n == 0: buf too small
//	n  < 0: value larger than 64 bits (overflow)
//              and -n is the number of bytes read
//
func Varint(buf []byte) (int64, int) {
	ux, n := Uvarint(buf) // ok to continue in presence of error
	x := int64(ux >> 1)
	if ux&1 != 0 {
		x = ^x
	}
	return x, n
}

var overflow = errors.New("binary: varint overflows a 64-bit integer")

// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
func ReadUvarint(r io.ByteReader) (uint64, error) {
	var x uint64
	var s uint
	for i := 0; ; i++ {
		b, err := r.ReadByte()
		if err != nil {
			return x, err
		}
		if b < 0x80 {
			if i > 9 || i == 9 && b > 1 {
				return x, overflow
			}
			return x | uint64(b)<<s, nil
		}
		x |= uint64(b&0x7f) << s
		s += 7
	}
	panic("unreachable")
}

// ReadVarint reads an encoded unsigned integer from r and returns it as an int64.
func ReadVarint(r io.ByteReader) (int64, error) {
	ux, err := ReadUvarint(r) // ok to continue in presence of error
	x := int64(ux >> 1)
	if ux&1 != 0 {
		x = ^x
	}
	return x, err
}
<|endoftext|>