<commit_before>package libproxy

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net"
	"sync"
	"time"
)

const (
	maxBufferSize = 65536
)

type windowState struct {
	current uint64
	allowed uint64
}

func (w *windowState) String() string {
	return fmt.Sprintf("current %d, allowed %d", w.current, w.allowed)
}

func newWindowState() *windowState {
	return &windowState{}
}
func (w *windowState) size() int {
	return int(w.allowed - w.current)
}
func (w *windowState) isAlmostClosed() bool {
	return w.size() < maxBufferSize/2
}
func (w *windowState) advance() {
	w.allowed = w.current + uint64(maxBufferSize)
}

type channel struct {
	m             *sync.Mutex
	c             *sync.Cond
	multiplexer   *Multiplexer
	destination   Destination
	ID            uint32
	read          *windowState
	write         *windowState
	readPipe      *bufferedPipe
	closeReceived bool
	closeSent     bool
	shutdownSent  bool
	writeDeadline time.Time
}

// newChannel registers a channel through the multiplexer
func newChannel(multiplexer *Multiplexer, ID uint32, d Destination) *channel {
	var m sync.Mutex
	c := sync.NewCond(&m)
	readPipe := newBufferedPipe()
	return &channel{
		m:           &m,
		c:           c,
		multiplexer: multiplexer,
		destination: d,
		ID:          ID,
		read:        &windowState{},
		write:       &windowState{},
		readPipe:    readPipe,
	}
}

func (c *channel) sendWindowUpdate() error {
	c.m.Lock()
	c.read.advance()
	seq := c.read.allowed
	c.m.Unlock()
	return c.multiplexer.send(NewWindow(c.ID, seq))
}

func (c *channel) recvWindowUpdate(seq uint64) {
	c.m.Lock()
	c.write.allowed = seq
	c.c.Signal()
	c.m.Unlock()
}

func (c *channel) Read(p []byte) (int, error) {
	n, err := c.readPipe.Read(p)
	c.m.Lock()
	c.read.current = c.read.current + uint64(n)
	needUpdate := c.read.isAlmostClosed()
	c.m.Unlock()
	if needUpdate {
		c.sendWindowUpdate()
	}
	return n, err
}

func (c *channel) Write(p []byte) (int, error) {
	c.m.Lock()
	defer c.m.Unlock()
	written := 0
	for {
		if len(p) == 0 {
			return written, nil
		}
		if c.closeReceived || c.closeSent || c.shutdownSent {
			return written, io.EOF
		}
		if c.write.size() > 0 {
			toWrite := c.write.size()
			if toWrite > len(p) {
				toWrite = len(p)
			}
			// need to write the header and the payload together
			c.multiplexer.writeMutex.Lock()
			f := NewData(c.ID, uint32(toWrite))
			err1 := f.Write(c.multiplexer.connW)
			_, err2 := c.multiplexer.connW.Write(p[0:toWrite])
			err3 := c.multiplexer.connW.Flush()
			c.multiplexer.writeMutex.Unlock()

			if err1 != nil {
				return written, err1
			}
			if err2 != nil {
				return written, err2
			}
			if err3 != nil {
				return written, err3
			}
			c.write.current = c.write.current + uint64(toWrite)
			p = p[toWrite:]
			written = written + toWrite
			continue
		}

		// Wait for the write window to be increased (or a timeout)
		done := make(chan struct{})
		timeout := make(chan time.Time)
		if !c.writeDeadline.IsZero() {
			go func() {
				time.Sleep(time.Until(c.writeDeadline))
				close(timeout)
			}()
		}
		go func() {
			c.c.Wait()
			close(done)
		}()
		select {
		case <-timeout:
			// clean up the goroutine
			c.c.Broadcast()
			<-done
			return written, &errTimeout{}
		case <-done:
			// The timeout will still fire in the background
			continue
		}
	}
}

func (c *channel) Close() error {
	// Avoid a Write() racing with us and sending after we Close()
	c.m.Lock()
	c.closeSent = true
	c.m.Unlock()

	if err := c.multiplexer.send(NewClose(c.ID)); err != nil {
		return err
	}
	c.m.Lock()
	defer c.m.Unlock()
	c.c.Broadcast()
	if c.closeSent && c.closeReceived {
		c.multiplexer.freeChannel(c.ID)
	}
	return nil
}

func (c *channel) CloseRead() error {
	return c.readPipe.CloseWrite()
}

func (c *channel) CloseWrite() error {
	// Avoid a Write() racing with us and sending after we Close()
	c.m.Lock()
	c.shutdownSent = true
	c.m.Unlock()

	if err := c.multiplexer.send(NewShutdown(c.ID)); err != nil {
		return err
	}
	c.m.Lock()
	defer c.m.Unlock()
	c.c.Broadcast()
	return nil
}

func (c *channel) recvClose() error {
	c.m.Lock()
	defer c.m.Unlock()
	c.closeReceived = true
	c.c.Broadcast()
	return nil
}

func (c *channel) isClosed() bool {
	c.m.Lock()
	defer c.m.Unlock()
	return c.closeReceived && c.closeSent
}

func (c *channel) SetReadDeadline(timeout time.Time) error {
	return c.readPipe.SetReadDeadline(timeout)
}

func (c *channel) SetWriteDeadline(timeout time.Time) error {
	c.m.Lock()
	defer c.m.Unlock()
	c.writeDeadline = timeout
	c.c.Broadcast()
	return nil
}

func (c *channel) SetDeadline(timeout time.Time) error {
	if err := c.SetReadDeadline(timeout); err != nil {
		return err
	}
	return c.SetWriteDeadline(timeout)
}

func (c *channel) RemoteAddr() net.Addr {
	return &channelAddr{
		d: c.destination,
	}
}

func (c *channel) LocalAddr() net.Addr {
	return c.RemoteAddr() // There is no local address
}

type channelAddr struct {
	d Destination
}

func (a *channelAddr) Network() string {
	return "channel"
}

func (a *channelAddr) String() string {
	return a.d.String()
}

// Multiplexer muxes and demuxes sub-connections over a single connection
type Multiplexer struct {
	label         string
	conn          io.Closer
	connR         io.Reader // with buffering
	connW         *bufio.Writer
	writeMutex    *sync.Mutex // hold when writing on the channel
	channels      map[uint32]*channel
	nextChannelID uint32
	metadataMutex *sync.Mutex // hold when reading/modifying this structure
	pendingAccept []*channel  // incoming connections
	acceptCond    *sync.Cond
	isRunning     bool
}

// NewMultiplexer constructs a multiplexer from a channel
func NewMultiplexer(label string, conn io.ReadWriteCloser) *Multiplexer {
	var writeMutex, metadataMutex sync.Mutex
	acceptCond := sync.NewCond(&metadataMutex)
	channels := make(map[uint32]*channel)
	connR := bufio.NewReader(conn)
	connW := bufio.NewWriter(conn)
	return &Multiplexer{
		label:         label,
		conn:          conn,
		connR:         connR,
		connW:         connW,
		writeMutex:    &writeMutex,
		channels:      channels,
		metadataMutex: &metadataMutex,
		acceptCond:    acceptCond,
	}
}

func (m *Multiplexer) send(f *Frame) error {
	m.writeMutex.Lock()
	defer m.writeMutex.Unlock()
	if err := f.Write(m.connW); err != nil {
		return err
	}
	return m.connW.Flush()
}

func (m *Multiplexer) findFreeChannelID() uint32 {
	// the metadataMutex is already held
	id := m.nextChannelID
	for {
		if _, ok := m.channels[id]; !ok {
			m.nextChannelID = id + 1
			return id
		}
		id++
	}
}

func (m *Multiplexer) freeChannel(ID uint32) {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	delete(m.channels, ID)
}

// Dial opens a connection to the given destination
func (m *Multiplexer) Dial(d Destination) (Conn, error) {
	m.metadataMutex.Lock()
	id := m.findFreeChannelID()
	channel := newChannel(m, id, d)
	m.channels[id] = channel
	m.metadataMutex.Unlock()

	if err := m.send(NewOpen(id, d)); err != nil {
		return nil, err
	}
	if err := channel.sendWindowUpdate(); err != nil {
		return nil, err
	}
	return channel, nil
}

// Accept returns the next client connection
func (m *Multiplexer) Accept() (Conn, *Destination, error) {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	for {
		if len(m.pendingAccept) > 0 {
			first := m.pendingAccept[0]
			m.pendingAccept = m.pendingAccept[1:]
			if err := first.sendWindowUpdate(); err != nil {
				return nil, nil, err
			}
			return first, &first.destination, nil
		}
		m.acceptCond.Wait()
	}
}

// Run starts handling the requests from the other side
func (m *Multiplexer) Run() {
	m.metadataMutex.Lock()
	m.isRunning = true
	m.metadataMutex.Unlock()
	go func() {
		if err := m.run(); err != nil {
			log.Printf("Multiplexer main loop failed with %v", err)
		}
		m.metadataMutex.Lock()
		m.isRunning = false
		m.metadataMutex.Unlock()
	}()
}

// IsRunning returns whether the multiplexer is running or not
func (m *Multiplexer) IsRunning() bool {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	return m.isRunning
}

func (m *Multiplexer) run() error {
	for {
		f, err := unmarshalFrame(m.connR)
		if err != nil {
			return fmt.Errorf("Failed to unmarshal command frame: %v", err)
		}
		switch f.Command {
		case Open:
			o, err := f.Open()
			if err != nil {
				return fmt.Errorf("Failed to unmarshal open command: %v", err)
			}
			switch o.Connection {
			case Dedicated:
				return fmt.Errorf("Dedicated connections are not implemented yet")
			case Multiplexed:
				m.metadataMutex.Lock()
				channel := newChannel(m, f.ID, o.Destination)
				m.channels[f.ID] = channel
				m.pendingAccept = append(m.pendingAccept, channel)
				m.acceptCond.Signal()
				m.metadataMutex.Unlock()
			}
		case Window:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			w, err := f.Window()
			if err != nil {
				return err
			}
			channel.recvWindowUpdate(w.seq)
		case Data:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			d, err := f.Data()
			if err != nil {
				return err
			}
			if _, err := io.CopyN(channel.readPipe, m.connR, int64(d.payloadlen)); err != nil {
				return err
			}
		case Shutdown:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			if err := channel.readPipe.CloseWrite(); err != nil {
				return err
			}
		case Close:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			// this will unblock waiting Read calls
			if err := channel.readPipe.CloseWrite(); err != nil {
				return err
			}
			// this will unblock waiting Write calls
			if err := channel.recvClose(); err != nil {
				return err
			}
			if channel.isClosed() {
				m.freeChannel(channel.ID)
			}
		default:
			return fmt.Errorf("Unknown command type: %v", f)
		}
	}
}

// Forward runs the TCP/UDP forwarder over a sub-connection
func Forward(conn Conn, destination Destination, quit chan struct{}) {
	defer conn.Close()

	switch destination.Proto {
	case TCP:
		backendAddr := net.TCPAddr{IP: destination.IP, Port: int(destination.Port), Zone: ""}
		if err := HandleTCPConnection(conn, &backendAddr, quit); err != nil {
			log.Printf("Error setting up TCP proxy subconnection: %v", err)
			return
		}
	case Unix:
		backendAddr, err := net.ResolveUnixAddr("unix", destination.Path)
		if err != nil {
			log.Printf("Error resolving Unix address %s", destination.Path)
			return
		}
		if err := HandleUnixConnection(conn, backendAddr, quit); err != nil {
			log.Printf("Error setting up Unix proxy subconnection: %v", err)
			return
		}
	case UDP:
		backendAddr := &net.UDPAddr{IP: destination.IP, Port: int(destination.Port), Zone: ""}

		proxy, err := NewUDPProxy(backendAddr, NewUDPConn(conn), backendAddr)
		if err != nil {
			log.Printf("Failed to setup UDP proxy for %s: %#v", backendAddr, err)
			return
		}
		proxy.Run()
		return
	default:
		log.Printf("Unknown protocol: %d", destination.Proto)
		return
	}
}
<commit_msg>pkg/libproxy: don't send Close or Shutdown more than once<commit_after>package libproxy

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net"
	"sync"
	"time"
)

const (
	maxBufferSize = 65536
)

type windowState struct {
	current uint64
	allowed uint64
}

func (w *windowState) String() string {
	return fmt.Sprintf("current %d, allowed %d", w.current, w.allowed)
}

func newWindowState() *windowState {
	return &windowState{}
}
func (w *windowState) size() int {
	return int(w.allowed - w.current)
}
func (w *windowState) isAlmostClosed() bool {
	return w.size() < maxBufferSize/2
}
func (w *windowState) advance() {
	w.allowed = w.current + uint64(maxBufferSize)
}

type channel struct {
	m             *sync.Mutex
	c             *sync.Cond
	multiplexer   *Multiplexer
	destination   Destination
	ID            uint32
	read          *windowState
	write         *windowState
	readPipe      *bufferedPipe
	closeReceived bool
	closeSent     bool
	shutdownSent  bool
	writeDeadline time.Time
}

// newChannel registers a channel through the multiplexer
func newChannel(multiplexer *Multiplexer, ID uint32, d Destination) *channel {
	var m sync.Mutex
	c := sync.NewCond(&m)
	readPipe := newBufferedPipe()
	return &channel{
		m:           &m,
		c:           c,
		multiplexer: multiplexer,
		destination: d,
		ID:          ID,
		read:        &windowState{},
		write:       &windowState{},
		readPipe:    readPipe,
	}
}

func (c *channel) sendWindowUpdate() error {
	c.m.Lock()
	c.read.advance()
	seq := c.read.allowed
	c.m.Unlock()
	return c.multiplexer.send(NewWindow(c.ID, seq))
}

func (c *channel) recvWindowUpdate(seq uint64) {
	c.m.Lock()
	c.write.allowed = seq
	c.c.Signal()
	c.m.Unlock()
}

func (c *channel) Read(p []byte) (int, error) {
	n, err := c.readPipe.Read(p)
	c.m.Lock()
	c.read.current = c.read.current + uint64(n)
	needUpdate := c.read.isAlmostClosed()
	c.m.Unlock()
	if needUpdate {
		c.sendWindowUpdate()
	}
	return n, err
}

func (c *channel) Write(p []byte) (int, error) {
	c.m.Lock()
	defer c.m.Unlock()
	written := 0
	for {
		if len(p) == 0 {
			return written, nil
		}
		if c.closeReceived || c.closeSent || c.shutdownSent {
			return written, io.EOF
		}
		if c.write.size() > 0 {
			toWrite := c.write.size()
			if toWrite > len(p) {
				toWrite = len(p)
			}
			// need to write the header and the payload together
			c.multiplexer.writeMutex.Lock()
			f := NewData(c.ID, uint32(toWrite))
			err1 := f.Write(c.multiplexer.connW)
			_, err2 := c.multiplexer.connW.Write(p[0:toWrite])
			err3 := c.multiplexer.connW.Flush()
			c.multiplexer.writeMutex.Unlock()

			if err1 != nil {
				return written, err1
			}
			if err2 != nil {
				return written, err2
			}
			if err3 != nil {
				return written, err3
			}
			c.write.current = c.write.current + uint64(toWrite)
			p = p[toWrite:]
			written = written + toWrite
			continue
		}

		// Wait for the write window to be increased (or a timeout)
		done := make(chan struct{})
		timeout := make(chan time.Time)
		if !c.writeDeadline.IsZero() {
			go func() {
				time.Sleep(time.Until(c.writeDeadline))
				close(timeout)
			}()
		}
		go func() {
			c.c.Wait()
			close(done)
		}()
		select {
		case <-timeout:
			// clean up the goroutine
			c.c.Broadcast()
			<-done
			return written, &errTimeout{}
		case <-done:
			// The timeout will still fire in the background
			continue
		}
	}
}

func (c *channel) Close() error {
	// Avoid a Write() racing with us and sending after we Close()
	// Avoid sending Close twice
	c.m.Lock()
	alreadyClosed := c.closeSent
	c.closeSent = true
	c.m.Unlock()

	if alreadyClosed {
		return nil
	}
	if err := c.multiplexer.send(NewClose(c.ID)); err != nil {
		return err
	}
	c.m.Lock()
	defer c.m.Unlock()
	c.c.Broadcast()
	if c.closeSent && c.closeReceived {
		c.multiplexer.freeChannel(c.ID)
	}
	return nil
}

func (c *channel) CloseRead() error {
	return c.readPipe.CloseWrite()
}

func (c *channel) CloseWrite() error {
	// Avoid a Write() racing with us and sending after we Close()
	// Avoid sending Shutdown twice
	c.m.Lock()
	alreadyShutdown := c.shutdownSent
	c.shutdownSent = true
	c.m.Unlock()

	if alreadyShutdown {
		return nil
	}
	if err := c.multiplexer.send(NewShutdown(c.ID)); err != nil {
		return err
	}
	c.m.Lock()
	defer c.m.Unlock()
	c.c.Broadcast()
	return nil
}

func (c *channel) recvClose() error {
	c.m.Lock()
	defer c.m.Unlock()
	c.closeReceived = true
	c.c.Broadcast()
	return nil
}

func (c *channel) isClosed() bool {
	c.m.Lock()
	defer c.m.Unlock()
	return c.closeReceived && c.closeSent
}

func (c *channel) SetReadDeadline(timeout time.Time) error {
	return c.readPipe.SetReadDeadline(timeout)
}

func (c *channel) SetWriteDeadline(timeout time.Time) error {
	c.m.Lock()
	defer c.m.Unlock()
	c.writeDeadline = timeout
	c.c.Broadcast()
	return nil
}

func (c *channel) SetDeadline(timeout time.Time) error {
	if err := c.SetReadDeadline(timeout); err != nil {
		return err
	}
	return c.SetWriteDeadline(timeout)
}

func (c *channel) RemoteAddr() net.Addr {
	return &channelAddr{
		d: c.destination,
	}
}

func (c *channel) LocalAddr() net.Addr {
	return c.RemoteAddr() // There is no local address
}

type channelAddr struct {
	d Destination
}

func (a *channelAddr) Network() string {
	return "channel"
}

func (a *channelAddr) String() string {
	return a.d.String()
}

// Multiplexer muxes and demuxes sub-connections over a single connection
type Multiplexer struct {
	label         string
	conn          io.Closer
	connR         io.Reader // with buffering
	connW         *bufio.Writer
	writeMutex    *sync.Mutex // hold when writing on the channel
	channels      map[uint32]*channel
	nextChannelID uint32
	metadataMutex *sync.Mutex // hold when reading/modifying this structure
	pendingAccept []*channel  // incoming connections
	acceptCond    *sync.Cond
	isRunning     bool
}

// NewMultiplexer constructs a multiplexer from a channel
func NewMultiplexer(label string, conn io.ReadWriteCloser) *Multiplexer {
	var writeMutex, metadataMutex sync.Mutex
	acceptCond := sync.NewCond(&metadataMutex)
	channels := make(map[uint32]*channel)
	connR := bufio.NewReader(conn)
	connW := bufio.NewWriter(conn)
	return &Multiplexer{
		label:         label,
		conn:          conn,
		connR:         connR,
		connW:         connW,
		writeMutex:    &writeMutex,
		channels:      channels,
		metadataMutex: &metadataMutex,
		acceptCond:    acceptCond,
	}
}

func (m *Multiplexer) send(f *Frame) error {
	m.writeMutex.Lock()
	defer m.writeMutex.Unlock()
	if err := f.Write(m.connW); err != nil {
		return err
	}
	return m.connW.Flush()
}

func (m *Multiplexer) findFreeChannelID() uint32 {
	// the metadataMutex is already held
	id := m.nextChannelID
	for {
		if _, ok := m.channels[id]; !ok {
			m.nextChannelID = id + 1
			return id
		}
		id++
	}
}

func (m *Multiplexer) freeChannel(ID uint32) {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	delete(m.channels, ID)
}

// Dial opens a connection to the given destination
func (m *Multiplexer) Dial(d Destination) (Conn, error) {
	m.metadataMutex.Lock()
	id := m.findFreeChannelID()
	channel := newChannel(m, id, d)
	m.channels[id] = channel
	m.metadataMutex.Unlock()

	if err := m.send(NewOpen(id, d)); err != nil {
		return nil, err
	}
	if err := channel.sendWindowUpdate(); err != nil {
		return nil, err
	}
	return channel, nil
}

// Accept returns the next client connection
func (m *Multiplexer) Accept() (Conn, *Destination, error) {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	for {
		if len(m.pendingAccept) > 0 {
			first := m.pendingAccept[0]
			m.pendingAccept = m.pendingAccept[1:]
			if err := first.sendWindowUpdate(); err != nil {
				return nil, nil, err
			}
			return first, &first.destination, nil
		}
		m.acceptCond.Wait()
	}
}

// Run starts handling the requests from the other side
func (m *Multiplexer) Run() {
	m.metadataMutex.Lock()
	m.isRunning = true
	m.metadataMutex.Unlock()
	go func() {
		if err := m.run(); err != nil {
			log.Printf("Multiplexer main loop failed with %v", err)
		}
		m.metadataMutex.Lock()
		m.isRunning = false
		m.metadataMutex.Unlock()
	}()
}

// IsRunning returns whether the multiplexer is running or not
func (m *Multiplexer) IsRunning() bool {
	m.metadataMutex.Lock()
	defer m.metadataMutex.Unlock()
	return m.isRunning
}

func (m *Multiplexer) run() error {
	for {
		f, err := unmarshalFrame(m.connR)
		if err != nil {
			return fmt.Errorf("Failed to unmarshal command frame: %v", err)
		}
		switch f.Command {
		case Open:
			o, err := f.Open()
			if err != nil {
				return fmt.Errorf("Failed to unmarshal open command: %v", err)
			}
			switch o.Connection {
			case Dedicated:
				return fmt.Errorf("Dedicated connections are not implemented yet")
			case Multiplexed:
				m.metadataMutex.Lock()
				channel := newChannel(m, f.ID, o.Destination)
				m.channels[f.ID] = channel
				m.pendingAccept = append(m.pendingAccept, channel)
				m.acceptCond.Signal()
				m.metadataMutex.Unlock()
			}
		case Window:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			w, err := f.Window()
			if err != nil {
				return err
			}
			channel.recvWindowUpdate(w.seq)
		case Data:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			d, err := f.Data()
			if err != nil {
				return err
			}
			if _, err := io.CopyN(channel.readPipe, m.connR, int64(d.payloadlen)); err != nil {
				return err
			}
		case Shutdown:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			if err := channel.readPipe.CloseWrite(); err != nil {
				return err
			}
		case Close:
			m.metadataMutex.Lock()
			channel, ok := m.channels[f.ID]
			m.metadataMutex.Unlock()
			if !ok {
				return fmt.Errorf("Unknown channel id: %v", f.ID)
			}
			// this will unblock waiting Read calls
			if err := channel.readPipe.CloseWrite(); err != nil {
				return err
			}
			// this will unblock waiting Write calls
			if err := channel.recvClose(); err != nil {
				return err
			}
			if channel.isClosed() {
				m.freeChannel(channel.ID)
			}
		default:
			return fmt.Errorf("Unknown command type: %v", f)
		}
	}
}

// Forward runs the TCP/UDP forwarder over a sub-connection
func Forward(conn Conn, destination Destination, quit chan struct{}) {
	defer conn.Close()

	switch destination.Proto {
	case TCP:
		backendAddr := net.TCPAddr{IP: destination.IP, Port: int(destination.Port), Zone: ""}
		if err := HandleTCPConnection(conn, &backendAddr, quit); err != nil {
			log.Printf("Error setting up TCP proxy subconnection: %v", err)
			return
		}
	case Unix:
		backendAddr, err := net.ResolveUnixAddr("unix", destination.Path)
		if err != nil {
			log.Printf("Error resolving Unix address %s", destination.Path)
			return
		}
		if err := HandleUnixConnection(conn, backendAddr, quit); err != nil {
			log.Printf("Error setting up Unix proxy subconnection: %v", err)
			return
		}
	case UDP:
		backendAddr := &net.UDPAddr{IP: destination.IP, Port: int(destination.Port), Zone: ""}

		proxy, err := NewUDPProxy(backendAddr, NewUDPConn(conn), backendAddr)
		if err != nil {
			log.Printf("Failed to setup UDP proxy for %s: %#v", backendAddr, err)
			return
		}
		proxy.Run()
		return
	default:
		log.Printf("Unknown protocol: %d", destination.Proto)
		return
	}
}
<|endoftext|>


<commit_before>package transports

import (
  "log"
)

type DummyMarshaler struct {
}

func (marshaler DummyMarshaler) Marshal(i *interface{}) (error, interface{}) {
  log.Println("** DummyMarshaler, input", *i)
  var err error
	return err, []byte("aa")
}

func (marshaler DummyMarshaler) Unmarshal() {
	return
}
<commit_msg>Return the original value from DummyMarshaler<commit_after>package transports

import (
  // "log"
)

type DummyMarshaler struct {
}

func (marshaler DummyMarshaler) Marshal(i *interface{}) (error, interface{}) {
  var err error
	return err, *i
}

func (marshaler DummyMarshaler) Unmarshal() {
	return
}
<|endoftext|>


<commit_before>package quicktemplate

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

// Writer implements auxiliary writer used by quicktemplate functions.
//
// Use AcquireWriter for creating new writers.
type Writer struct {
	e QWriter
	n QWriter
}

// W returns the underlying writer passed to AcquireWriter.
func (qw *Writer) W() io.Writer {
	return qw.n.w
}

// E returns QWriter with enabled html escaping.
func (qw *Writer) E() *QWriter {
	return &qw.e
}

// N returns QWriter without html escaping.
func (qw *Writer) N() *QWriter {
	return &qw.n
}

// AcquireWriter returns new writer from the pool.
//
// Return unneeded writer to the pool by calling ReleaseWriter
// in order to reduce memory allocations.
func AcquireWriter(w io.Writer) *Writer {
	v := writerPool.Get()
	if v == nil {
		qw := &Writer{}
		qw.e.w = &htmlEscapeWriter{}
		v = qw
	}
	qw := v.(*Writer)
	qw.e.w.(*htmlEscapeWriter).w = w
	qw.n.w = w
	return qw
}

// ReleaseWriter returns the writer to the pool.
//
// Do not access released writer, otherwise data races may occur.
func ReleaseWriter(qw *Writer) {
	hw := qw.e.w.(*htmlEscapeWriter)
	hw.w = nil
	qw.e.Reset()
	qw.e.w = hw

	qw.n.Reset()

	writerPool.Put(qw)
}

var writerPool sync.Pool

// QWriter is auxiliary writer used by Writer.
type QWriter struct {
	w   io.Writer
	err error
	b   []byte
}

// Write implements io.Writer.
func (w *QWriter) Write(p []byte) (int, error) {
	if w.err != nil {
		return 0, w.err
	}
	n, err := w.w.Write(p)
	if err != nil {
		w.err = err
	}
	return n, err
}

// Reset resets QWriter to the original state.
func (w *QWriter) Reset() {
	w.w = nil
	w.err = nil
	w.b = w.b[:0]
}

// S writes s to w.
func (w *QWriter) S(s string) {
	w.Write(unsafeStrToBytes(s))
}

// Z writes z to w.
func (w *QWriter) Z(z []byte) {
	w.Write(z)
}

// SZ is a synonym to Z.
func (w *QWriter) SZ(z []byte) {
	w.Write(z)
}

// D writes n to w.
func (w *QWriter) D(n int) {
	w.b = strconv.AppendInt(w.b[:0], int64(n), 10)
	w.Write(w.b)
}

// F writes f to w.
func (w *QWriter) F(f float64) {
	w.FPrec(f, -1)
}

// FPrec writes f to w using the given floating point precision.
func (w *QWriter) FPrec(f float64, prec int) {
	w.b = strconv.AppendFloat(w.b[:0], f, 'f', prec, 64)
	w.Write(w.b)
}

// Q writes quoted json-safe s to w.
func (w *QWriter) Q(s string) {
	w.Write(strQuote)
	writeJSONString(w, s)
	w.Write(strQuote)
}

var strQuote = []byte(`"`)

// QZ writes quoted json-safe z to w.
func (w *QWriter) QZ(z []byte) {
	w.Q(unsafeBytesToStr(z))
}

// J writes json-safe s to w.
//
// Unlike Q it doesn't qoute resulting s.
func (w *QWriter) J(s string) {
	writeJSONString(w, s)
}

// JZ writes json-safe z to w.
//
// Unlike Q it doesn't qoute resulting z.
func (w *QWriter) JZ(z []byte) {
	w.J(unsafeBytesToStr(z))
}

// V writes v to w.
func (w *QWriter) V(v interface{}) {
	fmt.Fprintf(w, "%v", v)
}

// U writes url-encoded s to w.
func (w *QWriter) U(s string) {
	w.b = appendURLEncode(w.b[:0], s)
	w.Write(w.b)
}

// UZ writes url-encoded z to w.
func (w *QWriter) UZ(z []byte) {
	w.U(unsafeBytesToStr(z))
}
<commit_msg>Optimization: skip temporary buffer in QWriter.D, QWriter.F and QWriter.U if the underlying writer is ByteBuffer<commit_after>package quicktemplate

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

// Writer implements auxiliary writer used by quicktemplate functions.
//
// Use AcquireWriter for creating new writers.
type Writer struct {
	e QWriter
	n QWriter
}

// W returns the underlying writer passed to AcquireWriter.
func (qw *Writer) W() io.Writer {
	return qw.n.w
}

// E returns QWriter with enabled html escaping.
func (qw *Writer) E() *QWriter {
	return &qw.e
}

// N returns QWriter without html escaping.
func (qw *Writer) N() *QWriter {
	return &qw.n
}

// AcquireWriter returns new writer from the pool.
//
// Return unneeded writer to the pool by calling ReleaseWriter
// in order to reduce memory allocations.
func AcquireWriter(w io.Writer) *Writer {
	v := writerPool.Get()
	if v == nil {
		qw := &Writer{}
		qw.e.w = &htmlEscapeWriter{}
		v = qw
	}
	qw := v.(*Writer)
	qw.e.w.(*htmlEscapeWriter).w = w
	qw.n.w = w
	return qw
}

// ReleaseWriter returns the writer to the pool.
//
// Do not access released writer, otherwise data races may occur.
func ReleaseWriter(qw *Writer) {
	hw := qw.e.w.(*htmlEscapeWriter)
	hw.w = nil
	qw.e.Reset()
	qw.e.w = hw

	qw.n.Reset()

	writerPool.Put(qw)
}

var writerPool sync.Pool

// QWriter is auxiliary writer used by Writer.
type QWriter struct {
	w   io.Writer
	err error
	b   []byte
}

// Write implements io.Writer.
func (w *QWriter) Write(p []byte) (int, error) {
	if w.err != nil {
		return 0, w.err
	}
	n, err := w.w.Write(p)
	if err != nil {
		w.err = err
	}
	return n, err
}

// Reset resets QWriter to the original state.
func (w *QWriter) Reset() {
	w.w = nil
	w.err = nil
}

// S writes s to w.
func (w *QWriter) S(s string) {
	w.Write(unsafeStrToBytes(s))
}

// Z writes z to w.
func (w *QWriter) Z(z []byte) {
	w.Write(z)
}

// SZ is a synonym to Z.
func (w *QWriter) SZ(z []byte) {
	w.Write(z)
}

// D writes n to w.
func (w *QWriter) D(n int) {
	bb, ok := w.w.(*ByteBuffer)
	if ok {
		bb.B = strconv.AppendInt(bb.B, int64(n), 10)
	} else {
		w.b = strconv.AppendInt(w.b[:0], int64(n), 10)
		w.Write(w.b)
	}
}

// F writes f to w.
func (w *QWriter) F(f float64) {
	w.FPrec(f, -1)
}

// FPrec writes f to w using the given floating point precision.
func (w *QWriter) FPrec(f float64, prec int) {
	bb, ok := w.w.(*ByteBuffer)
	if ok {
		bb.B = strconv.AppendFloat(bb.B, f, 'f', prec, 64)
	} else {
		w.b = strconv.AppendFloat(w.b[:0], f, 'f', prec, 64)
		w.Write(w.b)
	}
}

// Q writes quoted json-safe s to w.
func (w *QWriter) Q(s string) {
	w.Write(strQuote)
	writeJSONString(w, s)
	w.Write(strQuote)
}

var strQuote = []byte(`"`)

// QZ writes quoted json-safe z to w.
func (w *QWriter) QZ(z []byte) {
	w.Q(unsafeBytesToStr(z))
}

// J writes json-safe s to w.
//
// Unlike Q it doesn't qoute resulting s.
func (w *QWriter) J(s string) {
	writeJSONString(w, s)
}

// JZ writes json-safe z to w.
//
// Unlike Q it doesn't qoute resulting z.
func (w *QWriter) JZ(z []byte) {
	w.J(unsafeBytesToStr(z))
}

// V writes v to w.
func (w *QWriter) V(v interface{}) {
	fmt.Fprintf(w, "%v", v)
}

// U writes url-encoded s to w.
func (w *QWriter) U(s string) {
	bb, ok := w.w.(*ByteBuffer)
	if ok {
		bb.B = appendURLEncode(bb.B, s)
	} else {
		w.b = appendURLEncode(w.b[:0], s)
		w.Write(w.b)
	}
}

// UZ writes url-encoded z to w.
func (w *QWriter) UZ(z []byte) {
	w.U(unsafeBytesToStr(z))
}
<|endoftext|>


<commit_before>// Copyright 2013 Benoît Amiaux. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package iobit

import (
	"encoding/binary"
	"errors"
)

// Writer wraps a raw byte array and provides multiple methoods to write data bit-by-bit
// Its methods don't return the usual error as it is too expensive.
// Instead, write errors can be checked with the Flush() method.
type Writer struct {
	dst   []byte
	cache uint64
	fill  uint
	idx   int
}

var (
	ErrOverflow  = errors.New("bit overflow")
	ErrUnderflow = errors.New("bit underflow")
)

// NewWriter returns a new writer writing to output byte array.
func NewWriter(dst []byte) Writer {
	return Writer{dst: dst}
}

// PutUint32 writes up to 32 bits in big-endian order.
func (w *Writer) PutUint32(bits uint, val uint32) {
	u := uint64(val) << (64 - bits)
	if w.fill+bits > 64 {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
			w.cache <<= 32
		}
		w.idx += 4
		w.fill -= 32
	}
	u >>= w.fill
	w.fill += bits
	w.cache |= u
}

// PutUint64 writes up to 64 bits in big-endian order.
func (w *Writer) PutUint64(bits uint, val uint64) {
	if bits > 32 {
		bits -= 32
		w.PutBe32(uint32(val >> bits))
	}
	w.PutUint32(bits, uint32(val))
}

// PutBit writes one bit to output.
func (w *Writer) PutBit(val bool) {
	v := uint32(0)
	if val {
		v = 1
	}
	w.PutUint32(1, v)
}

// PutByte writes one byte.
func (w *Writer) PutByte(val byte) {
	w.PutUint32(8, uint32(val))
}

// PutLe16 writes 16 bits in little-endian order.
func (w *Writer) PutLe16(val uint16) {
	w.PutUint32(16, uint32(bswap16(val)))
}

// PutBe16 writes 16 bits in big-endian order.
func (w *Writer) PutBe16(val uint16) {
	w.PutUint32(16, uint32(val))
}

// PutLe32 writes 32 bits in little-endian order.
func (w *Writer) PutLe32(val uint32) {
	w.PutUint32(32, bswap32(val))
}

// PutBe32 writes 32 bits in big-endian order.
func (w *Writer) PutBe32(val uint32) {
	w.PutUint32(32, val)
}

// PutLe64 writes 64 bits in little-endian order.
func (w *Writer) PutLe64(val uint64) {
	w.PutLe32(uint32(val))
	w.PutLe32(uint32(val >> 32))
}

// PutBe64 writes 64 bits in big-endian order.
func (w *Writer) PutBe64(val uint64) {
	w.PutUint64(64, val)
}

// PutUint8 writes up to 8 bits.
func (w *Writer) PutUint8(bits uint, val byte) {
	w.PutUint32(bits, uint32(val))
}

// PutInt8 writes up to 8 signed bits.
func (w *Writer) PutInt8(bits uint, val int8) {
	w.PutUint32(bits, uint32(val))
}

// PutUint16 writes up to 16 bits in big-endian order.
func (w *Writer) PutUint16(bits uint, val uint16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt16 writes up to 16 signed bits in big-endian order.
func (w *Writer) PutInt16(bits uint, val int16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt32 writes up to 32 signed bits in big-endian order.
func (w *Writer) PutInt32(bits uint, val int32) {
	w.PutUint32(bits, uint32(val))
}

// PutInt64 writes up to 64 signed bits in big-endian order.
func (w *Writer) PutInt64(bits uint, val int64) {
	w.PutUint64(bits, uint64(val))
}

// Flush flushes the writer to its underlying buffer.
// Returns ErrUnderflow if the output is not byte-aligned.
// Returns ErrOverflow if the output array is too small.
func (w *Writer) Flush() error {
	for w.fill >= 8 && w.idx < len(w.dst) {
		w.dst[w.idx] = byte(w.cache >> 56)
		w.idx += 1
		w.cache <<= 8
		w.fill -= 8
	}
	if w.idx+int(w.fill) > len(w.dst) {
		return ErrOverflow
	}
	if w.fill != 0 {
		return ErrUnderflow
	}
	return nil
}

// Write writes a whole slice p at once.
// Returns an error if the writer is not byte-aligned.
func (w *Writer) Write(p []byte) (int, error) {
	err := w.Flush()
	if err != nil {
		return 0, err
	}
	n := 0
	if w.idx < len(w.dst) {
		n = copy(w.dst[w.idx:], p)
	}
	w.idx += len(p)
	if n != len(p) {
		return n, ErrOverflow
	}
	return n, nil
}

// Index returns the current writer position in bits.
func (w *Writer) Index() int {
	return w.idx<<3 + int(w.fill)
}

func imin(a, b int) int {
	if a > b {
		return b
	}
	return a
}

// Bits returns the number of bits available to write.
func (w *Writer) Bits() int {
	size := len(w.dst)
	return size<<3 - imin(w.idx<<3+int(w.fill), size<<3)
}

// Bytes returns a byte array of what's left to write.
// Note that this array is 8-bit aligned even if the writer is not.
func (w *Writer) Bytes() []byte {
	skip := w.idx + int(w.fill>>3)
	if skip >= len(w.dst) {
		return w.dst[:0]
	}
	return w.dst[skip:len(w.dst)]
}

// Reset resets the writer to its initial position.
func (w *Writer) Reset() {
	w.fill = 0
	w.idx = 0
}
<commit_msg>optimize PutLe64 & PutBe64 functions<commit_after>// Copyright 2013 Benoît Amiaux. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package iobit

import (
	"encoding/binary"
	"errors"
)

// Writer wraps a raw byte array and provides multiple methoods to write data bit-by-bit
// Its methods don't return the usual error as it is too expensive.
// Instead, write errors can be checked with the Flush() method.
type Writer struct {
	dst   []byte
	cache uint64
	fill  uint
	idx   int
}

var (
	ErrOverflow  = errors.New("bit overflow")
	ErrUnderflow = errors.New("bit underflow")
)

// NewWriter returns a new writer writing to output byte array.
func NewWriter(dst []byte) Writer {
	return Writer{dst: dst}
}

// PutUint32 writes up to 32 bits in big-endian order.
func (w *Writer) PutUint32(bits uint, val uint32) {
	u := uint64(val) << (64 - bits)
	if w.fill > 64-bits {
		if w.idx+4 <= len(w.dst) {
			binary.BigEndian.PutUint32(w.dst[w.idx:], uint32(w.cache>>32))
		}
		w.idx += 4
		w.fill -= 32
		w.cache <<= 32
	}
	u >>= w.fill
	w.fill += bits
	w.cache |= u
}

// PutUint64 writes up to 64 bits in big-endian order.
func (w *Writer) PutUint64(bits uint, val uint64) {
	if bits > 32 {
		bits -= 32
		w.PutBe32(uint32(val >> bits))
	}
	w.PutUint32(bits, uint32(val))
}

// PutBit writes one bit to output.
func (w *Writer) PutBit(val bool) {
	v := uint32(0)
	if val {
		v = 1
	}
	w.PutUint32(1, v)
}

// PutByte writes one byte.
func (w *Writer) PutByte(val byte) {
	w.PutUint32(8, uint32(val))
}

// PutLe16 writes 16 bits in little-endian order.
func (w *Writer) PutLe16(val uint16) {
	w.PutUint32(16, uint32(bswap16(val)))
}

// PutBe16 writes 16 bits in big-endian order.
func (w *Writer) PutBe16(val uint16) {
	w.PutUint32(16, uint32(val))
}

// PutLe32 writes 32 bits in little-endian order.
func (w *Writer) PutLe32(val uint32) {
	w.PutUint32(32, bswap32(val))
}

// PutBe32 writes 32 bits in big-endian order.
func (w *Writer) PutBe32(val uint32) {
	w.PutUint32(32, val)
}

// PutLe64 writes 64 bits in little-endian order.
func (w *Writer) PutLe64(val uint64) {
	w.PutBe32(bswap32(uint32(val)))
	w.PutBe32(bswap32(uint32(val >> 32)))
}

// PutBe64 writes 64 bits in big-endian order.
func (w *Writer) PutBe64(val uint64) {
	w.PutBe32(uint32(val >> 32))
	w.PutBe32(uint32(val))
}

// PutUint8 writes up to 8 bits.
func (w *Writer) PutUint8(bits uint, val byte) {
	w.PutUint32(bits, uint32(val))
}

// PutInt8 writes up to 8 signed bits.
func (w *Writer) PutInt8(bits uint, val int8) {
	w.PutUint32(bits, uint32(val))
}

// PutUint16 writes up to 16 bits in big-endian order.
func (w *Writer) PutUint16(bits uint, val uint16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt16 writes up to 16 signed bits in big-endian order.
func (w *Writer) PutInt16(bits uint, val int16) {
	w.PutUint32(bits, uint32(val))
}

// PutInt32 writes up to 32 signed bits in big-endian order.
func (w *Writer) PutInt32(bits uint, val int32) {
	w.PutUint32(bits, uint32(val))
}

// PutInt64 writes up to 64 signed bits in big-endian order.
func (w *Writer) PutInt64(bits uint, val int64) {
	w.PutUint64(bits, uint64(val))
}

// Flush flushes the writer to its underlying buffer.
// Returns ErrUnderflow if the output is not byte-aligned.
// Returns ErrOverflow if the output array is too small.
func (w *Writer) Flush() error {
	for w.fill >= 8 && w.idx < len(w.dst) {
		w.dst[w.idx] = byte(w.cache >> 56)
		w.idx += 1
		w.cache <<= 8
		w.fill -= 8
	}
	if w.idx+int(w.fill) > len(w.dst) {
		return ErrOverflow
	}
	if w.fill != 0 {
		return ErrUnderflow
	}
	return nil
}

// Write writes a whole slice p at once.
// Returns an error if the writer is not byte-aligned.
func (w *Writer) Write(p []byte) (int, error) {
	err := w.Flush()
	if err != nil {
		return 0, err
	}
	n := 0
	if w.idx < len(w.dst) {
		n = copy(w.dst[w.idx:], p)
	}
	w.idx += len(p)
	if n != len(p) {
		return n, ErrOverflow
	}
	return n, nil
}

// Index returns the current writer position in bits.
func (w *Writer) Index() int {
	return w.idx<<3 + int(w.fill)
}

func imin(a, b int) int {
	if a > b {
		return b
	}
	return a
}

// Bits returns the number of bits available to write.
func (w *Writer) Bits() int {
	size := len(w.dst)
	return size<<3 - imin(w.idx<<3+int(w.fill), size<<3)
}

// Bytes returns a byte array of what's left to write.
// Note that this array is 8-bit aligned even if the writer is not.
func (w *Writer) Bytes() []byte {
	skip := w.idx + int(w.fill>>3)
	if skip >= len(w.dst) {
		return w.dst[:0]
	}
	return w.dst[skip:len(w.dst)]
}

// Reset resets the writer to its initial position.
func (w *Writer) Reset() {
	w.fill = 0
	w.idx = 0
}
<|endoftext|>


<commit_before>package signals

import "encoding/gob"

func init() {
	gob.Register(ADSREnvelope{})
}

//  Attack Decay Sustain Release (ADSR) envelope.  see https://en.wikipedia.org/wiki/Synthesizer#Attack_Decay_Sustain_Release_.28ADSR.29_envelope
type ADSREnvelope struct {
	attackEnd    x
	attackSlope  y
	decaySlope   y
	sustainStart x
	sustain      y
	sustainEnd   x
	releaseSlope y
	end          x
}

func NewADSREnvelope(attack, decay, sustain x, sustainy y, release x) LimitedFunction {
	// TODO release attack or decay of zero!
	return ADSREnvelope{attack, Maxy / y(attack), (Maxy - sustainy) / y(decay), attack + decay, sustainy, attack + decay + sustain, sustainy / y(release), attack + decay + sustain + release}
}

func (s ADSREnvelope) Call(t x) y {
	if t > s.end {
		return 0
	} else if t > s.sustainEnd {
		return y(s.end-t) * s.releaseSlope
	} else if t > s.sustainStart {
		return s.sustain
	} else if t > s.attackEnd {
		return y(s.sustainStart-t)*s.decaySlope + s.sustain
	} else if t > 0 {
		return y(t) * s.attackSlope
	} else {
		return 0
	}
}

func (s ADSREnvelope) MaxX() x {
	return s.end
}
<commit_msg>dont return interface<commit_after>package signals

import "encoding/gob"

func init() {
	gob.Register(ADSREnvelope{})
}

//  Attack Decay Sustain Release (ADSR) envelope.  see https://en.wikipedia.org/wiki/Synthesizer#Attack_Decay_Sustain_Release_.28ADSR.29_envelope
type ADSREnvelope struct {
	attackEnd    x
	attackSlope  y
	decaySlope   y
	sustainStart x
	sustain      y
	sustainEnd   x
	releaseSlope y
	end          x
}

func NewADSREnvelope(attack, decay, sustain x, sustainy y, release x) ADSREnvelope {
	// TODO release attack or decay of zero!
	return ADSREnvelope{attack, Maxy / y(attack), (Maxy - sustainy) / y(decay), attack + decay, sustainy, attack + decay + sustain, sustainy / y(release), attack + decay + sustain + release}
}

func (s ADSREnvelope) Call(t x) y {
	if t > s.end {
		return 0
	} else if t > s.sustainEnd {
		return y(s.end-t) * s.releaseSlope
	} else if t > s.sustainStart {
		return s.sustain
	} else if t > s.attackEnd {
		return y(s.sustainStart-t)*s.decaySlope + s.sustain
	} else if t > 0 {
		return y(t) * s.attackSlope
	} else {
		return 0
	}
}

func (s ADSREnvelope) MaxX() x {
	return s.end
}
<|endoftext|>


<commit_before>// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
// at http://cyan4973.github.io/xxHash/.
package xxhash

import (
	"encoding/binary"
	"hash"
)

// TODO: Implement custom seed

// NOTE(caleb): These are vars instead of consts to make them easier to use with
// intentional overflow without having to realize them as vars first.
var (
	prime1 uint64 = 11400714785074694791
	prime2 uint64 = 14029467366897019727
	prime3 uint64 = 1609587929392839161
	prime4 uint64 = 9650029242287828579
	prime5 uint64 = 2870177450012600261
)

type xxh struct {
	total int
	v1    uint64
	v2    uint64
	v3    uint64
	v4    uint64
	mem   [32]byte
	n     int // how much of mem is used
}

// Sum64 computes the 64-bit xxHash digest of b.
func Sum64(b []byte) uint64 {
	// A simpler version would be
	//   x := New()
	//   x.Write(b)
	//   return x.Sum64()
	// but this is faster, particularly for small inputs.

	n := len(b)
	var h uint64

	if n >= 32 {
		v1 := prime1 + prime2
		v2 := prime2
		v3 := uint64(0)
		v4 := -prime1
		for len(b) >= 32 {
			v1 = round(v1, u64(b[0:8]))
			v2 = round(v2, u64(b[8:16]))
			v3 = round(v3, u64(b[16:24]))
			v4 = round(v4, u64(b[24:32]))
			b = b[32:]
		}
		h = rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = prime5
	}

	h += uint64(n)

	i, end := 0, len(b)
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(b[i:i+8]))
		h ^= k1
		h = rotl(h, 27)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(b[i:i+4])) * prime1
		h = rotl(h, 23)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(b[i]) * prime5
		h = rotl(h, 11) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h

}

// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm.
func New() hash.Hash64 {
	var x xxh
	x.Reset()
	return &x
}

func (x *xxh) Reset() {
	x.n = 0
	x.total = 0
	x.v1 = prime1 + prime2
	x.v2 = prime2
	x.v3 = 0
	x.v4 = -prime1
}

func (x *xxh) Size() int      { return 8 }
func (x *xxh) BlockSize() int { return 32 }

// Write adds more data to x. It always returns len(b), nil.
func (x *xxh) Write(b []byte) (n int, err error) {
	n = len(b)
	x.total += len(b)

	if x.n+len(b) < 32 {
		// This new data doesn't even fill the current block.
		copy(x.mem[x.n:], b)
		x.n += len(b)
		return
	}

	if x.n > 0 {
		// Finish off the partial block.
		copy(x.mem[x.n:], b)
		x.v1 = round(x.v1, u64(x.mem[0:8]))
		x.v2 = round(x.v2, u64(x.mem[8:16]))
		x.v3 = round(x.v3, u64(x.mem[16:24]))
		x.v4 = round(x.v4, u64(x.mem[24:32]))
		b = b[32-x.n:]
		x.n = 0
	}

	if len(b) >= 32 {
		// One or more full blocks left.
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		for len(b) >= 32 {
			v1 = round(v1, u64(b[0:8]))
			v2 = round(v2, u64(b[8:16]))
			v3 = round(v3, u64(b[16:24]))
			v4 = round(v4, u64(b[24:32]))
			b = b[32:]
		}
		x.v1, x.v2, x.v3, x.v4 = v1, v2, v3, v4
	}

	// Store any remaining partial block.
	copy(x.mem[:], b)
	x.n = len(b)

	return
}

func (x *xxh) Sum(b []byte) []byte {
	s := x.Sum64()
	return append(
		b,
		byte(s>>56),
		byte(s>>48),
		byte(s>>40),
		byte(s>>32),
		byte(s>>24),
		byte(s>>16),
		byte(s>>8),
		byte(s),
	)
}

func (x *xxh) Sum64() uint64 {
	var h uint64

	if x.total >= 32 {
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		h = rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = x.v3 + prime5
	}

	h += uint64(x.total)

	i, end := 0, x.n
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(x.mem[i:i+8]))
		h ^= k1
		h = rotl(h, 27)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(x.mem[i:i+4])) * prime1
		h = rotl(h, 23)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(x.mem[i]) * prime5
		h = rotl(h, 11) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h
}

func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }

func round(acc, input uint64) uint64 {
	acc += input * prime2
	acc = rotl(acc, 31)
	acc *= prime1
	return acc
}

func mergeRound(acc, val uint64) uint64 {
	val = round(0, val)
	acc ^= val
	acc = acc*prime1 + prime4
	return acc
}

func rotl(x, r uint64) uint64 { return (x << r) | (x >> (64 - r)) }
<commit_msg>Coerce the compiler to elide some bounds checks<commit_after>// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
// at http://cyan4973.github.io/xxHash/.
package xxhash

import (
	"encoding/binary"
	"hash"
)

// TODO: Implement custom seed

// NOTE(caleb): These are vars instead of consts to make them easier to use with
// intentional overflow without having to realize them as vars first.
var (
	prime1 uint64 = 11400714785074694791
	prime2 uint64 = 14029467366897019727
	prime3 uint64 = 1609587929392839161
	prime4 uint64 = 9650029242287828579
	prime5 uint64 = 2870177450012600261
)

type xxh struct {
	total int
	v1    uint64
	v2    uint64
	v3    uint64
	v4    uint64
	mem   [32]byte
	n     int // how much of mem is used
}

// Sum64 computes the 64-bit xxHash digest of b.
func Sum64(b []byte) uint64 {
	// A simpler version would be
	//   x := New()
	//   x.Write(b)
	//   return x.Sum64()
	// but this is faster, particularly for small inputs.

	n := len(b)
	var h uint64

	if n >= 32 {
		v1 := prime1 + prime2
		v2 := prime2
		v3 := uint64(0)
		v4 := -prime1
		for len(b) >= 32 {
			v1 = round(v1, u64(b[0:8:len(b)]))
			v2 = round(v2, u64(b[8:16:len(b)]))
			v3 = round(v3, u64(b[16:24:len(b)]))
			v4 = round(v4, u64(b[24:32:len(b)]))
			b = b[32:len(b):len(b)]
		}
		h = rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = prime5
	}

	h += uint64(n)

	i, end := 0, len(b)
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(b[i:i+8:len(b)]))
		h ^= k1
		h = rotl(h, 27)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
		h = rotl(h, 23)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(b[i]) * prime5
		h = rotl(h, 11) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h

}

// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm.
func New() hash.Hash64 {
	var x xxh
	x.Reset()
	return &x
}

func (x *xxh) Reset() {
	x.n = 0
	x.total = 0
	x.v1 = prime1 + prime2
	x.v2 = prime2
	x.v3 = 0
	x.v4 = -prime1
}

func (x *xxh) Size() int      { return 8 }
func (x *xxh) BlockSize() int { return 32 }

// Write adds more data to x. It always returns len(b), nil.
func (x *xxh) Write(b []byte) (n int, err error) {
	n = len(b)
	x.total += len(b)

	if x.n+len(b) < 32 {
		// This new data doesn't even fill the current block.
		copy(x.mem[x.n:], b)
		x.n += len(b)
		return
	}

	if x.n > 0 {
		// Finish off the partial block.
		copy(x.mem[x.n:], b)
		x.v1 = round(x.v1, u64(x.mem[0:8]))
		x.v2 = round(x.v2, u64(x.mem[8:16]))
		x.v3 = round(x.v3, u64(x.mem[16:24]))
		x.v4 = round(x.v4, u64(x.mem[24:32]))
		b = b[32-x.n:]
		x.n = 0
	}

	if len(b) >= 32 {
		// One or more full blocks left.
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		for len(b) >= 32 {
			v1 = round(v1, u64(b[0:8:len(b)]))
			v2 = round(v2, u64(b[8:16:len(b)]))
			v3 = round(v3, u64(b[16:24:len(b)]))
			v4 = round(v4, u64(b[24:32:len(b)]))
			b = b[32:len(b):len(b)]
		}
		x.v1, x.v2, x.v3, x.v4 = v1, v2, v3, v4
	}

	// Store any remaining partial block.
	copy(x.mem[:], b)
	x.n = len(b)

	return
}

func (x *xxh) Sum(b []byte) []byte {
	s := x.Sum64()
	return append(
		b,
		byte(s>>56),
		byte(s>>48),
		byte(s>>40),
		byte(s>>32),
		byte(s>>24),
		byte(s>>16),
		byte(s>>8),
		byte(s),
	)
}

func (x *xxh) Sum64() uint64 {
	var h uint64

	if x.total >= 32 {
		v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
		h = rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18)
		h = mergeRound(h, v1)
		h = mergeRound(h, v2)
		h = mergeRound(h, v3)
		h = mergeRound(h, v4)
	} else {
		h = x.v3 + prime5
	}

	h += uint64(x.total)

	i, end := 0, x.n
	for ; i+8 <= end; i += 8 {
		k1 := round(0, u64(x.mem[i:i+8]))
		h ^= k1
		h = rotl(h, 27)*prime1 + prime4
	}
	if i+4 <= end {
		h ^= uint64(u32(x.mem[i:i+4])) * prime1
		h = rotl(h, 23)*prime2 + prime3
		i += 4
	}
	for i < end {
		h ^= uint64(x.mem[i]) * prime5
		h = rotl(h, 11) * prime1
		i++
	}

	h ^= h >> 33
	h *= prime2
	h ^= h >> 29
	h *= prime3
	h ^= h >> 32

	return h
}

func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }

func round(acc, input uint64) uint64 {
	acc += input * prime2
	acc = rotl(acc, 31)
	acc *= prime1
	return acc
}

func mergeRound(acc, val uint64) uint64 {
	val = round(0, val)
	acc ^= val
	acc = acc*prime1 + prime4
	return acc
}

func rotl(x, r uint64) uint64 { return (x << r) | (x >> (64 - r)) }
<|endoftext|>


<commit_before>package monotime

import (
	"time"
)

type Elapsed struct {
	t0 Time
	x0 int64
}

func NewElapsed() *Elapsed {
	return &Elapsed{Now(), time.Now().UnixNano()}
}

func (t Elapsed) Current() time.Duration {
	n := int64(Now() - t.t0)
	x := time.Now().UnixNano() - t.x0
	if x-2000000000 < n || x+2000000000 > n {
		return time.Duration(n)
	}
	return time.Duration(x)
}
<commit_msg>Fix Elapsed<commit_after>package monotime

import (
	"time"
)

type Elapsed struct {
	t0 Time
	x0 int64
}

func NewElapsed() *Elapsed {
	return &Elapsed{Now(), time.Now().UnixNano()}
}

func (t Elapsed) Current() time.Duration {
	n := int64(Now() - t.t0)
	x := time.Now().UnixNano() - t.x0
	if x-2000000000 > n || x+2000000000 < n {
		return time.Duration(n)
	}
	return time.Duration(x)
}
<|endoftext|>


<commit_before>// Package palette summarizes the colors of a website.
package palette

import (
	"github.com/lucasb-eyer/go-colorful"
	"github.com/nochso/colourl/css"
	"github.com/nochso/colourl/page"
	"sort"
)

type ColorScore struct {
	Score int
	Color *colorful.Color
}

// Palette is a list of Colors sorted by score.
// The score is calculated by anything that implements the palette.Score interface.
type Palette []*ColorScore

// Trim returns a new Palette with max amount of colors.
// Boring colors are ignored if possible.
func (p Palette) Trim(max int) Palette {
	white, _ := colorful.Hex("#ffffff")
	black, _ := colorful.Hex("#000000")
	count := len(p)
	max = minInt(max, count)
	scores := make([]*ColorScore, max)
	scoreCount := 0
	for i, c := range p {
		if scoreCount == max {
			break
		}
		if count-i > max-scoreCount {
			// Ignore gray/low saturation
			_, s, _ := c.Color.Hsv()
			if s < 0.1 {
				continue
			}
			// Ignore almost white or black
			if c.Color.DistanceCIE76(white) <= 0.05 || c.Color.DistanceCIE76(black) <= 0.05 {
				continue
			}
		}
		scores[scoreCount] = c
		scoreCount++
	}
	return scores
}

func minInt(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func (p Palette) Len() int      { return len(p) }
func (p Palette) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Palette) Less(i, j int) bool {
	// Sort identical scores by color to make it deterministic
	if p[i].Score == p[j].Score {
		return p[i].Color.Hex() > p[j].Color.Hex()
	}
	return p[i].Score >= p[j].Score
}

var _ sort.Interface = (*Palette)(nil)

// New creates a Palette from a websites CSS colors.
// Colors are sorted by their score.
func New(url string, scorer Scorer) (Palette, error) {
	pg, err := page.New(url)
	if err != nil {
		return nil, err
	}
	cml, err := css.ParsePage(pg)
	if err != nil {
		return nil, err
	}
	return Group(cml, scorer), nil
}

// Group a CML (ColorMention list) as a Palette.
// Mentions are grouped by color and scored with the specified Scorer implementation.
// If scorer is nil, it will fall back on palette.SumScore
func Group(cml *css.CML, scorer Scorer) Palette {
	pal := Palette{}
	if scorer == nil {
		scorer = &SumScore{}
	}
	// Map hex color to index in Palette
	keys := map[string]int{}
	for _, cm := range cml.Mentions {
		score := scorer.Score(cml, cm)
		k, ok := keys[cm.Color.Hex()]
		if ok { // Add score to known color
			pal[k].Score += score
		} else { // Append new ColorScore and remember its position by color
			cs := &ColorScore{score, cm.Color}
			pal = append(pal, cs)
			keys[cm.Color.Hex()] = len(pal) - 1
		}
	}
	sort.Sort(pal)
	return pal
}
<commit_msg>Add Palette.ScoreSum()<commit_after>// Package palette summarizes the colors of a website.
package palette

import (
	"github.com/lucasb-eyer/go-colorful"
	"github.com/nochso/colourl/css"
	"github.com/nochso/colourl/page"
	"sort"
)

type ColorScore struct {
	Score int
	Color *colorful.Color
}

// Palette is a list of Colors sorted by score.
// The score is calculated by anything that implements the palette.Score interface.
type Palette []*ColorScore

// Trim returns a new Palette with max amount of colors.
// Boring colors are ignored if possible.
func (p Palette) Trim(max int) Palette {
	white, _ := colorful.Hex("#ffffff")
	black, _ := colorful.Hex("#000000")
	count := len(p)
	max = minInt(max, count)
	scores := make([]*ColorScore, max)
	scoreCount := 0
	for i, c := range p {
		if scoreCount == max {
			break
		}
		if count-i > max-scoreCount {
			// Ignore gray/low saturation
			_, s, _ := c.Color.Hsv()
			if s < 0.1 {
				continue
			}
			// Ignore almost white or black
			if c.Color.DistanceCIE76(white) <= 0.05 || c.Color.DistanceCIE76(black) <= 0.05 {
				continue
			}
		}
		scores[scoreCount] = c
		scoreCount++
	}
	return scores
}

func minInt(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// ScoreSum returns the sum of the score of all ColorScores.
func (p Palette) ScoreSum() int {
	sum := 0
	for _, cs := range p {
		sum += cs.Score
	}
	return sum
}

func (p Palette) Len() int      { return len(p) }
func (p Palette) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Palette) Less(i, j int) bool {
	// Sort identical scores by color to make it deterministic
	if p[i].Score == p[j].Score {
		return p[i].Color.Hex() > p[j].Color.Hex()
	}
	return p[i].Score >= p[j].Score
}

var _ sort.Interface = (*Palette)(nil)

// New creates a Palette from a websites CSS colors.
// Colors are sorted by their score.
func New(url string, scorer Scorer) (Palette, error) {
	pg, err := page.New(url)
	if err != nil {
		return nil, err
	}
	cml, err := css.ParsePage(pg)
	if err != nil {
		return nil, err
	}
	return Group(cml, scorer), nil
}

// Group a CML (ColorMention list) as a Palette.
// Mentions are grouped by color and scored with the specified Scorer implementation.
// If scorer is nil, it will fall back on palette.SumScore
func Group(cml *css.CML, scorer Scorer) Palette {
	pal := Palette{}
	if scorer == nil {
		scorer = &SumScore{}
	}
	// Map hex color to index in Palette
	keys := map[string]int{}
	for _, cm := range cml.Mentions {
		score := scorer.Score(cml, cm)
		k, ok := keys[cm.Color.Hex()]
		if ok { // Add score to known color
			pal[k].Score += score
		} else { // Append new ColorScore and remember its position by color
			cs := &ColorScore{score, cm.Color}
			pal = append(pal, cs)
			keys[cm.Color.Hex()] = len(pal) - 1
		}
	}
	sort.Sort(pal)
	return pal
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"regexp"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/codeartifact"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccAWSCodeArtifactDomainPermissionsPolicy_basic(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyUpdatedConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:ListRepositoriesInDomain")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_owner(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyOwnerConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_disappears(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsCodeArtifactDomainPermissionsPolicy(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_disappears_domain(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsCodeArtifactDomain(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSCodeArtifactDomainPermissionsExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("no CodeArtifact domain set")
		}

		conn := testAccProvider.Meta().(*AWSClient).codeartifactconn

		domainOwner, domainName, err := decodeCodeArtifactDomainID(rs.Primary.ID)
		if err != nil {
			return err
		}

		_, err = conn.GetDomainPermissionsPolicy(&codeartifact.GetDomainPermissionsPolicyInput{
			Domain:      aws.String(domainName),
			DomainOwner: aws.String(domainOwner),
		})

		return err
	}
}

func testAccCheckAWSCodeArtifactDomainPermissionsDestroy(s *terraform.State) error {
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_codeartifact_domain_permissions_policy" {
			continue
		}

		conn := testAccProvider.Meta().(*AWSClient).codeartifactconn

		domainOwner, domainName, err := decodeCodeArtifactDomainID(rs.Primary.ID)
		if err != nil {
			return err
		}

		resp, err := conn.GetDomainPermissionsPolicy(&codeartifact.GetDomainPermissionsPolicyInput{
			Domain:      aws.String(domainName),
			DomainOwner: aws.String(domainOwner),
		})

		if err == nil {
			if aws.StringValue(resp.Policy.ResourceArn) == rs.Primary.ID {
				return fmt.Errorf("CodeArtifact Domain %s still exists", rs.Primary.ID)
			}
		}

		if isAWSErr(err, codeartifact.ErrCodeResourceNotFoundException, "") {
			return nil
		}

		return err
	}

	return nil
}

func testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "codeartifact:CreateRepository",
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}

func testAccAWSCodeArtifactDomainPermissionsPolicyOwnerConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  domain_owner    = aws_codeartifact_domain.test.owner
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "codeartifact:CreateRepository",
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}

func testAccAWSCodeArtifactDomainPermissionsPolicyUpdatedConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
 				"codeartifact:CreateRepository",
				"codeartifact:ListRepositoriesInDomain"
			],
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}
<commit_msg>test lint<commit_after>package aws

import (
	"fmt"
	"regexp"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/codeartifact"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccAWSCodeArtifactDomainPermissionsPolicy_basic(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyUpdatedConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:ListRepositoriesInDomain")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_owner(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyOwnerConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_codeartifact_domain.test", "arn"),
					resource.TestCheckResourceAttr(resourceName, "domain", rName),
					resource.TestMatchResourceAttr(resourceName, "policy_document", regexp.MustCompile("codeartifact:CreateRepository")),
					resource.TestCheckResourceAttrPair(resourceName, "domain_owner", "aws_codeartifact_domain.test", "owner"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_disappears(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsCodeArtifactDomainPermissionsPolicy(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func TestAccAWSCodeArtifactDomainPermissionsPolicy_disappears_domain(t *testing.T) {
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_codeartifact_domain_permissions_policy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeArtifactDomainPermissionsDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeArtifactDomainPermissionsExists(resourceName),
					testAccCheckResourceDisappears(testAccProvider, resourceAwsCodeArtifactDomain(), resourceName),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckAWSCodeArtifactDomainPermissionsExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("no CodeArtifact domain set")
		}

		conn := testAccProvider.Meta().(*AWSClient).codeartifactconn

		domainOwner, domainName, err := decodeCodeArtifactDomainID(rs.Primary.ID)
		if err != nil {
			return err
		}

		_, err = conn.GetDomainPermissionsPolicy(&codeartifact.GetDomainPermissionsPolicyInput{
			Domain:      aws.String(domainName),
			DomainOwner: aws.String(domainOwner),
		})

		return err
	}
}

func testAccCheckAWSCodeArtifactDomainPermissionsDestroy(s *terraform.State) error {
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_codeartifact_domain_permissions_policy" {
			continue
		}

		conn := testAccProvider.Meta().(*AWSClient).codeartifactconn

		domainOwner, domainName, err := decodeCodeArtifactDomainID(rs.Primary.ID)
		if err != nil {
			return err
		}

		resp, err := conn.GetDomainPermissionsPolicy(&codeartifact.GetDomainPermissionsPolicyInput{
			Domain:      aws.String(domainName),
			DomainOwner: aws.String(domainOwner),
		})

		if err == nil {
			if aws.StringValue(resp.Policy.ResourceArn) == rs.Primary.ID {
				return fmt.Errorf("CodeArtifact Domain %s still exists", rs.Primary.ID)
			}
		}

		if isAWSErr(err, codeartifact.ErrCodeResourceNotFoundException, "") {
			return nil
		}

		return err
	}

	return nil
}

func testAccAWSCodeArtifactDomainPermissionsPolicyBasicConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description             = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "codeartifact:CreateRepository",
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}

func testAccAWSCodeArtifactDomainPermissionsPolicyOwnerConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description             = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  domain_owner    = aws_codeartifact_domain.test.owner
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "codeartifact:CreateRepository",
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}

func testAccAWSCodeArtifactDomainPermissionsPolicyUpdatedConfig(rName string) string {
	return fmt.Sprintf(`
resource "aws_kms_key" "test" {
  description             = %[1]q
  deletion_window_in_days = 7
}

resource "aws_codeartifact_domain" "test" {
  domain         = %[1]q
  encryption_key = aws_kms_key.test.arn
}

resource "aws_codeartifact_domain_permissions_policy" "test" {
  domain          = aws_codeartifact_domain.test.domain
  policy_document = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
 				"codeartifact:CreateRepository",
				"codeartifact:ListRepositoriesInDomain"
			],
            "Effect": "Allow",
            "Principal": "*",
            "Resource": "${aws_codeartifact_domain.test.arn}"
        }
    ]
}
EOF
}
`, rName)
}
<|endoftext|>


<commit_before>// rand2 is a collection of functions meant to supplement the capabilities
// provided by the standard "math/rand" package.
package rand2

import (
	"math/rand"
	"os"
	"sort"
	"sync"
	"time"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
)

type lockedSource struct {
	mutex sync.Mutex
	src   rand.Source
}

func (r *lockedSource) Int63() int64 {
	r.mutex.Lock()
	val := r.src.Int63()
	r.mutex.Unlock()
	return val
}

func (r *lockedSource) Seed(seed int64) {
	r.mutex.Lock()
	r.src.Seed(seed)
	r.mutex.Unlock()
}

// This returns a thread-safe random source.
func NewSource(seed int64) rand.Source {
	return &lockedSource{
		src: rand.NewSource(seed),
	}
}

// This returns a new Rand.  See rand.New for documentation.
func New(src rand.Source) *rand.Rand {
	return rand.New(src)
}

var globalRand *rand.Rand

func init() {
	now := time.Now()
	seed := now.Unix() + int64(now.Nanosecond()) + 12345*int64(os.Getpid())
	globalRand = New(NewSource(seed))
}

// See rand for documentation.
func Seed(seed int64) { globalRand.Seed(seed) }

// See rand for documentation.
func Int63() int64 { return globalRand.Int63() }

// See rand for documentation.
func Uint32() uint32 { return globalRand.Uint32() }

// See rand for documentation.
func Int31() int32 { return globalRand.Int31() }

// See rand for documentation.
func Int() int { return globalRand.Int() }

// See rand for documentation.
func Int63n(n int64) int64 { return globalRand.Int63n(n) }

// See rand for documentation.
func Int31n(n int32) int32 { return globalRand.Int31n(n) }

// See rand for documentation.
func Intn(n int) int { return globalRand.Intn(n) }

// See rand for documentation.
func Float64() float64 { return globalRand.Float64() }

// See rand for documentation.
func Float32() float32 { return globalRand.Float32() }

// See rand for documentation.
func Perm(n int) []int { return globalRand.Perm(n) }

// See rand for documentation.
func NormFloat64() float64 { return globalRand.NormFloat64() }

// See rand for documentation.
func ExpFloat64() float64 { return globalRand.ExpFloat64() }

// Samples 'k' unique ints from the range [0, n)
func SampleInts(n int, k int) (res []int, err error) {
	if k < 0 {
		err = errors.Newf("invalid sample size k")
		return
	}

	if n < k {
		err = errors.Newf("sample size k larger than n")
		return
	}

	picked := set.NewSet()
	for picked.Len() < k {
		i := Intn(n)
		picked.Add(i)
	}

	res = make([]int, k)
	e := 0
	for i := range picked.Iter() {
		res[e] = i.(int)
		e++
	}

	return
}

// Samples 'k' elements from the given slice
func Sample(population []interface{}, k int) (res []interface{}, err error) {
	n := len(population)
	idxs, err := SampleInts(n, k)
	if err != nil {
		return
	}

	res = []interface{}{}
	for _, idx := range idxs {
		res = append(res, population[idx])
	}

	return
}

// Same as 'Sample' except it returns both the 'picked' sample set and the 'remaining' elements.
func PickN(population []interface{}, n int) (
	picked []interface{}, remaining []interface{}, err error) {

	total := len(population)
	idxs, err := SampleInts(total, n)
	if err != nil {
		return
	}
	sort.Ints(idxs)

	picked, remaining = []interface{}{}, []interface{}{}
	for x, elem := range population {
		if len(idxs) > 0 && x == idxs[0] {
			picked = append(picked, elem)
			idxs = idxs[1:]
		} else {
			remaining = append(remaining, elem)
		}
	}

	return
}
<commit_msg>update comment<commit_after>// rand2 is a drop-in replacement for the "math/rand" package.  It initializes
// the global random generator with a random seed (instead of 1), and provides
// additional functionality over the standard "math/rand" package.
package rand2

import (
	"math/rand"
	"os"
	"sort"
	"sync"
	"time"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
)

type lockedSource struct {
	mutex sync.Mutex
	src   rand.Source
}

func (r *lockedSource) Int63() int64 {
	r.mutex.Lock()
	val := r.src.Int63()
	r.mutex.Unlock()
	return val
}

func (r *lockedSource) Seed(seed int64) {
	r.mutex.Lock()
	r.src.Seed(seed)
	r.mutex.Unlock()
}

// This returns a thread-safe random source.
func NewSource(seed int64) rand.Source {
	return &lockedSource{
		src: rand.NewSource(seed),
	}
}

// This returns a new Rand.  See math/rand for documentation.
func New(src rand.Source) *rand.Rand {
	return rand.New(src)
}

var globalRand *rand.Rand

func init() {
	now := time.Now()
	seed := now.Unix() + int64(now.Nanosecond()) + 12345*int64(os.Getpid())
	globalRand = New(NewSource(seed))
}

// See math/rand for documentation.
func Seed(seed int64) { globalRand.Seed(seed) }

// See math/rand for documentation.
func Int63() int64 { return globalRand.Int63() }

// See math/rand for documentation.
func Uint32() uint32 { return globalRand.Uint32() }

// See math/rand for documentation.
func Int31() int32 { return globalRand.Int31() }

// See math/rand for documentation.
func Int() int { return globalRand.Int() }

// See math/rand for documentation.
func Int63n(n int64) int64 { return globalRand.Int63n(n) }

// See math/rand for documentation.
func Int31n(n int32) int32 { return globalRand.Int31n(n) }

// See math/rand for documentation.
func Intn(n int) int { return globalRand.Intn(n) }

// See math/rand for documentation.
func Float64() float64 { return globalRand.Float64() }

// See math/rand for documentation.
func Float32() float32 { return globalRand.Float32() }

// See math/rand for documentation.
func Perm(n int) []int { return globalRand.Perm(n) }

// See math/rand for documentation.
func NormFloat64() float64 { return globalRand.NormFloat64() }

// See math/rand for documentation.
func ExpFloat64() float64 { return globalRand.ExpFloat64() }

// Samples 'k' unique ints from the range [0, n)
func SampleInts(n int, k int) (res []int, err error) {
	if k < 0 {
		err = errors.Newf("invalid sample size k")
		return
	}

	if n < k {
		err = errors.Newf("sample size k larger than n")
		return
	}

	picked := set.NewSet()
	for picked.Len() < k {
		i := Intn(n)
		picked.Add(i)
	}

	res = make([]int, k)
	e := 0
	for i := range picked.Iter() {
		res[e] = i.(int)
		e++
	}

	return
}

// Samples 'k' elements from the given slice
func Sample(population []interface{}, k int) (res []interface{}, err error) {
	n := len(population)
	idxs, err := SampleInts(n, k)
	if err != nil {
		return
	}

	res = []interface{}{}
	for _, idx := range idxs {
		res = append(res, population[idx])
	}

	return
}

// Same as 'Sample' except it returns both the 'picked' sample set and the 'remaining' elements.
func PickN(population []interface{}, n int) (
	picked []interface{}, remaining []interface{}, err error) {

	total := len(population)
	idxs, err := SampleInts(total, n)
	if err != nil {
		return
	}
	sort.Ints(idxs)

	picked, remaining = []interface{}{}, []interface{}{}
	for x, elem := range population {
		if len(idxs) > 0 && x == idxs[0] {
			picked = append(picked, elem)
			idxs = idxs[1:]
		} else {
			remaining = append(remaining, elem)
		}
	}

	return
}
<|endoftext|>


<commit_before>package putio

import "fmt"

// File represents a Put.io file.
type File struct {
	ID                int64  `json:"id"`
	Name              string `json:"name"`
	Size              int64  `json:"size"`
	ContentType       string `json:"content_type"`
	CreatedAt         *Time  `json:"created_at"`
	FirstAccessedAt   *Time  `json:"first_accessed_at"`
	ParentID          int64  `json:"parent_id"`
	Screenshot        string `json:"screenshot"`
	OpensubtitlesHash string `json:"opensubtitles_hash"`
	IsMP4Available    bool   `json:"is_mp4_available"`
	Icon              string `json:"icon"`
	CRC32             string `json:"crc32"`
	IsShared          bool   `json:"is_shared"`
}

func (f *File) String() string {
	return fmt.Sprintf("<ID: %v Name: %q Size: %v>", f.ID, f.Name, f.Size)
}

// IsDir reports whether the file is a directory.
func (f *File) IsDir() bool {
	return f.ContentType == "application/x-directory"
}

// Upload represents a Put.io upload. If the uploaded file is a torrent file,
// Transfer field will represent the status of the transfer.
type Upload struct {
	File     *File     `json:"file"`
	Transfer *Transfer `json:"transfer"`
}

// Search represents a search response.
type Search struct {
	Files []File `json:"files"`
	Next  string `json:"next"`
}

// Transfer represents a Put.io transfer state.
type Transfer struct {
	Availability   int    `json:"availability"`
	CallbackURL    string `json:"callback_url"`
	CreatedAt      *Time  `json:"created_at"`
	CreatedTorrent bool   `json:"created_torrent"`
	ClientIP       string `json:"client_ip"`

	// FIXME: API returns either string or float non-deterministically.
	// CurrentRatio       float32 `json:"current_ratio"`

	DownloadSpeed      int    `json:"down_speed"`
	Downloaded         int64  `json:"downloaded"`
	DownloadID         int64  `json:"download_id"`
	ErrorMessage       string `json:"error_message"`
	EstimatedTime      int64  `json:"estimated_time"`
	Extract            bool   `json:"extract"`
	FileID             int64  `json:"file_id"`
	FinishedAt         *Time  `json:"finished_at"`
	ID                 int64  `json:"id"`
	IsPrivate          bool   `json:"is_private"`
	MagnetURI          string `json:"magneturi"`
	Name               string `json:"name"`
	PeersConnected     int    `json:"peers_connected"`
	PeersGettingFromUs int    `json:"peers_getting_from_us"`
	PeersSendingToUs   int    `json:"peers_sending_to_us"`
	PercentDone        int    `json:"percent_done"`
	SaveParentID       int64  `json:"save_parent_id"`
	SecondsSeeding     int    `json:"seconds_seeding"`
	Size               int    `json:"size"`
	Source             string `json:"source"`
	Status             string `json:"status"`
	StatusMessage      string `json:"status_message"`
	SubscriptionID     int    `json:"subscription_id"`
	TorrentLink        string `json:"torrent_link"`
	TrackerMessage     string `json:"tracker_message"`
	Trackers           string `json:"tracker"`
	Type               string `json:"type"`
	UploadSpeed        int    `json:"up_speed"`
	Uploaded           int64  `json:"uploaded"`
}

// AccountInfo represents user's account information.
type AccountInfo struct {
	AccountActive           bool   `json:"account_active"`
	AvatarURL               string `json:"avatar_url"`
	DaysUntilFilesDeletion  int    `json:"days_until_files_deletion"`
	DefaultSubtitleLanguage string `json:"default_subtitle_language"`
	Disk                    struct {
		Avail int64 `json:"avail"`
		Size  int64 `json:"size"`
		Used  int64 `json:"used"`
	} `json:"disk"`
	HasVoucher                int      `json:"has_voucher"`
	Mail                      string   `json:"mail"`
	PlanExpirationDate        string   `json:"plan_expiration_date"`
	Settings                  Settings `json:"settings"`
	SimultaneousDownloadLimit int      `json:"simultaneous_download_limit"`
	SubtitleLanguages         []string `json:"subtitle_languages"`
	UserID                    int64    `json:"user_id"`
	Username                  string   `json:"username"`
}

// Settings represents user's personal settings.
type Settings struct {
	CallbackURL             string      `json:"callback_url"`
	DefaultDownloadFolder   int64       `json:"default_download_folder"`
	DefaultSubtitleLanguage string      `json:"default_subtitle_language"`
	DownloadFolderUnset     bool        `json:"download_folder_unset"`
	IsInvisible             bool        `json:"is_invisible"`
	Nextepisode             bool        `json:"nextepisode"`
	PrivateDownloadHostIP   interface{} `json:"private_download_host_ip"`
	PushoverToken           string      `json:"pushover_token"`
	Routing                 string      `json:"routing"`
	Sorting                 string      `json:"sorting"`
	SSLEnabled              bool        `json:"ssl_enabled"`
	StartFrom               bool        `json:"start_from"`
	SubtitleLanguages       []string    `json:"subtitle_languages"`
}

// Friend represents Put.io user's friend.
type Friend struct {
	ID        int64  `json:"id"`
	Name      string `json:"name"`
	AvatarURL string `json:"avatar_url"`
}

// Zip represents Put.io zip file.
type Zip struct {
	ID        int64 `json:"id"`
	CreatedAt *Time `json:"created_at"`

	Size   int64  `json:"size"`
	Status string `json:"status"`
	URL    string `json:"url"`

	// FIXME: missing_files field is missin
	missingFiles string
}

// Subtitle represents a subtitle.
type Subtitle struct {
	Key      string
	Language string
	Name     string
	Source   string
}

// Event represents a Put.io event. It could be a transfer or a shared file.
type Event struct {
	ID           int64  `json:"id"`
	FileID       int64  `json:"file_id"`
	Source       string `json:"source"`
	Type         string `json:"type"`
	TransferName string `json:"transfer_name"`
	TransferSize int64  `json:"transfer_size"`
	CreatedAt    *Time  `json:"created_at"`
}

type share struct {
	FileID   int64  `json:"file_id"`
	Filename string `json:"file_name"`
	// Number of friends the file is shared with
	SharedWith int64 `json:"shared_with"`
}

// errorResponse represents a common error message that Put.io v2 API sends on
// error.
type errorResponse struct {
	ErrorMessage string `json:"error_message"`
	ErrorType    string `json:"error_type"`
	ErrorURI     string `json:"error_uri"`
	Status       string `json:"status"`
	StatusCode   int    `json:"status_code"`
}

func (e errorResponse) Error() string {
	return fmt.Sprintf("StatusCode: %v ErrorType: %v ErrorMsg: %v", e.StatusCode, e.ErrorType, e.ErrorMessage)
}
<commit_msg>Fix incorrect type for HasVoucher<commit_after>package putio

import "fmt"

// File represents a Put.io file.
type File struct {
	ID                int64  `json:"id"`
	Name              string `json:"name"`
	Size              int64  `json:"size"`
	ContentType       string `json:"content_type"`
	CreatedAt         *Time  `json:"created_at"`
	FirstAccessedAt   *Time  `json:"first_accessed_at"`
	ParentID          int64  `json:"parent_id"`
	Screenshot        string `json:"screenshot"`
	OpensubtitlesHash string `json:"opensubtitles_hash"`
	IsMP4Available    bool   `json:"is_mp4_available"`
	Icon              string `json:"icon"`
	CRC32             string `json:"crc32"`
	IsShared          bool   `json:"is_shared"`
}

func (f *File) String() string {
	return fmt.Sprintf("<ID: %v Name: %q Size: %v>", f.ID, f.Name, f.Size)
}

// IsDir reports whether the file is a directory.
func (f *File) IsDir() bool {
	return f.ContentType == "application/x-directory"
}

// Upload represents a Put.io upload. If the uploaded file is a torrent file,
// Transfer field will represent the status of the transfer.
type Upload struct {
	File     *File     `json:"file"`
	Transfer *Transfer `json:"transfer"`
}

// Search represents a search response.
type Search struct {
	Files []File `json:"files"`
	Next  string `json:"next"`
}

// Transfer represents a Put.io transfer state.
type Transfer struct {
	Availability   int    `json:"availability"`
	CallbackURL    string `json:"callback_url"`
	CreatedAt      *Time  `json:"created_at"`
	CreatedTorrent bool   `json:"created_torrent"`
	ClientIP       string `json:"client_ip"`

	// FIXME: API returns either string or float non-deterministically.
	// CurrentRatio       float32 `json:"current_ratio"`

	DownloadSpeed      int    `json:"down_speed"`
	Downloaded         int64  `json:"downloaded"`
	DownloadID         int64  `json:"download_id"`
	ErrorMessage       string `json:"error_message"`
	EstimatedTime      int64  `json:"estimated_time"`
	Extract            bool   `json:"extract"`
	FileID             int64  `json:"file_id"`
	FinishedAt         *Time  `json:"finished_at"`
	ID                 int64  `json:"id"`
	IsPrivate          bool   `json:"is_private"`
	MagnetURI          string `json:"magneturi"`
	Name               string `json:"name"`
	PeersConnected     int    `json:"peers_connected"`
	PeersGettingFromUs int    `json:"peers_getting_from_us"`
	PeersSendingToUs   int    `json:"peers_sending_to_us"`
	PercentDone        int    `json:"percent_done"`
	SaveParentID       int64  `json:"save_parent_id"`
	SecondsSeeding     int    `json:"seconds_seeding"`
	Size               int    `json:"size"`
	Source             string `json:"source"`
	Status             string `json:"status"`
	StatusMessage      string `json:"status_message"`
	SubscriptionID     int    `json:"subscription_id"`
	TorrentLink        string `json:"torrent_link"`
	TrackerMessage     string `json:"tracker_message"`
	Trackers           string `json:"tracker"`
	Type               string `json:"type"`
	UploadSpeed        int    `json:"up_speed"`
	Uploaded           int64  `json:"uploaded"`
}

// AccountInfo represents user's account information.
type AccountInfo struct {
	AccountActive           bool   `json:"account_active"`
	AvatarURL               string `json:"avatar_url"`
	DaysUntilFilesDeletion  int    `json:"days_until_files_deletion"`
	DefaultSubtitleLanguage string `json:"default_subtitle_language"`
	Disk                    struct {
		Avail int64 `json:"avail"`
		Size  int64 `json:"size"`
		Used  int64 `json:"used"`
	} `json:"disk"`
	HasVoucher                bool     `json:"has_voucher"`
	Mail                      string   `json:"mail"`
	PlanExpirationDate        string   `json:"plan_expiration_date"`
	Settings                  Settings `json:"settings"`
	SimultaneousDownloadLimit int      `json:"simultaneous_download_limit"`
	SubtitleLanguages         []string `json:"subtitle_languages"`
	UserID                    int64    `json:"user_id"`
	Username                  string   `json:"username"`
}

// Settings represents user's personal settings.
type Settings struct {
	CallbackURL             string      `json:"callback_url"`
	DefaultDownloadFolder   int64       `json:"default_download_folder"`
	DefaultSubtitleLanguage string      `json:"default_subtitle_language"`
	DownloadFolderUnset     bool        `json:"download_folder_unset"`
	IsInvisible             bool        `json:"is_invisible"`
	Nextepisode             bool        `json:"nextepisode"`
	PrivateDownloadHostIP   interface{} `json:"private_download_host_ip"`
	PushoverToken           string      `json:"pushover_token"`
	Routing                 string      `json:"routing"`
	Sorting                 string      `json:"sorting"`
	SSLEnabled              bool        `json:"ssl_enabled"`
	StartFrom               bool        `json:"start_from"`
	SubtitleLanguages       []string    `json:"subtitle_languages"`
}

// Friend represents Put.io user's friend.
type Friend struct {
	ID        int64  `json:"id"`
	Name      string `json:"name"`
	AvatarURL string `json:"avatar_url"`
}

// Zip represents Put.io zip file.
type Zip struct {
	ID        int64 `json:"id"`
	CreatedAt *Time `json:"created_at"`

	Size   int64  `json:"size"`
	Status string `json:"status"`
	URL    string `json:"url"`

	// FIXME: missing_files field is missin
	missingFiles string
}

// Subtitle represents a subtitle.
type Subtitle struct {
	Key      string
	Language string
	Name     string
	Source   string
}

// Event represents a Put.io event. It could be a transfer or a shared file.
type Event struct {
	ID           int64  `json:"id"`
	FileID       int64  `json:"file_id"`
	Source       string `json:"source"`
	Type         string `json:"type"`
	TransferName string `json:"transfer_name"`
	TransferSize int64  `json:"transfer_size"`
	CreatedAt    *Time  `json:"created_at"`
}

type share struct {
	FileID   int64  `json:"file_id"`
	Filename string `json:"file_name"`
	// Number of friends the file is shared with
	SharedWith int64 `json:"shared_with"`
}

// errorResponse represents a common error message that Put.io v2 API sends on
// error.
type errorResponse struct {
	ErrorMessage string `json:"error_message"`
	ErrorType    string `json:"error_type"`
	ErrorURI     string `json:"error_uri"`
	Status       string `json:"status"`
	StatusCode   int    `json:"status_code"`
}

func (e errorResponse) Error() string {
	return fmt.Sprintf("StatusCode: %v ErrorType: %v ErrorMsg: %v", e.StatusCode, e.ErrorType, e.ErrorMessage)
}
<|endoftext|>