<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"

	"github.com/bgentry/go-netrc/netrc"
	"github.com/bgentry/speakeasy"
	"github.com/codegangsta/cli"
	"github.com/heroku/hk/term"
	"github.com/mgutz/ansi"
)

// Error codes returned by auth failures
var (
	ErrEmptyToken = errors.New("auth: You must be logged in. Please use `gemnasium login` first, or pass your api token with --token.")
)

func netrcPath() string {
	if s := os.Getenv("NETRC_PATH"); s != "" {
		return s
	}

	return filepath.Join(os.Getenv("HOME"), netrcFilename)
}

var loadNetrc = func() *netrc.Netrc {
	nrc, err := netrc.ParseFile(netrcPath())
	if err != nil {
		if os.IsNotExist(err) {
			nrc = &netrc.Netrc{}
		}
		if err != nil {
			printFatal("loading netrc: " + err.Error())
		}
	}
	return nrc
}

func saveCreds(host, user, pass string) error {
	nrc := loadNetrc()
	m := nrc.FindMachine(host)
	if m == nil || m.IsDefault() {
		m = nrc.NewMachine(host, user, pass, "")
	}
	m.UpdateLogin(user)
	m.UpdatePassword(pass)

	body, err := nrc.MarshalText()
	if err != nil {
		return err
	}
	return writeNetrcFile(body)
}

var writeNetrcFile = func(body []byte) error {
	return ioutil.WriteFile(netrcPath(), body, 0600)
}

func removeCreds(host string) error {
	nrc := loadNetrc()
	nrc.RemoveMachine(host)

	body, err := nrc.MarshalText()
	if err != nil {
		return err
	}
	return writeNetrcFile(body)
}

func getCreds(config *Config) (user, pass string) {
	nrc := loadNetrc()
	if nrc == nil {
		return "", ""
	}

	apiURL, err := url.Parse(config.APIEndpoint)
	if err != nil {
		printFatal("invalid API URL: %s", err)
	}
	if apiURL.Host == "" {
		printFatal("missing API host: %s", config.APIEndpoint)
	}
	if apiURL.User != nil {
		pw, _ := apiURL.User.Password()
		return apiURL.User.Username(), pw
	}

	m := nrc.FindMachine(apiURL.Host)
	if m == nil {
		return "", ""
	}
	return m.Login, m.Password
}

func printFatal(message string, args ...interface{}) {
	log.Fatal(colorizeMessage("red", "error:", message, args...))
}

func colorizeMessage(color, prefix, message string, args ...interface{}) string {
	prefResult := ""
	if prefix != "" {
		prefResult = ansi.Color(prefix, color+"+b") + " " + ansi.ColorCode("reset")
	}
	return prefResult + ansi.Color(fmt.Sprintf(message, args...), color) + ansi.ColorCode("reset")
}

// Lambda to be overriden in tests
var getCredentials = func() (email, password string, err error) {
	fmt.Printf("Enter your email: ")
	fmt.Scanf("%s", &email)
	// NOTE: gopass doesn't support multi-byte chars on Windows
	password, err = readPassword("Enter password (will be hidden): ")
	if err != nil {
		return "", "", err
	}
	return email, password, nil
}

func readPassword(prompt string) (password string, err error) {
	if acceptPasswordFromStdin && !term.IsTerminal(os.Stdin) {
		_, err = fmt.Scanln(&password)
		return
	}
	// NOTE: speakeasy may not support multi-byte chars on Windows
	return speakeasy.Ask("Enter password: ")
}

// Try to get credential from 3 sources (in that exact order):
// - from netrc file
// - local config file (ie: .gemnasium.yml), with a `api_key` yaml key
// - from command line flag `token`
//
// Each source will override previous one (token flag has priority above all).
//
// WARNING: Directly exit the programm in case of error
func AttemptLogin(ctx *cli.Context, config *Config) {
	// APIKey has been set localy in config file
	if config.APIKey == "" {
		_, config.APIKey = getCreds(config)
	}
	// User can override token
	if ctx.GlobalString("token") != "" {
		// Try to fetch token from command line
		config.APIKey = ctx.GlobalString("token")
	}
	if config.APIKey == "" {
		ExitWithError(ErrEmptyToken)
	}
}
<commit_msg>Add NewAPIRequest helper<commit_after>package main

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"

	"github.com/bgentry/go-netrc/netrc"
	"github.com/bgentry/speakeasy"
	"github.com/codegangsta/cli"
	"github.com/heroku/hk/term"
	"github.com/mgutz/ansi"
)

// Error codes returned by auth failures
var (
	ErrEmptyToken = errors.New("auth: You must be logged in. Please use `gemnasium login` first, or pass your api token with --token.")
)

func netrcPath() string {
	if s := os.Getenv("NETRC_PATH"); s != "" {
		return s
	}

	return filepath.Join(os.Getenv("HOME"), netrcFilename)
}

var loadNetrc = func() *netrc.Netrc {
	nrc, err := netrc.ParseFile(netrcPath())
	if err != nil {
		if os.IsNotExist(err) {
			nrc = &netrc.Netrc{}
		}
		if err != nil {
			printFatal("loading netrc: " + err.Error())
		}
	}
	return nrc
}

func saveCreds(host, user, pass string) error {
	nrc := loadNetrc()
	m := nrc.FindMachine(host)
	if m == nil || m.IsDefault() {
		m = nrc.NewMachine(host, user, pass, "")
	}
	m.UpdateLogin(user)
	m.UpdatePassword(pass)

	body, err := nrc.MarshalText()
	if err != nil {
		return err
	}
	return writeNetrcFile(body)
}

var writeNetrcFile = func(body []byte) error {
	return ioutil.WriteFile(netrcPath(), body, 0600)
}

func removeCreds(host string) error {
	nrc := loadNetrc()
	nrc.RemoveMachine(host)

	body, err := nrc.MarshalText()
	if err != nil {
		return err
	}
	return writeNetrcFile(body)
}

func getCreds(config *Config) (user, pass string) {
	nrc := loadNetrc()
	if nrc == nil {
		return "", ""
	}

	apiURL, err := url.Parse(config.APIEndpoint)
	if err != nil {
		printFatal("invalid API URL: %s", err)
	}
	if apiURL.Host == "" {
		printFatal("missing API host: %s", config.APIEndpoint)
	}
	if apiURL.User != nil {
		pw, _ := apiURL.User.Password()
		return apiURL.User.Username(), pw
	}

	m := nrc.FindMachine(apiURL.Host)
	if m == nil {
		return "", ""
	}
	return m.Login, m.Password
}

func printFatal(message string, args ...interface{}) {
	log.Fatal(colorizeMessage("red", "error:", message, args...))
}

func colorizeMessage(color, prefix, message string, args ...interface{}) string {
	prefResult := ""
	if prefix != "" {
		prefResult = ansi.Color(prefix, color+"+b") + " " + ansi.ColorCode("reset")
	}
	return prefResult + ansi.Color(fmt.Sprintf(message, args...), color) + ansi.ColorCode("reset")
}

// Lambda to be overriden in tests
var getCredentials = func() (email, password string, err error) {
	fmt.Printf("Enter your email: ")
	fmt.Scanf("%s", &email)
	// NOTE: gopass doesn't support multi-byte chars on Windows
	password, err = readPassword("Enter password (will be hidden): ")
	if err != nil {
		return "", "", err
	}
	return email, password, nil
}

func readPassword(prompt string) (password string, err error) {
	if acceptPasswordFromStdin && !term.IsTerminal(os.Stdin) {
		_, err = fmt.Scanln(&password)
		return
	}
	// NOTE: speakeasy may not support multi-byte chars on Windows
	return speakeasy.Ask("Enter password: ")
}

// Try to get credential from 3 sources (in that exact order):
// - from netrc file
// - local config file (ie: .gemnasium.yml), with a `api_key` yaml key
// - from command line flag `token`
//
// Each source will override previous one (token flag has priority above all).
//
// WARNING: Directly exit the programm in case of error
func AttemptLogin(ctx *cli.Context, config *Config) {
	// APIKey has been set localy in config file
	if config.APIKey == "" {
		_, config.APIKey = getCreds(config)
	}
	// User can override token
	if ctx.GlobalString("token") != "" {
		// Try to fetch token from command line
		config.APIKey = ctx.GlobalString("token")
	}
	if config.APIKey == "" {
		ExitWithError(ErrEmptyToken)
	}
}

// Create a new API request, with needed headers for auth and content-type
func NewAPIRequest(method, urlStr, APIKey string, body io.Reader) (*http.Request, error) {
	req, err := http.NewRequest(method, urlStr, body)
	if err != nil {
		return nil, err
	}
	req.SetBasicAuth("x", APIKey)
	req.Header.Add("Content-Type", "application/json")
	return req, nil
}
<|endoftext|>


<commit_before>// chris 072315

package main

import (
	"errors"
	"fmt"

	"math/rand"
)

var ErrBadRange = errors.New("bad range")

// ChooseInt returns, as an int, a random integer in [begin, end] from
// the default Source.  It panics if begin > end.
func ChooseInt(begin, end int) int {
	if begin > end {
		panic(fmt.Sprintf("invalid arguments to ChooseInt: begin %d > end %d", begin, end))
	}
	return begin + rand.Intn(end - begin + 1)
}

// ChooseRune returns a random rune that is lexically and inclusively
// between begin and end.  Specifically, the output x satisfies
// begin <= x <= end.
func ChooseRune(begin, end rune) rune {
	return rune(ChooseInt(int(begin), int(end)))
}

// ChooseString returns a random string that is lexically and
// inclusively between begin and end.  Specifically, the output x
// satisfies begin <= x <= end.  If the begin and end strings don't
// contain the same number of runes, the empty string is returned with
// ErrBadRange.
func ChooseString(begin, end string) (string, error) {
	br := []rune(begin)
	er := []rune(end)
	if len(br) != len(er) {
		return "", ErrBadRange
	}
	ret := make([]rune, len(br))
	for i := range ret {
		ret[i] = ChooseRune(br[i], er[i])
	}
	return string(ret), nil
}
<commit_msg>Updates with go format revisions.<commit_after>// chris 072315

package main

import (
	"errors"
	"fmt"

	"math/rand"
)

var ErrBadRange = errors.New("bad range")

// ChooseInt returns, as an int, a random integer in [begin, end] from
// the default Source.  It panics if begin > end.
func ChooseInt(begin, end int) int {
	if begin > end {
		panic(fmt.Sprintf("invalid arguments to ChooseInt: begin %d > end %d", begin, end))
	}
	return begin + rand.Intn(end-begin+1)
}

// ChooseRune returns a random rune that is lexically and inclusively
// between begin and end.  Specifically, the output x satisfies
// begin <= x <= end.
func ChooseRune(begin, end rune) rune {
	return rune(ChooseInt(int(begin), int(end)))
}

// ChooseString returns a random string that is lexically and
// inclusively between begin and end.  Specifically, the output x
// satisfies begin <= x <= end.  If the begin and end strings don't
// contain the same number of runes, the empty string is returned with
// ErrBadRange.
func ChooseString(begin, end string) (string, error) {
	br := []rune(begin)
	er := []rune(end)
	if len(br) != len(er) {
		return "", ErrBadRange
	}
	ret := make([]rune, len(br))
	for i := range ret {
		ret[i] = ChooseRune(br[i], er[i])
	}
	return string(ret), nil
}
<|endoftext|>


<commit_before>package osincli

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

// Parse basic authentication header
type BasicAuth struct {
	Username string
	Password string
}

// Download and parse OAuth2 JSON access request
func downloadData(method string, u *url.URL, auth *BasicAuth, transport http.RoundTripper, output ResponseData) error {
	var postdata url.Values
	var body io.Reader
	var contenttype string

	if method == "POST" {
		// Convert query parameters to post data
		postdata = u.Query()
		u.RawQuery = ""
		body = strings.NewReader(postdata.Encode())
		contenttype = "application/x-www-form-urlencoded"
	}

	// Create a new request
	preq, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return err
	}

	if auth != nil {
		preq.SetBasicAuth(auth.Username, auth.Password)
	}

	// Set content type for post request
	if contenttype != "" {
		preq.Header.Set("Content-Type", contenttype)
	}

	// do request
	client := &http.Client{}
	if transport != nil {
		client.Transport = transport
	}
	presp, err := client.Do(preq)
	if err != nil {
		return err
	}

	// must close body
	defer presp.Body.Close()

	if presp.StatusCode != 200 {
		return errors.New(fmt.Sprintf("Invalid status code (%d): %s", presp.StatusCode, presp.Status))
	}

	// decode JSON and detect OAuth error
	jdec := json.NewDecoder(presp.Body)
	if err = jdec.Decode(&output); err == nil {
		if em, eok := output["error"]; eok {
			return NewError(fmt.Sprintf("%v", em), fmt.Sprintf("%v", output["error_description"]),
				fmt.Sprintf("%v", output["error_uri"]), fmt.Sprintf("%v", output["state"]))
		}
	}
	return err
}
<commit_msg>Explicitly set Accept header to JSON<commit_after>package osincli

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

// Parse basic authentication header
type BasicAuth struct {
	Username string
	Password string
}

// Download and parse OAuth2 JSON access request
func downloadData(method string, u *url.URL, auth *BasicAuth, transport http.RoundTripper, output ResponseData) error {
	var postdata url.Values
	var body io.Reader
	var contenttype string

	if method == "POST" {
		// Convert query parameters to post data
		postdata = u.Query()
		u.RawQuery = ""
		body = strings.NewReader(postdata.Encode())
		contenttype = "application/x-www-form-urlencoded"
	}

	// Create a new request
	preq, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return err
	}

	if auth != nil {
		preq.SetBasicAuth(auth.Username, auth.Password)
	}

	// Set content type for post request
	if contenttype != "" {
		preq.Header.Set("Content-Type", contenttype)
	}

	// Explicitly set accept header to JSON
	preq.Header.Set("Accept", "application/json")

	// do request
	client := &http.Client{}
	if transport != nil {
		client.Transport = transport
	}
	presp, err := client.Do(preq)
	if err != nil {
		return err
	}

	// must close body
	defer presp.Body.Close()

	if presp.StatusCode != 200 {
		return errors.New(fmt.Sprintf("Invalid status code (%d): %s", presp.StatusCode, presp.Status))
	}

	// decode JSON and detect OAuth error
	jdec := json.NewDecoder(presp.Body)
	if err = jdec.Decode(&output); err == nil {
		if em, eok := output["error"]; eok {
			return NewError(fmt.Sprintf("%v", em), fmt.Sprintf("%v", output["error_description"]),
				fmt.Sprintf("%v", output["error_uri"]), fmt.Sprintf("%v", output["state"]))
		}
	}
	return err
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"math"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{}
)

func EntryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// FactoshiToFactoid converts a uint64 factoshi ammount into a fixed point
// number represented as a string
func FactoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	ds := fmt.Sprintf("%d", d)
	rs := fmt.Sprintf("%08d", r)
	rs = strings.TrimRight(rs, "0")
	if len(rs) > 0 {
		ds = ds + "."
	}
	return fmt.Sprintf("%s%s", ds, rs)
}

// FactoidToFactoshi takes a Factoid amount as a string and returns the value in
// factoids
func FactoidToFactoshi(amt string) uint64 {
	valid := regexp.MustCompile(`^([0-9]+)?(\.[0-9]+)?$`)
	if !valid.MatchString(amt) {
		return 0
	}

	var total uint64 = 0

	dot := regexp.MustCompile(`\.`)
	pieces := dot.Split(amt, 2)
	whole, _ := strconv.Atoi(pieces[0])
	total += uint64(whole) * 1e8

	if len(pieces) > 1 {
		a := regexp.MustCompile(`(0*)([0-9]+)$`)

		as := a.FindStringSubmatch(pieces[1])
		part, _ := strconv.Atoi(as[0])
		power := len(as[1]) + len(as[2])
		total += uint64(part * 1e8 / int(math.Pow10(power)))
	}

	return total
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}
<commit_msg>added default values for rpc config<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"math"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{
		FactomdServer: "localhost:8088",
		WalletServer:  "localhost:8089",
	}
)

func EntryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// FactoshiToFactoid converts a uint64 factoshi ammount into a fixed point
// number represented as a string
func FactoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	ds := fmt.Sprintf("%d", d)
	rs := fmt.Sprintf("%08d", r)
	rs = strings.TrimRight(rs, "0")
	if len(rs) > 0 {
		ds = ds + "."
	}
	return fmt.Sprintf("%s%s", ds, rs)
}

// FactoidToFactoshi takes a Factoid amount as a string and returns the value in
// factoids
func FactoidToFactoshi(amt string) uint64 {
	valid := regexp.MustCompile(`^([0-9]+)?(\.[0-9]+)?$`)
	if !valid.MatchString(amt) {
		return 0
	}

	var total uint64 = 0

	dot := regexp.MustCompile(`\.`)
	pieces := dot.Split(amt, 2)
	whole, _ := strconv.Atoi(pieces[0])
	total += uint64(whole) * 1e8

	if len(pieces) > 1 {
		a := regexp.MustCompile(`(0*)([0-9]+)$`)

		as := a.FindStringSubmatch(pieces[1])
		part, _ := strconv.Atoi(as[0])
		power := len(as[1]) + len(as[2])
		total += uint64(part * 1e8 / int(math.Pow10(power)))
	}

	return total
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"syscall"

	"github.com/alienth/go-fastly"
	"github.com/urfave/cli"
	"golang.org/x/crypto/ssh/terminal"
)

func getServiceByNameOrID(client *fastly.Client, identifier string) (*fastly.Service, error) {
	var service *fastly.Service
	service, err := client.SearchService(&fastly.SearchServiceInput{Name: identifier})
	if err != nil {
		if service, err = client.GetService(&fastly.GetServiceInput{ID: identifier}); err != nil {
			return nil, fmt.Errorf("Error fetching service %s: %s", identifier, err)
		}
	}
	return service, nil
}

// getActiveVersion takes in a *fastly.Service and spits out the config version
// that is currently active for that service.
func getActiveVersion(service *fastly.Service) (string, error) {
	// Depending on how the service was fetched, it may or may not
	// have a filled ActiveVersion field.
	if service.ActiveVersion != 0 {
		return strconv.Itoa(int(service.ActiveVersion)), nil
	} else {
		for _, version := range service.Versions {
			if version.Active {
				return version.Number, nil
			}
		}
	}
	return "", fmt.Errorf("Unable to find the active version for service %s", service.Name)
}

func prompt(question string) (bool, error) {
	var input string
	for {
		fmt.Printf("%s (y/n): ", question)
		if _, err := fmt.Scanln(&input); err != nil {
			return false, err
		}
		if input == "y" {
			return true, nil
		} else if input == "n" {
			return false, nil
		} else {
			fmt.Printf("Invalid input: %s", input)
		}
	}
}

func countChanges(diff *string) (int, int) {
	removals := regexp.MustCompile(`(^|\n)\-`)
	additions := regexp.MustCompile(`(^|\n)\+`)
	return len(additions.FindAllString(*diff, -1)), len(removals.FindAllString(*diff, -1))
}

func activateVersion(c *cli.Context, client *fastly.Client, s *fastly.Service, v *fastly.Version) error {
	activeVersion, err := getActiveVersion(s)
	if err != nil {
		return err
	}
	assumeYes := c.GlobalBool("assume-yes")
	diff, err := client.GetDiff(&fastly.GetDiffInput{Service: s.ID, Format: "text", From: activeVersion, To: v.Number})
	if err != nil {
		return err
	}

	interactive := terminal.IsTerminal(syscall.Stdin)
	pager := getPager()

	additions, removals := countChanges(&diff.Diff)
	var proceed bool
	if !assumeYes {
		if proceed, err = prompt(fmt.Sprintf("%d additions and %d removals in diff. View?", additions, removals)); err != nil {
			return err
		}
	}

	if proceed || assumeYes {
		if pager != nil && interactive && !assumeYes {
			r, stdin := io.Pipe()
			pager.Stdin = r
			pager.Stdout = os.Stdout
			pager.Stderr = os.Stderr

			c := make(chan struct{})
			go func() {
				defer close(c)
				pager.Run()
			}()

			fmt.Fprintf(stdin, diff.Diff)
			stdin.Close()
			<-c
		} else {
			fmt.Printf("Diff for %s:\n\n", s.Name)
			fmt.Println(diff.Diff)
		}
	}

	if !assumeYes {
		if proceed, err = prompt("Activate version " + v.Number + " for service " + s.Name + "?"); err != nil {
			return err
		}
	}
	if proceed || assumeYes {
		if _, err = client.ActivateVersion(&fastly.ActivateVersionInput{Service: s.ID, Version: v.Number}); err != nil {
			return err
		}
	}
	fmt.Printf("Activated version %s for %s. Old version: %s\n", v.Number, s.Name, activeVersion)
	return nil
}

// Returns true if two versions of a given service are identical.  Generated
// VCL is not suitable as the ordering output of GeneratedVCL will vary if a
// no-op change has been made to a config (for example, removing and re-adding
// all domains). As such, this function generates a known-noop diff by
// comparing a version with itself, and then generating a diff between the from
// and to versions.  If the two diffs are identical, then there is no
// difference between from and to.
func versionsEqual(c *fastly.Client, s *fastly.Service, from string, to string) (bool, error) {
	var i fastly.GetDiffInput
	i.Service = s.ID
	// Intentional
	i.To = from
	i.From = from
	noDiff, err := c.GetDiff(&i)
	if err != nil {
		return false, err
	}
	i.To = to
	diff, err := c.GetDiff(&i)
	if err != nil {
		return false, err
	}
	return noDiff.Diff == diff.Diff, nil
}

func stringInSlice(check string, slice []string) bool {
	for _, element := range slice {
		if element == check {
			return true
		}
	}
	return false
}

func getPager() *exec.Cmd {
	for _, pager := range [3]string{os.Getenv("PAGER"), "pager", "less"} {
		// we expect some NotFounds, so ignore errors
		path, _ := exec.LookPath(pager)
		if path != "" {
			return exec.Command(path)
		}
	}
	return nil
}
<commit_msg>Only say we activated if we did.<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"syscall"

	"github.com/alienth/go-fastly"
	"github.com/urfave/cli"
	"golang.org/x/crypto/ssh/terminal"
)

func getServiceByNameOrID(client *fastly.Client, identifier string) (*fastly.Service, error) {
	var service *fastly.Service
	service, err := client.SearchService(&fastly.SearchServiceInput{Name: identifier})
	if err != nil {
		if service, err = client.GetService(&fastly.GetServiceInput{ID: identifier}); err != nil {
			return nil, fmt.Errorf("Error fetching service %s: %s", identifier, err)
		}
	}
	return service, nil
}

// getActiveVersion takes in a *fastly.Service and spits out the config version
// that is currently active for that service.
func getActiveVersion(service *fastly.Service) (string, error) {
	// Depending on how the service was fetched, it may or may not
	// have a filled ActiveVersion field.
	if service.ActiveVersion != 0 {
		return strconv.Itoa(int(service.ActiveVersion)), nil
	} else {
		for _, version := range service.Versions {
			if version.Active {
				return version.Number, nil
			}
		}
	}
	return "", fmt.Errorf("Unable to find the active version for service %s", service.Name)
}

func prompt(question string) (bool, error) {
	var input string
	for {
		fmt.Printf("%s (y/n): ", question)
		if _, err := fmt.Scanln(&input); err != nil {
			return false, err
		}
		if input == "y" {
			return true, nil
		} else if input == "n" {
			return false, nil
		} else {
			fmt.Printf("Invalid input: %s", input)
		}
	}
}

func countChanges(diff *string) (int, int) {
	removals := regexp.MustCompile(`(^|\n)\-`)
	additions := regexp.MustCompile(`(^|\n)\+`)
	return len(additions.FindAllString(*diff, -1)), len(removals.FindAllString(*diff, -1))
}

func activateVersion(c *cli.Context, client *fastly.Client, s *fastly.Service, v *fastly.Version) error {
	activeVersion, err := getActiveVersion(s)
	if err != nil {
		return err
	}
	assumeYes := c.GlobalBool("assume-yes")
	diff, err := client.GetDiff(&fastly.GetDiffInput{Service: s.ID, Format: "text", From: activeVersion, To: v.Number})
	if err != nil {
		return err
	}

	interactive := terminal.IsTerminal(syscall.Stdin)
	pager := getPager()

	additions, removals := countChanges(&diff.Diff)
	var proceed bool
	if !assumeYes {
		if proceed, err = prompt(fmt.Sprintf("%d additions and %d removals in diff. View?", additions, removals)); err != nil {
			return err
		}
	}

	if proceed || assumeYes {
		if pager != nil && interactive && !assumeYes {
			r, stdin := io.Pipe()
			pager.Stdin = r
			pager.Stdout = os.Stdout
			pager.Stderr = os.Stderr

			c := make(chan struct{})
			go func() {
				defer close(c)
				pager.Run()
			}()

			fmt.Fprintf(stdin, diff.Diff)
			stdin.Close()
			<-c
		} else {
			fmt.Printf("Diff for %s:\n\n", s.Name)
			fmt.Println(diff.Diff)
		}
	}

	if !assumeYes {
		if proceed, err = prompt("Activate version " + v.Number + " for service " + s.Name + "?"); err != nil {
			return err
		}
	}
	if proceed || assumeYes {
		if _, err = client.ActivateVersion(&fastly.ActivateVersionInput{Service: s.ID, Version: v.Number}); err != nil {
			return err
		}
		fmt.Printf("Activated version %s for %s. Old version: %s\n", v.Number, s.Name, activeVersion)
	}
	return nil
}

// Returns true if two versions of a given service are identical.  Generated
// VCL is not suitable as the ordering output of GeneratedVCL will vary if a
// no-op change has been made to a config (for example, removing and re-adding
// all domains). As such, this function generates a known-noop diff by
// comparing a version with itself, and then generating a diff between the from
// and to versions.  If the two diffs are identical, then there is no
// difference between from and to.
func versionsEqual(c *fastly.Client, s *fastly.Service, from string, to string) (bool, error) {
	var i fastly.GetDiffInput
	i.Service = s.ID
	// Intentional
	i.To = from
	i.From = from
	noDiff, err := c.GetDiff(&i)
	if err != nil {
		return false, err
	}
	i.To = to
	diff, err := c.GetDiff(&i)
	if err != nil {
		return false, err
	}
	return noDiff.Diff == diff.Diff, nil
}

func stringInSlice(check string, slice []string) bool {
	for _, element := range slice {
		if element == check {
			return true
		}
	}
	return false
}

func getPager() *exec.Cmd {
	for _, pager := range [3]string{os.Getenv("PAGER"), "pager", "less"} {
		// we expect some NotFounds, so ignore errors
		path, _ := exec.LookPath(pager)
		if path != "" {
			return exec.Command(path)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package wire

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"

	"golang.org/x/crypto/ripemd160"

	. "github.com/tendermint/go-common"
)

func BinaryBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteBinary(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// ptr: a pointer to the object to be filled
func ReadBinaryBytes(d []byte, ptr interface{}) error {
	r, n, err := bytes.NewBuffer(d), new(int), new(error)
	ReadBinaryPtr(ptr, r, 0, n, err)
	return *err
}

func JSONBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteJSON(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// NOTE: inefficient
func JSONBytesPretty(o interface{}) []byte {
	jsonBytes := JSONBytes(o)
	var object interface{}
	err := json.Unmarshal(jsonBytes, &object)
	if err != nil {
		PanicSanity(err)
	}
	jsonBytes, err = json.MarshalIndent(object, "", "\t")
	if err != nil {
		PanicSanity(err)
	}
	return jsonBytes
}

// ptr: a pointer to the object to be filled
func ReadJSONBytes(d []byte, ptr interface{}) (err error) {
	ReadJSONPtr(ptr, d, &err)
	return
}

// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b interface{}) bool {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Equal(aBytes, bBytes)
}

// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b interface{}) int {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Compare(aBytes, bBytes)
}

// NOTE: only use this if you need 32 bytes.
func BinarySha256(o interface{}) []byte {
	hasher, n, err := sha256.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}

// NOTE: The default hash function is Ripemd160.
func BinaryRipemd160(o interface{}) []byte {
	hasher, n, err := ripemd160.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}
<commit_msg>Stop overflows in ReadBinaryBytes<commit_after>package wire

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"

	"golang.org/x/crypto/ripemd160"

	. "github.com/tendermint/go-common"
)

func BinaryBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteBinary(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// ptr: a pointer to the object to be filled
func ReadBinaryBytes(d []byte, ptr interface{}) error {
	r, n, err := bytes.NewBuffer(d), new(int), new(error)
	ReadBinaryPtr(ptr, r, len(d), n, err)
	return *err
}

func JSONBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteJSON(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// NOTE: inefficient
func JSONBytesPretty(o interface{}) []byte {
	jsonBytes := JSONBytes(o)
	var object interface{}
	err := json.Unmarshal(jsonBytes, &object)
	if err != nil {
		PanicSanity(err)
	}
	jsonBytes, err = json.MarshalIndent(object, "", "\t")
	if err != nil {
		PanicSanity(err)
	}
	return jsonBytes
}

// ptr: a pointer to the object to be filled
func ReadJSONBytes(d []byte, ptr interface{}) (err error) {
	ReadJSONPtr(ptr, d, &err)
	return
}

// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b interface{}) bool {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Equal(aBytes, bBytes)
}

// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b interface{}) int {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Compare(aBytes, bBytes)
}

// NOTE: only use this if you need 32 bytes.
func BinarySha256(o interface{}) []byte {
	hasher, n, err := sha256.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}

// NOTE: The default hash function is Ripemd160.
func BinaryRipemd160(o interface{}) []byte {
	hasher, n, err := ripemd160.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}
<|endoftext|>


<commit_before>/*
Package uuid implements a fast representation of UUIDs
(Universally Unique Identifiers) and integrates with JSON and SQL drivers.

This package supports reading of multiple formats of UUIDs, including but
not limited to:

	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
	A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
	{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
	a0eebc999c0b4ef8bb6d6bb9bd380a11
	a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
	{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}

The parsing-speed of UUIDs in this package is achieved in several ways:

A lookup table converts hexadecimal digits to bytes.

Scanning and parsing is done in place without allocating anything.

Resulting bytes are written to the UUID as it is parsed. On parse errors
this will leave the UUID only partially populated with data from the
input string, leaving the rest of the UUID unmodified.

This package just ignores non-hexadecimal digits when scanning. This can cause
some odd representations of hexadecimal data to be parsed as valid UUIDs, and
longer strings like these will parse successfully:

	a0eebc99,9c0b,4ef8,bb6d,6bb9bd380a11
	a0eebc99This9cIs0b4eOKf8bb6d6bb9bdLOL380a11
	a0-ee-bc-99-9c-0b-4e-f8-bb-6d-6b-b9-bd-38-0a-11

However, the hexadecimal digits MUST come in pairs, and the total number of
bytes represented by them MUST equal 16, or it will generate a parse error.
For example, invalid UUIDs like these will not parse:

	a0eebc999-c0b-4ef8-bb6d-6bb9bd380a11
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a111
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a1111

All string-creating functions will generate UUIDs in the canonical format of:

	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

*/
package uuid

import (
	"crypto/rand"
	"fmt"
)

// UUID represents a Universally-Unique-Identifier.
type UUID [16]byte

// zero is the zero-UUID, every single byte set to 0.
var zero = [16]byte{}

// ScanError contains the scanner-state for when the error occurred.
type ScanError struct {
	// Scanned is the number of bytes of the source string which has been
	// considered.
	Scanned int
	// Written is the number of decoded hexadecimal bytes which has
	// been written to the UUID instance.
	Written int
	// Length is the length of the source string.
	Length int
}

// ErrTooShort occurs when the supplied string does not contain enough
// hexadecimal characters to represent a UUID.
type ErrTooShort ScanError

func (e ErrTooShort) Error() string {
	return fmt.Sprintf("invalid UUID: too few bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// ErrTooLong occurs when the supplied string contains more than the
// required number of hexadecimal characters to represent a UUID.
type ErrTooLong ScanError

func (e ErrTooLong) Error() string {
	return fmt.Sprintf("invalid UUID: too many bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// ErrUneven occurs when a hexadecimal digit is not part of a pair, making it
// impossible to decode it to a byte.
type ErrUneven ScanError

func (e ErrUneven) Error() string {
	return fmt.Sprintf("invalid UUID: uneven hexadecimal bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// hexchar2byte contains the integer byte-value represented by a hexadecimal character,
// 255 if it is an invalid character.
var hexchar2byte = []byte{
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}

// V4 creates a new random UUID with data from crypto/rand.Read().
func V4() (UUID, error) {
	u := UUID{}

	_, err := rand.Read(u[:])
	if err != nil {
		return u, err
	}

	u[8] = (u[8] | 0x80) & 0xBF
	u[6] = (u[6] | 0x40) & 0x4F

	return u, nil
}

// FromString reads a UUID into a new UUID instance.
func FromString(str string) (UUID, error) {
	u := UUID{}

	err := u.SetString(str)

	return u, err
}

// SetString reads the supplied string-representation of the UUID into the instance.
// On invalid UUID an error is returned and the UUID state will be undetermined.
// This function will ignore all non-hexadecimal digits.
func (u *UUID) SetString(str string) error {
	/* NOTE: Duplicate of SetString, with different method signature, to
	   prevent unnecessary copying of memory due to string <-> []byte conversion */
	i := 0
	x := 0
	c := len(str)

	for x < c {
		a := hexchar2byte[str[x]]
		if a == 255 {
			// Invalid char, skip
			x++

			continue
		}

		// We need to perform this check after the attempted hex-read in case
		// we have trailing "}" characters
		if i >= 16 {
			return &ErrTooLong{x, i, c}
		}
		if x+1 >= c {
			// Not enough to scan
			return &ErrTooShort{x, i, c}
		}

		b := hexchar2byte[str[x+1]]
		if b == 255 {
			// Uneven hexadecimal byte
			return &ErrUneven{x, i, c}
		}

		u[i] = (a << 4) | b

		x += 2
		i++
	}

	if i != 16 {
		// Can only be too short here
		return &ErrTooShort{x, i, c}
	}

	return nil
}

// ReadBytes reads the supplied byte array of hexadecimal characters representing
// a UUID into the instance.
// On invalid UUID an error is returned and the UUID state will be undetermined.
// This function will ignore all non-hexadecimal digits.
func (u *UUID) ReadBytes(str []byte) error {
	/* NOTE: Duplicate of SetString, with different method signature, to
	   prevent unnecessary copying of memory due to string <-> []byte conversion */
	i := 0
	x := 0
	c := len(str)

	for x < c {
		a := hexchar2byte[str[x]]
		if a == 255 {
			// Invalid char, skip
			x++

			continue
		}

		// We need to perform this check after the attempted hex-read in case
		// we have trailing "}" characters
		if i >= 16 {
			return &ErrTooLong{x, i, c}
		}
		if x+1 >= c {
			// Not enough to scan
			return &ErrTooShort{x, i, c}
		}

		b := hexchar2byte[str[x+1]]
		if b == 255 {
			// Uneven hexadecimal byte
			return &ErrUneven{x, i, c}
		}

		u[i] = (a << 4) | b

		x += 2
		i++
	}

	if i != 16 {
		// Can only be too short here
		return &ErrTooShort{x, i, c}
	}

	return nil
}

// IsZero returns true if the UUID is zero.
func (u UUID) IsZero() bool {
	return u == zero
}

// halfbyte2hexchar contains an array of character values corresponding to
// hexadecimal values for the position in the array, 0 to 15 (0x0-0xf, half-byte).
var halfbyte2hexchar = []byte{
	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102,
}

// String returns the string representation of the UUID.
// This method returns the canonical representation of
// ``xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx``.
func (u UUID) String() string {
	/* It is a lot (~10x) faster to allocate a byte slice of specific size and
	   then use a lookup table to write the characters to the byte-array and
	   finally cast to string instead of using fmt.Sprintf() */
	b := make([]byte, 36)

	for i, n := range []int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34,
	} {
		b[n] = halfbyte2hexchar[(u[i] >> 4) & 0x0f]
		b[n+1] = halfbyte2hexchar[u[i] & 0x0f]
	}

	b[8] = '-'
	b[13] = '-'
	b[18] = '-'
	b[23] = '-'

	return string(b)
}
<commit_msg>Replaced make() call with array-literal<commit_after>/*
Package uuid implements a fast representation of UUIDs
(Universally Unique Identifiers) and integrates with JSON and SQL drivers.

This package supports reading of multiple formats of UUIDs, including but
not limited to:

	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
	A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
	{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
	a0eebc999c0b4ef8bb6d6bb9bd380a11
	a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
	{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}

The parsing-speed of UUIDs in this package is achieved in several ways:

A lookup table converts hexadecimal digits to bytes.

Scanning and parsing is done in place without allocating anything.

Resulting bytes are written to the UUID as it is parsed. On parse errors
this will leave the UUID only partially populated with data from the
input string, leaving the rest of the UUID unmodified.

This package just ignores non-hexadecimal digits when scanning. This can cause
some odd representations of hexadecimal data to be parsed as valid UUIDs, and
longer strings like these will parse successfully:

	a0eebc99,9c0b,4ef8,bb6d,6bb9bd380a11
	a0eebc99This9cIs0b4eOKf8bb6d6bb9bdLOL380a11
	a0-ee-bc-99-9c-0b-4e-f8-bb-6d-6b-b9-bd-38-0a-11

However, the hexadecimal digits MUST come in pairs, and the total number of
bytes represented by them MUST equal 16, or it will generate a parse error.
For example, invalid UUIDs like these will not parse:

	a0eebc999-c0b-4ef8-bb6d-6bb9bd380a11
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a111
	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a1111

All string-creating functions will generate UUIDs in the canonical format of:

	a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

*/
package uuid

import (
	"crypto/rand"
	"fmt"
)

// UUID represents a Universally-Unique-Identifier.
type UUID [16]byte

// zero is the zero-UUID, every single byte set to 0.
var zero = [16]byte{}

// ScanError contains the scanner-state for when the error occurred.
type ScanError struct {
	// Scanned is the number of bytes of the source string which has been
	// considered.
	Scanned int
	// Written is the number of decoded hexadecimal bytes which has
	// been written to the UUID instance.
	Written int
	// Length is the length of the source string.
	Length int
}

// ErrTooShort occurs when the supplied string does not contain enough
// hexadecimal characters to represent a UUID.
type ErrTooShort ScanError

func (e ErrTooShort) Error() string {
	return fmt.Sprintf("invalid UUID: too few bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// ErrTooLong occurs when the supplied string contains more than the
// required number of hexadecimal characters to represent a UUID.
type ErrTooLong ScanError

func (e ErrTooLong) Error() string {
	return fmt.Sprintf("invalid UUID: too many bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// ErrUneven occurs when a hexadecimal digit is not part of a pair, making it
// impossible to decode it to a byte.
type ErrUneven ScanError

func (e ErrUneven) Error() string {
	return fmt.Sprintf("invalid UUID: uneven hexadecimal bytes (scanned characters: %d, written bytes: %d, string length: %d)", e.Scanned, e.Written, e.Length)
}

// hexchar2byte contains the integer byte-value represented by a hexadecimal character,
// 255 if it is an invalid character.
var hexchar2byte = []byte{
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}

// halfbyte2hexchar contains an array of character values corresponding to
// hexadecimal values for the position in the array, 0 to 15 (0x0-0xf, half-byte).
var halfbyte2hexchar = []byte{
	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102,
}

// V4 creates a new random UUID with data from crypto/rand.Read().
func V4() (UUID, error) {
	u := UUID{}

	_, err := rand.Read(u[:])
	if err != nil {
		return u, err
	}

	u[8] = (u[8] | 0x80) & 0xBF
	u[6] = (u[6] | 0x40) & 0x4F

	return u, nil
}

// FromString reads a UUID into a new UUID instance.
func FromString(str string) (UUID, error) {
	u := UUID{}

	err := u.SetString(str)

	return u, err
}

// SetString reads the supplied string-representation of the UUID into the instance.
// On invalid UUID an error is returned and the UUID state will be undetermined.
// This function will ignore all non-hexadecimal digits.
func (u *UUID) SetString(str string) error {
	/* NOTE: Duplicate of SetString, with different method signature, to
	   prevent unnecessary copying of memory due to string <-> []byte conversion */
	i := 0
	x := 0
	c := len(str)

	for x < c {
		a := hexchar2byte[str[x]]
		if a == 255 {
			// Invalid char, skip
			x++

			continue
		}

		// We need to perform this check after the attempted hex-read in case
		// we have trailing "}" characters
		if i >= 16 {
			return &ErrTooLong{x, i, c}
		}
		if x+1 >= c {
			// Not enough to scan
			return &ErrTooShort{x, i, c}
		}

		b := hexchar2byte[str[x+1]]
		if b == 255 {
			// Uneven hexadecimal byte
			return &ErrUneven{x, i, c}
		}

		u[i] = (a << 4) | b

		x += 2
		i++
	}

	if i != 16 {
		// Can only be too short here
		return &ErrTooShort{x, i, c}
	}

	return nil
}

// ReadBytes reads the supplied byte array of hexadecimal characters representing
// a UUID into the instance.
// On invalid UUID an error is returned and the UUID state will be undetermined.
// This function will ignore all non-hexadecimal digits.
func (u *UUID) ReadBytes(str []byte) error {
	/* NOTE: Duplicate of SetString, with different method signature, to
	   prevent unnecessary copying of memory due to string <-> []byte conversion */
	i := 0
	x := 0
	c := len(str)

	for x < c {
		a := hexchar2byte[str[x]]
		if a == 255 {
			// Invalid char, skip
			x++

			continue
		}

		// We need to perform this check after the attempted hex-read in case
		// we have trailing "}" characters
		if i >= 16 {
			return &ErrTooLong{x, i, c}
		}
		if x+1 >= c {
			// Not enough to scan
			return &ErrTooShort{x, i, c}
		}

		b := hexchar2byte[str[x+1]]
		if b == 255 {
			// Uneven hexadecimal byte
			return &ErrUneven{x, i, c}
		}

		u[i] = (a << 4) | b

		x += 2
		i++
	}

	if i != 16 {
		// Can only be too short here
		return &ErrTooShort{x, i, c}
	}

	return nil
}

// IsZero returns true if the UUID is zero.
func (u UUID) IsZero() bool {
	return u == zero
}

// String returns the string representation of the UUID.
// This method returns the canonical representation of
// ``xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx``.
func (u UUID) String() string {
	/* It is a lot (~10x) faster to allocate a byte slice of specific size and
	   then use a lookup table to write the characters to the byte-array and
	   finally cast to string instead of using fmt.Sprintf() */
	/* Slightly faster to not use make([]byte, 36), guessing either call
	   overhead or slice-header overhead is the cause */
	b := [36]byte{}

	for i, n := range []int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34,
	} {
		b[n] = halfbyte2hexchar[(u[i]>>4)&0x0f]
		b[n+1] = halfbyte2hexchar[u[i]&0x0f]
	}

	b[8] = '-'
	b[13] = '-'
	b[18] = '-'
	b[23] = '-'

	/* Oddly does not seem to cause a memory allocation,
	   internal data-array is most likely just moved over
	   to the string-header: */
	return string(b[:])
}
<|endoftext|>


<commit_before>package wdte

import (
	"bytes"
	"fmt"
	"io"

	"github.com/DeedleFake/wdte/ast"
)

// A Module is the result of parsing a WDTE script. It is the main
// type of this entire library.
type Module struct {
	// Imports maps IDs to other modules. WDTE import statements create
	// these when parsed.
	Imports map[ID]*Module

	// Funcs maps IDs to functions. WDTE function declarations create
	// these when parsed.
	Funcs map[ID]Func
}

// Parse parses an AST from r and then translates it into a module. im
// is used to handle import statements. If im is nil, a no-op importer
// is used.
func Parse(r io.Reader, im Importer) (*Module, error) {
	root, err := ast.Parse(r)
	if err != nil {
		return nil, err
	}

	return FromAST(root, im)
}

// FromAST translates an AST into a module. im is used to handle
// import statements. If im is nil, a no-op importer is used.
func FromAST(root ast.Node, im Importer) (*Module, error) {
	return fromScript(root.(*ast.NTerm), im)
}

// An Importer creates modules from strings. When parsing a WDTE script, an importer is used to import modules.
//
// When the WDTE import statement
//
//    'example' => e;
//
// is parsed, the associated Importer will be invoked as follows:
//
//    im.Import(example)
//
// The return value will then be added to the module's Imports map.
type Importer interface {
	Import(from string) (*Module, error)
}

// ImportFunc is a wrapper around simple functions to allow them to be
// used as Importers.
type ImportFunc func(from string) (*Module, error)

func (f ImportFunc) Import(from string) (*Module, error) {
	return f(from)
}

// ID represents a WDTE ID, such as a function or imported module
// name.
type ID string

// Func is the base type through which all data is handled by WDTE. It
// represents everything that can be passed around in the language.
// This includes functions, of course, expressions, strings, numbers,
// Go functions, and anything else the client wants to pass into WDTE.
type Func interface {
	// Call calls the function with the given arguments, returning its
	// return value. frame represents the current call frame. This is
	// used to keep track of function arguments during the evaluation of
	// expressions, and can largely be ignored by clients.
	Call(frame Frame, args ...Func) Func

	// Equals returns true if one function equals another one. This is
	// meaningless for the majority of implementations, and should
	// largely be ignored by clients. When implementing custom
	// functions, if you're not sure what to do for this, you probably
	// won't have any issues. This is only used, by default, by switches
	// as a way of checking if the condition matches one of the cases.
	Equals(other Func) bool
}

// A Frame tracks information about the current function call.
type Frame struct {
	id   ID
	args []Func

	p *Frame
}

// F returns a top-level frame. This can be used by Go code calling
// WDTE functions directly if another frame is not available.
func F() Frame {
	return Frame{
		id: "unknown function, maybe Go",
	}
}

// New creates a new frame from a previous frame. id should be the ID
// of the function that generated the frame, and args should be the
// arguments given to that function.
func (f Frame) New(id ID, args []Func) Frame {
	return Frame{
		id:   id,
		args: args,
		p:    &f,
	}
}

// WithID is a convienence function for creating a frame with a new ID
// but the same arguments as the previous frame.
func (f Frame) WithID(id ID) Frame {
	return f.New(id, f.args)
}

// ID returns the ID of the frame. This is generally the function that
// created the frame.
func (f Frame) ID() ID {
	return f.id
}

// Args returns the arguments of the frame.
func (f Frame) Args() []Func {
	return f.args
}

// Parent returns the frame that this frame was created from, or a
// blank frame if there was none.
func (f Frame) Parent() Frame {
	if f.p == nil {
		return Frame{}
	}

	return *f.p
}

// Backtrace prints a backtrace to w.
func (f Frame) Backtrace(w io.Writer) error {
	_, err := fmt.Fprintf(w, "\t%v\n", f.ID())
	if err != nil {
		return err
	}

	return f.p.backtrace(w)
}

func (f *Frame) backtrace(w io.Writer) error {
	if f == nil {
		return nil
	}

	id := f.ID()
	if id == "" {
		return nil
	}

	_, err := fmt.Fprintf(w, "\tCalled from %v\n", id)
	if err != nil {
		return err
	}

	return f.p.backtrace(w)
}

// A GoFunc is an implementation of Func that calls a Go function.
// This is the easiest way to implement lower-level systems for WDTE
// scripts to make use of.
//
// For example, to implement a simple, non-type-safe addition
// function:
//
//    module.Funcs["+"] = GoFunc(func(frame wdte.Frame, args ...wdte.Func) wdte.Func {
//      var sum wdte.Number
//      for _, arg := range(args) {
//        sum += arg.Call(frame).(wdte.Number)
//      }
//      return sum
//    })
//
// This can then be called from WDTE as follows:
//
//    + 3 6 9
//
// As shown, it is recommended that arguments be passed the given
// frame when evaluating them. Failing to do so without knowing what
// you're doing can cause unexpected behavior, including sending the
// evaluation system into infinite loops or causing panics.
type GoFunc func(frame Frame, args ...Func) Func

func (f GoFunc) Call(frame Frame, args ...Func) (r Func) {
	defer func() {
		if err, ok := recover().(error); ok {
			r = Error{
				Err: err,

				// Hmmm...
				Frame: frame.WithID("panic in GoFunc"),
			}
		}
	}()

	return f(frame, args...)
}

func (f GoFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// A DeclFunc is a function that was declared in a WDTE function
// declaration. This is the primary source of the frame argument that
// is passed around everywhere.
type DeclFunc struct {
	// ID is the name that the function was declared with. This is
	// primarily for debugging.
	ID ID

	// Expr is the expression that the function maps to.
	Expr Func

	// Args is the number of arguments the function expects.
	Args int

	// Stored is the arguments that have already been passed to a
	// function if it was given less arguments than it was declared
	// with.
	Stored []Func
}

func (f DeclFunc) Call(frame Frame, args ...Func) Func {
	if len(args) < f.Args {
		return &DeclFunc{
			ID:     f.ID,
			Expr:   f,
			Args:   f.Args - len(args),
			Stored: args,
		}
	}

	next := make([]Func, 0, len(f.Stored)+len(args))
	for _, arg := range f.Stored {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	for _, arg := range args {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}

	return f.Expr.Call(frame.New(f.ID, next), next...)
}

func (f DeclFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Expr is an unevaluated expression. This is usually the
// right-hand side of a function declaration, but could also be any of
// various pieces of switches, compounds, or arrays.
type Expr struct {
	// Func is the underlying function.
	Func Func

	// Args are the arguments to pass to Func.
	Args []Func
}

func (f Expr) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(frame, f.Args...)
}

func (f Expr) Equals(other Func) bool {
	panic("Not implemented.")
}

// Chain is an unevaluated chain expression.
type Chain struct {
	// Func is the expression at the current part of the chain.
	Func Func

	// Args is the arguments to Func.
	Args []Func

	// Prev is the previous part of the chain.
	Prev Func
}

func (f Chain) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(frame, f.Args...).Call(frame, f.Prev.Call(frame))
}

func (f Chain) Equals(other Func) bool {
	panic("Not implemented.")
}

// External represents a function from an imported module. It looks
// the function up when called, so it is safe to pass Externals around
// before importing, so long as they are not evaluated until after
// importing.
type External struct {
	// Module is the module that the function was called from. This is
	// *not* the module that the function was declared in. Unless, for
	// some reason, the module has itself as an import.
	Module *Module

	// Import is the import ID of the module that the function was
	// declared in.
	Import ID

	// Func is the ID of the function in the module it was declared in.
	Func ID
}

func (e External) Call(frame Frame, args ...Func) Func {
	i, ok := e.Module.Imports[e.Import]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Import %q does not exist", e.Import),
			Frame: frame,
		}
	}
	f, ok := i.Funcs[e.Func]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Function %q does not exist in import %q", e.Func, e.Import),
			Frame: frame,
		}
	}

	return f.Call(frame, args...)
}

func (e External) Equals(other Func) bool {
	o, ok := other.(External)
	return ok && (e.Import == o.Import) && (e.Func == o.Func)
}

// Local represents a function from a module, usually the current one.
// It looks the function up when called, so it is safe to pass Locals
// around before importing, so long as they are not evaluated until
// after importing.
type Local struct {
	// Module is the module that the function was declared in.
	Module *Module

	// Func is the ID of the function in the module.
	Func ID
}

func (local Local) Call(frame Frame, args ...Func) Func {
	f, ok := local.Module.Funcs[local.Func]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Function %q does not exist", local.Func),
			Frame: frame,
		}
	}

	return f.Call(frame, args...)
}

func (local Local) Equals(other Func) bool {
	o, ok := other.(Local)
	return ok && (local.Func == o.Func)
}

// A Compound represents a compound expression. Calling it calls each
// of the expressions in the compound, returning the value of the last
// one. If the compound is empty, nil is returned.
type Compound []Func

func (c Compound) Call(frame Frame, args ...Func) Func {
	var last Func
	for _, f := range c {
		last = f.Call(frame)
		if _, ok := last.(error); ok {
			return last
		}
	}

	return last
}

func (c Compound) Equals(other Func) bool {
	panic("Not implemented.")
}

// Switch represents a switch expression.
type Switch struct {
	// Check is the condition at the front of the switch.
	Check Func

	// Cases is the switch's cases. Each contains two functions. The
	// first index is the left-hand side, while the second is the
	// right-hand side. When the switch is evaluated, the cases are run
	// in order. If any matches, the right-hand side is evaluated and
	// its return value is returned.
	//
	// A default case is represented by a nil in the first index. It is
	// possible to have cases after a default, but pointless, as a
	// default is always run when it is encountered.
	Cases [][2]Func
}

func (s Switch) Call(frame Frame, args ...Func) Func {
	check := s.Check.Call(frame)
	if _, ok := check.(error); ok {
		return check
	}

	for _, c := range s.Cases {
		if c[0] == nil {
			return c[1].Call(frame)
		}

		lhs := c[0].Call(frame)
		if _, ok := lhs.(error); ok {
			return lhs
		}

		if check.Equals(lhs) {
			return c[1].Call(frame)
		}
	}

	return nil
}

func (s Switch) Equals(other Func) bool {
	panic("Not implemented.")
}

// Arg represents an argument in the current frame. It is the opposite
// end from DeclFunc of the frame argument that gets passed around all
// over the place.
type Arg int

func (a Arg) Call(frame Frame, args ...Func) Func {
	if int(a) >= len(frame.Args()) {
		// I don't think this can happen normally, but some GoFunc
		// somewhere could generate an Arg for some bizarre reason and
		// cause this.
		return Error{
			Err: fmt.Errorf(
				"Attempted to access %vth argument in a frame containing %v",
				a,
				len(frame.Args()),
			),
			Frame: frame,
		}
	}

	return frame.Args()[a].Call(frame, args...)
}

func (a Arg) Equals(other Func) bool {
	panic("Not implemented.")
}

// A FramedFunc is a function which keeps track of its own calling
// frame.
type FramedFunc struct {
	// Func is the actual function.
	Func Func

	// Frame is the frame to call Func with.
	Frame Frame
}

func (f FramedFunc) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(f.Frame, args...)
}

func (f FramedFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

type Memo struct {
	Func Func

	cache memoCache
}

func (m *Memo) Call(frame Frame, args ...Func) Func {
	if m.cache == nil {
		m.cache = make(memoCache)
	}

	for i := range args {
		args[i] = args[i].Call(frame)
	}

	key := m.cache.Key(args)

	cached, ok := m.cache[key]
	if ok {
		return cached
	}

	r := m.Func.Call(frame, args...)
	m.cache[key] = r
	return r
}

func (m Memo) Equals(other Func) bool {
	panic("Not implemented.")
}

type memoCache map[string]Func

func (cache memoCache) Key(args []Func) string {
	var buf bytes.Buffer
	for _, arg := range args {
		// TODO: Figure out a way to do this that isn't stupid.
		fmt.Fprint(&buf, arg)
	}
	return buf.String()
}
<commit_msg>wdte: Add Godoc comment to Memo.<commit_after>package wdte

import (
	"bytes"
	"fmt"
	"io"

	"github.com/DeedleFake/wdte/ast"
)

// A Module is the result of parsing a WDTE script. It is the main
// type of this entire library.
type Module struct {
	// Imports maps IDs to other modules. WDTE import statements create
	// these when parsed.
	Imports map[ID]*Module

	// Funcs maps IDs to functions. WDTE function declarations create
	// these when parsed.
	Funcs map[ID]Func
}

// Parse parses an AST from r and then translates it into a module. im
// is used to handle import statements. If im is nil, a no-op importer
// is used.
func Parse(r io.Reader, im Importer) (*Module, error) {
	root, err := ast.Parse(r)
	if err != nil {
		return nil, err
	}

	return FromAST(root, im)
}

// FromAST translates an AST into a module. im is used to handle
// import statements. If im is nil, a no-op importer is used.
func FromAST(root ast.Node, im Importer) (*Module, error) {
	return fromScript(root.(*ast.NTerm), im)
}

// An Importer creates modules from strings. When parsing a WDTE script, an importer is used to import modules.
//
// When the WDTE import statement
//
//    'example' => e;
//
// is parsed, the associated Importer will be invoked as follows:
//
//    im.Import(example)
//
// The return value will then be added to the module's Imports map.
type Importer interface {
	Import(from string) (*Module, error)
}

// ImportFunc is a wrapper around simple functions to allow them to be
// used as Importers.
type ImportFunc func(from string) (*Module, error)

func (f ImportFunc) Import(from string) (*Module, error) {
	return f(from)
}

// ID represents a WDTE ID, such as a function or imported module
// name.
type ID string

// Func is the base type through which all data is handled by WDTE. It
// represents everything that can be passed around in the language.
// This includes functions, of course, expressions, strings, numbers,
// Go functions, and anything else the client wants to pass into WDTE.
type Func interface {
	// Call calls the function with the given arguments, returning its
	// return value. frame represents the current call frame. This is
	// used to keep track of function arguments during the evaluation of
	// expressions, and can largely be ignored by clients.
	Call(frame Frame, args ...Func) Func

	// Equals returns true if one function equals another one. This is
	// meaningless for the majority of implementations, and should
	// largely be ignored by clients. When implementing custom
	// functions, if you're not sure what to do for this, you probably
	// won't have any issues. This is only used, by default, by switches
	// as a way of checking if the condition matches one of the cases.
	Equals(other Func) bool
}

// A Frame tracks information about the current function call.
type Frame struct {
	id   ID
	args []Func

	p *Frame
}

// F returns a top-level frame. This can be used by Go code calling
// WDTE functions directly if another frame is not available.
func F() Frame {
	return Frame{
		id: "unknown function, maybe Go",
	}
}

// New creates a new frame from a previous frame. id should be the ID
// of the function that generated the frame, and args should be the
// arguments given to that function.
func (f Frame) New(id ID, args []Func) Frame {
	return Frame{
		id:   id,
		args: args,
		p:    &f,
	}
}

// WithID is a convienence function for creating a frame with a new ID
// but the same arguments as the previous frame.
func (f Frame) WithID(id ID) Frame {
	return f.New(id, f.args)
}

// ID returns the ID of the frame. This is generally the function that
// created the frame.
func (f Frame) ID() ID {
	return f.id
}

// Args returns the arguments of the frame.
func (f Frame) Args() []Func {
	return f.args
}

// Parent returns the frame that this frame was created from, or a
// blank frame if there was none.
func (f Frame) Parent() Frame {
	if f.p == nil {
		return Frame{}
	}

	return *f.p
}

// Backtrace prints a backtrace to w.
func (f Frame) Backtrace(w io.Writer) error {
	_, err := fmt.Fprintf(w, "\t%v\n", f.ID())
	if err != nil {
		return err
	}

	return f.p.backtrace(w)
}

func (f *Frame) backtrace(w io.Writer) error {
	if f == nil {
		return nil
	}

	id := f.ID()
	if id == "" {
		return nil
	}

	_, err := fmt.Fprintf(w, "\tCalled from %v\n", id)
	if err != nil {
		return err
	}

	return f.p.backtrace(w)
}

// A GoFunc is an implementation of Func that calls a Go function.
// This is the easiest way to implement lower-level systems for WDTE
// scripts to make use of.
//
// For example, to implement a simple, non-type-safe addition
// function:
//
//    module.Funcs["+"] = GoFunc(func(frame wdte.Frame, args ...wdte.Func) wdte.Func {
//      var sum wdte.Number
//      for _, arg := range(args) {
//        sum += arg.Call(frame).(wdte.Number)
//      }
//      return sum
//    })
//
// This can then be called from WDTE as follows:
//
//    + 3 6 9
//
// As shown, it is recommended that arguments be passed the given
// frame when evaluating them. Failing to do so without knowing what
// you're doing can cause unexpected behavior, including sending the
// evaluation system into infinite loops or causing panics.
type GoFunc func(frame Frame, args ...Func) Func

func (f GoFunc) Call(frame Frame, args ...Func) (r Func) {
	defer func() {
		if err, ok := recover().(error); ok {
			r = Error{
				Err: err,

				// Hmmm...
				Frame: frame.WithID("panic in GoFunc"),
			}
		}
	}()

	return f(frame, args...)
}

func (f GoFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// A DeclFunc is a function that was declared in a WDTE function
// declaration. This is the primary source of the frame argument that
// is passed around everywhere.
type DeclFunc struct {
	// ID is the name that the function was declared with. This is
	// primarily for debugging.
	ID ID

	// Expr is the expression that the function maps to.
	Expr Func

	// Args is the number of arguments the function expects.
	Args int

	// Stored is the arguments that have already been passed to a
	// function if it was given less arguments than it was declared
	// with.
	Stored []Func
}

func (f DeclFunc) Call(frame Frame, args ...Func) Func {
	if len(args) < f.Args {
		return &DeclFunc{
			ID:     f.ID,
			Expr:   f,
			Args:   f.Args - len(args),
			Stored: args,
		}
	}

	next := make([]Func, 0, len(f.Stored)+len(args))
	for _, arg := range f.Stored {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	for _, arg := range args {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}

	return f.Expr.Call(frame.New(f.ID, next), next...)
}

func (f DeclFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Expr is an unevaluated expression. This is usually the
// right-hand side of a function declaration, but could also be any of
// various pieces of switches, compounds, or arrays.
type Expr struct {
	// Func is the underlying function.
	Func Func

	// Args are the arguments to pass to Func.
	Args []Func
}

func (f Expr) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(frame, f.Args...)
}

func (f Expr) Equals(other Func) bool {
	panic("Not implemented.")
}

// Chain is an unevaluated chain expression.
type Chain struct {
	// Func is the expression at the current part of the chain.
	Func Func

	// Args is the arguments to Func.
	Args []Func

	// Prev is the previous part of the chain.
	Prev Func
}

func (f Chain) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(frame, f.Args...).Call(frame, f.Prev.Call(frame))
}

func (f Chain) Equals(other Func) bool {
	panic("Not implemented.")
}

// External represents a function from an imported module. It looks
// the function up when called, so it is safe to pass Externals around
// before importing, so long as they are not evaluated until after
// importing.
type External struct {
	// Module is the module that the function was called from. This is
	// *not* the module that the function was declared in. Unless, for
	// some reason, the module has itself as an import.
	Module *Module

	// Import is the import ID of the module that the function was
	// declared in.
	Import ID

	// Func is the ID of the function in the module it was declared in.
	Func ID
}

func (e External) Call(frame Frame, args ...Func) Func {
	i, ok := e.Module.Imports[e.Import]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Import %q does not exist", e.Import),
			Frame: frame,
		}
	}
	f, ok := i.Funcs[e.Func]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Function %q does not exist in import %q", e.Func, e.Import),
			Frame: frame,
		}
	}

	return f.Call(frame, args...)
}

func (e External) Equals(other Func) bool {
	o, ok := other.(External)
	return ok && (e.Import == o.Import) && (e.Func == o.Func)
}

// Local represents a function from a module, usually the current one.
// It looks the function up when called, so it is safe to pass Locals
// around before importing, so long as they are not evaluated until
// after importing.
type Local struct {
	// Module is the module that the function was declared in.
	Module *Module

	// Func is the ID of the function in the module.
	Func ID
}

func (local Local) Call(frame Frame, args ...Func) Func {
	f, ok := local.Module.Funcs[local.Func]
	if !ok {
		return Error{
			Err:   fmt.Errorf("Function %q does not exist", local.Func),
			Frame: frame,
		}
	}

	return f.Call(frame, args...)
}

func (local Local) Equals(other Func) bool {
	o, ok := other.(Local)
	return ok && (local.Func == o.Func)
}

// A Compound represents a compound expression. Calling it calls each
// of the expressions in the compound, returning the value of the last
// one. If the compound is empty, nil is returned.
type Compound []Func

func (c Compound) Call(frame Frame, args ...Func) Func {
	var last Func
	for _, f := range c {
		last = f.Call(frame)
		if _, ok := last.(error); ok {
			return last
		}
	}

	return last
}

func (c Compound) Equals(other Func) bool {
	panic("Not implemented.")
}

// Switch represents a switch expression.
type Switch struct {
	// Check is the condition at the front of the switch.
	Check Func

	// Cases is the switch's cases. Each contains two functions. The
	// first index is the left-hand side, while the second is the
	// right-hand side. When the switch is evaluated, the cases are run
	// in order. If any matches, the right-hand side is evaluated and
	// its return value is returned.
	//
	// A default case is represented by a nil in the first index. It is
	// possible to have cases after a default, but pointless, as a
	// default is always run when it is encountered.
	Cases [][2]Func
}

func (s Switch) Call(frame Frame, args ...Func) Func {
	check := s.Check.Call(frame)
	if _, ok := check.(error); ok {
		return check
	}

	for _, c := range s.Cases {
		if c[0] == nil {
			return c[1].Call(frame)
		}

		lhs := c[0].Call(frame)
		if _, ok := lhs.(error); ok {
			return lhs
		}

		if check.Equals(lhs) {
			return c[1].Call(frame)
		}
	}

	return nil
}

func (s Switch) Equals(other Func) bool {
	panic("Not implemented.")
}

// Arg represents an argument in the current frame. It is the opposite
// end from DeclFunc of the frame argument that gets passed around all
// over the place.
type Arg int

func (a Arg) Call(frame Frame, args ...Func) Func {
	if int(a) >= len(frame.Args()) {
		// I don't think this can happen normally, but some GoFunc
		// somewhere could generate an Arg for some bizarre reason and
		// cause this.
		return Error{
			Err: fmt.Errorf(
				"Attempted to access %vth argument in a frame containing %v",
				a,
				len(frame.Args()),
			),
			Frame: frame,
		}
	}

	return frame.Args()[a].Call(frame, args...)
}

func (a Arg) Equals(other Func) bool {
	panic("Not implemented.")
}

// A FramedFunc is a function which keeps track of its own calling
// frame.
type FramedFunc struct {
	// Func is the actual function.
	Func Func

	// Frame is the frame to call Func with.
	Frame Frame
}

func (f FramedFunc) Call(frame Frame, args ...Func) Func {
	return f.Func.Call(f.Frame, args...)
}

func (f FramedFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// A Memo wraps another function, caching the results of calls with
// the same arguments.
type Memo struct {
	Func Func

	cache memoCache
}

func (m *Memo) Call(frame Frame, args ...Func) Func {
	if m.cache == nil {
		m.cache = make(memoCache)
	}

	for i := range args {
		args[i] = args[i].Call(frame)
	}

	key := m.cache.Key(args)

	cached, ok := m.cache[key]
	if ok {
		return cached
	}

	r := m.Func.Call(frame, args...)
	m.cache[key] = r
	return r
}

func (m Memo) Equals(other Func) bool {
	panic("Not implemented.")
}

type memoCache map[string]Func

func (cache memoCache) Key(args []Func) string {
	var buf bytes.Buffer
	for _, arg := range args {
		// TODO: Figure out a way to do this that isn't stupid.
		fmt.Fprint(&buf, arg)
	}
	return buf.String()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"os"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

func main() {
	w := Wikidata{
		bucket: os.Getenv("AWS_BUCKET_NAME"),
		region: os.Getenv("AWS_BUCKET_REGION"),
	}
	w.connect()

	router := gin.Default()
	store := sessions.NewCookieStore([]byte("secret"))
	router.Use(sessions.Sessions("mysession", store))
	router.LoadHTMLGlob("style/*.html")

	router.Use(s3Middleware(&w))
	router.GET("/login", getloginfunc)
	router.POST("/login", postloginfunc)
	router.GET("/signup", getsignupfunc)
	router.POST("/signup", postsignupfunc)
	router.GET("/logout", getlogoutfunc)

	router.GET("/auth/callback", authCallback)
	router.GET("/auth", authenticate)
	router.StaticFile("/layout.css", "style/layout.css")
	router.StaticFile("/favicon.ico", "style/favicon.ico")

	auth := router.Group("/")
	auth.Use(authMiddleware())
	{
		auth.GET("/", func(c *gin.Context) {
			c.Redirect(http.StatusFound, "/page/Home")
		})
		auth.GET("/page/:title/edit", editfunc)
		auth.GET("/page/:title", getfunc)
		auth.POST("/page/:title", postfunc)
		auth.POST("/page/:title/acl", aclfunc)
		auth.PUT("/page/:title", putfunc)
		auth.DELETE("/page/:title", deletefunc)
	}

	router.Run(":8080")
}

func s3Middleware(s3 *Wikidata) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Set("S3", s3)
		c.Next()
	}
}

func editfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	body := ""
	markdown, err := s3.loadMarkdown(title)
	if err == nil {
		body = markdown.body
	}
	c.HTML(http.StatusOK, "edit.html", gin.H{
		"Title": c.Param("title"),
		"Body":  body,
	})
}

func postfunc(c *gin.Context) {
	method, _ := c.GetPostForm("_method")
	fmt.Println(method)
	switch method {
	case "put":
		putfunc(c)
	case "delete":
		deletefunc(c)
	}
}

func aclfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	acl, _ := c.GetPostForm("acl")
	switch acl {
	case "public":
		s3.aclPublic(title)
	case "private":
		s3.aclPrivate(title)
	}
	c.Redirect(http.StatusFound, "/page/"+title)
}

type breadcrumb struct {
	List []string `json:"list"`
}

func getfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	html, err := s3.loadHTML(title)
	if err != nil {
		c.Redirect(http.StatusFound, "/page/"+title+"/edit")
		return
	}

	public := s3.checkPublic(title)
	publicURL := s3.publicURL(title)

	session := sessions.Default(c)
	jsonStr := session.Get("breadcrumb")

	var u breadcrumb
	u.List = []string{}
	if jsonStr != nil {
		json.Unmarshal(jsonStr.([]byte), &u)
	}

	var array []string

	for _, l := range u.List {
		if l != title {
			array = append(array, l)
		}
	}

	maxSize := 5

	u.List = append(array, title)
	if len(u.List) > maxSize {
		u.List = u.List[1 : maxSize+1]
	}
	jsonOut, _ := json.Marshal(&u)
	session.Set("breadcrumb", jsonOut)
	session.Save()

	c.HTML(http.StatusOK, "view.html", gin.H{
		"Title":        title,
		"Body":         template.HTML(html.body),
		"Breadcrumb":   array,
		"Public":       public,
		"PublicURL":    publicURL,
		"LastModified": html.lastUpdate,
		"Author":       html.author,
	})
}

func deletefunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	s3.deleteMarkdown(title)
	s3.deleteHTML(title)
	c.Redirect(http.StatusFound, "/")
}

func putfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")

	session := sessions.Default(c)
	user := session.Get("user")

	id, err := s3.loadDocumentID(title)
	if err != nil {
		id, err = randomString()
		if err != nil {
			return
		}
	}

	var markdown, html pageData

	markdown.title = title
	markdown.author = user.(string)
	markdown.body, _ = c.GetPostForm("body")
	markdown.id = id
	s3.saveMarkdown(markdown)

	html.title = title
	html.author = user.(string)
	html.body, _ = MarkdownToHTML([]byte(markdown.body))
	html.id = id
	s3.saveHTML(html)
	c.Redirect(http.StatusFound, "/page/"+title)
}
<commit_msg>Add default string<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"os"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

func main() {
	w := Wikidata{
		bucket: os.Getenv("AWS_BUCKET_NAME"),
		region: os.Getenv("AWS_BUCKET_REGION"),
	}
	w.connect()

	router := gin.Default()
	store := sessions.NewCookieStore([]byte("secret"))
	router.Use(sessions.Sessions("mysession", store))
	router.LoadHTMLGlob("style/*.html")

	router.Use(s3Middleware(&w))
	router.GET("/login", getloginfunc)
	router.POST("/login", postloginfunc)
	router.GET("/signup", getsignupfunc)
	router.POST("/signup", postsignupfunc)
	router.GET("/logout", getlogoutfunc)

	router.GET("/auth/callback", authCallback)
	router.GET("/auth", authenticate)
	router.StaticFile("/layout.css", "style/layout.css")
	router.StaticFile("/favicon.ico", "style/favicon.ico")

	auth := router.Group("/")
	auth.Use(authMiddleware())
	{
		auth.GET("/", func(c *gin.Context) {
			c.Redirect(http.StatusFound, "/page/Home")
		})
		auth.GET("/page/:title/edit", editfunc)
		auth.GET("/page/:title", getfunc)
		auth.POST("/page/:title", postfunc)
		auth.POST("/page/:title/acl", aclfunc)
		auth.PUT("/page/:title", putfunc)
		auth.DELETE("/page/:title", deletefunc)
	}

	router.Run(":8080")
}

func s3Middleware(s3 *Wikidata) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Set("S3", s3)
		c.Next()
	}
}

func editfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	body := "# " + title + "\n"
	markdown, err := s3.loadMarkdown(title)
	if err == nil {
		body = markdown.body
	}
	c.HTML(http.StatusOK, "edit.html", gin.H{
		"Title": c.Param("title"),
		"Body":  body,
	})
}

func postfunc(c *gin.Context) {
	method, _ := c.GetPostForm("_method")
	fmt.Println(method)
	switch method {
	case "put":
		putfunc(c)
	case "delete":
		deletefunc(c)
	}
}

func aclfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	acl, _ := c.GetPostForm("acl")
	switch acl {
	case "public":
		s3.aclPublic(title)
	case "private":
		s3.aclPrivate(title)
	}
	c.Redirect(http.StatusFound, "/page/"+title)
}

type breadcrumb struct {
	List []string `json:"list"`
}

func getfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	html, err := s3.loadHTML(title)
	if err != nil {
		c.Redirect(http.StatusFound, "/page/"+title+"/edit")
		return
	}

	public := s3.checkPublic(title)
	publicURL := s3.publicURL(title)

	session := sessions.Default(c)
	jsonStr := session.Get("breadcrumb")

	var u breadcrumb
	u.List = []string{}
	if jsonStr != nil {
		json.Unmarshal(jsonStr.([]byte), &u)
	}

	var array []string

	for _, l := range u.List {
		if l != title {
			array = append(array, l)
		}
	}

	maxSize := 5

	u.List = append(array, title)
	if len(u.List) > maxSize {
		u.List = u.List[1 : maxSize+1]
	}
	jsonOut, _ := json.Marshal(&u)
	session.Set("breadcrumb", jsonOut)
	session.Save()

	c.HTML(http.StatusOK, "view.html", gin.H{
		"Title":        title,
		"Body":         template.HTML(html.body),
		"Breadcrumb":   array,
		"Public":       public,
		"PublicURL":    publicURL,
		"LastModified": html.lastUpdate,
		"Author":       html.author,
	})
}

func deletefunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")
	s3.deleteMarkdown(title)
	s3.deleteHTML(title)
	c.Redirect(http.StatusFound, "/")
}

func putfunc(c *gin.Context) {
	s3 := c.MustGet("S3").(*Wikidata)
	title := c.Param("title")

	session := sessions.Default(c)
	user := session.Get("user")

	id, err := s3.loadDocumentID(title)
	if err != nil {
		id, err = randomString()
		if err != nil {
			return
		}
	}

	var markdown, html pageData

	markdown.title = title
	markdown.author = user.(string)
	markdown.body, _ = c.GetPostForm("body")
	markdown.id = id
	s3.saveMarkdown(markdown)

	html.title = title
	html.author = user.(string)
	html.body, _ = MarkdownToHTML([]byte(markdown.body))
	html.id = id
	s3.saveHTML(html)
	c.Redirect(http.StatusFound, "/page/"+title)
}
<|endoftext|>


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

package openid

import (
	"encoding/xml"
	"io"
	"strings"
)

type xrdsIdentifier struct {
	XMLName xml.Name "Service"
	Type    []string
	URI     string
	LocalID string
}
type xrd struct {
	XMLName xml.Name "XRD"
	Service xrdsIdentifier
}
type xrds struct {
	XMLName xml.Name "XRDS"
	XRD     xrd
}

// Parse a XRDS document provided through a io.Reader
// Return the OP EndPoint and, if found, the Claimed Identifier
func ParseXRDS(r io.Reader) (string, string) {
	xrds := new(xrds)
	err := xml.NewDecoder(r).Decode(xrds)
	if err != nil {
		//fmt.Printf(err.String())
		return "", ""
	}
	xrdsi := xrds.XRD.Service

	xrdsi.URI = strings.TrimSpace(xrdsi.URI)
	xrdsi.LocalID = strings.TrimSpace(xrdsi.LocalID)

	//fmt.Printf("%v\n", xrdsi)

	if stringTableContains(xrdsi.Type, "http://specs.openid.net/auth/2.0/server") {
		//fmt.Printf("OP Identifier Element found\n")
		return xrdsi.URI, ""
	} else if stringTableContains(xrdsi.Type, "http://specs.openid.net/auth/2.0/signon") {
		//fmt.Printf("Claimed Identifier Element found\n")
		return xrdsi.URI, xrdsi.LocalID
	}
	return "", ""
}

func stringTableContains(t []string, s string) bool {
	for _, v := range t {
		if v == s {
			return true
		}
	}
	return false
}
<commit_msg>some small refactoring again<commit_after>// Copyright 2010 Florian Duraffourg. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package openid

import (
	"encoding/xml"
	"io"
	"strings"
)

type xrdsIdentifier struct {
	XMLName xml.Name "Service"
	Type    []string
	URI     string
	LocalID string
}
type xrd struct {
	XMLName xml.Name "XRD"
	Service xrdsIdentifier
}
type xrds struct {
	XMLName xml.Name "XRDS"
	XRD     xrd
}

// Parse a XRDS document provided through a io.Reader
// Return the OP EndPoint and, if found, the Claimed Identifier
func ParseXRDS(r io.Reader) (string, string) {
	xrds := xrds{}
	err := xml.NewDecoder(r).Decode(&xrds)
	if err != nil {
		//fmt.Printf(err.String())
		return "", ""
	}
	xrdsi := xrds.XRD.Service

	xrdsi.URI = strings.TrimSpace(xrdsi.URI)
	xrdsi.LocalID = strings.TrimSpace(xrdsi.LocalID)

	//fmt.Printf("%v\n", xrdsi)

	if stringTableContains(xrdsi.Type, "http://specs.openid.net/auth/2.0/server") {
		//fmt.Printf("OP Identifier Element found\n")
		return xrdsi.URI, ""
	} else if stringTableContains(xrdsi.Type, "http://specs.openid.net/auth/2.0/signon") {
		//fmt.Printf("Claimed Identifier Element found\n")
		return xrdsi.URI, xrdsi.LocalID
	}
	return "", ""
}

func stringTableContains(t []string, s string) bool {
	for _, v := range t {
		if v == s {
			return true
		}
	}
	return false
}
<|endoftext|>