<commit_before>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/andrewtj/dnssd"
	"io"
	"log"
	"net"
	"net/textproto"
	"strings"
	"sync"
	//"bytes"
)

const (
	protocolType = "RTSP/1.0"
	carReturn    = "\r\n"
)

//starts the ROAP service
func startRAOP(hardwareAddr net.HardwareAddr, hostName string) {

	port := 5000
	name := fmt.Sprintf("%s@%s", hex.EncodeToString(hardwareAddr), hostName)
	op := dnssd.NewRegisterOp(name, "_raop._tcp", port, RegisterRAOPCallbackFunc)

	op.SetTXTPair("txtvers", "1")
	op.SetTXTPair("ch", "2")
	op.SetTXTPair("cn", "0,1")
	op.SetTXTPair("et", "0,1")
	op.SetTXTPair("sv", "false")
	op.SetTXTPair("da", "true")
	op.SetTXTPair("sr", "44100")
	op.SetTXTPair("ss", "16")
	op.SetTXTPair("pw", "false")
	op.SetTXTPair("vn", "3")
	op.SetTXTPair("tp", "TCP,UDP")
	op.SetTXTPair("md", "0,1,2")
	op.SetTXTPair("vs", "130.14")
	op.SetTXTPair("sm", "false")
	op.SetTXTPair("ek", "1")
	err := op.Start()
	if err != nil {
		log.Printf("Failed to register RAOP service: %s", err)
		return
	}
	log.Println("started RAOP service")
	startRAOPServer(port)
	// later...
	//op.Stop()
}

//helper method for the ROAP service
func RegisterRAOPCallbackFunc(op *dnssd.RegisterOp, err error, add bool, name, serviceType, domain string) {
	if err != nil {
		// op is now inactive
		log.Printf("RAOP Service registration failed: %s", err)
		return
	}
	if add {
		log.Printf("RAOP Service registered as “%s“ in %s", name, domain)
	} else {
		log.Printf("RAOP Service “%s” removed from %s", name, domain)
	}
}

//starts the RTSP server
func startRAOPServer(port int) {
	StartServer(port, func(c *conn) {
		log.Println("got a RAOP connection from: ", c.rwc.RemoteAddr())
		verb, resource, headers, data, err := readRequest(c.buf.Reader)
		if err != nil {
			return
		}
		var resHeaders map[string]string
		key := "Cseq"
		resHeaders[key] = headers[key][0]
		resHeaders["Server"] = "AirTunes/130.14"
		resData, status := processRequest(verb, resource, &resHeaders, data)
		c.buf.Write(createResponse(status, resHeaders, resData))
		c.rwc.Close()
	})
}

//creates a response to send back to the client
func createResponse(success bool, headers map[string]string, data []byte) []byte {
	s := protocolType
	if success {
		s += " 200 OK" + carReturn
		for key, val := range headers {
			s += fmt.Sprintf("%s: %s%s", key, val, carReturn)
		}
	} else {
		s += " 400 Bad Request" + carReturn
	}
	log.Println("response is (minus data):", s)
	body := []byte(s + carReturn)
	if data != nil {
		body = append(body, data...)
	}
	return body
}

//processes the request by dispatching to the proper method for each response
func processRequest(verb, resource string, headers *map[string]string, data []byte) ([]byte, bool) {
	log.Println("resource is:", resource)
	log.Println("verb is:", verb)
	if verb == "POST" && resource == "/fp-setup" {
		//do fairplay stuff
	} else if verb == "OPTIONS" && resource == "*" {
		//do the auth and such
	}
	//more stuff
	return nil, false
}

//some request handling stuff
var textprotoReaderPool sync.Pool

//create a new reader from the pool
func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
	if v := textprotoReaderPool.Get(); v != nil {
		tr := v.(*textproto.Reader)
		tr.R = br
		return tr
	}
	return textproto.NewReader(br)
}

//put our reader in the pool
func putTextprotoReader(r *textproto.Reader) {
	r.R = nil
	textprotoReaderPool.Put(r)
}

//reads the request and breaks it up in proper chunks
func readRequest(b *bufio.Reader) (v string, r string, h map[string][]string, buf []byte, err error) {

	tp := newTextprotoReader(b)

	var s string
	if s, err = tp.ReadLine(); err != nil {
		return "", "", nil, nil, err
	}
	defer func() {
		putTextprotoReader(tp)
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()
	verb, resource, err := parseFirstLine(s)
	if err != nil {
		log.Println("unable to read RAOP request:", err)
		return "", "", nil, nil, err
	}
	headers, err := tp.ReadMIMEHeader()
	if err != nil {
		log.Println("unable to read RAOP mimeHeaders:", err)
		return "", "", nil, nil, err
	}
	count := b.Buffered()
	buffer, _ := b.Peek(count)

	return verb, resource, headers, buffer, nil
}

//parses and returns the verb and resource of the request
func parseFirstLine(line string) (string, string, error) {
	s1 := strings.Index(line, " ")
	s2 := strings.Index(line[s1+1:], " ")
	if s1 < 0 || s2 < 0 {
		return "", "", errors.New("Invalid RTSP format")
	}
	s2 += s1 + 1
	return line[:s1], line[s1+1 : s2], nil
}
<commit_msg>fairplay work<commit_after>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/andrewtj/dnssd"
	"io"
	"log"
	"net"
	"net/textproto"
	"strings"
	"sync"
	//"bytes"
)

const (
	protocolType = "RTSP/1.0"
	carReturn    = "\r\n"
)

//starts the ROAP service
func startRAOP(hardwareAddr net.HardwareAddr, hostName string) {

	port := 5000
	name := fmt.Sprintf("%s@%s", hex.EncodeToString(hardwareAddr), hostName)
	op := dnssd.NewRegisterOp(name, "_raop._tcp", port, RegisterRAOPCallbackFunc)

	op.SetTXTPair("txtvers", "1")
	op.SetTXTPair("ch", "2")
	op.SetTXTPair("cn", "0,1")
	op.SetTXTPair("et", "0,1")
	op.SetTXTPair("sv", "false")
	op.SetTXTPair("da", "true")
	op.SetTXTPair("sr", "44100")
	op.SetTXTPair("ss", "16")
	op.SetTXTPair("pw", "false")
	op.SetTXTPair("vn", "3")
	op.SetTXTPair("tp", "TCP,UDP")
	op.SetTXTPair("md", "0,1,2")
	op.SetTXTPair("vs", "130.14")
	op.SetTXTPair("sm", "false")
	op.SetTXTPair("ek", "1")
	err := op.Start()
	if err != nil {
		log.Printf("Failed to register RAOP service: %s", err)
		return
	}
	log.Println("started RAOP service")
	startRAOPServer(port)
	// later...
	//op.Stop()
}

//helper method for the ROAP service
func RegisterRAOPCallbackFunc(op *dnssd.RegisterOp, err error, add bool, name, serviceType, domain string) {
	if err != nil {
		// op is now inactive
		log.Printf("RAOP Service registration failed: %s", err)
		return
	}
	if add {
		log.Printf("RAOP Service registered as “%s“ in %s", name, domain)
	} else {
		log.Printf("RAOP Service “%s” removed from %s", name, domain)
	}
}

//starts the RTSP server
func startRAOPServer(port int) {
	StartServer(port, func(c *conn) {
		log.Println("got a RAOP connection from: ", c.rwc.RemoteAddr())
		verb, resource, headers, data, err := readRequest(c.buf.Reader)
		if err != nil {
			return
		}
		resHeaders := make(map[string]string)
		resHeaders["Server"] = "AirTunes/130.14"
		key := "Cseq"
		if headers[key] != nil {
			resHeaders[key] = headers[key][0]
		}
		resData, status := processRequest(verb, resource, &resHeaders, data)
		c.buf.Write(createResponse(status, resHeaders, resData))
		c.buf.Writer.Flush()
		c.rwc.Close()
		c.buf.Flush()
	})
}

//creates a response to send back to the client
func createResponse(success bool, headers map[string]string, data []byte) []byte {
	s := protocolType
	if success {
		s += " 200 OK" + carReturn
		if data != nil {
			s += fmt.Sprintf("Content-Type: application/octet-stream%s", carReturn)
			s += fmt.Sprintf("Content-Length: %d%s", len(data), carReturn)
		}
		for key, val := range headers {
			s += fmt.Sprintf("%s: %s%s", key, val, carReturn)
		}
	} else {
		s += " 400 Bad Request" + carReturn
	}
	log.Println("response is (minus data):", s)
	body := []byte(s + carReturn)
	if data != nil {
		body = append(body, data...)
	}
	return body
}

//processes the request by dispatching to the proper method for each response
func processRequest(verb, resource string, headers *map[string]string, data []byte) ([]byte, bool) {
	log.Println("resource is:", resource)
	log.Println("verb is:", verb)
	if verb == "POST" && resource == "/fp-setup" {
		return handleFairPlay(headers, data), true
	} else if verb == "OPTIONS" && resource == "*" {
		//do the auth and such
	}
	//more stuff
	return nil, false
}

//process fair play requests
func handleFairPlay(headers *map[string]string, data []byte) []byte {
	if data[6] == 1 {
		return []byte{0x46, 0x50, 0x4c, 0x59, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x82,
			0x02, 0x02, 0x2f, 0x7b, 0x69, 0xe6, 0xb2, 0x7e, 0xbb, 0xf0, 0x68, 0x5f, 0x98, 0x54, 0x7f, 0x37,
			0xce, 0xcf, 0x87, 0x06, 0x99, 0x6e, 0x7e, 0x6b, 0x0f, 0xb2, 0xfa, 0x71, 0x20, 0x53, 0xe3, 0x94,
			0x83, 0xda, 0x22, 0xc7, 0x83, 0xa0, 0x72, 0x40, 0x4d, 0xdd, 0x41, 0xaa, 0x3d, 0x4c, 0x6e, 0x30,
			0x22, 0x55, 0xaa, 0xa2, 0xda, 0x1e, 0xb4, 0x77, 0x83, 0x8c, 0x79, 0xd5, 0x65, 0x17, 0xc3, 0xfa,
			0x01, 0x54, 0x33, 0x9e, 0xe3, 0x82, 0x9f, 0x30, 0xf0, 0xa4, 0x8f, 0x76, 0xdf, 0x77, 0x11, 0x7e,
			0x56, 0x9e, 0xf3, 0x95, 0xe8, 0xe2, 0x13, 0xb3, 0x1e, 0xb6, 0x70, 0xec, 0x5a, 0x8a, 0xf2, 0x6a,
			0xfc, 0xbc, 0x89, 0x31, 0xe6, 0x7e, 0xe8, 0xb9, 0xc5, 0xf2, 0xc7, 0x1d, 0x78, 0xf3, 0xef, 0x8d,
			0x61, 0xf7, 0x3b, 0xcc, 0x17, 0xc3, 0x40, 0x23, 0x52, 0x4a, 0x8b, 0x9c, 0xb1, 0x75, 0x05, 0x66,
			0xe6, 0xb3}
	} else {
		log.Println("some other kind of FP setup:", data[6])
	}
	return nil
}

//some request handling stuff
var textprotoReaderPool sync.Pool

//create a new reader from the pool
func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
	if v := textprotoReaderPool.Get(); v != nil {
		tr := v.(*textproto.Reader)
		tr.R = br
		return tr
	}
	return textproto.NewReader(br)
}

//put our reader in the pool
func putTextprotoReader(r *textproto.Reader) {
	r.R = nil
	textprotoReaderPool.Put(r)
}

//reads the request and breaks it up in proper chunks
func readRequest(b *bufio.Reader) (v string, r string, h map[string][]string, buf []byte, err error) {

	tp := newTextprotoReader(b)

	var s string
	if s, err = tp.ReadLine(); err != nil {
		return "", "", nil, nil, err
	}
	defer func() {
		putTextprotoReader(tp)
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()
	verb, resource, err := parseFirstLine(s)
	if err != nil {
		log.Println("unable to read RAOP request:", err)
		return "", "", nil, nil, err
	}
	headers, err := tp.ReadMIMEHeader()
	if err != nil {
		log.Println("unable to read RAOP mimeHeaders:", err)
		return "", "", nil, nil, err
	}
	count := b.Buffered()
	buffer, _ := b.Peek(count)

	return verb, resource, headers, buffer, nil
}

//parses and returns the verb and resource of the request
func parseFirstLine(line string) (string, string, error) {
	s1 := strings.Index(line, " ")
	s2 := strings.Index(line[s1+1:], " ")
	if s1 < 0 || s2 < 0 {
		return "", "", errors.New("Invalid RTSP format")
	}
	s2 += s1 + 1
	return line[:s1], line[s1+1 : s2], nil
}
<|endoftext|>


<commit_before>package rcon

import (
	"encoding/binary"
	"errors"
	"net"
	"strings"
)

const (
	terminationSequence        = "\x00"
	failedAuthResponseID int32 = -1
)

var (
	ErrInvalidWrite        = errors.New("rcon: failed to write to remote connection")
	ErrInvalidRead         = errors.New("rcon: failed to read from remote connection")
	ErrInvalidID           = errors.New("rcon: invalid response ID from remote connection")
	ErrInvalidAuthResponse = errors.New("rcon: invalid response type during auth")
	ErrAuthFailed          = errors.New("rcon: authentication failed")
)

type RCON struct {
	// TODO: add some more useful stuff here?
	Address string
	conn    net.Conn
}

// func (r *RCON) LocalAddr() net.Addr {
// 	return r.conn.LocalAddr()
// }

// func (r *RCON) RemoteAddr() net.Addr {
// 	return r.conn.RemoteAddr()
// }

func Dial(address string) (*RCON, error) {
	// dial tcp
	conn, err := net.Dial("tcp", address)
	if err != nil {
		return nil, err
	}

	// create remote console
	rc := &RCON{Address: address, conn: conn}
	return rc, nil
}

func (r *RCON) Close() error {
	return r.conn.Close()
}

func (r *RCON) Execute(command string) (response *Packet, err error) {
	// Send command to execute
	cmd := NewPacket(ExecCommand, command)
	if err = r.WritePacket(cmd); err != nil {
		return
	}

	// Send "sentinel" packet, to detect if the response has been split.
	// We'll send an empty ResponseValue packet to the server, which will get
	// a new id. The server will respond back with another empty ResponseValue.
	// Because it the server always answers in the order that it received
	// packets, we can use this empty packet to determine when we're done with
	// fetching the response. This approach is documented here:
	// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses
	sentinel := NewPacket(ResponseValue, "")
	if err = r.WritePacket(sentinel); err != nil {
		return
	}

	// Get responses until we hit the sentinel value
	responses := []*Packet{}
	for {
		response, err = r.ReadPacket()
		if err != nil {
			return
		}
		if response.ID == cmd.ID {
			responses = append(responses, response)
		} else {
			break
		}
	}

	// Merge responses into one packet
	response, err = MergePackets(responses)
	if err != nil {
		return
	}
	return
}

func (r *RCON) Authenticate(password string) (err error) {
	// Send auth package
	packet := NewPacket(Auth, password)
	if err = r.WritePacket(packet); err != nil {
		return
	}

	// Get response
	var response *Packet
	response, err = r.ReadPacket()
	if err != nil {
		return
	}
	// Check that response returned correct ID
	if response.ID != packet.ID {
		return ErrInvalidID
	}

	// The server will potentiall send a blank ResponseValue packet before giving
	// back the correct AuthResponse. This can safely be discarded, as documented here:
	// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#SERVERDATA_AUTH_RESPONSE
	if response.Type == ResponseValue {
		response, err = r.ReadPacket()
		if err != nil {
			return err
		}
	}

	// By now we should for sure have an AuthResponse. If we don't, there's something weird
	// going on server-side
	if response.Type != AuthResponse {
		panic("WTF!?")
	}

	// Check that we did not receive an ID indicating that authentication failed.
	if response.ID == failedAuthResponseID {
		return ErrAuthFailed
	}
	return
}

func (r *RCON) WritePacket(packet *Packet) (err error) {
	// generate payload
	var payload []byte
	payload, err = packet.Payload()
	if err != nil {
		return
	}

	// write payload to tcp socket
	var n int
	n, err = r.conn.Write(payload)
	if err != nil {
		return
	}
	if n != len(payload) {
		return ErrInvalidWrite
	}
	return
}

func (r *RCON) ReadPacket() (response *Packet, err error) {
	// Read header fields into Packet struct
	var packet Packet
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.Size); err != nil {
		return
	}
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.ID); err != nil {
		return
	}
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.Type); err != nil {
		return
	}

	// Read rest of packet
	var n int
	bytesRead := 0
	bytesTotal := int(packet.Size - packetHeaderSize)
	buf := make([]byte, bytesTotal)

	for bytesRead < bytesTotal {
		n, err = r.conn.Read(buf[bytesRead:])
		if err != nil {
			return
		}
		bytesRead += n
	}

	// Trim null bytes off body
	packet.Body = strings.TrimRight(string(buf), terminationSequence)

	// Construct final response packet
	return &packet, nil
}
<commit_msg>Fix bug about handling of sentinel values<commit_after>package rcon

import (
	"encoding/binary"
	"errors"
	"net"
	"strings"
)

const (
	terminationSequence        = "\x00"
	failedAuthResponseID int32 = -1
)

var (
	ErrInvalidWrite        = errors.New("rcon: failed to write to remote connection")
	ErrInvalidRead         = errors.New("rcon: failed to read from remote connection")
	ErrInvalidID           = errors.New("rcon: invalid response ID from remote connection")
	ErrInvalidAuthResponse = errors.New("rcon: invalid response type during auth")
	ErrInvalidPacketOrder  = errors.New("rcon: packets from server received out of order")
	ErrAuthFailed          = errors.New("rcon: authentication failed")
)

type RCON struct {
	// TODO: add some more useful stuff here?
	Address string
	conn    net.Conn
}

// func (r *RCON) LocalAddr() net.Addr {
// 	return r.conn.LocalAddr()
// }

// func (r *RCON) RemoteAddr() net.Addr {
// 	return r.conn.RemoteAddr()
// }

func Dial(address string) (*RCON, error) {
	// dial tcp
	conn, err := net.Dial("tcp", address)
	if err != nil {
		return nil, err
	}

	// create remote console
	rc := &RCON{Address: address, conn: conn}
	return rc, nil
}

func (r *RCON) Close() error {
	return r.conn.Close()
}

func (r *RCON) Execute(command string) (response *Packet, err error) {
	// Send command to execute
	cmd := NewPacket(ExecCommand, command)
	if err = r.WritePacket(cmd); err != nil {
		return
	}

	// Send "sentinel" packet, to detect if the response has been split.
	// We'll send an empty ResponseValue packet to the server, which will get
	// a new id. The server will respond back with another empty ResponseValue.
	// Because it the server always answers in the order that it received
	// packets, we can use this empty packet to determine when we're done with
	// fetching the response. This approach is documented here:
	// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses
	sentinel := NewPacket(ResponseValue, "")
	if err = r.WritePacket(sentinel); err != nil {
		return
	}

	// Get responses until we hit the sentinel value
	responses := []*Packet{}
	for {
		response, err = r.ReadPacket()
		if err != nil {
			return
		}

		// Handle sentinel package
		if response.ID == cmd.ID {
			// append responses with same id
			responses = append(responses, response)
		} else if response.ID == sentinel.ID {
			// if it's a sentinel packet, it might not be the final one
			// check for specific body to determine end of sentinel packets
			if response.Body == "\x00\x01" {
				break
			}
		} else {
			// something has gotten out of order
			return nil, ErrInvalidPacketOrder
		}
	}

	// Merge responses into one packet
	response, err = MergePackets(responses)
	if err != nil {
		return
	}
	return
}

func (r *RCON) Authenticate(password string) (err error) {
	// Send auth package
	packet := NewPacket(Auth, password)
	if err = r.WritePacket(packet); err != nil {
		return
	}

	// Get response
	var response *Packet
	response, err = r.ReadPacket()
	if err != nil {
		return
	}
	// Check that response returned correct ID
	if response.ID != packet.ID {
		return ErrInvalidID
	}

	// The server will potentiall send a blank ResponseValue packet before giving
	// back the correct AuthResponse. This can safely be discarded, as documented here:
	// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#SERVERDATA_AUTH_RESPONSE
	if response.Type == ResponseValue {
		response, err = r.ReadPacket()
		if err != nil {
			return err
		}
	}

	// By now we should for sure have an AuthResponse. If we don't, there's something weird
	// going on server-side
	if response.Type != AuthResponse {
		panic("WTF!?")
	}

	// Check that we did not receive an ID indicating that authentication failed.
	if response.ID == failedAuthResponseID {
		return ErrAuthFailed
	}
	return
}

func (r *RCON) WritePacket(packet *Packet) (err error) {
	// generate payload
	var payload []byte
	payload, err = packet.Payload()
	if err != nil {
		return
	}

	// write payload to tcp socket
	var n int
	n, err = r.conn.Write(payload)
	if err != nil {
		return
	}
	if n != len(payload) {
		return ErrInvalidWrite
	}
	return
}

func (r *RCON) ReadPacket() (response *Packet, err error) {
	// Read header fields into Packet struct
	var packet Packet
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.Size); err != nil {
		return
	}
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.ID); err != nil {
		return
	}
	if err = binary.Read(r.conn, binary.LittleEndian, &packet.Type); err != nil {
		return
	}

	// Read rest of packet
	var n int
	bytesRead := 0
	bytesTotal := int(packet.Size - packetHeaderSize)
	buf := make([]byte, bytesTotal)

	for bytesRead < bytesTotal {
		n, err = r.conn.Read(buf[bytesRead:])
		if err != nil {
			return
		}
		bytesRead += n
	}

	// Trim null bytes off body
	packet.Body = strings.TrimRight(string(buf), terminationSequence)

	// Construct final response packet
	return &packet, nil
}
<|endoftext|>


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

package zannotate

import (
	"flag"
	"net"
)

type RDNSAnnotatorFactory struct {
	BasePluginConf
	RawResolvers string
}

type RDNSAnnotator struct {
	Factory *RDNSAnnotatorFactory
	Id      int
}

// RDNS Annotator Factory (Global)

func (a *RDNSAnnotatorFactory) MakeAnnotator(i int) Annotator {
	var v RDNSAnnotator
	v.Factory = a
	v.Id = i
	return &v
}

func (a *RDNSAnnotatorFactory) Initialize(conf *GlobalConf) error {
	return nil
}

func (a *RDNSAnnotatorFactory) GetWorkers() int {
	return a.Threads
}

func (a *RDNSAnnotatorFactory) Close() error {
	return nil
}

func (a *RDNSAnnotatorFactory) IsEnabled() bool {
	return a.Enabled
}

func (a *RDNSAnnotatorFactory) AddFlags(flags *flag.FlagSet) {
	// Reverse DNS Lookup
	flags.BoolVar(&a.Enabled, "rdns", false, "reverse dns lookup")
	flags.StringVar(&a.RawResolvers, "rdns-dns-servers", "", "list of DNS servers to use for DNS lookups")
	flags.IntVar(&a.Threads, "rdns-threads", 100, "how many reverse dns threads")
}

// RDNS Annotator (Per-Worker)

func (a *RDNSAnnotator) Initialize() error {
	return nil
}

func (a *RDNSAnnotator) GetFieldName() string {
	return "rdns"
}

func (a *RDNSAnnotator) Annotate(ip net.IP) interface{} {
	return nil
}

func (a *RDNSAnnotator) Close() error {
	return nil
}

func init() {
	s := new(RDNSAnnotatorFactory)
	RegisterAnnotator(s)
}
<commit_msg>do not register rdns for now<commit_after>/*
 * ZAnnotate Copyright 2018 Regents of the University of Michigan
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package zannotate

import (
	"flag"
	"net"
)

type RDNSAnnotatorFactory struct {
	BasePluginConf
	RawResolvers string
}

type RDNSAnnotator struct {
	Factory *RDNSAnnotatorFactory
	Id      int
}

// RDNS Annotator Factory (Global)

func (a *RDNSAnnotatorFactory) MakeAnnotator(i int) Annotator {
	var v RDNSAnnotator
	v.Factory = a
	v.Id = i
	return &v
}

func (a *RDNSAnnotatorFactory) Initialize(conf *GlobalConf) error {
	return nil
}

func (a *RDNSAnnotatorFactory) GetWorkers() int {
	return a.Threads
}

func (a *RDNSAnnotatorFactory) Close() error {
	return nil
}

func (a *RDNSAnnotatorFactory) IsEnabled() bool {
	return a.Enabled
}

func (a *RDNSAnnotatorFactory) AddFlags(flags *flag.FlagSet) {
	// Reverse DNS Lookup
	flags.BoolVar(&a.Enabled, "rdns", false, "reverse dns lookup")
	flags.StringVar(&a.RawResolvers, "rdns-dns-servers", "", "list of DNS servers to use for DNS lookups")
	flags.IntVar(&a.Threads, "rdns-threads", 100, "how many reverse dns threads")
}

// RDNS Annotator (Per-Worker)

func (a *RDNSAnnotator) Initialize() error {
	return nil
}

func (a *RDNSAnnotator) GetFieldName() string {
	return "rdns"
}

func (a *RDNSAnnotator) Annotate(ip net.IP) interface{} {
	return nil
}

func (a *RDNSAnnotator) Close() error {
	return nil
}

//func init() {
//	s := new(RDNSAnnotatorFactory)
//	RegisterAnnotator(s)
//}
<|endoftext|>


<commit_before>package main

import (
	"time"
)

type Post struct {
	Id      int       `json:"id"`
	Title   string    `json:"title"`
	Content string    `json:"content"`
	Posted  time.Time `json:"posted"`
}

type Posts []Post
<commit_msg>change attr type<commit_after>package main

import ()

type Post struct {
	Id      int    `json:"id"`
	Title   string `json:"title"`
	Content string `json:"content"`
	Posted  string `json:"posted"`
}

type Posts []Post
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// Create a PostCreator that operate in specified directory
func NewPostCreator(dir string) PostCreator {
	return PostCreator{dir}
}

// A PostCreator create folder and files for a new post
type PostCreator struct {
	// directory to create post
	dir string
}

// Create a post with specified title
func (pc PostCreator) Create(title string) error {
	date := time.Now().Format(ISO8601Date)

	postDir := filepath.Join(pc.dir, date+"-"+Prettify(title))
	if err := os.Mkdir(postDir, os.ModePerm); err != nil {
		return fmt.Errorf("Unable to create folder %s", postDir)
	}

	file, err := os.Create(filepath.Join(postDir, "post.md"))
	if err != nil {
		return fmt.Errorf("Unable to create post.md")
	}
	content := fmt.Sprintf(`---
date: %s
title: %s
---
`, date, title)
	file.WriteString(content)
	return nil
}

// PostParser parse file into Post
type PostParser struct {
	converter MarkdownConverter
}

func NewPostParser() PostParser {
	return PostParser{NewGithubMarkdownConverter()}
}

// Parse will parse Post from specified post folder
func (pp PostParser) Parse(dir string) Post {
	post := NewPost()
	file, _ := os.Open(filepath.Join(dir, PostFileName))
	post.variables, post.content = pp.parseLineByLine(file)
	post.htmlContent, _ = pp.converter.Convert(post.content)
	post.key = filepath.Base(dir)
	return *post
}

func (pp PostParser) parseLineByLine(f *os.File) (variables map[string]string, content string) {
	variables = make(map[string]string)
	content = ""

	defer f.Close()

	isInVariablesBlock := false
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		if !isInVariablesBlock && line == "---" {
			isInVariablesBlock = true
			continue
		} else if isInVariablesBlock && line == "---" {
			isInVariablesBlock = false
			continue
		}

		if isInVariablesBlock {
			if key, value, err := pp.parseVariable(line); err == nil {
				variables[key] = value
			}
		} else {
			content += (line + "\n")
		}
	}

	return
}

func (pp PostParser) parseVariable(line string) (key string, value string, err error) {
	pair := strings.SplitN(line, ":", 2)
	if len(pair) == 2 {
		key = strings.TrimSpace(pair[0])
		value = strings.TrimSpace(pair[1])
	} else {
		err = fmt.Errorf("Invalid post variable format : %s", line)
	}
	return
}

func NewPost() *Post {
	p := new(Post)
	return p
}

// Post represented a post in blog
type Post struct {
	// post folder name as the post identifier
	key string
	// variables in post file
	variables map[string]string
	// content in Markdown
	content string
	// content in HTML converted from Markdown
	htmlContent string
}

func (p Post) Title() string {
	return p.variables["title"]
}

func (p Post) Date() string {
	return p.variables["date"]
}

func (p Post) Content() string {
	return p.content
}

func (p Post) HtmlContent() string {
	return p.htmlContent
}

func (p Post) Key() string {
	return p.key
}
<commit_msg>clean up ParsePostFile<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// Create a PostCreator that operate in specified directory
func NewPostCreator(dir string) PostCreator {
	return PostCreator{dir}
}

// A PostCreator create folder and files for a new post
type PostCreator struct {
	// directory to create post
	dir string
}

// Create a post with specified title
func (pc PostCreator) Create(title string) error {
	date := time.Now().Format(ISO8601Date)

	postDir := filepath.Join(pc.dir, date+"-"+Prettify(title))
	if err := os.Mkdir(postDir, os.ModePerm); err != nil {
		return fmt.Errorf("Unable to create folder %s", postDir)
	}

	file, err := os.Create(filepath.Join(postDir, "post.md"))
	if err != nil {
		return fmt.Errorf("Unable to create post.md")
	}
	content := fmt.Sprintf(`---
date: %s
title: %s
---
`, date, title)
	file.WriteString(content)
	return nil
}

// PostParser parse file into Post
type PostParser struct {
	converter MarkdownConverter
}

func NewPostParser() PostParser {
	return PostParser{NewGithubMarkdownConverter()}
}

// Parse will parse Post from specified post folder
func (pp PostParser) Parse(dir string) Post {
	post := NewPost()

	post.key = filepath.Base(dir)
	post.variables, post.content = pp.parsePostFile(dir)
	post.htmlContent, _ = pp.converter.Convert(post.content)
	return *post
}

func (pp PostParser) parsePostFile(dir string) (map[string]string, string) {

	f, _ := os.Open(filepath.Join(dir, PostFileName))
	defer f.Close()

	variables := make(map[string]string)
	content := ""

	isInVariablesBlock := false
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		if !isInVariablesBlock && line == "---" {
			isInVariablesBlock = true
			continue
		} else if isInVariablesBlock && line == "---" {
			isInVariablesBlock = false
			continue
		}

		if isInVariablesBlock {
			if key, value, err := pp.parseVariable(line); err == nil {
				variables[key] = value
			}
		} else {
			content += (line + "\n")
		}
	}
	return variables, content
}

func (pp PostParser) parseVariable(line string) (key string, value string, err error) {
	pair := strings.SplitN(line, ":", 2)
	if len(pair) == 2 {
		key = strings.TrimSpace(pair[0])
		value = strings.TrimSpace(pair[1])
	} else {
		err = fmt.Errorf("Invalid post variable format : %s", line)
	}
	return
}

func NewPost() *Post {
	p := new(Post)
	return p
}

// Post represented a post in blog
type Post struct {
	// post folder name as the post identifier
	key string
	// variables in post file
	variables map[string]string
	// content in Markdown
	content string
	// content in HTML converted from Markdown
	htmlContent string
}

func (p Post) Title() string {
	return p.variables["title"]
}

func (p Post) Date() string {
	return p.variables["date"]
}

func (p Post) Content() string {
	return p.content
}

func (p Post) HtmlContent() string {
	return p.htmlContent
}

func (p Post) Key() string {
	return p.key
}
<|endoftext|>


<commit_before>package raft

import (
	"fmt"

	"golang.org/x/net/context"

	pb "github.com/relab/raft/raftpb"
)

// ErrNotLeader is returned by Raft when a method is invoked requiring the
// server to be the leader, and it's not. A hint about the actual leader is
// provided.
type ErrNotLeader struct {
	Leader uint64
}

func (e *ErrNotLeader) Error() string {
	return fmt.Sprintf("not leader, %d is", e.Leader)
}

// Raft represents the interface a Raft node needs expose to the application
// layer.
type Raft interface {
	// ProposeCmd proposes a command. Blocks until Raft handles the message
	// or the context is canceled, i.e., server is busy. Immediately returns
	// an ErrNotLeader error if server isn't the leader.
	ProposeCmd(context.Context, []byte) error

	// Read blocks until Raft has had a successful round of heartbeats in
	// its current term, and the read index is read from Committed, i.e.,
	// Read must not block reads on Committed. A successful call to Read
	// allows read-only queries accumulated up to the point where Read was
	// called, to be safely executed on the state machine. If the context is
	// canceled, i.e., server is busy, and error is returned and Read must
	// be retried. Immediately returns an ErrNotLeader error if server isn't
	// the leader.
	Read(context.Context) error

	// ProposeConf proposes a new configuration. Blocks until Raft handles
	// the message or the context is canceled, i.e., server is busy.
	// Immediately returns an ErrNotLeader error if server isn't the leader.
	ProposeConf(context.Context, TODOConfChange) error

	// Committed returns a stream of committed commands which should be
	// applied to the applications state machine.
	Committed() chan<- []pb.Entry
}

type TODOConfChange struct{}
<commit_msg>raft.go: Rename import from pb to commonpb<commit_after>package raft

import (
	"fmt"

	"golang.org/x/net/context"

	commonpb "github.com/relab/raft/raftpb"
)

// ErrNotLeader is returned by Raft when a method is invoked requiring the
// server to be the leader, and it's not. A hint about the actual leader is
// provided.
type ErrNotLeader struct {
	Leader uint64
}

func (e *ErrNotLeader) Error() string {
	return fmt.Sprintf("not leader, %d is", e.Leader)
}

// Raft represents the interface a Raft node needs expose to the application
// layer.
type Raft interface {
	// ProposeCmd proposes a command. Blocks until Raft handles the message
	// or the context is canceled, i.e., server is busy. Immediately returns
	// an ErrNotLeader error if server isn't the leader.
	ProposeCmd(context.Context, []byte) error

	// Read blocks until Raft has had a successful round of heartbeats in
	// its current term, and the read index is read from Committed, i.e.,
	// Read must not block reads on Committed. A successful call to Read
	// allows read-only queries accumulated up to the point where Read was
	// called, to be safely executed on the state machine. If the context is
	// canceled, i.e., server is busy, and error is returned and Read must
	// be retried. Immediately returns an ErrNotLeader error if server isn't
	// the leader.
	Read(context.Context) error

	// ProposeConf proposes a new configuration. Blocks until Raft handles
	// the message or the context is canceled, i.e., server is busy.
	// Immediately returns an ErrNotLeader error if server isn't the leader.
	ProposeConf(context.Context, TODOConfChange) error

	// Committed returns a stream of committed commands which should be
	// applied to the applications state machine.
	Committed() chan<- []commonpb.Entry
}

type TODOConfChange struct{}
<|endoftext|>


<commit_before>package throttled

import (
	"fmt"
	"time"
)

const (
	// Maximum number of times to retry SetIfNotExists/CompareAndSwap operations
	// before returning an error.
	maxCASAttempts = 10
)

// A RateLimiter manages limiting the rate of actions by key.
type RateLimiter interface {
	// RateLimit checks whether a particular key has exceeded a rate
	// limit. It also returns a RateLimitResult to provide additional
	// information about the state of the RateLimiter.
	//
	// If the rate limit has not been exceeded, the underlying storage
	// is updated by the supplied quantity. For example, a quantity of
	// 1 might be used to rate limit a single request while a greater
	// quantity could rate limit based on the size of a file upload in
	// megabytes. If quantity is 0, no update is performed allowing
	// you to "peek" at the state of the RateLimiter for a given key.
	RateLimit(key string, quantity int) (bool, RateLimitResult, error)
}

// RateLimitResult represents the state of the RateLimiter for a
// given key at the time of the query. This state can be used, for
// example, to communicate information to the client via HTTP
// headers. Negative values indicate that the attribute is not
// relevant to the implementation or state.
type RateLimitResult struct {
	// Limit is the maximum number of requests that could be permitted
	// instantaneously for this key starting from an empty state. For
	// example, if a rate limiter allows 10 requests per second per
	// key, Limit would always be 10.
	Limit int

	// Remaining is the maximum number of requests that could be
	// permitted instantaneously for this key given the current
	// state. For example, if a rate limiter allows 10 requests per
	// second and has already received 6 requests for this key this
	// second, Remaining would be 4.
	Remaining int

	// ResetAfter is the time until the RateLimiter returns to its
	// initial state for a given key. For example, if a rate limiter
	// manages requests per second and received one request 200ms ago,
	// Reset would return 800ms. You can also think of this as the time
	// until Limit and Remaining will be equal.
	ResetAfter time.Duration

	// RetryAfter is the time until the next request will be permitted.
	// It should be -1 unless the rate limit has been exceeded.
	RetryAfter time.Duration
}

type limitResult struct {
	limited bool
}

func (r *limitResult) Limited() bool { return r.limited }

type rateLimitResult struct {
	limitResult

	limit, remaining  int
	reset, retryAfter time.Duration
}

func (r *rateLimitResult) Limit() int                { return r.limit }
func (r *rateLimitResult) Remaining() int            { return r.remaining }
func (r *rateLimitResult) Reset() time.Duration      { return r.reset }
func (r *rateLimitResult) RetryAfter() time.Duration { return r.retryAfter }

// Rate describes a frequency of an activity such as the number of requests
// allowed per minute.
type Rate struct {
	period time.Duration // Time between equally spaced requests at the rate
	count  int           // Used internally for deprecated `RateLimit` interface only
}

// RateQuota describes the number of requests allowed per time period.
// MaxRate specified the maximum sustained rate of requests and must
// be greater than zero. MaxBurst defines the number of requests that
// will be allowed to exceed the rate in a single burst and must be
// greater than or equal to zero.
//
// Rate{PerSec(1), 0} would mean that after each request, no more
// requests will be permitted for that client for one second.
// Rate{PerSec(2), 0} permits one request per 0.5 seconds rather than
// two requests in one second. In practice, you probably want to set
// MaxBurst >0 to provide some flexibility to clients that only need
// to make a handful of requests. In fact a MaxBurst of zero will
// *never* permit a request with a quantity greater than one because
// it will immediately exceed the limit.
type RateQuota struct {
	MaxRate  Rate
	MaxBurst int
}

// PerSec represents a number of requests per second.
func PerSec(n int) Rate { return Rate{time.Second / time.Duration(n), n} }

// PerMin represents a number of requests per minute.
func PerMin(n int) Rate { return Rate{time.Minute / time.Duration(n), n} }

// PerHour represents a number of requests per hour.
func PerHour(n int) Rate { return Rate{time.Hour / time.Duration(n), n} }

// PerDay represents a number of requests per day.
func PerDay(n int) Rate { return Rate{24 * time.Hour / time.Duration(n), n} }

// PerDuration represents a number of requests per provided duration.
func PerDuration(n int, d time.Duration) Rate { return Rate{d / time.Duration(n), n} }

// GCRARateLimiter is a RateLimiter that users the generic cell-rate
// algorithm. The algorithm has been slightly modified from its usual
// form to support limiting with an additional quantity parameter, such
// as for limiting the number of bytes uploaded.
type GCRARateLimiter struct {
	limit int

	// Think of the DVT as our flexibility:
	// How far can you deviate from the nominal equally spaced schedule?
	// If you like leaky buckets, think about it as the size of your bucket.
	delayVariationTolerance time.Duration

	// Think of the emission interval as the time between events
	// in the nominal equally spaced schedule. If you like leaky buckets,
	// think of it as how frequently the bucket leaks one unit.
	emissionInterval time.Duration

	store GCRAStore

	// Maximum number of times to retry SetIfNotExists/CompareAndSwap operations
	// before returning an error.
	maxCASAttemptsLimit int
}

// NewGCRARateLimiter creates a GCRARateLimiter. quota.Count defines
// the maximum number of requests permitted in an instantaneous burst
// and quota.Count / quota.Period defines the maximum sustained
// rate. For example, PerMin(60) permits 60 requests instantly per key
// followed by one request per second indefinitely whereas PerSec(1)
// only permits one request per second with no tolerance for bursts.
func NewGCRARateLimiter(st GCRAStore, quota RateQuota) (*GCRARateLimiter, error) {
	if quota.MaxBurst < 0 {
		return nil, fmt.Errorf("invalid RateQuota %#v; MaxBurst must be greater than zero", quota)
	}
	if quota.MaxRate.period <= 0 {
		return nil, fmt.Errorf("invalid RateQuota %#v; MaxRate must be greater than zero", quota)
	}

	return &GCRARateLimiter{
		delayVariationTolerance: quota.MaxRate.period * (time.Duration(quota.MaxBurst) + 1),
		emissionInterval:        quota.MaxRate.period,
		limit:                   quota.MaxBurst + 1,
		store:                   st,
		maxCASAttemptsLimit:     maxCASAttempts,
	}, nil
}

// SetMaxCASAttemptsLimit allows you to set the maxCASAttempts limit. This is set to 10
// be default.
func (g *GCRARateLimiter) SetMaxCASAttemptsLimit(limit int) {
	g.maxCASAttemptsLimit = limit
}

// RateLimit checks whether a particular key has exceeded a rate
// limit. It also returns a RateLimitResult to provide additional
// information about the state of the RateLimiter.
//
// If the rate limit has not been exceeded, the underlying storage is
// updated by the supplied quantity. For example, a quantity of 1
// might be used to rate limit a single request while a greater
// quantity could rate limit based on the size of a file upload in
// megabytes. If quantity is 0, no update is performed allowing you
// to "peek" at the state of the RateLimiter for a given key.
func (g *GCRARateLimiter) RateLimit(key string, quantity int) (bool, RateLimitResult, error) {
	var tat, newTat, now time.Time
	var ttl time.Duration
	rlc := RateLimitResult{Limit: g.limit, RetryAfter: -1}
	limited := false

	i := 0
	for {
		var err error
		var tatVal int64
		var updated bool

		// tat refers to the theoretical arrival time that would be expected
		// from equally spaced requests at exactly the rate limit.
		tatVal, now, err = g.store.GetWithTime(key)
		if err != nil {
			return false, rlc, err
		}

		if tatVal == -1 {
			tat = now
		} else {
			tat = time.Unix(0, tatVal)
		}

		increment := time.Duration(quantity) * g.emissionInterval
		if now.After(tat) {
			newTat = now.Add(increment)
		} else {
			newTat = tat.Add(increment)
		}

		// Block the request if the next permitted time is in the future
		allowAt := newTat.Add(-(g.delayVariationTolerance))
		if diff := now.Sub(allowAt); diff < 0 {
			if increment <= g.delayVariationTolerance {
				rlc.RetryAfter = -diff
				ttl = tat.Sub(now)
			}
			limited = true
			break
		}

		ttl = newTat.Sub(now)

		if tatVal == -1 {
			updated, err = g.store.SetIfNotExistsWithTTL(key, newTat.UnixNano(), ttl)
		} else {
			updated, err = g.store.CompareAndSwapWithTTL(key, tatVal, newTat.UnixNano(), ttl)
		}

		if err != nil {
			return false, rlc, err
		}
		if updated {
			break
		}

		i++
		if i >= g.maxCASAttemptsLimit {
			return false, rlc, fmt.Errorf(
				"Failed to store updated rate limit data for key %s after %d attempts",
				key, i,
			)
		}
	}

	next := g.delayVariationTolerance - ttl
	if next > -g.emissionInterval {
		rlc.Remaining = int(next / g.emissionInterval)
	}
	rlc.ResetAfter = ttl

	return limited, rlc, nil
}
<commit_msg>Update rate.go<commit_after>package throttled

import (
	"fmt"
	"time"
)

const (
	// Maximum number of times to retry SetIfNotExists/CompareAndSwap operations
	// before returning an error.
	maxCASAttempts = 10
)

// A RateLimiter manages limiting the rate of actions by key.
type RateLimiter interface {
	// RateLimit checks whether a particular key has exceeded a rate
	// limit. It also returns a RateLimitResult to provide additional
	// information about the state of the RateLimiter.
	//
	// If the rate limit has not been exceeded, the underlying storage
	// is updated by the supplied quantity. For example, a quantity of
	// 1 might be used to rate limit a single request while a greater
	// quantity could rate limit based on the size of a file upload in
	// megabytes. If quantity is 0, no update is performed allowing
	// you to "peek" at the state of the RateLimiter for a given key.
	RateLimit(key string, quantity int) (bool, RateLimitResult, error)
}

// RateLimitResult represents the state of the RateLimiter for a
// given key at the time of the query. This state can be used, for
// example, to communicate information to the client via HTTP
// headers. Negative values indicate that the attribute is not
// relevant to the implementation or state.
type RateLimitResult struct {
	// Limit is the maximum number of requests that could be permitted
	// instantaneously for this key starting from an empty state. For
	// example, if a rate limiter allows 10 requests per second per
	// key, Limit would always be 10.
	Limit int

	// Remaining is the maximum number of requests that could be
	// permitted instantaneously for this key given the current
	// state. For example, if a rate limiter allows 10 requests per
	// second and has already received 6 requests for this key this
	// second, Remaining would be 4.
	Remaining int

	// ResetAfter is the time until the RateLimiter returns to its
	// initial state for a given key. For example, if a rate limiter
	// manages requests per second and received one request 200ms ago,
	// Reset would return 800ms. You can also think of this as the time
	// until Limit and Remaining will be equal.
	ResetAfter time.Duration

	// RetryAfter is the time until the next request will be permitted.
	// It should be -1 unless the rate limit has been exceeded.
	RetryAfter time.Duration
}

type limitResult struct {
	limited bool
}

func (r *limitResult) Limited() bool { return r.limited }

type rateLimitResult struct {
	limitResult

	limit, remaining  int
	reset, retryAfter time.Duration
}

func (r *rateLimitResult) Limit() int                { return r.limit }
func (r *rateLimitResult) Remaining() int            { return r.remaining }
func (r *rateLimitResult) Reset() time.Duration      { return r.reset }
func (r *rateLimitResult) RetryAfter() time.Duration { return r.retryAfter }

// Rate describes a frequency of an activity such as the number of requests
// allowed per minute.
type Rate struct {
	period time.Duration // Time between equally spaced requests at the rate
	count  int           // Used internally for deprecated `RateLimit` interface only
}

// RateQuota describes the number of requests allowed per time period.
// MaxRate specified the maximum sustained rate of requests and must
// be greater than zero. MaxBurst defines the number of requests that
// will be allowed to exceed the rate in a single burst and must be
// greater than or equal to zero.
//
// Rate{PerSec(1), 0} would mean that after each request, no more
// requests will be permitted for that client for one second.
// Rate{PerSec(2), 0} permits one request per 0.5 seconds rather than
// two requests in one second. In practice, you probably want to set
// MaxBurst >0 to provide some flexibility to clients that only need
// to make a handful of requests. In fact a MaxBurst of zero will
// *never* permit a request with a quantity greater than one because
// it will immediately exceed the limit.
type RateQuota struct {
	MaxRate  Rate
	MaxBurst int
}

// PerSec represents a number of requests per second.
func PerSec(n int) Rate { return Rate{time.Second / time.Duration(n), n} }

// PerMin represents a number of requests per minute.
func PerMin(n int) Rate { return Rate{time.Minute / time.Duration(n), n} }

// PerHour represents a number of requests per hour.
func PerHour(n int) Rate { return Rate{time.Hour / time.Duration(n), n} }

// PerDay represents a number of requests per day.
func PerDay(n int) Rate { return Rate{24 * time.Hour / time.Duration(n), n} }

// PerDuration represents a number of requests per provided duration.
func PerDuration(n int, d time.Duration) Rate { return Rate{d / time.Duration(n), n} }

// GCRARateLimiter is a RateLimiter that uses the generic cell-rate
// algorithm. The algorithm has been slightly modified from its usual
// form to support limiting with an additional quantity parameter, such
// as for limiting the number of bytes uploaded.
type GCRARateLimiter struct {
	limit int

	// Think of the DVT as our flexibility:
	// How far can you deviate from the nominal equally spaced schedule?
	// If you like leaky buckets, think about it as the size of your bucket.
	delayVariationTolerance time.Duration

	// Think of the emission interval as the time between events
	// in the nominal equally spaced schedule. If you like leaky buckets,
	// think of it as how frequently the bucket leaks one unit.
	emissionInterval time.Duration

	store GCRAStore

	// Maximum number of times to retry SetIfNotExists/CompareAndSwap operations
	// before returning an error.
	maxCASAttemptsLimit int
}

// NewGCRARateLimiter creates a GCRARateLimiter. quota.Count defines
// the maximum number of requests permitted in an instantaneous burst
// and quota.Count / quota.Period defines the maximum sustained
// rate. For example, PerMin(60) permits 60 requests instantly per key
// followed by one request per second indefinitely whereas PerSec(1)
// only permits one request per second with no tolerance for bursts.
func NewGCRARateLimiter(st GCRAStore, quota RateQuota) (*GCRARateLimiter, error) {
	if quota.MaxBurst < 0 {
		return nil, fmt.Errorf("invalid RateQuota %#v; MaxBurst must be greater than zero", quota)
	}
	if quota.MaxRate.period <= 0 {
		return nil, fmt.Errorf("invalid RateQuota %#v; MaxRate must be greater than zero", quota)
	}

	return &GCRARateLimiter{
		delayVariationTolerance: quota.MaxRate.period * (time.Duration(quota.MaxBurst) + 1),
		emissionInterval:        quota.MaxRate.period,
		limit:                   quota.MaxBurst + 1,
		store:                   st,
		maxCASAttemptsLimit:     maxCASAttempts,
	}, nil
}

// SetMaxCASAttemptsLimit allows you to set the maxCASAttempts limit. This is set to 10
// be default.
func (g *GCRARateLimiter) SetMaxCASAttemptsLimit(limit int) {
	g.maxCASAttemptsLimit = limit
}

// RateLimit checks whether a particular key has exceeded a rate
// limit. It also returns a RateLimitResult to provide additional
// information about the state of the RateLimiter.
//
// If the rate limit has not been exceeded, the underlying storage is
// updated by the supplied quantity. For example, a quantity of 1
// might be used to rate limit a single request while a greater
// quantity could rate limit based on the size of a file upload in
// megabytes. If quantity is 0, no update is performed allowing you
// to "peek" at the state of the RateLimiter for a given key.
func (g *GCRARateLimiter) RateLimit(key string, quantity int) (bool, RateLimitResult, error) {
	var tat, newTat, now time.Time
	var ttl time.Duration
	rlc := RateLimitResult{Limit: g.limit, RetryAfter: -1}
	limited := false

	i := 0
	for {
		var err error
		var tatVal int64
		var updated bool

		// tat refers to the theoretical arrival time that would be expected
		// from equally spaced requests at exactly the rate limit.
		tatVal, now, err = g.store.GetWithTime(key)
		if err != nil {
			return false, rlc, err
		}

		if tatVal == -1 {
			tat = now
		} else {
			tat = time.Unix(0, tatVal)
		}

		increment := time.Duration(quantity) * g.emissionInterval
		if now.After(tat) {
			newTat = now.Add(increment)
		} else {
			newTat = tat.Add(increment)
		}

		// Block the request if the next permitted time is in the future
		allowAt := newTat.Add(-(g.delayVariationTolerance))
		if diff := now.Sub(allowAt); diff < 0 {
			if increment <= g.delayVariationTolerance {
				rlc.RetryAfter = -diff
				ttl = tat.Sub(now)
			}
			limited = true
			break
		}

		ttl = newTat.Sub(now)

		if tatVal == -1 {
			updated, err = g.store.SetIfNotExistsWithTTL(key, newTat.UnixNano(), ttl)
		} else {
			updated, err = g.store.CompareAndSwapWithTTL(key, tatVal, newTat.UnixNano(), ttl)
		}

		if err != nil {
			return false, rlc, err
		}
		if updated {
			break
		}

		i++
		if i >= g.maxCASAttemptsLimit {
			return false, rlc, fmt.Errorf(
				"Failed to store updated rate limit data for key %s after %d attempts",
				key, i,
			)
		}
	}

	next := g.delayVariationTolerance - ttl
	if next > -g.emissionInterval {
		rlc.Remaining = int(next / g.emissionInterval)
	}
	rlc.ResetAfter = ttl

	return limited, rlc, nil
}
<|endoftext|>


<commit_before>package archive

import (
	"fmt"
	"io"
	"os"
	"path"

	"pault.ag/go/blobstore"
	"pault.ag/go/debian/control"
	"pault.ag/go/debian/deb"
)

type Pool struct {
	store blobstore.Store
	suite *Suite
}

func poolPrefix(source string) string {
	return path.Join(source[0:1], source)
}

func (p Pool) Copy(path string) (*blobstore.Object, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	writer, err := p.store.Create()
	if err != nil {
		return nil, err
	}
	defer writer.Close()

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

	obj, err := p.store.Commit(*writer)
	if err != nil {
		return nil, err
	}

	return obj, nil
}

func (p Pool) IncludeSources(dsc *control.DSC) (string, map[string]blobstore.Object, error) {
	files := map[string]blobstore.Object{}

	targetDir := path.Join("pool", poolPrefix(dsc.Source))

	for _, file := range dsc.Files {
		obj, err := p.Copy(file.Filename)
		if err != nil {
			return "", nil, err
		}

		localName := path.Base(file.Filename)
		files[path.Join(targetDir, localName)] = *obj
	}

	obj, err := p.Copy(dsc.Filename)
	if err != nil {
		return "", nil, err
	}

	localName := path.Base(dsc.Filename)
	files[path.Join(targetDir, localName)] = *obj

	for path, object := range files {
		if err := p.store.Link(object, path); err != nil {
			return "", nil, err
		}
	}

	return targetDir, files, nil
}

func (p Pool) IncludeDeb(debFile *deb.Deb) (string, *blobstore.Object, error) {
	obj, err := p.Copy(debFile.Path)
	if err != nil {
		return "", nil, err
	}

	debPath := path.Join(
		"pool",
		poolPrefix(debFile.Control.SourceName()),
		fmt.Sprintf(
			"%s_%s_%s.deb",
			debFile.Control.Package,
			debFile.Control.Version,
			debFile.Control.Architecture,
		),
	)

	return debPath, obj, p.store.Link(*obj, debPath)
}
<commit_msg>Update.<commit_after>package archive

import (
	"fmt"
	"io"
	"os"
	"path"

	"pault.ag/go/blobstore"
	"pault.ag/go/debian/control"
	"pault.ag/go/debian/deb"
)

type Pool struct {
	store blobstore.Store
	suite *Suite
}

func poolPrefix(source string) string {
	return path.Join(source[0:1], source)
}

func (p Pool) Copy(path string) (*blobstore.Object, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	writer, err := p.store.Create()
	if err != nil {
		return nil, err
	}
	defer writer.Close()

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

	obj, err := p.store.Commit(*writer)
	if err != nil {
		return nil, err
	}

	return obj, nil
}

func (p Pool) IncludeSources(dsc *control.DSC) (string, map[string]blobstore.Object, error) {
	files := map[string]blobstore.Object{}

	targetDir := path.Join("pool", poolPrefix(dsc.Source))

	for _, file := range dsc.Files {
		obj, err := p.Copy(file.Filename)
		if err != nil {
			return "", nil, err
		}

		localName := path.Base(file.Filename)
		files[path.Join(targetDir, localName)] = *obj
	}

	obj, err := p.Copy(dsc.Filename)
	if err != nil {
		return "", nil, err
	}

	localName := path.Base(dsc.Filename)
	files[path.Join(targetDir, localName)] = *obj

	for path, object := range files {
		if err := p.store.Link(object, path); err != nil {
			return "", nil, err
		}
	}

	return targetDir, files, nil
}

func (p Pool) IncludeDeb(debFile *deb.Deb) (string, *blobstore.Object, error) {
	obj, err := p.Copy(debFile.Path)
	if err != nil {
		return "", nil, err
	}

	debPath := path.Join(
		"pool",
		poolPrefix(debFile.Control.SourceName()),
		fmt.Sprintf(
			"%s_%s_%s.deb",
			debFile.Control.Package,
			debFile.Control.Version,
			debFile.Control.Architecture,
		),
	)

	return debPath, obj, p.store.Link(*obj, debPath)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"database/sql"
	"encoding/base32"
	"encoding/binary"
	"encoding/xml"
	"fmt"
	"github.com/bmizerany/pq"
	"log"
	"strings"
	"time"
)

var db *sql.DB

type Post struct {
	Id      uint64
	Html    string
	Posted  time.Time
	Created time.Time
	Deleted pq.NullTime
}

func NewPost() (p *Post) {
	p = &Post{0, "", time.Now(), time.Now().UTC(), pq.NullTime{time.Unix(0, 0), false}}
	return
}

func (p *Post) Permalink() string {
	return fmt.Sprintf("/post/%s", p.Slug())
}

func (p *Post) PostedTime() string {
	return p.Posted.Format("3:04")
}

func (p *Post) PostedAM() string {
	return p.Posted.Format("PM")
}

func (p *Post) PostedDate() string {
	return p.Posted.Format("_2 Jan 2006")
}

func (p *Post) PostedRSS() string {
	return p.Posted.UTC().Format(time.RFC1123)
}

func (p *Post) HtmlXML() string {
	var buf bytes.Buffer
	xml.Escape(&buf, []byte(p.Html))
	return buf.String()
}

func (p *Post) Slug() string {
	var binSlug [binary.MaxVarintLen64]byte
	n := binary.PutUvarint(binSlug[0:binary.MaxVarintLen64], uint64(p.Id))
	slug := base32.StdEncoding.EncodeToString(binSlug[:n])
	return strings.TrimRight(slug, "=")
}

func (p *Post) Save() (err error) {
	if p.Id == 0 {
		//var result sql.Result
		//result, err = db.Exec("INSERT INTO post (html, posted) VALUES ($1, $2) RETURNING id",
		row := db.QueryRow("INSERT INTO post (html, posted, created, deleted) VALUES ($1, $2, $3, $4) RETURNING id",
			p.Html, p.Posted, p.Created, p.Deleted)
		var id uint64
		err = row.Scan(&id)
		if err != nil {
			return err
		}
		p.Id = id
	} else {
		_, err = db.Exec("UPDATE post SET html = $2, posted = $3, created = $4, deleted = $5 WHERE id = $1",
			p.Id, p.Html, p.Posted, p.Created, p.Deleted)
	}
	return nil
}

func (p *Post) MarkDeleted() (err error) {
	p.Deleted = pq.NullTime{time.Now().UTC(), true}
	return p.Save()
}

func PostById(id uint64) (*Post, error) {
	row := db.QueryRow("SELECT html, posted, created FROM post WHERE id = $1 AND deleted IS NULL", id)

	var html string
	var posted time.Time
	var created time.Time
	err := row.Scan(&html, &posted, &created)
	if err != nil {
		log.Println("Error querying database for post #", id, ":", err.Error())
		return nil, err
	}

	deleted := pq.NullTime{time.Unix(0, 0), false}
	post := &Post{id, html, posted, created, deleted}
	return post, nil
}

func PostBySlug(slug string) (*Post, error) {
	log.Println("Finding post id from slug", slug)

	// The decoder will want an even multiple of 8 bytes.
	padLen := 8 - (len(slug) % 8)
	slug += strings.Repeat("=", padLen)

	binSlug, err := base32.StdEncoding.DecodeString(slug)
	if err != nil {
		return nil, err
	}

	id, n := binary.Uvarint(binSlug)
	if n <= 0 {
		return nil, fmt.Errorf("Read %d bytes decoding slug code %s", n, slug)
	}
	log.Println("Yay, reckoned slug", slug, "is id", id, ", looking up")

	return PostById(id)
}

func RecentPosts(count int) ([]*Post, error) {
	rows, err := db.Query("SELECT id, html, posted, created FROM post WHERE deleted IS NULL ORDER BY posted DESC LIMIT 10")
	if err != nil {
		log.Println("Error querying database for", count, "posts:", err.Error())
		return nil, err
	}

	log.Println("Deserializing all the returned posts")
	posts := make([]*Post, 0, count)
	var id uint64
	var html string
	var posted time.Time
	var created time.Time
	i := 0
	for rows.Next() {
		err = rows.Scan(&id, &html, &posted, &created)
		if err != nil {
			log.Println("Error scanning row", i, ":", err.Error())
			return nil, err
		}

		posts = posts[0 : i+1]
		posts[i] = &Post{id, html, posted, created, pq.NullTime{time.Unix(0, 0), false}}
		i++
	}

	err = rows.Err()
	if err != nil {
		log.Println("Error lookin' at rows:", err.Error())
		return nil, err
	}

	return posts, nil
}
<commit_msg>rm unused comment<commit_after>package main

import (
	"bytes"
	"database/sql"
	"encoding/base32"
	"encoding/binary"
	"encoding/xml"
	"fmt"
	"github.com/bmizerany/pq"
	"log"
	"strings"
	"time"
)

var db *sql.DB

type Post struct {
	Id      uint64
	Html    string
	Posted  time.Time
	Created time.Time
	Deleted pq.NullTime
}

func NewPost() (p *Post) {
	p = &Post{0, "", time.Now(), time.Now().UTC(), pq.NullTime{time.Unix(0, 0), false}}
	return
}

func (p *Post) Permalink() string {
	return fmt.Sprintf("/post/%s", p.Slug())
}

func (p *Post) PostedTime() string {
	return p.Posted.Format("3:04")
}

func (p *Post) PostedAM() string {
	return p.Posted.Format("PM")
}

func (p *Post) PostedDate() string {
	return p.Posted.Format("_2 Jan 2006")
}

func (p *Post) PostedRSS() string {
	return p.Posted.UTC().Format(time.RFC1123)
}

func (p *Post) HtmlXML() string {
	var buf bytes.Buffer
	xml.Escape(&buf, []byte(p.Html))
	return buf.String()
}

func (p *Post) Slug() string {
	var binSlug [binary.MaxVarintLen64]byte
	n := binary.PutUvarint(binSlug[0:binary.MaxVarintLen64], uint64(p.Id))
	slug := base32.StdEncoding.EncodeToString(binSlug[:n])
	return strings.TrimRight(slug, "=")
}

func (p *Post) Save() (err error) {
	if p.Id == 0 {
		row := db.QueryRow("INSERT INTO post (html, posted, created, deleted) VALUES ($1, $2, $3, $4) RETURNING id",
			p.Html, p.Posted, p.Created, p.Deleted)
		var id uint64
		err = row.Scan(&id)
		if err != nil {
			return err
		}
		p.Id = id
	} else {
		_, err = db.Exec("UPDATE post SET html = $2, posted = $3, created = $4, deleted = $5 WHERE id = $1",
			p.Id, p.Html, p.Posted, p.Created, p.Deleted)
	}
	return nil
}

func (p *Post) MarkDeleted() (err error) {
	p.Deleted = pq.NullTime{time.Now().UTC(), true}
	return p.Save()
}

func PostById(id uint64) (*Post, error) {
	row := db.QueryRow("SELECT html, posted, created FROM post WHERE id = $1 AND deleted IS NULL", id)

	var html string
	var posted time.Time
	var created time.Time
	err := row.Scan(&html, &posted, &created)
	if err != nil {
		log.Println("Error querying database for post #", id, ":", err.Error())
		return nil, err
	}

	deleted := pq.NullTime{time.Unix(0, 0), false}
	post := &Post{id, html, posted, created, deleted}
	return post, nil
}

func PostBySlug(slug string) (*Post, error) {
	log.Println("Finding post id from slug", slug)

	// The decoder will want an even multiple of 8 bytes.
	padLen := 8 - (len(slug) % 8)
	slug += strings.Repeat("=", padLen)

	binSlug, err := base32.StdEncoding.DecodeString(slug)
	if err != nil {
		return nil, err
	}

	id, n := binary.Uvarint(binSlug)
	if n <= 0 {
		return nil, fmt.Errorf("Read %d bytes decoding slug code %s", n, slug)
	}
	log.Println("Yay, reckoned slug", slug, "is id", id, ", looking up")

	return PostById(id)
}

func RecentPosts(count int) ([]*Post, error) {
	rows, err := db.Query("SELECT id, html, posted, created FROM post WHERE deleted IS NULL ORDER BY posted DESC LIMIT 10")
	if err != nil {
		log.Println("Error querying database for", count, "posts:", err.Error())
		return nil, err
	}

	log.Println("Deserializing all the returned posts")
	posts := make([]*Post, 0, count)
	var id uint64
	var html string
	var posted time.Time
	var created time.Time
	i := 0
	for rows.Next() {
		err = rows.Scan(&id, &html, &posted, &created)
		if err != nil {
			log.Println("Error scanning row", i, ":", err.Error())
			return nil, err
		}

		posts = posts[0 : i+1]
		posts[i] = &Post{id, html, posted, created, pq.NullTime{time.Unix(0, 0), false}}
		i++
	}

	err = rows.Err()
	if err != nil {
		log.Println("Error lookin' at rows:", err.Error())
		return nil, err
	}

	return posts, nil
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"io"
	"os"
	"strings"
	"sync"

	"golang.org/x/tools/oracle"
)

var srcPackage string

func init() {
	flag.StringVar(&srcPackage, "src", "", "Source package, to load types from")
	flag.Usage = func() {
		fmt.Println("Searchs for public types declared in the source package that are unused in the given import paths.")
		fmt.Printf("\nUsage of %s:\n\n", os.Args[0])
		fmt.Printf("%s [flags] <import_path1> [import_path2] ... [import_path3]\n\n", os.Args[0])
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}
	flag.Parse()
}

type OraclePos struct {
	Identifier string
	Pos        string
	Filename   string
	Line       int
	Column     int
}

func getOraclePos(position token.Position) OraclePos {
	return OraclePos{
		Pos:      fmt.Sprintf("%s:#%d", position.Filename, position.Offset),
		Filename: position.Filename,
		Line:     position.Line,
		Column:   position.Column,
	}
}

func positionToStr(position token.Position) string {
	return fmt.Sprintf("%s:#%d", position.Filename, position.Offset)
}

func getFuncs(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, len(pkg.Funcs))
	for i, function := range pkg.Funcs {
		pos := function.Decl.Name.Pos()
		opos := getOraclePos(fileSet.Position(pos))
		opos.Identifier = function.Name
		result[i] = opos
	}
	return result
}

func getTypes(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Types))
	for _, tp := range pkg.Types {
		for _, spec := range tp.Decl.Specs {
			pos := spec.(*ast.TypeSpec).Name.Pos()
			opos := getOraclePos(fileSet.Position(pos))
			opos.Identifier = tp.Name
			result = append(result, opos)
		}
		for _, method := range tp.Methods {
			pos := method.Decl.Name.Pos()
			opos := getOraclePos(fileSet.Position(pos))
			opos.Identifier = method.Name
			result = append(result, opos)
		}
	}
	return result
}

func getConsts(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Consts))
	for _, constant := range pkg.Consts {
		for _, spec := range constant.Decl.Specs {
			for _, name := range spec.(*ast.ValueSpec).Names {
				position := fileSet.Position(name.Pos())
				opos := getOraclePos(position)
				opos.Identifier = name.Name
				result = append(result, opos)
			}
		}
	}
	return result
}

func getVars(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Vars))
	for _, variable := range pkg.Vars {
		for _, spec := range variable.Decl.Specs {
			for _, name := range spec.(*ast.ValueSpec).Names {
				position := fileSet.Position(name.Pos())
				opos := getOraclePos(position)
				opos.Identifier = name.Name
				result = append(result, opos)
			}
		}
	}
	return result
}

func loadDir(dir string, includeTests bool) ([]OraclePos, error) {
	filter := func(fi os.FileInfo) bool {
		return includeTests || !strings.Contains(fi.Name(), "_test")
	}
	fileSet := token.NewFileSet()
	pkgs, err := parser.ParseDir(fileSet, dir, filter, 0)
	if err != nil {
		return nil, err
	}
	var result []OraclePos
	for name, pkg := range pkgs {
		docPkg := doc.New(pkg, name, 0)
		result = append(result, getConsts(fileSet, docPkg)...)
		result = append(result, getVars(fileSet, docPkg)...)
		result = append(result, getTypes(fileSet, docPkg)...)
		result = append(result, getFuncs(fileSet, docPkg)...)
	}
	return result, nil
}

func runPackage(srcPackage string, dstPackages []string, output io.Writer) error {
	var status int
	dirName := strings.TrimRight(build.Default.GOPATH, "/") + "/src/" + srcPackage
	items, err := loadDir(dirName, false)
	if err != nil {
		return err
	}
	var wg sync.WaitGroup
	errs := make(chan error, len(items))
	finish := make(chan int)
	for _, item := range items {
		wg.Add(1)
		go func(item OraclePos) {
			defer wg.Done()
			result, err := oracle.Query(dstPackages, "referrers", item.Pos, nil, &build.Default, true)
			if err != nil {
				msg := err.Error()
				if msg == "no identifier here" {
					msg = fmt.Sprintf("%s:%d:%d - %s", item.Filename, item.Line, item.Column, msg)
				}
				errs <- fmt.Errorf(msg)
			}
			if len(result.Serial().Referrers.Refs) < 1 {
				errs <- fmt.Errorf("%s:%d:%d: %s is unused", item.Filename, item.Line, item.Column, item.Identifier)
			}
		}(item)
	}
	go func() {
		wg.Wait()
		close(finish)
	}()
	for {
		select {
		case err := <-errs:
			fmt.Fprintln(output, err)
			status = 1
		case <-finish:
			os.Exit(status)
		}
	}
}

func main() {
	flag.Parse()
	dstPackages := flag.Args()
	runPackage(srcPackage, dstPackages, os.Stderr)
}
<commit_msg>pray: fix copyright notice<commit_after>// Copyright 2015 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/parser"
	"go/token"
	"io"
	"os"
	"strings"
	"sync"

	"golang.org/x/tools/oracle"
)

var srcPackage string

func init() {
	flag.StringVar(&srcPackage, "src", "", "Source package, to load types from")
	flag.Usage = func() {
		fmt.Println("Searchs for public types declared in the source package that are unused in the given import paths.")
		fmt.Printf("\nUsage of %s:\n\n", os.Args[0])
		fmt.Printf("%s [flags] <import_path1> [import_path2] ... [import_path3]\n\n", os.Args[0])
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}
	flag.Parse()
}

type OraclePos struct {
	Identifier string
	Pos        string
	Filename   string
	Line       int
	Column     int
}

func getOraclePos(position token.Position) OraclePos {
	return OraclePos{
		Pos:      fmt.Sprintf("%s:#%d", position.Filename, position.Offset),
		Filename: position.Filename,
		Line:     position.Line,
		Column:   position.Column,
	}
}

func positionToStr(position token.Position) string {
	return fmt.Sprintf("%s:#%d", position.Filename, position.Offset)
}

func getFuncs(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, len(pkg.Funcs))
	for i, function := range pkg.Funcs {
		pos := function.Decl.Name.Pos()
		opos := getOraclePos(fileSet.Position(pos))
		opos.Identifier = function.Name
		result[i] = opos
	}
	return result
}

func getTypes(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Types))
	for _, tp := range pkg.Types {
		for _, spec := range tp.Decl.Specs {
			pos := spec.(*ast.TypeSpec).Name.Pos()
			opos := getOraclePos(fileSet.Position(pos))
			opos.Identifier = tp.Name
			result = append(result, opos)
		}
		for _, method := range tp.Methods {
			pos := method.Decl.Name.Pos()
			opos := getOraclePos(fileSet.Position(pos))
			opos.Identifier = method.Name
			result = append(result, opos)
		}
	}
	return result
}

func getConsts(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Consts))
	for _, constant := range pkg.Consts {
		for _, spec := range constant.Decl.Specs {
			for _, name := range spec.(*ast.ValueSpec).Names {
				position := fileSet.Position(name.Pos())
				opos := getOraclePos(position)
				opos.Identifier = name.Name
				result = append(result, opos)
			}
		}
	}
	return result
}

func getVars(fileSet *token.FileSet, pkg *doc.Package) []OraclePos {
	result := make([]OraclePos, 0, len(pkg.Vars))
	for _, variable := range pkg.Vars {
		for _, spec := range variable.Decl.Specs {
			for _, name := range spec.(*ast.ValueSpec).Names {
				position := fileSet.Position(name.Pos())
				opos := getOraclePos(position)
				opos.Identifier = name.Name
				result = append(result, opos)
			}
		}
	}
	return result
}

func loadDir(dir string, includeTests bool) ([]OraclePos, error) {
	filter := func(fi os.FileInfo) bool {
		return includeTests || !strings.Contains(fi.Name(), "_test")
	}
	fileSet := token.NewFileSet()
	pkgs, err := parser.ParseDir(fileSet, dir, filter, 0)
	if err != nil {
		return nil, err
	}
	var result []OraclePos
	for name, pkg := range pkgs {
		docPkg := doc.New(pkg, name, 0)
		result = append(result, getConsts(fileSet, docPkg)...)
		result = append(result, getVars(fileSet, docPkg)...)
		result = append(result, getTypes(fileSet, docPkg)...)
		result = append(result, getFuncs(fileSet, docPkg)...)
	}
	return result, nil
}

func runPackage(srcPackage string, dstPackages []string, output io.Writer) error {
	var status int
	dirName := strings.TrimRight(build.Default.GOPATH, "/") + "/src/" + srcPackage
	items, err := loadDir(dirName, false)
	if err != nil {
		return err
	}
	var wg sync.WaitGroup
	errs := make(chan error, len(items))
	finish := make(chan int)
	for _, item := range items {
		wg.Add(1)
		go func(item OraclePos) {
			defer wg.Done()
			result, err := oracle.Query(dstPackages, "referrers", item.Pos, nil, &build.Default, true)
			if err != nil {
				msg := err.Error()
				if msg == "no identifier here" {
					msg = fmt.Sprintf("%s:%d:%d - %s", item.Filename, item.Line, item.Column, msg)
				}
				errs <- fmt.Errorf(msg)
			}
			if len(result.Serial().Referrers.Refs) < 1 {
				errs <- fmt.Errorf("%s:%d:%d: %s is unused", item.Filename, item.Line, item.Column, item.Identifier)
			}
		}(item)
	}
	go func() {
		wg.Wait()
		close(finish)
	}()
	for {
		select {
		case err := <-errs:
			fmt.Fprintln(output, err)
			status = 1
		case <-finish:
			os.Exit(status)
		}
	}
}

func main() {
	flag.Parse()
	dstPackages := flag.Args()
	runPackage(srcPackage, dstPackages, os.Stderr)
}
<|endoftext|>


<commit_before>package modd

import (
	"bufio"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/cortesi/modd/conf"
	"github.com/cortesi/modd/filter"
	"github.com/cortesi/termlog"
)

const moddMarker = "|MODD|"

// MinRestart is the minimum amount of time between daemon restarts
const MinRestart = 1 * time.Second

const lineLimit = 80

// quotePath quotes a path for use on the command-line
func quotePath(path string) string {
	path = strings.Replace(path, "\"", "\\\"", -1)
	return "\"" + path + "\""
}

// mkArgs prepares a list of paths for the command line
func mkArgs(paths []string) string {
	escaped := make([]string, len(paths))
	for i, s := range paths {
		escaped[i] = quotePath(s)
	}
	return strings.Join(escaped, " ")
}

// shortCommand shortens a command to a name we can use in a notification
// header.
func shortCommand(command string) string {
	ret := command
	parts := strings.Split(command, "\n")
	for _, i := range parts {
		i = strings.TrimLeft(i, " \t#")
		i = strings.TrimRight(i, " \t\\")
		if i != "" {
			ret = i
			break
		}
	}
	return ret
}

// niceHeader tries to produce a nicer process name. We condense whitespace to
// make commands split over multiple lines with indentation more legible, and
// limit the line length to 80 characters.
func niceHeader(preamble string, command string) string {
	pre := termlog.DefaultPalette.Timestamp.SprintFunc()(preamble)
	command = termlog.DefaultPalette.Header.SprintFunc()(shortCommand(command))
	return pre + command
}

func getShell() string {
	return "/bin/sh"
}

func logOutput(fp io.ReadCloser, out func(string, ...interface{})) {
	r := bufio.NewReader(fp)
	for {
		line, _, err := r.ReadLine()
		if err != nil {
			return
		}
		out(string(line))
	}
}

// RunProc runs a process to completion, sending output to log
func RunProc(cmd string, log termlog.Stream) error {
	log.Header()
	sh := getShell()
	c := exec.Command(sh, "-c", cmd)
	stdo, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	stde, err := c.StderrPipe()
	if err != nil {
		return err
	}
	go logOutput(stde, log.Warn)
	go logOutput(stdo, log.Say)
	err = c.Start()
	if err != nil {
		return err
	}
	err = c.Wait()
	if err != nil {
		log.Shout("%s", c.ProcessState.String())
		return err
	}
	// FIXME: rusage stats here
	log.NoticeAs("cmdstats", "run time: %s", c.ProcessState.UserTime())
	return nil
}

// RunPreps runs all commands in sequence. Stops if any command returns an error.
func RunPreps(b conf.Block, mod *Mod, log termlog.TermLog) error {
	var fargs *string
	for _, p := range b.Preps {
		cmd := p.Command
		if strings.Contains(cmd, moddMarker) {
			// We only want to calculate this once
			if fargs == nil {
				var modified []string
				var err error
				if mod != nil {
					modified = mod.All()
				} else {
					modified, err = filter.Find(".", b.Include, b.Exclude)
					if err != nil {
						return err
					}
				}
				args := mkArgs(modified)
				fargs = &args
			}
			cmd = strings.Replace(cmd, moddMarker, *fargs, -1)
		}
		err := RunProc(cmd, log.Stream(niceHeader("prep: ", p.Command)))
		if err != nil {
			return err
		}
	}
	return nil
}

type daemon struct {
	conf conf.Daemon
	log  termlog.Stream
	cmd  *exec.Cmd
	stop bool
}

func (d *daemon) Run() {
	var lastStart time.Time
	for d.stop != true {
		d.log.Header()
		since := time.Now().Sub(lastStart)
		if since < MinRestart {
			time.Sleep(MinRestart - since)
		}
		lastStart = time.Now()
		sh := getShell()
		c := exec.Command(sh, "-c", d.conf.Command)
		stdo, err := c.StdoutPipe()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		stde, err := c.StderrPipe()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		go logOutput(stde, d.log.Warn)
		go logOutput(stdo, d.log.Say)
		err = c.Start()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		d.cmd = c
		err = c.Wait()
		if err != nil {
			d.log.Shout("%s", c.ProcessState.String())
			continue
		}
	}
}

func (d *daemon) Restart() {
	if d.cmd != nil {
		d.log.Header()
		d.cmd.Process.Signal(d.conf.RestartSignal)
	}
}

func (d *daemon) Shutdown(sig os.Signal) {
	d.stop = true
	if d.cmd != nil {
		d.cmd.Process.Signal(sig)
		d.cmd.Wait()
	}
}

// DaemonPen is a group of daemons, managed as a unit.
type DaemonPen struct {
	daemons *[]daemon
	sync.Mutex
}

var ws = regexp.MustCompile(`\s\s+`)

// Start starts set of daemons, each specified by a command
func (dp *DaemonPen) Start(daemons []conf.Daemon, log termlog.TermLog) {
	dp.Lock()
	defer dp.Unlock()
	d := make([]daemon, len(daemons))
	for i, dmn := range daemons {
		d[i] = daemon{
			conf: dmn,
			log: log.Stream(
				niceHeader("daemon: ", dmn.Command),
			),
		}
		go d[i].Run()
	}
	dp.daemons = &d
}

// Restart all daemons in the pen
func (dp *DaemonPen) Restart() {
	dp.Lock()
	defer dp.Unlock()
	if dp.daemons != nil {
		for _, d := range *dp.daemons {
			d.Restart()
		}
	}
}

// Shutdown all daemons in the pen
func (dp *DaemonPen) Shutdown(sig os.Signal) {
	dp.Lock()
	defer dp.Unlock()
	if dp.daemons != nil {
		for _, d := range *dp.daemons {
			d.Shutdown(sig)
		}
	}
}
<commit_msg>Change default shell from sh to bash<commit_after>package modd

import (
	"bufio"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/cortesi/modd/conf"
	"github.com/cortesi/modd/filter"
	"github.com/cortesi/termlog"
)

const moddMarker = "|MODD|"

// MinRestart is the minimum amount of time between daemon restarts
const MinRestart = 1 * time.Second

const lineLimit = 80

// quotePath quotes a path for use on the command-line
func quotePath(path string) string {
	path = strings.Replace(path, "\"", "\\\"", -1)
	return "\"" + path + "\""
}

// mkArgs prepares a list of paths for the command line
func mkArgs(paths []string) string {
	escaped := make([]string, len(paths))
	for i, s := range paths {
		escaped[i] = quotePath(s)
	}
	return strings.Join(escaped, " ")
}

// shortCommand shortens a command to a name we can use in a notification
// header.
func shortCommand(command string) string {
	ret := command
	parts := strings.Split(command, "\n")
	for _, i := range parts {
		i = strings.TrimLeft(i, " \t#")
		i = strings.TrimRight(i, " \t\\")
		if i != "" {
			ret = i
			break
		}
	}
	return ret
}

// niceHeader tries to produce a nicer process name. We condense whitespace to
// make commands split over multiple lines with indentation more legible, and
// limit the line length to 80 characters.
func niceHeader(preamble string, command string) string {
	pre := termlog.DefaultPalette.Timestamp.SprintFunc()(preamble)
	command = termlog.DefaultPalette.Header.SprintFunc()(shortCommand(command))
	return pre + command
}

func getShell() string {
	return "bash"
}

func logOutput(fp io.ReadCloser, out func(string, ...interface{})) {
	r := bufio.NewReader(fp)
	for {
		line, _, err := r.ReadLine()
		if err != nil {
			return
		}
		out(string(line))
	}
}

// RunProc runs a process to completion, sending output to log
func RunProc(cmd string, log termlog.Stream) error {
	log.Header()
	sh := getShell()
	c := exec.Command(sh, "-c", cmd)
	stdo, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	stde, err := c.StderrPipe()
	if err != nil {
		return err
	}
	go logOutput(stde, log.Warn)
	go logOutput(stdo, log.Say)
	err = c.Start()
	if err != nil {
		return err
	}
	err = c.Wait()
	if err != nil {
		log.Shout("%s", c.ProcessState.String())
		return err
	}
	// FIXME: rusage stats here
	log.NoticeAs("cmdstats", "run time: %s", c.ProcessState.UserTime())
	return nil
}

// RunPreps runs all commands in sequence. Stops if any command returns an error.
func RunPreps(b conf.Block, mod *Mod, log termlog.TermLog) error {
	var fargs *string
	for _, p := range b.Preps {
		cmd := p.Command
		if strings.Contains(cmd, moddMarker) {
			// We only want to calculate this once
			if fargs == nil {
				var modified []string
				var err error
				if mod != nil {
					modified = mod.All()
				} else {
					modified, err = filter.Find(".", b.Include, b.Exclude)
					if err != nil {
						return err
					}
				}
				args := mkArgs(modified)
				fargs = &args
			}
			cmd = strings.Replace(cmd, moddMarker, *fargs, -1)
		}
		err := RunProc(cmd, log.Stream(niceHeader("prep: ", p.Command)))
		if err != nil {
			return err
		}
	}
	return nil
}

type daemon struct {
	conf conf.Daemon
	log  termlog.Stream
	cmd  *exec.Cmd
	stop bool
}

func (d *daemon) Run() {
	var lastStart time.Time
	for d.stop != true {
		d.log.Header()
		since := time.Now().Sub(lastStart)
		if since < MinRestart {
			time.Sleep(MinRestart - since)
		}
		lastStart = time.Now()
		sh := getShell()
		c := exec.Command(sh, "-c", d.conf.Command)
		stdo, err := c.StdoutPipe()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		stde, err := c.StderrPipe()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		go logOutput(stde, d.log.Warn)
		go logOutput(stdo, d.log.Say)
		err = c.Start()
		if err != nil {
			d.log.Shout("%s", err)
			continue
		}
		d.cmd = c
		err = c.Wait()
		if err != nil {
			d.log.Shout("%s", c.ProcessState.String())
			continue
		}
	}
}

func (d *daemon) Restart() {
	if d.cmd != nil {
		d.log.Header()
		d.cmd.Process.Signal(d.conf.RestartSignal)
	}
}

func (d *daemon) Shutdown(sig os.Signal) {
	d.stop = true
	if d.cmd != nil {
		d.cmd.Process.Signal(sig)
		d.cmd.Wait()
	}
}

// DaemonPen is a group of daemons, managed as a unit.
type DaemonPen struct {
	daemons *[]daemon
	sync.Mutex
}

var ws = regexp.MustCompile(`\s\s+`)

// Start starts set of daemons, each specified by a command
func (dp *DaemonPen) Start(daemons []conf.Daemon, log termlog.TermLog) {
	dp.Lock()
	defer dp.Unlock()
	d := make([]daemon, len(daemons))
	for i, dmn := range daemons {
		d[i] = daemon{
			conf: dmn,
			log: log.Stream(
				niceHeader("daemon: ", dmn.Command),
			),
		}
		go d[i].Run()
	}
	dp.daemons = &d
}

// Restart all daemons in the pen
func (dp *DaemonPen) Restart() {
	dp.Lock()
	defer dp.Unlock()
	if dp.daemons != nil {
		for _, d := range *dp.daemons {
			d.Restart()
		}
	}
}

// Shutdown all daemons in the pen
func (dp *DaemonPen) Shutdown(sig os.Signal) {
	dp.Lock()
	defer dp.Unlock()
	if dp.daemons != nil {
		for _, d := range *dp.daemons {
			d.Shutdown(sig)
		}
	}
}
<|endoftext|>


<commit_before>// Alexandria
//
// Copyright (C) 2015-2016  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package alexandria

import (
	"fmt"
	"strings"
)

// Figure out what type of a document we have
func DocumentType(m Metadata) string {
	return m.Type
}

// Return the lines of the last LaTeX comment block without the leading %.  In
// addition, leading and trailing whitespace is removed.
func findMetadataLines(doc string) []string {
	var metadata []string
	for _, line_ := range strings.Split(doc, "\n") {
		line := strings.TrimSpace(line_)
		if line == "" {
			continue
		}

		// If the current line does not begin with a LaTeX comment, we
		// have not yet encountered the last block of comments, so we
		// should discard all data gathered so far.
		if line[0] != '%' {
			metadata = make([]string, 0, 10)
			continue
		}
		// Remove any leading % and whitespaces
		line = strings.TrimLeft(line, "%  \t")
		if line != "" {
			metadata = append(metadata, line)
		}
	}
	return metadata
}

// Parse a comma separated list of tags into a slice, tranfsorming everything
// to lower case.
func parseTags(line string) []string {
	var tags []string
	for _, tag := range strings.Split(line, ",") {
		tmp := strings.ToLower(strings.TrimSpace(tag))
		if tmp != "" {
			tags = append(tags, tmp)
		}
	}
	return tags
}

// Parse the tags in the given scroll content.  The format of a scroll is
// generally of the following form:
//
//	\LaTeX\ code ...
//
//	% @source Author: Title
//	% @source Lemma 3.2, p. 41
//	% @type proposition
//	% counter-example, analysis, TopOloGY, Weierstraß
//
// In this example, the scroll contains a proposition and is tagged with
// 'counter-example', 'analysis', 'topology' and 'weierstraß'.  It can be found
// in Author: Title as Lemma 3.2 on pase 41.  All the metadata is stored in the
// final block of LaTeX comments.  Also, we simply ignore any empty lines.
func ParseMetadata(doc string) Metadata {
	// TODO Handle different types of tags: @source, @doctype, @keywords, and normal tags.
	var source []string
	var scroll_type string
	var tags []string

	for _, line := range findMetadataLines(doc) {
		switch {
		case strings.HasPrefix(line, "@source "):
			source = append(source, strings.TrimSpace(strings.TrimPrefix(line, "@source ")))
		case strings.HasPrefix(line, "@type "):
			tmp := strings.TrimSpace(strings.TrimPrefix(line, "@type "))
			if scroll_type != "" {
				panic(fmt.Sprintf("Scroll has two different types: %s and %s", scroll_type, tmp))
			} else {
				scroll_type = tmp
			}
		default:
			tags = append(tags, parseTags(line)...)
		}
	}

	return Metadata{scroll_type, source, tags}
}
<commit_msg>Allow the metadata block to be up to 100 lines<commit_after>// Alexandria
//
// Copyright (C) 2015-2016  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package alexandria

import (
	"fmt"
	"strings"
)

// Figure out what type of a document we have
func DocumentType(m Metadata) string {
	return m.Type
}

// Return the lines of the last LaTeX comment block without the leading %.  In
// addition, leading and trailing whitespace is removed.
func findMetadataLines(doc string) []string {
	var metadata []string
	for _, line_ := range strings.Split(doc, "\n") {
		line := strings.TrimSpace(line_)
		if line == "" {
			continue
		}

		// If the current line does not begin with a LaTeX comment, we
		// have not yet encountered the last block of comments, so we
		// should discard all data gathered so far.
		if line[0] != '%' {
			metadata = make([]string, 0, 100) // FIXME magic constant
			continue
		}
		// Remove any leading % and whitespaces
		line = strings.TrimLeft(line, "%  \t")
		if line != "" {
			metadata = append(metadata, line)
		}
	}
	return metadata
}

// Parse a comma separated list of tags into a slice, tranfsorming everything
// to lower case.
func parseTags(line string) []string {
	var tags []string
	for _, tag := range strings.Split(line, ",") {
		tmp := strings.ToLower(strings.TrimSpace(tag))
		if tmp != "" {
			tags = append(tags, tmp)
		}
	}
	return tags
}

// Parse the tags in the given scroll content.  The format of a scroll is
// generally of the following form:
//
//	\LaTeX\ code ...
//
//	% @source Author: Title
//	% @source Lemma 3.2, p. 41
//	% @type proposition
//	% counter-example, analysis, TopOloGY, Weierstraß
//
// In this example, the scroll contains a proposition and is tagged with
// 'counter-example', 'analysis', 'topology' and 'weierstraß'.  It can be found
// in Author: Title as Lemma 3.2 on pase 41.  All the metadata is stored in the
// final block of LaTeX comments.  Also, we simply ignore any empty lines.
func ParseMetadata(doc string) Metadata {
	// TODO Handle different types of tags: @source, @doctype, @keywords, and normal tags.
	var source []string
	var scroll_type string
	var tags []string

	for _, line := range findMetadataLines(doc) {
		switch {
		case strings.HasPrefix(line, "@source "):
			source = append(source, strings.TrimSpace(strings.TrimPrefix(line, "@source ")))
		case strings.HasPrefix(line, "@type "):
			tmp := strings.TrimSpace(strings.TrimPrefix(line, "@type "))
			if scroll_type != "" {
				panic(fmt.Sprintf("Scroll has two different types: %s and %s", scroll_type, tmp))
			} else {
				scroll_type = tmp
			}
		default:
			tags = append(tags, parseTags(line)...)
		}
	}

	return Metadata{scroll_type, source, tags}
}
<|endoftext|>


<commit_before>package rect

// Package rect implements utilities for manipulating axis aligned 2d rectangles

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

type Coord struct {
	X, Y int
}

func Add(lhs, rhs Coord) Coord {
	return Coord{lhs.X + rhs.X, lhs.Y + rhs.Y}
}

func (c *Coord) Add(rhs Coord) {
	c.X += rhs.X
	c.Y += rhs.Y
}

func Sub(lhs, rhs Coord) Coord {
	return Coord{lhs.X - rhs.X, lhs.Y - rhs.Y}
}

func (c *Coord) Sub(rhs Coord) {
	c.X -= rhs.X
	c.Y -= rhs.Y
}

type Rectangle struct {
	Min, Max Coord
}

func XYWH(x, y, w, h int) Rectangle {
	return Rectangle{Coord{x, y}, Coord{x + w, y + h}}
}

func XYXY(x1, y1, x2, y2 int) Rectangle {
	return Normalise(Rectangle{Coord{x1, y1}, Coord{x2, y2}})
}

func FromPosSize(pos, size Coord) Rectangle {
	return Rectangle{pos, Add(pos, size)}
}

func FromSize(size Coord) Rectangle {
	return Rectangle{Max: size}
}

func (r *Rectangle) Normalise() {
	if r.Min.X > r.Max.X {
		r.Min.X, r.Max.X = r.Max.X, r.Min.X
	}

	if r.Min.Y > r.Max.Y {
		r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
	}
}

func Normalise(r Rectangle) Rectangle {
	r.Normalise()
	return r
}

func (r *Rectangle) Width() int {
	return r.Max.X - r.Min.X
}

func (r *Rectangle) Height() int {
	return r.Max.Y - r.Min.Y
}

func (r *Rectangle) Size() Coord {
	return Coord{r.Width(), r.Height()}
}

func (r *Rectangle) IsEmpty() bool {
	return (r.Min.X == r.Max.X) || (r.Min.Y == r.Max.Y)
}

func (r *Rectangle) IsNormal() bool {
	return (r.Min.X <= r.Max.X) && (r.Min.Y <= r.Max.Y)
}

func (r *Rectangle) Expand(c Coord) {
	r.Min.Sub(c)
	r.Max.Add(c)
}

func Expand(r Rectangle, c Coord) Rectangle {
	r.Expand(c)
	return r
}

func (r *Rectangle) Translate(c Coord) {
	r.Min.Add(c)
	r.Max.Add(c)
}

func Translate(r Rectangle, c Coord) Rectangle {
	r.Translate(c)
	return r
}

func PointInRectangle(r Rectangle, p Coord) bool {
	return (r.Min.X <= p.X) && (r.Min.Y <= p.Y) && (p.X < r.Max.X) && (p.Y < r.Max.Y)
}

func Intersection(r1, r2 Rectangle) (intersect Rectangle, ok bool) {
	intersect = Rectangle{
		Min: Coord{max(r1.Min.X, r2.Min.X), max(r1.Min.Y, r2.Min.Y)},
		Max: Coord{min(r1.Max.X, r2.Max.X), min(r1.Max.Y, r2.Max.Y)},
	}

	ok = intersect.IsNormal()
	return
}

func Union(r1, r2 Rectangle) Rectangle {
	return Rectangle{
		Min: Coord{min(r1.Min.X, r2.Min.X), min(r1.Min.Y, r2.Min.Y)},
		Max: Coord{max(r1.Max.X, r2.Max.X), max(r1.Max.Y, r2.Max.Y)},
	}
}

func Contains(rOuter, rInner Rectangle) bool {
	return PointInRectangle(rOuter, rInner.Min) && PointInRectangle(rOuter, rInner.Max)
}
<commit_msg>tidy up and documenting<commit_after>// Package rect implements utilities for manipulating axis aligned 2d rectangles
package rect

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

// Coord is the a basic cordinate in 2d space
type Coord struct {
	X, Y int
}

// Add standalone function implements lhs + rhs
func Add(lhs, rhs Coord) Coord {
	return Coord{lhs.X + rhs.X, lhs.Y + rhs.Y}
}

// Add method implements c = c + rhs. Modifies receiver value
func (c *Coord) Add(rhs Coord) {
	c.X += rhs.X
	c.Y += rhs.Y
}

// Sub standalone function implements lhs - rhs
func Sub(lhs, rhs Coord) Coord {
	return Coord{lhs.X - rhs.X, lhs.Y - rhs.Y}
}

// Sub method implements c = c - rhs. Modifies receiver value
func (c *Coord) Sub(rhs Coord) {
	c.X -= rhs.X
	c.Y -= rhs.Y
}

// Rectangle is an Axis aligned 2d Rectangle
// It comprises 2 Coord values.
type Rectangle struct {
	Min, Max Coord
}

func XYWH(x, y, w, h int) Rectangle {
	return Rectangle{Coord{x, y}, Coord{x + w, y + h}}
}

func XYXY(x1, y1, x2, y2 int) Rectangle {
	return Normalise(Rectangle{Coord{x1, y1}, Coord{x2, y2}})
}

func FromPosSize(pos, size Coord) Rectangle {
	return Rectangle{pos, Add(pos, size)}
}

func FromSize(size Coord) Rectangle {
	return Rectangle{Max: size}
}

func (r *Rectangle) Normalise() {
	if r.Min.X > r.Max.X {
		r.Min.X, r.Max.X = r.Max.X, r.Min.X
	}

	if r.Min.Y > r.Max.Y {
		r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y
	}
}

func Normalise(r Rectangle) Rectangle {
	r.Normalise()
	return r
}

func (r *Rectangle) Width() int {
	return r.Max.X - r.Min.X
}

func (r *Rectangle) Height() int {
	return r.Max.Y - r.Min.Y
}

func (r *Rectangle) Size() Coord {
	return Coord{r.Width(), r.Height()}
}

func (r *Rectangle) IsEmpty() bool {
	return (r.Min.X == r.Max.X) || (r.Min.Y == r.Max.Y)
}

func (r *Rectangle) IsNormal() bool {
	return (r.Min.X <= r.Max.X) && (r.Min.Y <= r.Max.Y)
}

func (r *Rectangle) Expand(c Coord) {
	r.Min.Sub(c)
	r.Max.Add(c)
}

func Expand(r Rectangle, c Coord) Rectangle {
	r.Expand(c)
	return r
}

func (r *Rectangle) Translate(c Coord) {
	r.Min.Add(c)
	r.Max.Add(c)
}

func Translate(r Rectangle, c Coord) Rectangle {
	r.Translate(c)
	return r
}

func PointInRectangle(r Rectangle, p Coord) bool {
	return (r.Min.X <= p.X) && (r.Min.Y <= p.Y) && (p.X < r.Max.X) && (p.Y < r.Max.Y)
}

func Intersection(r1, r2 Rectangle) (intersect Rectangle, ok bool) {
	intersect = Rectangle{
		Min: Coord{max(r1.Min.X, r2.Min.X), max(r1.Min.Y, r2.Min.Y)},
		Max: Coord{min(r1.Max.X, r2.Max.X), min(r1.Max.Y, r2.Max.Y)},
	}

	ok = intersect.IsNormal()
	return
}

func Union(r1, r2 Rectangle) Rectangle {
	return Rectangle{
		Min: Coord{min(r1.Min.X, r2.Min.X), min(r1.Min.Y, r2.Min.Y)},
		Max: Coord{max(r1.Max.X, r2.Max.X), max(r1.Max.Y, r2.Max.Y)},
	}
}

func Contains(rOuter, rInner Rectangle) bool {
	return PointInRectangle(rOuter, rInner.Min) && PointInRectangle(rOuter, rInner.Max)
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file provides a REPL.

package golisp

import (
	"container/list"
	"fmt"
)

func Repl() {
	IsInteractive = true
	fmt.Printf("Welcome to GoLisp\n")
	fmt.Printf("Copyright 2014 SteelSeries\n")
	fmt.Printf("Evaluate '(quit)' to exit.\n\n")
	prompt := "> "
	LoadHistoryFromFile(".golisp_history")
	lastInput := ""
	for true {
		defer func() {
			if x := recover(); x != nil {
				fmt.Printf("Don't Panic! %v\n", x)
			}
		}()
		DebugCurrentFrame = nil
		DebugSingleStep = false
		DebugEvalInDebugRepl = false
		Global.CurrentCode = list.New()
		input := *ReadLine(&prompt)
		if input != "" {
			if input != lastInput {
				AddHistory(input)
			}
			lastInput = input
			code, err := Parse(input)
			if err != nil {
				fmt.Printf("Error: %s\n", err)
			} else {
				d, err := Eval(code, Global)
				if err != nil {
					fmt.Printf("Error in evaluation: %s\n", err)
					if DebugOnError {
						DebugRepl(DebugErrorEnv)
					}
				} else {
					fmt.Printf("==> %s\n", String(d))
				}
			}
		}
	}
}
<commit_msg>Handle C-d to clean up and exit (calls the implementation of quit)<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file provides a REPL.

package golisp

import (
	"container/list"
	"fmt"
)

func Repl() {
	IsInteractive = true
	fmt.Printf("Welcome to GoLisp\n")
	fmt.Printf("Copyright 2014 SteelSeries\n")
	fmt.Printf("Evaluate '(quit)' to exit.\n\n")
	prompt := "> "
	LoadHistoryFromFile(".golisp_history")
	lastInput := ""
	for true {
		defer func() {
			if x := recover(); x != nil {
				fmt.Printf("Don't Panic! %v\n", x)
			}
		}()
		DebugCurrentFrame = nil
		DebugSingleStep = false
		DebugEvalInDebugRepl = false
		Global.CurrentCode = list.New()
		inputp := ReadLine(&prompt)
		fmt.Printf("inputp: %v\n", inputp)
		if inputp == nil {
			QuitImpl(nil, nil)
		} else {
			input := *inputp
			fmt.Printf("input: <%s>\n", inputp)
			if input != "" {
				if input != lastInput {
					AddHistory(input)
				}
				lastInput = input
				code, err := Parse(input)
				if err != nil {
					fmt.Printf("Error: %s\n", err)
				} else {
					d, err := Eval(code, Global)
					if err != nil {
						fmt.Printf("Error in evaluation: %s\n", err)
						if DebugOnError {
							DebugRepl(DebugErrorEnv)
						}
					} else {
						fmt.Printf("==> %s\n", String(d))
					}
				}
			}
		}
	}
}
<|endoftext|>