<commit_before>package convolution

import (
	"errors"
	"fmt"
	"image"
	"math"

	"github.com/urandom/drawgl"
	"github.com/urandom/graph"
	"github.com/urandom/graph/base"
)

type Convolution struct {
	base.Node
	opts ConvolutionOptions
}

type ConvolutionOptions struct {
	Kernel    Kernel
	Channel   drawgl.Channel
	Normalize bool
	Region    image.Rectangle
}

func NewConvolutionLinker(opts ConvolutionOptions) (graph.Linker, error) {
	if len(opts.Kernel.Weights()) == 0 {
		return nil, errors.New("Empty kernel")
	}

	opts.Channel.Normalize()

	return base.NewLinkerNode(Convolution{Node: base.NewNode(), opts: opts}), nil
}

func (n Convolution) Process(wd graph.WalkData, buffers map[graph.ConnectorName]drawgl.Result, output chan<- drawgl.Result) {
	var err error
	res := drawgl.Result{Id: n.Id()}

	defer func() {
		if err != nil {
			res.Error = fmt.Errorf("Error applying convolution using %v: %v", n.opts, err)
		}
		output <- res

		wd.Close()
	}()

	r := buffers[graph.InputName]
	buf := r.Buffer
	res.Meta = r.Meta
	if buf == nil {
		err = fmt.Errorf("no input buffer")
		return
	}

	hasRegion := false
	if !n.opts.Region.Empty() {
		hasRegion = true
	}

	var weights []float64
	var offset float64
	if n.opts.Normalize {
		weights, offset = n.opts.Kernel.Normalized()
	} else {
		weights = n.opts.Kernel.Weights()
	}

	src := drawgl.CopyImage(buf)
	b := buf.Bounds()
	l := len(weights)
	size := int(math.Sqrt(float64(l)))
	half := int(size / 2)

	opaque := buf.Opaque()
	drawgl.ParallelRectangleIterator(b).Iterate(func(pt image.Point) {
		if hasRegion && !pt.In(n.opts.Region) {
			return
		}

		var rsum, gsum, bsum, asum float64
		for cy := pt.Y - half; cy <= pt.Y+half; cy++ {
			for cx := pt.X - half; cx <= pt.X+half; cx++ {
				coeff := weights[l-((cy-pt.Y+half)*size+cx-pt.X+half)-1]

				mx := cx
				my := cy
				if mx < b.Min.X {
					mx = 2*b.Min.X - mx
				} else if mx >= b.Max.X {
					mx = (b.Max.X-1)*2 - mx
				}

				if my < b.Min.Y {
					my = 2*b.Min.Y - my
				} else if my >= b.Max.Y {
					my = (b.Max.Y-1)*2 - my
				}

				c := src.NRGBA64At(mx, my)

				if n.opts.Channel&drawgl.Red > 0 {
					rsum += coeff * float64(c.R)
				}
				if n.opts.Channel&drawgl.Green > 0 {
					gsum += coeff * float64(c.G)
				}
				if n.opts.Channel&drawgl.Blue > 0 {
					bsum += coeff * float64(c.B)
				}
				if !opaque && n.opts.Channel&drawgl.Alpha > 0 {
					asum += coeff * float64(c.A)
				}
			}
		}

		c := src.NRGBA64At(pt.X, pt.Y)

		if n.opts.Channel&drawgl.Red > 0 {
			c.R = drawgl.ClampUint16(rsum + offset)
		}
		if n.opts.Channel&drawgl.Green > 0 {
			c.G = drawgl.ClampUint16(gsum + offset)
		}
		if n.opts.Channel&drawgl.Blue > 0 {
			c.B = drawgl.ClampUint16(bsum + offset)
		}
		if !opaque && n.opts.Channel&drawgl.Alpha > 0 {
			c.A = drawgl.ClampUint16(asum + offset)
		}

		buf.SetNRGBA64(pt.X, pt.Y, c)
	})

	res.Buffer = buf
}
<commit_msg>add more options to the convolution operation<commit_after>package convolution

import (
	"errors"
	"fmt"
	"image"
	"math"

	"github.com/urandom/drawgl"
	"github.com/urandom/graph"
	"github.com/urandom/graph/base"
)

type Convolution struct {
	base.Node
	opts ConvolutionOptions
}

type ConvolutionOptions struct {
	Kernel    Kernel
	Channel   drawgl.Channel
	Normalize bool
	Region    image.Rectangle
	Alpha     bool
	Linear    bool
}

func NewConvolutionLinker(opts ConvolutionOptions) (graph.Linker, error) {
	if len(opts.Kernel.Weights()) == 0 {
		return nil, errors.New("Empty kernel")
	}

	opts.Channel.Normalize()

	return base.NewLinkerNode(Convolution{Node: base.NewNode(), opts: opts}), nil
}

func (n Convolution) Process(wd graph.WalkData, buffers map[graph.ConnectorName]drawgl.Result, output chan<- drawgl.Result) {
	var err error
	res := drawgl.Result{Id: n.Id()}

	defer func() {
		if err != nil {
			res.Error = fmt.Errorf("Error applying convolution using %v: %v", n.opts, err)
		}
		output <- res

		wd.Close()
	}()

	r := buffers[graph.InputName]
	buf := r.Buffer
	res.Meta = r.Meta
	if buf == nil {
		err = fmt.Errorf("no input buffer")
		return
	}

	hasRegion := false
	if !n.opts.Region.Empty() {
		hasRegion = true
	}

	var weights []float64
	var offset float64
	if n.opts.Normalize {
		weights, offset = n.opts.Kernel.Normalized()
	} else {
		weights = n.opts.Kernel.Weights()
	}

	src := drawgl.CopyImage(buf)
	b := buf.Bounds()
	l := len(weights)
	size := int(math.Sqrt(float64(l)))
	half := int(size / 2)

	var it drawgl.RectangleIterator
	if n.opts.Linear {
		it = drawgl.LinearRectangleIterator(b)
	} else {
		it = drawgl.ParallelRectangleIterator(b)
	}

	it.Iterate(func(pt image.Point) {
		if hasRegion && !pt.In(n.opts.Region) {
			return
		}

		var rsum, gsum, bsum, asum float64
		for cy := pt.Y - half; cy <= pt.Y+half; cy++ {
			for cx := pt.X - half; cx <= pt.X+half; cx++ {
				coeff := weights[l-((cy-pt.Y+half)*size+cx-pt.X+half)-1]

				mx := cx
				my := cy
				if mx < b.Min.X {
					mx = 2*b.Min.X - mx
				} else if mx >= b.Max.X {
					mx = (b.Max.X-1)*2 - mx
				}

				if my < b.Min.Y {
					my = 2*b.Min.Y - my
				} else if my >= b.Max.Y {
					my = (b.Max.Y-1)*2 - my
				}

				c := src.NRGBA64At(mx, my)

				if n.opts.Channel&drawgl.Red > 0 {
					rsum += coeff * float64(c.R)
				}
				if n.opts.Channel&drawgl.Green > 0 {
					gsum += coeff * float64(c.G)
				}
				if n.opts.Channel&drawgl.Blue > 0 {
					bsum += coeff * float64(c.B)
				}
				if n.opts.Alpha && n.opts.Channel&drawgl.Alpha > 0 {
					asum += coeff * float64(c.A)
				}
			}
		}

		c := src.NRGBA64At(pt.X, pt.Y)

		if n.opts.Channel&drawgl.Red > 0 {
			c.R = drawgl.ClampUint16(rsum + offset)
		}
		if n.opts.Channel&drawgl.Green > 0 {
			c.G = drawgl.ClampUint16(gsum + offset)
		}
		if n.opts.Channel&drawgl.Blue > 0 {
			c.B = drawgl.ClampUint16(bsum + offset)
		}
		if n.opts.Alpha && n.opts.Channel&drawgl.Alpha > 0 {
			c.A = drawgl.ClampUint16(asum + offset)
		}

		buf.SetNRGBA64(pt.X, pt.Y, c)
	})

	res.Buffer = buf
}
<|endoftext|>


<commit_before>package acmewrapper

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestCert(t *testing.T) {
	os.Remove("cert.crt")
	os.Remove("key.pem")

	w, err := New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSAgree,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",
	})

	require.NoError(t, err)

	c := w.GetCertificate().Certificate[0]

	// Make sure the files were written
	_, err = os.Stat("cert.crt")
	require.False(t, os.IsNotExist(err))
	_, err = os.Stat("key.pem")
	require.False(t, os.IsNotExist(err))

	// Make sure that the key and cert were generated correctly - make the TOS fail,
	// and the renew callback fail, since ACME shouldn't need to be set at all
	hadfailure := false
	w, err = New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSDecline,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			hadfailure = true
		},
	})

	require.NoError(t, err)
	require.False(t, hadfailure)
	require.True(t, bytes.Equal(w.GetCertificate().Certificate[0], c))

	// Now make sure that we can load without ACME enabled using our currentkeys
	w, err = New(Config{
		Server:       TESTAPI,
		AcmeDisabled: true,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",
	})

	require.NoError(t, err)
	require.False(t, hadfailure)
	require.True(t, bytes.Equal(w.GetCertificate().Certificate[0], c))

	// Lastly: Make sure we can start without ACME enabled, but enable it later.
	// NOTE: This also tests our renewal function
	renewnum := 0
	w, err = New(Config{
		AcmeDisabled: true,
		Server:       TESTAPI,
		TOSCallback:  TOSAgree,
		Domains:      TESTDOMAINS,
		Address:      TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			renewnum++
		},

		RenewTime:  50 * 365 * 24 * time.Hour, // A ridiculous value so that renew always happens
		RenewCheck: 3 * time.Second,
		RetryDelay: 3 * time.Second,

		RenewFailedCallback: func(err error) {
			require.NoError(t, err)
		},
	})

	require.NoError(t, err)

	// Now start a server with the config
	listener, err := tls.Listen("tcp", TLSADDRESS, w.TLSConfig())
	require.NoError(t, err)
	go func() {
		http.Serve(listener, nil)
	}()

	fmt.Printf("acmeenable\n")
	require.NoError(t, w.AcmeDisabled(false))

	// Now the certificate should be set
	fmt.Printf("getcert\n")
	crt := w.GetCertificate()
	fmt.Printf("Sleeping for 8 seconds...\n")
	time.Sleep(8 * time.Second)
	fmt.Printf("Done sleeping\n")

	// The certificate should be renewed
	require.NotEqual(t, crt, w.GetCertificate())
	require.True(t, renewnum >= 2)

	// Stop it from being annoying in the background anymore
	w.Config.RenewCheck = 9999 * 24 * time.Hour
	w.Config.RetryDelay = 9999 * 24 * time.Hour
	w.Config.RenewTime = 30 * time.Hour
	listener.Close()
}
<commit_msg>Added domain change tests<commit_after>package acmewrapper

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestCert(t *testing.T) {
	os.Remove("cert.crt")
	os.Remove("key.pem")

	w, err := New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSAgree,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",
	})

	require.NoError(t, err)

	c := w.GetCertificate().Certificate[0]

	// Make sure the files were written
	_, err = os.Stat("cert.crt")
	require.False(t, os.IsNotExist(err))
	_, err = os.Stat("key.pem")
	require.False(t, os.IsNotExist(err))

	// Make sure that the key and cert were generated correctly - make the TOS fail,
	// and the renew callback fail, since ACME shouldn't need to be set at all
	hadfailure := false
	w, err = New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSDecline,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			hadfailure = true
		},
	})

	require.NoError(t, err)
	require.False(t, hadfailure)
	require.True(t, bytes.Equal(w.GetCertificate().Certificate[0], c))

	// Now make sure that we can load without ACME enabled using our currentkeys
	w, err = New(Config{
		Server:       TESTAPI,
		AcmeDisabled: true,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",
	})

	require.NoError(t, err)
	require.False(t, hadfailure)
	require.True(t, bytes.Equal(w.GetCertificate().Certificate[0], c))

	// Lastly: Make sure we can start without ACME enabled, but enable it later.
	// NOTE: This also tests our renewal function
	renewnum := 0
	w, err = New(Config{
		AcmeDisabled: true,
		Server:       TESTAPI,
		TOSCallback:  TOSAgree,
		Domains:      TESTDOMAINS,
		Address:      TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			renewnum++
		},

		RenewTime:  50 * 365 * 24 * time.Hour, // A ridiculous value so that renew always happens
		RenewCheck: 3 * time.Second,
		RetryDelay: 3 * time.Second,

		RenewFailedCallback: func(err error) {
			require.NoError(t, err)
		},
	})

	require.NoError(t, err)

	// Now start a server with the config
	listener, err := tls.Listen("tcp", TLSADDRESS, w.TLSConfig())
	require.NoError(t, err)
	go func() {
		http.Serve(listener, nil)
	}()

	fmt.Printf("acmeenable\n")
	require.NoError(t, w.AcmeDisabled(false))

	// Now the certificate should be set
	fmt.Printf("getcert\n")
	crt := w.GetCertificate()
	fmt.Printf("Sleeping for 8 seconds...\n")
	time.Sleep(8 * time.Second)
	fmt.Printf("Done sleeping\n")

	// The certificate should be renewed
	require.NotEqual(t, crt, w.GetCertificate())
	require.True(t, renewnum >= 2)

	// Stop it from being annoying in the background anymore
	w.Config.RenewCheck = 9999 * 24 * time.Hour
	w.Config.RetryDelay = 9999 * 24 * time.Hour
	w.Config.RenewTime = 30 * time.Hour
	listener.Close()
}

// We now test to make sure that if the domain is changed,
// the cert is changed
func TestDomainChange(t *testing.T) {
	os.Remove("cert.crt")
	os.Remove("key.pem")
	newdomains := []string{"www." + TESTDOMAINS[0], TESTDOMAINS[0]}

	domainchanged := false

	// First set up the domain cert
	_, err := New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSAgree,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			domainchanged = true
		},
	})

	require.NoError(t, err)
	require.True(t, domainchanged)

	// Now running again will not renew
	domainchanged = false
	// First set up the domain cert
	_, err = New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSAgree,
		Domains:          TESTDOMAINS,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			domainchanged = true
		},
	})
	require.NoError(t, err)
	require.False(t, domainchanged)

	// Finally, we run one more time, but this time we change the domains - and check to see if renew is called
	// Now running again will not call domainchanged
	domainchanged = false
	_, err = New(Config{
		Server:           TESTAPI,
		TOSCallback:      TOSAgree,
		Domains:          newdomains,
		PrivateKeyFile:   "testinguser.key",
		RegistrationFile: "testinguser.reg",
		Address:          TLSADDRESS,

		TLSCertFile: "cert.crt",
		TLSKeyFile:  "key.pem",

		RenewCallback: func() {
			domainchanged = true
		},
	})
	require.NoError(t, err)
	require.True(t, domainchanged)
}
<|endoftext|>


<commit_before>package websocket

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"net/url"

	tpt "github.com/libp2p/go-libp2p-transport"
	ma "github.com/multiformats/go-multiaddr"
	manet "github.com/multiformats/go-multiaddr-net"
	mafmt "github.com/whyrusleeping/mafmt"
	ws "golang.org/x/net/websocket"
)

var WsProtocol = ma.Protocol{
	Code:  477,
	Name:  "ws",
	VCode: ma.CodeToVarint(477),
}

var WsFmt = mafmt.And(mafmt.TCP, mafmt.Base(WsProtocol.Code))

var WsCodec = &manet.NetCodec{
	NetAddrNetworks:  []string{"websocket"},
	ProtocolName:     "ws",
	ConvertMultiaddr: ConvertWebsocketMultiaddrToNetAddr,
	ParseNetAddr:     ParseWebsocketNetAddr,
}

func init() {
	err := ma.AddProtocol(WsProtocol)
	if err != nil {
		panic(fmt.Errorf("error registering websocket protocol: %s", err))
	}

	manet.RegisterNetCodec(WsCodec)
}

func ConvertWebsocketMultiaddrToNetAddr(maddr ma.Multiaddr) (net.Addr, error) {
	_, host, err := manet.DialArgs(maddr)
	if err != nil {
		return nil, err
	}

	a := &ws.Addr{
		URL: &url.URL{
			Host: host,
		},
	}
	return a, nil
}

func ParseWebsocketNetAddr(a net.Addr) (ma.Multiaddr, error) {
	wsa, ok := a.(*ws.Addr)
	if !ok {
		return nil, fmt.Errorf("not a websocket address")
	}

	tcpaddr, err := net.ResolveTCPAddr("tcp", wsa.Host)
	if err != nil {
		return nil, err
	}

	tcpma, err := manet.FromNetAddr(tcpaddr)
	if err != nil {
		return nil, err
	}

	wsma, err := ma.NewMultiaddr("/ws")
	if err != nil {
		return nil, err
	}

	return tcpma.Encapsulate(wsma), nil
}

type WebsocketTransport struct{}

func (t *WebsocketTransport) Matches(a ma.Multiaddr) bool {
	return WsFmt.Matches(a)
}

func (t *WebsocketTransport) Dialer(_ ma.Multiaddr, opts ...tpt.DialOpt) (tpt.Dialer, error) {
	return &dialer{}, nil
}

type dialer struct{}

func parseMultiaddr(a ma.Multiaddr) (string, error) {
	_, host, err := manet.DialArgs(a)
	if err != nil {
		return "", err
	}

	return "ws://" + host, nil
}

func (d *dialer) Dial(raddr ma.Multiaddr) (tpt.Conn, error) {
	return d.DialContext(context.Background(), raddr)
}

func (d *dialer) DialContext(ctx context.Context, raddr ma.Multiaddr) (tpt.Conn, error) {
	wsurl, err := parseMultiaddr(raddr)
	if err != nil {
		return nil, err
	}

	wscon, err := ws.Dial(wsurl, "", "http://127.0.0.1:0/")
	if err != nil {
		return nil, err
	}

	mnc, err := manet.WrapNetConn(wscon)
	if err != nil {
		return nil, err
	}

	return &wsConn{
		Conn: mnc,
	}, nil
}

func (d *dialer) Matches(a ma.Multiaddr) bool {
	return WsFmt.Matches(a)
}

type wsConn struct {
	manet.Conn
	t tpt.Transport
}

func (c *wsConn) Transport() tpt.Transport {
	return c.t
}

type listener struct {
	manet.Listener

	incoming chan *conn

	tpt tpt.Transport
}

type conn struct {
	*ws.Conn

	done func()
}

func (c *conn) Close() error {
	c.done()
	return c.Conn.Close()
}

func (t *WebsocketTransport) Listen(a ma.Multiaddr) (tpt.Listener, error) {
	list, err := manet.Listen(a)
	if err != nil {
		return nil, err
	}

	tlist := t.wrapListener(list)

	u, err := url.Parse("ws://" + list.Addr().String())
	if err != nil {
		return nil, err
	}

	s := &ws.Server{
		Handler: tlist.handleWsConn,
		Config:  ws.Config{Origin: u},
	}

	go http.Serve(list.NetListener(), s)

	return tlist, nil
}

func (t *WebsocketTransport) wrapListener(l manet.Listener) *listener {
	return &listener{
		Listener: l,
		incoming: make(chan *conn),
		tpt:      t,
	}
}

func (l *listener) handleWsConn(s *ws.Conn) {
	ctx, cancel := context.WithCancel(context.Background())
	s.PayloadType = ws.BinaryFrame

	l.incoming <- &conn{
		Conn: s,
		done: cancel,
	}

	// wait until conn gets closed, otherwise the handler closes it early
	<-ctx.Done()
}

func (l *listener) Accept() (tpt.Conn, error) {
	c, ok := <-l.incoming
	if !ok {
		return nil, fmt.Errorf("listener is closed")
	}

	mnc, err := manet.WrapNetConn(c)
	if err != nil {
		return nil, err
	}

	return &wsConn{
		Conn: mnc,
		t:    l.tpt,
	}, nil
}

func (l *listener) Multiaddr() ma.Multiaddr {
	wsma, err := ma.NewMultiaddr("/ws")
	if err != nil {
		panic(err)
	}

	return l.Listener.Multiaddr().Encapsulate(wsma)
}

var _ tpt.Transport = (*WebsocketTransport)(nil)
<commit_msg>feat: upgrade to use gorilla/websocket<commit_after>package websocket

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"time"

	wsGorilla "github.com/gorilla/websocket"
	tpt "github.com/libp2p/go-libp2p-transport"
	ma "github.com/multiformats/go-multiaddr"
	manet "github.com/multiformats/go-multiaddr-net"
	mafmt "github.com/whyrusleeping/mafmt"
	ws "golang.org/x/net/websocket"
)

var WsProtocol = ma.Protocol{
	Code:  477,
	Name:  "ws",
	VCode: ma.CodeToVarint(477),
}

var WsFmt = mafmt.And(mafmt.TCP, mafmt.Base(WsProtocol.Code))

var WsCodec = &manet.NetCodec{
	NetAddrNetworks:  []string{"websocket"},
	ProtocolName:     "ws",
	ConvertMultiaddr: ConvertWebsocketMultiaddrToNetAddr,
	ParseNetAddr:     ParseWebsocketNetAddr,
}

// Default gorilla upgrader
var upgrader = wsGorilla.Upgrader{}

func init() {
	err := ma.AddProtocol(WsProtocol)
	if err != nil {
		panic(fmt.Errorf("error registering websocket protocol: %s", err))
	}

	manet.RegisterNetCodec(WsCodec)
}

func ConvertWebsocketMultiaddrToNetAddr(maddr ma.Multiaddr) (net.Addr, error) {
	_, host, err := manet.DialArgs(maddr)
	if err != nil {
		return nil, err
	}

	a := &ws.Addr{
		URL: &url.URL{
			Host: host,
		},
	}
	return a, nil
}

func ParseWebsocketNetAddr(a net.Addr) (ma.Multiaddr, error) {
	wsa, ok := a.(*ws.Addr)
	if !ok {
		return nil, fmt.Errorf("not a websocket address")
	}

	tcpaddr, err := net.ResolveTCPAddr("tcp", wsa.Host)
	if err != nil {
		return nil, err
	}

	tcpma, err := manet.FromNetAddr(tcpaddr)
	if err != nil {
		return nil, err
	}

	wsma, err := ma.NewMultiaddr("/ws")
	if err != nil {
		return nil, err
	}

	return tcpma.Encapsulate(wsma), nil
}

type WebsocketTransport struct{}

func (t *WebsocketTransport) Matches(a ma.Multiaddr) bool {
	return WsFmt.Matches(a)
}

func (t *WebsocketTransport) Dialer(_ ma.Multiaddr, opts ...tpt.DialOpt) (tpt.Dialer, error) {
	return &dialer{}, nil
}

type dialer struct{}

func parseMultiaddr(a ma.Multiaddr) (string, error) {
	_, host, err := manet.DialArgs(a)
	if err != nil {
		return "", err
	}

	return "ws://" + host, nil
}

func (d *dialer) Dial(raddr ma.Multiaddr) (tpt.Conn, error) {
	return d.DialContext(context.Background(), raddr)
}

func (d *dialer) DialContext(ctx context.Context, raddr ma.Multiaddr) (tpt.Conn, error) {
	wsurl, err := parseMultiaddr(raddr)
	if err != nil {
		return nil, err
	}

	// TODO: figure out origins, probably don't work for us
	// header := http.Header{}
	// header.Set("Origin", "http://127.0.0.1:0/")
	wscon, _, err := wsGorilla.DefaultDialer.Dial(wsurl, nil)
	if err != nil {
		return nil, err
	}

	mnc, err := manet.WrapNetConn(NewGorillaNetConn(wscon))
	if err != nil {
		return nil, err
	}

	return &wsConn{
		Conn: mnc,
	}, nil
}

func (d *dialer) Matches(a ma.Multiaddr) bool {
	return WsFmt.Matches(a)
}

type wsConn struct {
	manet.Conn
	t tpt.Transport
}

func (c *wsConn) Transport() tpt.Transport {
	return c.t
}

type listener struct {
	manet.Listener

	incoming chan *conn

	tpt tpt.Transport

	origin *url.URL
}

type conn struct {
	*GorillaNetConn

	done func()
}

func (c *conn) Close() error {
	c.done()
	return c.GorillaNetConn.Close()
}

func (t *WebsocketTransport) Listen(a ma.Multiaddr) (tpt.Listener, error) {
	list, err := manet.Listen(a)
	if err != nil {
		return nil, err
	}

	u, err := url.Parse("http://" + list.Addr().String())
	if err != nil {
		return nil, err
	}

	tlist := t.wrapListener(list, u)

	http.HandleFunc("/", tlist.handleWsConn)
	go http.Serve(list.NetListener(), nil)

	return tlist, nil
}

func (t *WebsocketTransport) wrapListener(l manet.Listener, origin *url.URL) *listener {
	return &listener{
		Listener: l,
		incoming: make(chan *conn),
		tpt:      t,
		origin:   origin,
	}
}

func (l *listener) handleWsConn(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		http.Error(w, "Failed to upgrade websocket", 400)
		return
	}

	ctx, cancel := context.WithCancel(context.Background())

	wrapped := NewGorillaNetConn(c)
	l.incoming <- &conn{
		GorillaNetConn: &wrapped,
		done:           cancel,
	}

	// wait until conn gets closed, otherwise the handler closes it early
	<-ctx.Done()
}

func (l *listener) Accept() (tpt.Conn, error) {
	c, ok := <-l.incoming
	if !ok {
		return nil, fmt.Errorf("listener is closed")
	}

	mnc, err := manet.WrapNetConn(c)
	if err != nil {
		return nil, err
	}

	return &wsConn{
		Conn: mnc,
		t:    l.tpt,
	}, nil
}

func (l *listener) Multiaddr() ma.Multiaddr {
	wsma, err := ma.NewMultiaddr("/ws")
	if err != nil {
		panic(err)
	}

	return l.Listener.Multiaddr().Encapsulate(wsma)
}

var _ tpt.Transport = (*WebsocketTransport)(nil)

type GorillaNetConn struct {
	Inner              *wsGorilla.Conn
	DefaultMessageType int
}

func (c GorillaNetConn) Read(b []byte) (n int, err error) {
	fmt.Println("reading")
	_, r, err := c.Inner.NextReader()
	if err != nil {
		return 0, err
	}

	return r.Read(b)
}

func (c GorillaNetConn) Write(b []byte) (n int, err error) {
	fmt.Printf("write %s\n", string(b))
	if err := c.Inner.WriteMessage(c.DefaultMessageType, b); err != nil {
		return 0, err
	}

	return len(b), nil
}

func (c GorillaNetConn) Close() error {
	return c.Inner.Close()
}

func (c GorillaNetConn) LocalAddr() net.Addr {
	return c.Inner.LocalAddr()
}

func (c GorillaNetConn) RemoteAddr() net.Addr {
	return c.Inner.RemoteAddr()
}

func (c GorillaNetConn) SetDeadline(t time.Time) error {
	if err := c.SetReadDeadline(t); err != nil {
		return err
	}

	return c.SetReadDeadline(t)
}

func (c GorillaNetConn) SetReadDeadline(t time.Time) error {
	return c.Inner.SetReadDeadline(t)
}

func (c GorillaNetConn) SetWriteDeadline(t time.Time) error {
	return c.Inner.SetWriteDeadline(t)
}

func NewGorillaNetConn(raw *wsGorilla.Conn) GorillaNetConn {
	return GorillaNetConn{
		Inner:              raw,
		DefaultMessageType: wsGorilla.BinaryMessage,
	}
}
<|endoftext|>


<commit_before>package windows_test

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/cloudfoundry/bosh-agent/integration/windows/utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var VagrantProvider = os.Getenv("VAGRANT_PROVIDER")

func TestWindows(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Windows Suite")
}

func tarFixtures(fixturesDir, filename string) error {
	fixtures := []string{
		"service_wrapper.xml",
		"service_wrapper.exe",
		"job-service-wrapper.exe",
		"bosh-blobstore-dav.exe",
		"bosh-agent.exe",
		"pipe.exe",
	}

	archive, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer archive.Close()

	gzipWriter := gzip.NewWriter(archive)
	tarWriter := tar.NewWriter(gzipWriter)

	for _, name := range fixtures {
		path := filepath.Join(fixturesDir, name)
		fi, err := os.Stat(path)
		if err != nil {
			return err
		}

		hdr, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return err
		}

		if err := tarWriter.WriteHeader(hdr); err != nil {
			return err
		}

		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()

		if _, err := io.Copy(tarWriter, f); err != nil {
			return err
		}
	}

	if err := tarWriter.Close(); err != nil {
		return err
	}
	if err := gzipWriter.Close(); err != nil {
		return err
	}
	return nil
}

var _ = BeforeSuite(func() {
	if _, ok := os.LookupEnv("NATS_PRIVATE_IP"); !ok {
		Fail("Environment variable NATS_PRIVATE_IP not set (default is 172.31.180.3 if running locally)", 1)
	}
	if os.Getenv("GOPATH") == "" {
		Fail("Environment variable GOPATH not set", 1)
	}

	if err := utils.BuildAgent(); err != nil {
		Fail(fmt.Sprintln("Could not build the bosh-agent project.\nError is:", err))
	}

	dirname := filepath.Join(os.Getenv("GOPATH"),
		"src/github.com/cloudfoundry/bosh-agent/integration/windows/fixtures")
	filename := filepath.Join(dirname, "fixtures.tgz")
	if err := tarFixtures(dirname, filename); err != nil {
		Fail(fmt.Sprintln("Creating fixtures TGZ::", err))
	}

	_, err := utils.StartVagrant(VagrantProvider)
	if err != nil {
		Fail(fmt.Sprintln("Could not setup and run vagrant.\nError is:", err))
	}
})
<commit_msg>Fix golint issue with a windows test<commit_after>package windows_test

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/cloudfoundry/bosh-agent/integration/windows/utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var VagrantProvider = os.Getenv("VAGRANT_PROVIDER")

func TestWindows(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Windows Suite")
}

func tarFixtures(fixturesDir, filename string) error {
	fixtures := []string{
		"service_wrapper.xml",
		"service_wrapper.exe",
		"job-service-wrapper.exe",
		"bosh-blobstore-dav.exe",
		"bosh-agent.exe",
		"pipe.exe",
	}

	archive, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer archive.Close()

	gzipWriter := gzip.NewWriter(archive)
	tarWriter := tar.NewWriter(gzipWriter)

	for _, name := range fixtures {
		path := filepath.Join(fixturesDir, name)
		fi, err := os.Stat(path)
		if err != nil {
			return err
		}

		hdr, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return err
		}

		if err := tarWriter.WriteHeader(hdr); err != nil {
			return err
		}

		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()

		if _, err := io.Copy(tarWriter, f); err != nil {
			return err
		}
	}

	if err := tarWriter.Close(); err != nil {
		return err
	}

	return gzipWriter.Close()
}

var _ = BeforeSuite(func() {
	if _, ok := os.LookupEnv("NATS_PRIVATE_IP"); !ok {
		Fail("Environment variable NATS_PRIVATE_IP not set (default is 172.31.180.3 if running locally)", 1)
	}
	if os.Getenv("GOPATH") == "" {
		Fail("Environment variable GOPATH not set", 1)
	}

	if err := utils.BuildAgent(); err != nil {
		Fail(fmt.Sprintln("Could not build the bosh-agent project.\nError is:", err))
	}

	dirname := filepath.Join(os.Getenv("GOPATH"),
		"src/github.com/cloudfoundry/bosh-agent/integration/windows/fixtures")
	filename := filepath.Join(dirname, "fixtures.tgz")
	if err := tarFixtures(dirname, filename); err != nil {
		Fail(fmt.Sprintln("Creating fixtures TGZ::", err))
	}

	_, err := utils.StartVagrant(VagrantProvider)
	if err != nil {
		Fail(fmt.Sprintln("Could not setup and run vagrant.\nError is:", err))
	}
})
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package serializer

import (
	"mime"
	"strings"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
	"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
)

// serializerExtensions are for serializers that are conditionally compiled in
var serializerExtensions = []func(*runtime.Scheme) (serializerType, bool){}

type serializerType struct {
	AcceptContentTypes []string
	ContentType        string
	FileExtensions     []string
	// EncodesAsText should be true if this content type can be represented safely in UTF-8
	EncodesAsText bool

	Serializer       runtime.Serializer
	PrettySerializer runtime.Serializer

	AcceptStreamContentTypes []string
	StreamContentType        string

	Framer           runtime.Framer
	StreamSerializer runtime.Serializer
}

func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
	jsonSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
	)
	jsonSerializerType := serializerType{
		AcceptContentTypes: []string{runtime.ContentTypeJSON},
		ContentType:        runtime.ContentTypeJSON,
		FileExtensions:     []string{"json"},
		EncodesAsText:      true,
		Serializer:         jsonSerializer,

		Framer:           json.Framer,
		StreamSerializer: jsonSerializer,
	}
	if options.Pretty {
		jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
			mf, scheme, scheme,
			json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
		)
	}

	yamlSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
	)
	protoSerializer := protobuf.NewSerializer(scheme, scheme)
	protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)

	serializers := []serializerType{
		jsonSerializerType,
		{
			AcceptContentTypes: []string{runtime.ContentTypeYAML},
			ContentType:        runtime.ContentTypeYAML,
			FileExtensions:     []string{"yaml"},
			EncodesAsText:      true,
			Serializer:         yamlSerializer,
		},
		{
			AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
			ContentType:        runtime.ContentTypeProtobuf,
			FileExtensions:     []string{"pb"},
			Serializer:         protoSerializer,

			Framer:           protobuf.LengthDelimitedFramer,
			StreamSerializer: protoRawSerializer,
		},
	}

	for _, fn := range serializerExtensions {
		if serializer, ok := fn(scheme); ok {
			serializers = append(serializers, serializer)
		}
	}
	return serializers
}

// CodecFactory provides methods for retrieving codecs and serializers for specific
// versions and content types.
type CodecFactory struct {
	scheme      *runtime.Scheme
	serializers []serializerType
	universal   runtime.Decoder
	accepts     []runtime.SerializerInfo

	legacySerializer runtime.Serializer
}

// CodecFactoryOptions holds the options for configuring CodecFactory behavior
type CodecFactoryOptions struct {
	// Strict configures all serializers in strict mode
	Strict bool
	// Pretty includes a pretty serializer along with the non-pretty one
	Pretty bool
}

// CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it.
// Functions implementing this type can be passed to the NewCodecFactory() constructor.
type CodecFactoryOptionsMutator func(*CodecFactoryOptions)

// EnablePretty enables including a pretty serializer along with the non-pretty one
func EnablePretty(options *CodecFactoryOptions) {
	options.Pretty = true
}

// DisablePretty disables including a pretty serializer along with the non-pretty one
func DisablePretty(options *CodecFactoryOptions) {
	options.Pretty = false
}

// EnableStrict enables configuring all serializers in strict mode
func EnableStrict(options *CodecFactoryOptions) {
	options.Strict = true
}

// DisableStrict disables configuring all serializers in strict mode
func DisableStrict(options *CodecFactoryOptions) {
	options.Strict = false
}

// NewCodecFactory provides methods for retrieving serializers for the supported wire formats
// and conversion wrappers to define preferred internal and external versions. In the future,
// as the internal version is used less, callers may instead use a defaulting serializer and
// only convert objects which are shared internally (Status, common API machinery).
//
// Mutators can be passed to change the CodecFactoryOptions before construction of the factory.
// It is recommended to explicitly pass mutators instead of relying on defaults.
// By default, Pretty is enabled -- this is conformant with previously supported behavior.
//
// TODO: allow other codecs to be compiled in?
// TODO: accept a scheme interface
func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
	options := CodecFactoryOptions{Pretty: true}
	for _, fn := range mutators {
		fn(&options)
	}

	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
	return newCodecFactory(scheme, serializers)
}

// newCodecFactory is a helper for testing that allows a different metafactory to be specified.
func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
	decoders := make([]runtime.Decoder, 0, len(serializers))
	var accepts []runtime.SerializerInfo
	alreadyAccepted := make(map[string]struct{})

	var legacySerializer runtime.Serializer
	for _, d := range serializers {
		decoders = append(decoders, d.Serializer)
		for _, mediaType := range d.AcceptContentTypes {
			if _, ok := alreadyAccepted[mediaType]; ok {
				continue
			}
			alreadyAccepted[mediaType] = struct{}{}
			info := runtime.SerializerInfo{
				MediaType:        d.ContentType,
				EncodesAsText:    d.EncodesAsText,
				Serializer:       d.Serializer,
				PrettySerializer: d.PrettySerializer,
			}

			mediaType, _, err := mime.ParseMediaType(info.MediaType)
			if err != nil {
				panic(err)
			}
			parts := strings.SplitN(mediaType, "/", 2)
			info.MediaTypeType = parts[0]
			info.MediaTypeSubType = parts[1]

			if d.StreamSerializer != nil {
				info.StreamSerializer = &runtime.StreamSerializerInfo{
					Serializer:    d.StreamSerializer,
					EncodesAsText: d.EncodesAsText,
					Framer:        d.Framer,
				}
			}
			accepts = append(accepts, info)
			if mediaType == runtime.ContentTypeJSON {
				legacySerializer = d.Serializer
			}
		}
	}
	if legacySerializer == nil {
		legacySerializer = serializers[0].Serializer
	}

	return CodecFactory{
		scheme:      scheme,
		serializers: serializers,
		universal:   recognizer.NewDecoder(decoders...),

		accepts: accepts,

		legacySerializer: legacySerializer,
	}
}

// WithoutConversion returns a NegotiatedSerializer that performs no conversion, even if the
// caller requests it.
func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
	return WithoutConversionCodecFactory{f}
}

// SupportedMediaTypes returns the RFC2046 media types that this factory has serializers for.
func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
	return f.accepts
}

// LegacyCodec encodes output to a given API versions, and decodes output into the internal form from
// any recognized source. The returned codec will always encode output to JSON. If a type is not
// found in the list of versions an error will be returned.
//
// This method is deprecated - clients and servers should negotiate a serializer by mime-type and
// invoke CodecForVersions. Callers that need only to read data should use UniversalDecoder().
//
// TODO: make this call exist only in pkg/api, and initialize it with the set of default versions.
//   All other callers will be forced to request a Codec directly.
func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
	return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
}

// UniversalDeserializer can convert any stored data recognized by this factory into a Go object that satisfies
// runtime.Object. It does not perform conversion. It does not perform defaulting.
func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
	return f.universal
}

// UniversalDecoder returns a runtime.Decoder capable of decoding all known API objects in all known formats. Used
// by clients that do not need to encode objects but want to deserialize API objects stored on disk. Only decodes
// objects in groups registered with the scheme. The GroupVersions passed may be used to select alternate
// versions of objects to return - by default, runtime.APIVersionInternal is used. If any versions are specified,
// unrecognized groups will be returned in the version they are encoded as (no conversion). This decoder performs
// defaulting.
//
// TODO: the decoder will eventually be removed in favor of dealing with objects in their versioned form
// TODO: only accept a group versioner
func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
	var versioner runtime.GroupVersioner
	if len(versions) == 0 {
		versioner = runtime.InternalGroupVersioner
	} else {
		versioner = schema.GroupVersions(versions)
	}
	return f.CodecForVersions(nil, f.universal, nil, versioner)
}

// CodecForVersions creates a codec with the provided serializer. If an object is decoded and its group is not in the list,
// it will default to runtime.APIVersionInternal. If encode is not specified for an object's group, the object is not
// converted. If encode or decode are nil, no conversion is performed.
func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
	// TODO: these are for backcompat, remove them in the future
	if encode == nil {
		encode = runtime.DisabledGroupVersioner
	}
	if decode == nil {
		decode = runtime.InternalGroupVersioner
	}
	return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
}

// DecoderToVersion returns a decoder that targets the provided group version.
func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
	return f.CodecForVersions(nil, decoder, nil, gv)
}

// EncoderForVersion returns an encoder that targets the provided group version.
func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
	return f.CodecForVersions(encoder, nil, gv, nil)
}

// WithoutConversionCodecFactory is a CodecFactory that will explicitly ignore requests to perform conversion.
// This wrapper is used while code migrates away from using conversion (such as external clients) and in the future
// will be unnecessary when we change the signature of NegotiatedSerializer.
type WithoutConversionCodecFactory struct {
	CodecFactory
}

// EncoderForVersion returns an encoder that does not do conversion, but does set the group version kind of the object
// when serialized.
func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
	return runtime.WithVersionEncoder{
		Version:     version,
		Encoder:     serializer,
		ObjectTyper: f.CodecFactory.scheme,
	}
}

// DecoderToVersion returns an decoder that does not do conversion.
func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
	return runtime.WithoutVersionDecoder{
		Decoder: serializer,
	}
}
<commit_msg>remove serializers from codec factory<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package serializer

import (
	"mime"
	"strings"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
	"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
)

// serializerExtensions are for serializers that are conditionally compiled in
var serializerExtensions = []func(*runtime.Scheme) (serializerType, bool){}

type serializerType struct {
	AcceptContentTypes []string
	ContentType        string
	FileExtensions     []string
	// EncodesAsText should be true if this content type can be represented safely in UTF-8
	EncodesAsText bool

	Serializer       runtime.Serializer
	PrettySerializer runtime.Serializer

	AcceptStreamContentTypes []string
	StreamContentType        string

	Framer           runtime.Framer
	StreamSerializer runtime.Serializer
}

func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
	jsonSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
	)
	jsonSerializerType := serializerType{
		AcceptContentTypes: []string{runtime.ContentTypeJSON},
		ContentType:        runtime.ContentTypeJSON,
		FileExtensions:     []string{"json"},
		EncodesAsText:      true,
		Serializer:         jsonSerializer,

		Framer:           json.Framer,
		StreamSerializer: jsonSerializer,
	}
	if options.Pretty {
		jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
			mf, scheme, scheme,
			json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
		)
	}

	yamlSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
	)
	protoSerializer := protobuf.NewSerializer(scheme, scheme)
	protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)

	serializers := []serializerType{
		jsonSerializerType,
		{
			AcceptContentTypes: []string{runtime.ContentTypeYAML},
			ContentType:        runtime.ContentTypeYAML,
			FileExtensions:     []string{"yaml"},
			EncodesAsText:      true,
			Serializer:         yamlSerializer,
		},
		{
			AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
			ContentType:        runtime.ContentTypeProtobuf,
			FileExtensions:     []string{"pb"},
			Serializer:         protoSerializer,

			Framer:           protobuf.LengthDelimitedFramer,
			StreamSerializer: protoRawSerializer,
		},
	}

	for _, fn := range serializerExtensions {
		if serializer, ok := fn(scheme); ok {
			serializers = append(serializers, serializer)
		}
	}
	return serializers
}

// CodecFactory provides methods for retrieving codecs and serializers for specific
// versions and content types.
type CodecFactory struct {
	scheme    *runtime.Scheme
	universal runtime.Decoder
	accepts   []runtime.SerializerInfo

	legacySerializer runtime.Serializer
}

// CodecFactoryOptions holds the options for configuring CodecFactory behavior
type CodecFactoryOptions struct {
	// Strict configures all serializers in strict mode
	Strict bool
	// Pretty includes a pretty serializer along with the non-pretty one
	Pretty bool
}

// CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it.
// Functions implementing this type can be passed to the NewCodecFactory() constructor.
type CodecFactoryOptionsMutator func(*CodecFactoryOptions)

// EnablePretty enables including a pretty serializer along with the non-pretty one
func EnablePretty(options *CodecFactoryOptions) {
	options.Pretty = true
}

// DisablePretty disables including a pretty serializer along with the non-pretty one
func DisablePretty(options *CodecFactoryOptions) {
	options.Pretty = false
}

// EnableStrict enables configuring all serializers in strict mode
func EnableStrict(options *CodecFactoryOptions) {
	options.Strict = true
}

// DisableStrict disables configuring all serializers in strict mode
func DisableStrict(options *CodecFactoryOptions) {
	options.Strict = false
}

// NewCodecFactory provides methods for retrieving serializers for the supported wire formats
// and conversion wrappers to define preferred internal and external versions. In the future,
// as the internal version is used less, callers may instead use a defaulting serializer and
// only convert objects which are shared internally (Status, common API machinery).
//
// Mutators can be passed to change the CodecFactoryOptions before construction of the factory.
// It is recommended to explicitly pass mutators instead of relying on defaults.
// By default, Pretty is enabled -- this is conformant with previously supported behavior.
//
// TODO: allow other codecs to be compiled in?
// TODO: accept a scheme interface
func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
	options := CodecFactoryOptions{Pretty: true}
	for _, fn := range mutators {
		fn(&options)
	}

	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
	return newCodecFactory(scheme, serializers)
}

// newCodecFactory is a helper for testing that allows a different metafactory to be specified.
func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
	decoders := make([]runtime.Decoder, 0, len(serializers))
	var accepts []runtime.SerializerInfo
	alreadyAccepted := make(map[string]struct{})

	var legacySerializer runtime.Serializer
	for _, d := range serializers {
		decoders = append(decoders, d.Serializer)
		for _, mediaType := range d.AcceptContentTypes {
			if _, ok := alreadyAccepted[mediaType]; ok {
				continue
			}
			alreadyAccepted[mediaType] = struct{}{}
			info := runtime.SerializerInfo{
				MediaType:        d.ContentType,
				EncodesAsText:    d.EncodesAsText,
				Serializer:       d.Serializer,
				PrettySerializer: d.PrettySerializer,
			}

			mediaType, _, err := mime.ParseMediaType(info.MediaType)
			if err != nil {
				panic(err)
			}
			parts := strings.SplitN(mediaType, "/", 2)
			info.MediaTypeType = parts[0]
			info.MediaTypeSubType = parts[1]

			if d.StreamSerializer != nil {
				info.StreamSerializer = &runtime.StreamSerializerInfo{
					Serializer:    d.StreamSerializer,
					EncodesAsText: d.EncodesAsText,
					Framer:        d.Framer,
				}
			}
			accepts = append(accepts, info)
			if mediaType == runtime.ContentTypeJSON {
				legacySerializer = d.Serializer
			}
		}
	}
	if legacySerializer == nil {
		legacySerializer = serializers[0].Serializer
	}

	return CodecFactory{
		scheme:    scheme,
		universal: recognizer.NewDecoder(decoders...),

		accepts: accepts,

		legacySerializer: legacySerializer,
	}
}

// WithoutConversion returns a NegotiatedSerializer that performs no conversion, even if the
// caller requests it.
func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
	return WithoutConversionCodecFactory{f}
}

// SupportedMediaTypes returns the RFC2046 media types that this factory has serializers for.
func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
	return f.accepts
}

// LegacyCodec encodes output to a given API versions, and decodes output into the internal form from
// any recognized source. The returned codec will always encode output to JSON. If a type is not
// found in the list of versions an error will be returned.
//
// This method is deprecated - clients and servers should negotiate a serializer by mime-type and
// invoke CodecForVersions. Callers that need only to read data should use UniversalDecoder().
//
// TODO: make this call exist only in pkg/api, and initialize it with the set of default versions.
//   All other callers will be forced to request a Codec directly.
func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
	return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
}

// UniversalDeserializer can convert any stored data recognized by this factory into a Go object that satisfies
// runtime.Object. It does not perform conversion. It does not perform defaulting.
func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
	return f.universal
}

// UniversalDecoder returns a runtime.Decoder capable of decoding all known API objects in all known formats. Used
// by clients that do not need to encode objects but want to deserialize API objects stored on disk. Only decodes
// objects in groups registered with the scheme. The GroupVersions passed may be used to select alternate
// versions of objects to return - by default, runtime.APIVersionInternal is used. If any versions are specified,
// unrecognized groups will be returned in the version they are encoded as (no conversion). This decoder performs
// defaulting.
//
// TODO: the decoder will eventually be removed in favor of dealing with objects in their versioned form
// TODO: only accept a group versioner
func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
	var versioner runtime.GroupVersioner
	if len(versions) == 0 {
		versioner = runtime.InternalGroupVersioner
	} else {
		versioner = schema.GroupVersions(versions)
	}
	return f.CodecForVersions(nil, f.universal, nil, versioner)
}

// CodecForVersions creates a codec with the provided serializer. If an object is decoded and its group is not in the list,
// it will default to runtime.APIVersionInternal. If encode is not specified for an object's group, the object is not
// converted. If encode or decode are nil, no conversion is performed.
func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
	// TODO: these are for backcompat, remove them in the future
	if encode == nil {
		encode = runtime.DisabledGroupVersioner
	}
	if decode == nil {
		decode = runtime.InternalGroupVersioner
	}
	return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
}

// DecoderToVersion returns a decoder that targets the provided group version.
func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
	return f.CodecForVersions(nil, decoder, nil, gv)
}

// EncoderForVersion returns an encoder that targets the provided group version.
func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
	return f.CodecForVersions(encoder, nil, gv, nil)
}

// WithoutConversionCodecFactory is a CodecFactory that will explicitly ignore requests to perform conversion.
// This wrapper is used while code migrates away from using conversion (such as external clients) and in the future
// will be unnecessary when we change the signature of NegotiatedSerializer.
type WithoutConversionCodecFactory struct {
	CodecFactory
}

// EncoderForVersion returns an encoder that does not do conversion, but does set the group version kind of the object
// when serialized.
func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
	return runtime.WithVersionEncoder{
		Version:     version,
		Encoder:     serializer,
		ObjectTyper: f.CodecFactory.scheme,
	}
}

// DecoderToVersion returns an decoder that does not do conversion.
func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
	return runtime.WithoutVersionDecoder{
		Decoder: serializer,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"goSpace/goSpace/topology"
	"goSpace/goSpace/tuplespace"
)

func main() {
	ts := tuplespace.CreateTupleSpace(8080)
	ptp := topology.CreatePointToPoint("Bookstore", "localhost", 8080)
	tuplespace.Put(ptp, 2, 2)
	tuplespace.Put(ptp, 2, 2)
	tuplespace.Put(ptp, 2, 3)
	tuplespace.Put(ptp, 2, 3)
	tuplespace.Put(ptp, 2, false)
	fmt.Println(ts)
	var i int
	fmt.Println(tuplespace.QueryAll(ptp, 2, 2))
	fmt.Println(tuplespace.GetAll(ptp, 2, &i))
	fmt.Println(tuplespace.QueryAll(ptp, 2, 2))
	fmt.Println(ts)
	/*
		addBooks(ptp)
		fmt.Println(ts)
		go cashier(ptp)
		costumer(ptp)
		time.Sleep(2 * time.Second)
	*/
}

func addBooks(ptp topology.PointToPoint) {
	//s := "Of Mice and Men"
	tuplespace.Put(ptp, "Of Mice and Men", 200)
}

func cashier(ptp topology.PointToPoint) {
	for {
		var i int
		var book string
		tuplespace.Get(ptp, "Payment", &book, &i)
		var price int
		tuplespace.Query(ptp, book, &price)
		if price == i {
			fmt.Printf("Recieved payment of %d for the book \"%s\".\n", i, book)
			tuplespace.Get(ptp, book, i)
		}
	}
}

func costumer(ptp topology.PointToPoint) {
	var i int
	book := "Of Mice and Men"
	//search for book and save price in i
	tuplespace.Query(ptp, book, &i)
	fmt.Printf("Checked price for book \"%s\". The price is %d.\n", book, i)
	//place payment
	tuplespace.Put(ptp, "Payment", book, i)
	fmt.Printf("Placed payment for book \"%s\", at the price of %d.\n", book, i)
}
<commit_msg>fixed bookstore<commit_after>package main

import (
	"fmt"
	"goSpace/goSpace/topology"
	"goSpace/goSpace/tuplespace"
	"time"
)

func main() {
	ts := tuplespace.CreateTupleSpace(8080)
	ptp := topology.CreatePointToPoint("Bookstore", "localhost", 8080)
	/*
		tuplespace.Put(ptp, 2, 2)
		tuplespace.Put(ptp, 2, 2)
		tuplespace.Put(ptp, 2, 3)
		tuplespace.Put(ptp, 2, 3)
		tuplespace.Put(ptp, 2, false)
		fmt.Println(ts)
		var i int
		fmt.Println(tuplespace.QueryAll(ptp, 2, 2))
		fmt.Println(tuplespace.GetAll(ptp, 2, &i))
		fmt.Println(tuplespace.QueryAll(ptp, 2, 2))
		fmt.Println(ts)
	*/
	addBooks(ptp)
	fmt.Println(ts)
	go cashier(ptp)
	costumer(ptp)
	time.Sleep(2 * time.Second)
}

func addBooks(ptp topology.PointToPoint) {
	//s := "Of Mice and Men"
	tuplespace.Put(ptp, "Of Mice and Men", 200)
}

func cashier(ptp topology.PointToPoint) {
	for {
		var i int
		var book string
		tuplespace.Get(ptp, "Payment", &book, &i)
		var price int
		tuplespace.Query(ptp, book, &price)
		if price == i {
			fmt.Printf("Recieved payment of %d for the book \"%s\".\n", i, book)
			tuplespace.Get(ptp, book, i)
		}
	}
}

func costumer(ptp topology.PointToPoint) {
	var i int
	book := "Of Mice and Men"
	//search for book and save price in i
	tuplespace.Query(ptp, book, &i)
	fmt.Printf("Checked price for book \"%s\". The price is %d.\n", book, i)
	//place payment
	tuplespace.Put(ptp, "Payment", book, i)
	fmt.Printf("Placed payment for book \"%s\", at the price of %d.\n", book, i)
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

// Editpcln displays and edits the file names stored in a Go object file or archive.
//
// Usage:
//
//	editpcln [-v] [-r from->to] old.a new.a
//
// Editpcln copies old.a to new.a (it can also be invoked on .5, .6, and .8 files),
// rewriting file paths beginning with 'from' into paths beginning with 'to'.
// The -r option can be repeated to apply multiple rewrites.
//
// The -v option prints information about the paths encountered and rewritten.
//
// To print the paths present in an object file without writing a new one, use
//
//	editpcln -v old.a /dev/null
//
package main

import (
	"bytes"
	"flag"
	"os"
	"io/ioutil"
	"io"
	"bufio"
	"log"
	"fmt"
	"strings"
	"strconv"
)

var (
	verbose = flag.Bool("v", false, "print all function and file names")
)

var rewrites [][2]string

type addRewrite struct{}

func (addRewrite) String() string {
	return ""
}

func (addRewrite) Set(s string) error {
	if strings.Count(s, "->") != 1 {
		return fmt.Errorf("-r argument must be of the form 'from -> to'")
	}
	i := strings.Index(s, "->")
	rewrites = append(rewrites, [2]string{strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+2:])})
	return nil
}

func rewritePath(s string) string {
	for _, oldnew := range rewrites {
		old, new := oldnew[0], oldnew[1]
		if s == old || strings.HasPrefix(s, old+"/") {
			return new+s[len(old):]
		}
	}
	return s
}

func main() {
	flag.Var(addRewrite{}, "r", "add 'from -> to' path rewrite (can be repeated)")

	flag.Parse()
	if flag.NArg() != 2 {
		flag.Usage()
	}

	rf, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	wf, err := os.Create(flag.Arg(1))
	if err != nil {
		log.Fatal(err)
	}

	r := newRewriter(rf, wf, rewritePath)

	r.verbose = *verbose
	if err := r.rewrite(); err != nil {
		log.Println(err)
		os.Exit(2)
	}
	if err := wf.Close(); err != nil {
		log.Println("writing %s: %v", wf.Name(), err)
		os.Exit(2)
	}
}

type rewriter struct {
	fn func(string) string
	rf *os.File
	wf *os.File
	r *bufio.Reader
	w *bufio.Writer
	roffset int64
	verbose bool
	tmp []byte
}

func newRewriter(rf, wf *os.File, fn func(string) string) *rewriter {
	return &rewriter{
		rf: rf,
		wf: wf,
		r: bufio.NewReader(rf),
		w: bufio.NewWriter(wf),
		fn: fn,
	}
}

type rewriterError struct {
	err error
}

func (r *rewriter) rewrite() (err error) {
	defer func() {
		e := recover()
		if re, ok := e.(rewriterError); ok {
			err = re.err
			return
		}
		if e != nil {
			panic(e)
		}
	}()

	buf, _ := r.r.Peek(8)
	if bytes.Equal(buf, []byte("!<arch>\n")) {
		r.readArchive()
	} else if bytes.Equal(buf, []byte("go objec")) {
		r.readObject()
	} else {
		panic(rewriterError{fmt.Errorf("reading %s: unrecognized file format", r.rf.Name())})
	}

	r.flush()
	return nil
}

func (r *rewriter) flush() {
	err := r.w.Flush()
	if err != nil {
		panic(rewriterError{fmt.Errorf("writing %s: %v", r.wf.Name(), err)})
	}
}

func (r *rewriter) wseek(delta int64, whence int) int64 {
	r.flush()
	off, err := r.wf.Seek(delta, whence)
	if err != nil {
		panic(rewriterError{fmt.Errorf("seeking in %s: %v", r.wf.Name(), err)})
	}
	return off
}

// trimSpace removes trailing spaces from b and returns the corresponding string.
// This effectively parses the form used in archive headers.
func trimSpace(b []byte) string {
	return string(bytes.TrimRight(b, " "))
}

func (r *rewriter) readArchive() {
	r.readFixed([]byte("!<arch>\n"))

	for {
		_, err := r.r.ReadByte()
		if err == io.EOF {
			return
		}
		r.r.UnreadByte()

		// Each file is preceded by this text header (slice indices in first column):
		//	 0:16	name
		//	16:28 date
		//	28:34 uid
		//	34:40 gid
		//	40:48 mode
		//	48:58 size
		//	58:60 magic - `\n
		buf := make([]byte, 60)
		r.readFull(buf)
		if buf[58] != '`' || buf[59] != '\n' {
			r.corrupt()
		}
		wstart := r.wseek(0, 1)

		name := trimSpace(buf[0:16])
		size, err := strconv.ParseInt(trimSpace(buf[48:58]), 10, 64)
		if err != nil {
			r.corrupt()
		}

		switch name {
		case "__.SYMDEF", "__.GOSYMDEF", "__.PKGDEF":
			r.skip(size+size&1)
			continue
		}

		start := r.roffset
		r.readObject()
		n := r.roffset - start
		if n != int64(size) {
			r.corrupt()
		}
		if size&1 != 0 {
			r.r.ReadByte()
			r.roffset++
		}

		wend := r.wseek(0, 1)
		wsize := wend - wstart
		r.wseek(wstart-60+48, 0)
		r.w.WriteString(fmt.Sprintf("%-10x", wsize))
		r.wseek(wend, 0)
		if wsize&1 != 0 {
			r.w.WriteByte(0)
		}
	}
}

func (r *rewriter) readObject() {
	var c1, c2, c3 byte
	for {
		c1, c2, c3 = c2, c3, r.readByte()
		if c1 == '\n' && c2 == '!' && c3 == '\n' {
			break
		}
	}

	// Header + version.
	r.readFixed([]byte("\x00\x00go13ld\x01"))

	// Package imports.
	for r.readString() != "" {
	}

	discard := bufio.NewWriter(ioutil.Discard)

	// Symbols.
	for {
		if b := r.readByte(); b != 0xfe {
			if b != 0xff {
				r.corrupt()
			}
			break
		}

		kind := r.readInt()
		name, _ := r.readSymID()
		r.readInt() // dupok
		r.readInt() // size
		r.readSymID() // type
		r.readData() // data
		n := r.readInt() // nreloc
		for i := 0; i < n; i++ { // reloc
			r.readInt() // offset
			r.readInt() // size
			r.readInt() // type
			r.readInt() // add
			r.readInt() // xadd
			r.readSymID() // sym
			r.readSymID() // xsym
		}

		const STEXT = 1
		if kind == STEXT {
			if r.verbose {
				fmt.Printf("%s\n", name)
			}
			r.readInt() // args
			r.readInt() // frame
			n = r.readInt() // nvar
			for i := 0; i < n; i++ { // var
				r.readSymID() // name
				r.readInt() // offset
				r.readInt() // kind
				r.readSymID() // type
			}

			r.readData() // pcsp
			r.readData() // pcfile
			r.readData() // pcline
			n = r.readInt() // npcdata
			for i := 0; i < n; i++ { // pcdata
				r.readData()
			}
			n = r.readInt() // nfuncdata
			for i := 0; i < n; i++ { // funcdata syms
				r.readSymID()
			}
			for i := 0; i < n; i++ { // funcdata offsets
				r.readInt()
			}
			n = r.readInt() // nfile
			w := r.w
			r.w = discard
			for i := 0; i < n; i++ {
				file, vers := r.readSymID() // file names
				wfile := file
				if r.fn != nil {
					wfile = r.fn(file)
				}
				if r.verbose {
					if wfile != file {
						fmt.Printf("\t%s -> %s\n", file, wfile)
					} else {
						fmt.Printf("\t%s\n", file)
					}
				}
				writeString(w, wfile)
				writeInt(w, vers)
			}
			r.w = w
		}
	}

	r.readFixed([]byte("\xffgo13ld")) // first ff already read
}

func (r *rewriter) readError(err error) {
	panic(rewriterError{fmt.Errorf("reading %s: %v", r.rf.Name(), err)})
}

func (r *rewriter) corrupt() {
	panic(rewriterError{fmt.Errorf("reading %s: corrupt file", r.rf.Name())})
}

func (r *rewriter) readFull(buf []byte) {
	_, err := io.ReadFull(r.r, buf)
	if err != nil {
		r.readError(err)
	}
	r.roffset += int64(len(buf))
	r.w.Write(buf)
}

func (r *rewriter) readFixed(match []byte) {
	buf := make([]byte, len(match))
	r.readFull(buf)
	if !bytes.Equal(buf, match) {
		r.corrupt()
	}
}

func (r *rewriter) skip(n int64) {
	const chunk = 1<<16
	if r.tmp == nil {
		r.tmp = make([]byte, chunk)
	}
	for n >= chunk {
		r.readFull(r.tmp)
		n -= chunk
	}
	if n > 0 {
		r.readFull(r.tmp[:n])
	}
}

func (r *rewriter) readByte() byte {
	b, err := r.r.ReadByte()
	if err != nil {
		r.readError(err)
	}
	r.roffset++
	r.w.WriteByte(b)
	return b
}

func (r *rewriter) readInt() int {
	var u uint64
	for shift := uint(0);; shift += 7 {
		if shift >= 64 {
			r.corrupt()
		}
		c := r.readByte()
		u |= uint64(c&0x7F)<<shift
		if c&0x80 == 0 {
			break
		}
	}
	v := int64(u>>1) ^ (int64(u)<<63>>63)
	if int64(int(v)) != v {
		r.corrupt()
	}
	return int(v)
}

func (r *rewriter) readString() string {
	n := r.readInt()
	buf := make([]byte, n)
	r.readFull(buf)
	return string(buf)
}

func (r *rewriter) readData() {
	n := r.readInt()
	buf := make([]byte, n)
	r.readFull(buf)
}

func (r *rewriter) readSymID() (string, int) {
	return r.readString(), r.readInt()
}

func writeInt(w *bufio.Writer, n int) {
	v := int64(n)
	u := uint64(v<<1) ^ uint64(v>>63)
	for u >= 0x80 {
		w.WriteByte(byte(u)|0x80)
		u >>= 7
	}
	w.WriteByte(byte(u))
}

func writeString(w *bufio.Writer, s string) {
	writeInt(w, len(s))
	w.WriteString(s)
}
<commit_msg>gofmt<commit_after>// Copyright 2014 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.

// Editpcln displays and edits the file names stored in a Go object file or archive.
//
// Usage:
//
//	editpcln [-v] [-r from->to] old.a new.a
//
// Editpcln copies old.a to new.a (it can also be invoked on .5, .6, and .8 files),
// rewriting file paths beginning with 'from' into paths beginning with 'to'.
// The -r option can be repeated to apply multiple rewrites.
//
// The -v option prints information about the paths encountered and rewritten.
//
// To print the paths present in an object file without writing a new one, use
//
//	editpcln -v old.a /dev/null
//
package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
)

var (
	verbose = flag.Bool("v", false, "print all function and file names")
)

var rewrites [][2]string

type addRewrite struct{}

func (addRewrite) String() string {
	return ""
}

func (addRewrite) Set(s string) error {
	if strings.Count(s, "->") != 1 {
		return fmt.Errorf("-r argument must be of the form 'from -> to'")
	}
	i := strings.Index(s, "->")
	rewrites = append(rewrites, [2]string{strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+2:])})
	return nil
}

func rewritePath(s string) string {
	for _, oldnew := range rewrites {
		old, new := oldnew[0], oldnew[1]
		if s == old || strings.HasPrefix(s, old+"/") {
			return new + s[len(old):]
		}
	}
	return s
}

func main() {
	flag.Var(addRewrite{}, "r", "add 'from -> to' path rewrite (can be repeated)")

	flag.Parse()
	if flag.NArg() != 2 {
		flag.Usage()
	}

	rf, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	wf, err := os.Create(flag.Arg(1))
	if err != nil {
		log.Fatal(err)
	}

	r := newRewriter(rf, wf, rewritePath)

	r.verbose = *verbose
	if err := r.rewrite(); err != nil {
		log.Println(err)
		os.Exit(2)
	}
	if err := wf.Close(); err != nil {
		log.Println("writing %s: %v", wf.Name(), err)
		os.Exit(2)
	}
}

type rewriter struct {
	fn      func(string) string
	rf      *os.File
	wf      *os.File
	r       *bufio.Reader
	w       *bufio.Writer
	roffset int64
	verbose bool
	tmp     []byte
}

func newRewriter(rf, wf *os.File, fn func(string) string) *rewriter {
	return &rewriter{
		rf: rf,
		wf: wf,
		r:  bufio.NewReader(rf),
		w:  bufio.NewWriter(wf),
		fn: fn,
	}
}

type rewriterError struct {
	err error
}

func (r *rewriter) rewrite() (err error) {
	defer func() {
		e := recover()
		if re, ok := e.(rewriterError); ok {
			err = re.err
			return
		}
		if e != nil {
			panic(e)
		}
	}()

	buf, _ := r.r.Peek(8)
	if bytes.Equal(buf, []byte("!<arch>\n")) {
		r.readArchive()
	} else if bytes.Equal(buf, []byte("go objec")) {
		r.readObject()
	} else {
		panic(rewriterError{fmt.Errorf("reading %s: unrecognized file format", r.rf.Name())})
	}

	r.flush()
	return nil
}

func (r *rewriter) flush() {
	err := r.w.Flush()
	if err != nil {
		panic(rewriterError{fmt.Errorf("writing %s: %v", r.wf.Name(), err)})
	}
}

func (r *rewriter) wseek(delta int64, whence int) int64 {
	r.flush()
	off, err := r.wf.Seek(delta, whence)
	if err != nil {
		panic(rewriterError{fmt.Errorf("seeking in %s: %v", r.wf.Name(), err)})
	}
	return off
}

// trimSpace removes trailing spaces from b and returns the corresponding string.
// This effectively parses the form used in archive headers.
func trimSpace(b []byte) string {
	return string(bytes.TrimRight(b, " "))
}

func (r *rewriter) readArchive() {
	r.readFixed([]byte("!<arch>\n"))

	for {
		_, err := r.r.ReadByte()
		if err == io.EOF {
			return
		}
		r.r.UnreadByte()

		// Each file is preceded by this text header (slice indices in first column):
		//	 0:16	name
		//	16:28 date
		//	28:34 uid
		//	34:40 gid
		//	40:48 mode
		//	48:58 size
		//	58:60 magic - `\n
		buf := make([]byte, 60)
		r.readFull(buf)
		if buf[58] != '`' || buf[59] != '\n' {
			r.corrupt()
		}
		wstart := r.wseek(0, 1)

		name := trimSpace(buf[0:16])
		size, err := strconv.ParseInt(trimSpace(buf[48:58]), 10, 64)
		if err != nil {
			r.corrupt()
		}

		switch name {
		case "__.SYMDEF", "__.GOSYMDEF", "__.PKGDEF":
			r.skip(size + size&1)
			continue
		}

		start := r.roffset
		r.readObject()
		n := r.roffset - start
		if n != int64(size) {
			r.corrupt()
		}
		if size&1 != 0 {
			r.r.ReadByte()
			r.roffset++
		}

		wend := r.wseek(0, 1)
		wsize := wend - wstart
		r.wseek(wstart-60+48, 0)
		r.w.WriteString(fmt.Sprintf("%-10x", wsize))
		r.wseek(wend, 0)
		if wsize&1 != 0 {
			r.w.WriteByte(0)
		}
	}
}

func (r *rewriter) readObject() {
	var c1, c2, c3 byte
	for {
		c1, c2, c3 = c2, c3, r.readByte()
		if c1 == '\n' && c2 == '!' && c3 == '\n' {
			break
		}
	}

	// Header + version.
	r.readFixed([]byte("\x00\x00go13ld\x01"))

	// Package imports.
	for r.readString() != "" {
	}

	discard := bufio.NewWriter(ioutil.Discard)

	// Symbols.
	for {
		if b := r.readByte(); b != 0xfe {
			if b != 0xff {
				r.corrupt()
			}
			break
		}

		kind := r.readInt()
		name, _ := r.readSymID()
		r.readInt()              // dupok
		r.readInt()              // size
		r.readSymID()            // type
		r.readData()             // data
		n := r.readInt()         // nreloc
		for i := 0; i < n; i++ { // reloc
			r.readInt()   // offset
			r.readInt()   // size
			r.readInt()   // type
			r.readInt()   // add
			r.readInt()   // xadd
			r.readSymID() // sym
			r.readSymID() // xsym
		}

		const STEXT = 1
		if kind == STEXT {
			if r.verbose {
				fmt.Printf("%s\n", name)
			}
			r.readInt()              // args
			r.readInt()              // frame
			n = r.readInt()          // nvar
			for i := 0; i < n; i++ { // var
				r.readSymID() // name
				r.readInt()   // offset
				r.readInt()   // kind
				r.readSymID() // type
			}

			r.readData()             // pcsp
			r.readData()             // pcfile
			r.readData()             // pcline
			n = r.readInt()          // npcdata
			for i := 0; i < n; i++ { // pcdata
				r.readData()
			}
			n = r.readInt()          // nfuncdata
			for i := 0; i < n; i++ { // funcdata syms
				r.readSymID()
			}
			for i := 0; i < n; i++ { // funcdata offsets
				r.readInt()
			}
			n = r.readInt() // nfile
			w := r.w
			r.w = discard
			for i := 0; i < n; i++ {
				file, vers := r.readSymID() // file names
				wfile := file
				if r.fn != nil {
					wfile = r.fn(file)
				}
				if r.verbose {
					if wfile != file {
						fmt.Printf("\t%s -> %s\n", file, wfile)
					} else {
						fmt.Printf("\t%s\n", file)
					}
				}
				writeString(w, wfile)
				writeInt(w, vers)
			}
			r.w = w
		}
	}

	r.readFixed([]byte("\xffgo13ld")) // first ff already read
}

func (r *rewriter) readError(err error) {
	panic(rewriterError{fmt.Errorf("reading %s: %v", r.rf.Name(), err)})
}

func (r *rewriter) corrupt() {
	panic(rewriterError{fmt.Errorf("reading %s: corrupt file", r.rf.Name())})
}

func (r *rewriter) readFull(buf []byte) {
	_, err := io.ReadFull(r.r, buf)
	if err != nil {
		r.readError(err)
	}
	r.roffset += int64(len(buf))
	r.w.Write(buf)
}

func (r *rewriter) readFixed(match []byte) {
	buf := make([]byte, len(match))
	r.readFull(buf)
	if !bytes.Equal(buf, match) {
		r.corrupt()
	}
}

func (r *rewriter) skip(n int64) {
	const chunk = 1 << 16
	if r.tmp == nil {
		r.tmp = make([]byte, chunk)
	}
	for n >= chunk {
		r.readFull(r.tmp)
		n -= chunk
	}
	if n > 0 {
		r.readFull(r.tmp[:n])
	}
}

func (r *rewriter) readByte() byte {
	b, err := r.r.ReadByte()
	if err != nil {
		r.readError(err)
	}
	r.roffset++
	r.w.WriteByte(b)
	return b
}

func (r *rewriter) readInt() int {
	var u uint64
	for shift := uint(0); ; shift += 7 {
		if shift >= 64 {
			r.corrupt()
		}
		c := r.readByte()
		u |= uint64(c&0x7F) << shift
		if c&0x80 == 0 {
			break
		}
	}
	v := int64(u>>1) ^ (int64(u) << 63 >> 63)
	if int64(int(v)) != v {
		r.corrupt()
	}
	return int(v)
}

func (r *rewriter) readString() string {
	n := r.readInt()
	buf := make([]byte, n)
	r.readFull(buf)
	return string(buf)
}

func (r *rewriter) readData() {
	n := r.readInt()
	buf := make([]byte, n)
	r.readFull(buf)
}

func (r *rewriter) readSymID() (string, int) {
	return r.readString(), r.readInt()
}

func writeInt(w *bufio.Writer, n int) {
	v := int64(n)
	u := uint64(v<<1) ^ uint64(v>>63)
	for u >= 0x80 {
		w.WriteByte(byte(u) | 0x80)
		u >>= 7
	}
	w.WriteByte(byte(u))
}

func writeString(w *bufio.Writer, s string) {
	writeInt(w, len(s))
	w.WriteString(s)
}
<|endoftext|>


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

//go:build example
// +build example

package main

import (
	"fmt"
	"math"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/inpututil"
)

// Game is an isometric demo game.
type Game struct {
	w, h         int
	currentLevel *Level

	camX, camY float64
	camScale   float64
	camScaleTo float64

	mousePanX, mousePanY int
}

// NewGame returns a new isometric demo Game.
func NewGame() (*Game, error) {
	l, err := NewLevel()
	if err != nil {
		return nil, fmt.Errorf("failed to create new level: %s", err)
	}

	g := &Game{
		currentLevel: l,
		camScale:     1,
		camScaleTo:   1,
		mousePanX:    math.MinInt32,
		mousePanY:    math.MinInt32,
	}
	return g, nil
}

// Update reads current user input and updates the Game state.
func (g *Game) Update() error {
	// Update target zoom level.
	var scrollY float64
	if ebiten.IsKeyPressed(ebiten.KeyC) || ebiten.IsKeyPressed(ebiten.KeyPageDown) {
		scrollY = -0.25
	} else if ebiten.IsKeyPressed(ebiten.KeyE) || ebiten.IsKeyPressed(ebiten.KeyPageUp) {
		scrollY = .25
	} else {
		_, scrollY = ebiten.Wheel()
		if scrollY < -1 {
			scrollY = -1
		} else if scrollY > 1 {
			scrollY = 1
		}
	}
	g.camScaleTo += scrollY * (g.camScaleTo / 7)

	// Clamp target zoom level.
	if g.camScaleTo < 0.01 {
		g.camScaleTo = 0.01
	} else if g.camScaleTo > 100 {
		g.camScaleTo = 100
	}

	// Smooth zoom transition.
	div := 10.0
	if g.camScaleTo > g.camScale {
		g.camScale += (g.camScaleTo - g.camScale) / div
	} else if g.camScaleTo < g.camScale {
		g.camScale -= (g.camScale - g.camScaleTo) / div
	}

	// Pan camera via keyboard.
	pan := 7.0 / g.camScale
	if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) {
		g.camX -= pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD) {
		g.camX += pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyS) {
		g.camY -= pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyW) {
		g.camY += pan
	}

	// Pan camera via mouse.
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
		if g.mousePanX == math.MinInt32 && g.mousePanY == math.MinInt32 {
			g.mousePanX, g.mousePanY = ebiten.CursorPosition()
		} else {
			x, y := ebiten.CursorPosition()
			dx, dy := float64(g.mousePanX-x)*(pan/100), float64(g.mousePanY-y)*(pan/100)
			g.camX, g.camY = g.camX-dx, g.camY+dy
		}
	} else if g.mousePanX != math.MinInt32 || g.mousePanY != math.MinInt32 {
		g.mousePanX, g.mousePanY = math.MinInt32, math.MinInt32
	}

	// Clamp camera position.
	worldWidth := float64(g.currentLevel.w * g.currentLevel.tileSize / 2)
	worldHeight := float64(g.currentLevel.h * g.currentLevel.tileSize / 2)
	if g.camX < -worldWidth {
		g.camX = -worldWidth
	} else if g.camX > worldWidth {
		g.camX = worldWidth
	}
	if g.camY < -worldHeight {
		g.camY = -worldHeight
	} else if g.camY > 0 {
		g.camY = 0
	}

	// Randomize level.
	if inpututil.IsKeyJustPressed(ebiten.KeyR) {
		l, err := NewLevel()
		if err != nil {
			return fmt.Errorf("failed to create new level: %s", err)
		}

		g.currentLevel = l
	}

	return nil
}

// Draw draws the Game on the screen.
func (g *Game) Draw(screen *ebiten.Image) {
	// Render level.
	g.renderLevel(screen)

	// Print game info.
	ebitenutil.DebugPrint(screen, fmt.Sprintf("KEYS WASD EC R\nFPS  %0.0f\nTPS  %0.0f\nSCA  %0.2f\nPOS  %0.0f,%0.0f", ebiten.CurrentFPS(), ebiten.CurrentTPS(), g.camScale, g.camX, g.camY))
}

// Layout is called when the Game's layout changes.
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	g.w, g.h = outsideWidth, outsideHeight
	return g.w, g.h
}

// cartesianToIso transforms cartesian coordinates into isometric coordinates.
func (g *Game) cartesianToIso(x, y float64) (float64, float64) {
	tileSize := g.currentLevel.tileSize
	ix := (x - y) * float64(tileSize/2)
	iy := (x + y) * float64(tileSize/4)
	return ix, iy
}

/*
This function might be useful for those who want to modify this example.

// isoToCartesian transforms isometric coordinates into cartesian coordinates.
func (g *Game) isoToCartesian(x, y float64) (float64, float64) {
	tileSize := g.currentLevel.tileSize
	cx := (x/float64(tileSize/2) + y/float64(tileSize/4)) / 2
	cy := (y/float64(tileSize/4) - (x / float64(tileSize/2))) / 2
	return cx, cy
}
*/

// renderLevel draws the current Level on the screen.
func (g *Game) renderLevel(screen *ebiten.Image) {
	op := &ebiten.DrawImageOptions{}
	padding := float64(g.currentLevel.tileSize) * g.camScale
	cx, cy := float64(g.w/2), float64(g.h/2)

	for y := 0; y < g.currentLevel.h; y++ {
		for x := 0; x < g.currentLevel.w; x++ {
			xi, yi := g.cartesianToIso(float64(x), float64(y))

			// Skip drawing off-screen tiles.
			drawX, drawY := ((xi-g.camX)*g.camScale)+cx, ((yi+g.camY)*g.camScale)+cy
			if drawX+padding < 0 || drawY+padding < 0 || drawX > float64(g.w) || drawY > float64(g.h) {
				continue
			}

			t := g.currentLevel.tiles[y][x]
			if t == nil {
				continue // No tile at this position.
			}

			op.GeoM.Reset()
			// Move to current isometric position.
			op.GeoM.Translate(xi, yi)
			// Translate camera position.
			op.GeoM.Translate(-g.camX, g.camY)
			// Zoom.
			op.GeoM.Scale(g.camScale, g.camScale)
			// Center.
			op.GeoM.Translate(cx, cy)

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

//go:build example
// +build example

package main

import (
	"fmt"
	"math"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/inpututil"
)

// Game is an isometric demo game.
type Game struct {
	w, h         int
	currentLevel *Level

	camX, camY float64
	camScale   float64
	camScaleTo float64

	mousePanX, mousePanY int

	offscreen *ebiten.Image
}

// NewGame returns a new isometric demo Game.
func NewGame() (*Game, error) {
	l, err := NewLevel()
	if err != nil {
		return nil, fmt.Errorf("failed to create new level: %s", err)
	}

	g := &Game{
		currentLevel: l,
		camScale:     1,
		camScaleTo:   1,
		mousePanX:    math.MinInt32,
		mousePanY:    math.MinInt32,
	}
	return g, nil
}

// Update reads current user input and updates the Game state.
func (g *Game) Update() error {
	// Update target zoom level.
	var scrollY float64
	if ebiten.IsKeyPressed(ebiten.KeyC) || ebiten.IsKeyPressed(ebiten.KeyPageDown) {
		scrollY = -0.25
	} else if ebiten.IsKeyPressed(ebiten.KeyE) || ebiten.IsKeyPressed(ebiten.KeyPageUp) {
		scrollY = .25
	} else {
		_, scrollY = ebiten.Wheel()
		if scrollY < -1 {
			scrollY = -1
		} else if scrollY > 1 {
			scrollY = 1
		}
	}
	g.camScaleTo += scrollY * (g.camScaleTo / 7)

	// Clamp target zoom level.
	if g.camScaleTo < 0.01 {
		g.camScaleTo = 0.01
	} else if g.camScaleTo > 100 {
		g.camScaleTo = 100
	}

	// Smooth zoom transition.
	div := 10.0
	if g.camScaleTo > g.camScale {
		g.camScale += (g.camScaleTo - g.camScale) / div
	} else if g.camScaleTo < g.camScale {
		g.camScale -= (g.camScale - g.camScaleTo) / div
	}

	// Pan camera via keyboard.
	pan := 7.0 / g.camScale
	if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) {
		g.camX -= pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD) {
		g.camX += pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyS) {
		g.camY -= pan
	}
	if ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyW) {
		g.camY += pan
	}

	// Pan camera via mouse.
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
		if g.mousePanX == math.MinInt32 && g.mousePanY == math.MinInt32 {
			g.mousePanX, g.mousePanY = ebiten.CursorPosition()
		} else {
			x, y := ebiten.CursorPosition()
			dx, dy := float64(g.mousePanX-x)*(pan/100), float64(g.mousePanY-y)*(pan/100)
			g.camX, g.camY = g.camX-dx, g.camY+dy
		}
	} else if g.mousePanX != math.MinInt32 || g.mousePanY != math.MinInt32 {
		g.mousePanX, g.mousePanY = math.MinInt32, math.MinInt32
	}

	// Clamp camera position.
	worldWidth := float64(g.currentLevel.w * g.currentLevel.tileSize / 2)
	worldHeight := float64(g.currentLevel.h * g.currentLevel.tileSize / 2)
	if g.camX < -worldWidth {
		g.camX = -worldWidth
	} else if g.camX > worldWidth {
		g.camX = worldWidth
	}
	if g.camY < -worldHeight {
		g.camY = -worldHeight
	} else if g.camY > 0 {
		g.camY = 0
	}

	// Randomize level.
	if inpututil.IsKeyJustPressed(ebiten.KeyR) {
		l, err := NewLevel()
		if err != nil {
			return fmt.Errorf("failed to create new level: %s", err)
		}

		g.currentLevel = l
	}

	return nil
}

// Draw draws the Game on the screen.
func (g *Game) Draw(screen *ebiten.Image) {
	// Render level.
	g.renderLevel(screen)

	// Print game info.
	ebitenutil.DebugPrint(screen, fmt.Sprintf("KEYS WASD EC R\nFPS  %0.0f\nTPS  %0.0f\nSCA  %0.2f\nPOS  %0.0f,%0.0f", ebiten.CurrentFPS(), ebiten.CurrentTPS(), g.camScale, g.camX, g.camY))
}

// Layout is called when the Game's layout changes.
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	g.w, g.h = outsideWidth, outsideHeight
	return g.w, g.h
}

// cartesianToIso transforms cartesian coordinates into isometric coordinates.
func (g *Game) cartesianToIso(x, y float64) (float64, float64) {
	tileSize := g.currentLevel.tileSize
	ix := (x - y) * float64(tileSize/2)
	iy := (x + y) * float64(tileSize/4)
	return ix, iy
}

/*
This function might be useful for those who want to modify this example.

// isoToCartesian transforms isometric coordinates into cartesian coordinates.
func (g *Game) isoToCartesian(x, y float64) (float64, float64) {
	tileSize := g.currentLevel.tileSize
	cx := (x/float64(tileSize/2) + y/float64(tileSize/4)) / 2
	cy := (y/float64(tileSize/4) - (x / float64(tileSize/2))) / 2
	return cx, cy
}
*/

// renderLevel draws the current Level on the screen.
func (g *Game) renderLevel(screen *ebiten.Image) {
	op := &ebiten.DrawImageOptions{}
	padding := float64(g.currentLevel.tileSize) * g.camScale
	cx, cy := float64(g.w/2), float64(g.h/2)

	scaleLater := g.camScale > 1
	target := screen
	scale := g.camScale

	// When zooming in, there can be slight gaps between tiles.
	// To avoid them, render the result on an offscreen first and then scale it later.
	if scaleLater {
		if g.offscreen == nil {
			g.offscreen = ebiten.NewImage(screen.Size())
		}
		target = g.offscreen
		target.Clear()
		scale = 1
	}

	for y := 0; y < g.currentLevel.h; y++ {
		for x := 0; x < g.currentLevel.w; x++ {
			xi, yi := g.cartesianToIso(float64(x), float64(y))

			// Skip drawing tiles that are out of the screen.
			drawX, drawY := ((xi-g.camX)*g.camScale)+cx, ((yi+g.camY)*g.camScale)+cy
			if drawX+padding < 0 || drawY+padding < 0 || drawX > float64(g.w) || drawY > float64(g.h) {
				continue
			}

			t := g.currentLevel.tiles[y][x]
			if t == nil {
				continue // No tile at this position.
			}

			op.GeoM.Reset()
			// Move to current isometric position.
			op.GeoM.Translate(xi, yi)
			// Translate camera position.
			op.GeoM.Translate(-g.camX, g.camY)
			// Zoom.
			op.GeoM.Scale(scale, scale)
			// Center.
			op.GeoM.Translate(cx, cy)

			t.Draw(target, op)
		}
	}

	if scaleLater {
		op := &ebiten.DrawImageOptions{}
		op.GeoM.Translate(-cx, -cy)
		op.GeoM.Scale(float64(g.camScale), float64(g.camScale))
		op.GeoM.Translate(cx, cy)
		screen.DrawImage(target, op)
	}
}
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"github.com/henrylee2cn/teleport"
	"log"
	"sync"
	"time"
)

// 获取一个管理中心连接
func GetManage() *Manage {
	return hubConns.getOne()
}

// 释放管理中心连接
func FreeManage(m ...*Manage) {
	hubConns.free(m...)
}

// 关闭并删除指定连接
func RemoveManage(m ...*Manage) {
	hubConns.remove(m...)
}

// 重置连接池
func ResetManage() {
	hubConns.reset()
}

// 请求并返回数据
func (self *Manage) Request(body interface{}, operation string, nodeuid ...string) (interface{}, bool) {
	self.Teleport.Request(body, operation, nodeuid...)
	r := <-self.result
	return r[0], r[1].(bool)
}

type Manage struct {
	teleport.Teleport
	result chan [2]interface{}
}

const (
	// 功能模块名称
	M_WEB = "data580" // data580网站
	// port of socket server
	MANANGE_SOCKET_PORT = ":8000"
	MANANGE_SOCKET_IP   = "127.0.0.1"
)

// 新建连接
func newManage() *Manage {
	m := &Manage{
		Teleport: teleport.New(),
		result:   make(chan [2]interface{}, 1),
	}
	uid := M_WEB + ":" + fmt.Sprint(time.Now().Unix())
	m.SetAPI(newManageApi(m)).SetUID(uid).Client(MANANGE_SOCKET_IP, MANANGE_SOCKET_PORT)
	return m
}

// 管理中心连接池
type hubPool struct {
	Cap int
	Src map[*Manage]bool
	sync.Mutex
}

var hubConns = &hubPool{
	Cap: 1024,
	Src: make(map[*Manage]bool),
}

// 并发安全地获取一个连接
func (self *hubPool) getOne() *Manage {
	self.Mutex.Lock()
	defer self.Mutex.Unlock()

	for {
		for k, v := range self.Src {
			if v {
				continue
			}
			self.Src[k] = true
			return k
		}
		if len(self.Src) <= self.Cap {
			self.increment()
		} else {
			time.Sleep(5e8)
		}
	}
	return nil
}

func (self *hubPool) free(m ...*Manage) {
	for i, count := 0, len(m); i < count; i++ {
		m[i].result = make(chan [2]interface{}, 1)
		self.Src[m[i]] = false
	}
}

// 关闭并删除指定连接
func (self *hubPool) remove(m ...*Manage) {
	for _, c := range m {
		c.Close()
		delete(self.Src, c)
	}
}

// 重置连接池
func (self *hubPool) reset() {
	for k, _ := range self.Src {
		k.Close()
		delete(self.Src, k)
	}
}

// 根据情况自动动态增加连接
func (self *hubPool) increment() {
	if len(self.Src) < self.Cap {
		self.Src[newManage()] = false
	}
}

func newManageApi(m *Manage) teleport.API {
	return teleport.API{
		// 获取数据
		"get": &result{m},
		// 获取table的清单
		"list": &result{m},
	}
}

// 获取数据
type result struct {
	*Manage
}

func (self *result) Process(receive *teleport.NetData) *teleport.NetData {
	if receive.Status != teleport.SUCCESS {
		log.Printf("error: %v，%v", receive.Body, receive.Status)
		self.result <- [2]interface{}{receive.Body, false}
	}
	self.result <- [2]interface{}{receive.Body, true}
	return nil
}
<commit_msg>修复bug<commit_after>package models

import (
	"fmt"
	"github.com/henrylee2cn/teleport"
	"log"
	"sync"
	"time"
)

// 请求并返回数据
func Request(body interface{}, operation string, nodeuid ...string) (interface{}, bool) {
	m := hubConns.getOne()
	m.Teleport.Request(body, operation, nodeuid...)
	r := <-m.result
	hubConns.free(m)
	return r[0], r[1].(bool)
}

// 重置连接池
func ResetManage() {
	hubConns.reset()
}

type Manage struct {
	teleport.Teleport
	result chan [2]interface{}
}

const (
	// 功能模块名称
	M_WEB = "data580" // data580网站
	// port of socket server
	MANANGE_SOCKET_PORT = ":8000"
	MANANGE_SOCKET_IP   = "127.0.0.1"
)

// 新建连接
func newManage() *Manage {
	m := &Manage{
		Teleport: teleport.New(),
		result:   make(chan [2]interface{}, 1),
	}
	uid := M_WEB + ":" + fmt.Sprint(time.Now().Unix())
	m.SetAPI(newManageApi(m)).SetUID(uid).Client(MANANGE_SOCKET_IP, MANANGE_SOCKET_PORT)
	return m
}

// 管理中心连接池
type hubPool struct {
	Cap int
	Src map[*Manage]bool
	sync.Mutex
}

var hubConns = &hubPool{
	Cap: 1024,
	Src: make(map[*Manage]bool),
}

// 并发安全地获取一个连接
func (self *hubPool) getOne() *Manage {
	self.Mutex.Lock()
	defer self.Mutex.Unlock()

	for {
		for k, v := range self.Src {
			if v {
				continue
			}
			self.Src[k] = true
			return k
		}
		if len(self.Src) <= self.Cap {
			self.increment()
		} else {
			time.Sleep(5e8)
		}
	}
	return nil
}

func (self *hubPool) free(m ...*Manage) {
	for i, count := 0, len(m); i < count; i++ {
		m[i].result = make(chan [2]interface{}, 1)
		self.Src[m[i]] = false
	}
}

// 关闭并删除指定连接
func (self *hubPool) remove(m ...*Manage) {
	for _, c := range m {
		c.Close()
		delete(self.Src, c)
	}
}

// 重置连接池
func (self *hubPool) reset() {
	for k, _ := range self.Src {
		k.Close()
		delete(self.Src, k)
	}
}

// 根据情况自动动态增加连接
func (self *hubPool) increment() {
	if len(self.Src) < self.Cap {
		self.Src[newManage()] = false
	}
}

func newManageApi(m *Manage) teleport.API {
	return teleport.API{
		// 获取数据
		"get": &result{m},
		// 获取table的清单
		"list": &result{m},
	}
}

// 获取数据
type result struct {
	*Manage
}

func (self *result) Process(receive *teleport.NetData) *teleport.NetData {
	if receive.Status != teleport.SUCCESS {
		log.Printf("error: %v，%v", receive.Body, receive.Status)
		self.result <- [2]interface{}{receive.Body, false}
	}
	self.result <- [2]interface{}{receive.Body, true}
	return nil
}
<|endoftext|>


<commit_before>//go:build e2e
// +build e2e

/*
Copyright 2021 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubernetes

import (
	"context"
	"io/ioutil"
	"os"
	"testing"

	apierrs "k8s.io/apimachinery/pkg/api/errors"

	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonresult"
	"github.com/tektoncd/operator/test/client"
	"github.com/tektoncd/operator/test/resources"
	"github.com/tektoncd/operator/test/utils"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TestTektonResultDeployment verifies the TektonResult creation, deployment recreation, and TektonResult deletion.
func TestTektonResultDeployment(t *testing.T) {
	platform := os.Getenv("PLATFORM")
	if platform == "linux/ppc64le" || platform == "linux/s390x" {
		t.Skipf("Tekton Result is not available for %q", platform)
	}

	crNames := utils.ResourceNames{
		TektonConfig:    "config",
		TektonPipeline:  "pipeline",
		TektonResult:    "result",
		TargetNamespace: "tekton-pipelines",
	}

	clients := client.Setup(t, crNames.TargetNamespace)

	utils.CleanupOnInterrupt(func() { utils.TearDownPipeline(clients, crNames.TektonPipeline) })
	utils.CleanupOnInterrupt(func() { utils.TearDownResult(clients, crNames.TektonResult) })
	utils.CleanupOnInterrupt(func() { utils.TearDownNamespace(clients, crNames.TargetNamespace) })
	defer utils.TearDownNamespace(clients, crNames.TargetNamespace)
	defer utils.TearDownPipeline(clients, crNames.TektonPipeline)
	defer utils.TearDownResult(clients, crNames.TektonResult)

	resources.EnsureNoTektonConfigInstance(t, clients, crNames)

	// Create a TektonPipeline
	if _, err := resources.EnsureTektonPipelineExists(clients.TektonPipeline(), crNames); err != nil {
		t.Fatalf("TektonPipeline %q failed to create: %v", crNames.TektonPipeline, err)
	}

	// Test if TektonPipeline can reach the READY status
	t.Run("create-pipeline", func(t *testing.T) {
		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
	})

	// Before Installing Results, create the required secrets
	t.Run("create-secrets", func(t *testing.T) {
		createSecret(t, clients, crNames.TargetNamespace)
	})

	// Create a TektonResult
	if _, err := resources.EnsureTektonResultExists(clients.TektonResult(), crNames); err != nil {
		t.Fatalf("TektonResult %q failed to create: %v", crNames.TektonResult, err)
	}

	// Test if TektonResult can reach the READY status
	t.Run("create-result", func(t *testing.T) {
		resources.AssertTektonResultCRReadyStatus(t, clients, crNames)
	})

	// Delete the TektonResult CR instance to see if all resources will be removed
	t.Run("delete-result", func(t *testing.T) {
		resources.AssertTektonResultCRReadyStatus(t, clients, crNames)
		resources.TektonResultCRDDelete(t, clients, crNames)
	})

	// Delete the TektonPipeline CR instance to see if all resources will be removed
	t.Run("delete-pipeline", func(t *testing.T) {
		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
		resources.TektonPipelineCRDelete(t, clients, crNames)
	})
}

func createSecret(t *testing.T, clients *utils.Clients, namespace string) {

	key, err := ioutil.ReadFile("./testdata/key.pem")
	if err != nil {
		t.Fatal(err)
	}

	cert, err := ioutil.ReadFile("./testdata/cert.pem")
	if err != nil {
		t.Fatal(err)
	}

	tlsSecret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: tektonresult.TlsSecretName,
		},
		Data: map[string][]byte{
			corev1.TLSCertKey:       cert,
			corev1.TLSPrivateKeyKey: key,
		},
		Type: corev1.SecretTypeTLS,
	}

	_, err = clients.KubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), tlsSecret, metav1.CreateOptions{})
	if err != nil && !apierrs.IsAlreadyExists(err) {
		t.Fatal(err)
	}

	dbSecret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: tektonresult.DbSecretName,
		},
		Data: map[string][]byte{
			"POSTGRES_USER":     []byte("postgres"),
			"POSTGRES_PASSWORD": []byte("test"),
		},
	}

	_, err = clients.KubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), dbSecret, metav1.CreateOptions{})
	if err != nil && !apierrs.IsAlreadyExists(err) {
		t.Fatal(err)
	}
}
<commit_msg>Skipping results e2e as it's failing due to PSA<commit_after>//go:build e2e
// +build e2e

/*
Copyright 2021 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubernetes

import (
	"context"
	"io/ioutil"
	"os"
	"testing"

	apierrs "k8s.io/apimachinery/pkg/api/errors"

	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonresult"
	"github.com/tektoncd/operator/test/client"
	"github.com/tektoncd/operator/test/resources"
	"github.com/tektoncd/operator/test/utils"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TestTektonResultDeployment verifies the TektonResult creation, deployment recreation, and TektonResult deletion.
func TestTektonResultDeployment(t *testing.T) {
	t.Skip()
	platform := os.Getenv("PLATFORM")
	if platform == "linux/ppc64le" || platform == "linux/s390x" {
		t.Skipf("Tekton Result is not available for %q", platform)
	}

	crNames := utils.ResourceNames{
		TektonConfig:    "config",
		TektonPipeline:  "pipeline",
		TektonResult:    "result",
		TargetNamespace: "tekton-pipelines",
	}

	clients := client.Setup(t, crNames.TargetNamespace)

	utils.CleanupOnInterrupt(func() { utils.TearDownPipeline(clients, crNames.TektonPipeline) })
	utils.CleanupOnInterrupt(func() { utils.TearDownResult(clients, crNames.TektonResult) })
	utils.CleanupOnInterrupt(func() { utils.TearDownNamespace(clients, crNames.TargetNamespace) })
	defer utils.TearDownNamespace(clients, crNames.TargetNamespace)
	defer utils.TearDownPipeline(clients, crNames.TektonPipeline)
	defer utils.TearDownResult(clients, crNames.TektonResult)

	resources.EnsureNoTektonConfigInstance(t, clients, crNames)

	// Create a TektonPipeline
	if _, err := resources.EnsureTektonPipelineExists(clients.TektonPipeline(), crNames); err != nil {
		t.Fatalf("TektonPipeline %q failed to create: %v", crNames.TektonPipeline, err)
	}

	// Test if TektonPipeline can reach the READY status
	t.Run("create-pipeline", func(t *testing.T) {
		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
	})

	// Before Installing Results, create the required secrets
	t.Run("create-secrets", func(t *testing.T) {
		createSecret(t, clients, crNames.TargetNamespace)
	})

	// Create a TektonResult
	if _, err := resources.EnsureTektonResultExists(clients.TektonResult(), crNames); err != nil {
		t.Fatalf("TektonResult %q failed to create: %v", crNames.TektonResult, err)
	}

	// Test if TektonResult can reach the READY status
	t.Run("create-result", func(t *testing.T) {
		resources.AssertTektonResultCRReadyStatus(t, clients, crNames)
	})

	// Delete the TektonResult CR instance to see if all resources will be removed
	t.Run("delete-result", func(t *testing.T) {
		resources.AssertTektonResultCRReadyStatus(t, clients, crNames)
		resources.TektonResultCRDDelete(t, clients, crNames)
	})

	// Delete the TektonPipeline CR instance to see if all resources will be removed
	t.Run("delete-pipeline", func(t *testing.T) {
		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
		resources.TektonPipelineCRDelete(t, clients, crNames)
	})
}

func createSecret(t *testing.T, clients *utils.Clients, namespace string) {

	key, err := ioutil.ReadFile("./testdata/key.pem")
	if err != nil {
		t.Fatal(err)
	}

	cert, err := ioutil.ReadFile("./testdata/cert.pem")
	if err != nil {
		t.Fatal(err)
	}

	tlsSecret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: tektonresult.TlsSecretName,
		},
		Data: map[string][]byte{
			corev1.TLSCertKey:       cert,
			corev1.TLSPrivateKeyKey: key,
		},
		Type: corev1.SecretTypeTLS,
	}

	_, err = clients.KubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), tlsSecret, metav1.CreateOptions{})
	if err != nil && !apierrs.IsAlreadyExists(err) {
		t.Fatal(err)
	}

	dbSecret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name: tektonresult.DbSecretName,
		},
		Data: map[string][]byte{
			"POSTGRES_USER":     []byte("postgres"),
			"POSTGRES_PASSWORD": []byte("test"),
		},
	}

	_, err = clients.KubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), dbSecret, metav1.CreateOptions{})
	if err != nil && !apierrs.IsAlreadyExists(err) {
		t.Fatal(err)
	}
}
<|endoftext|>