<commit_before>package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"

	"log"

	"fmt"
	"strings"

	"time"

	"strconv"

	"github.com/golang-commonmark/markdown"
	"github.com/justinas/alice"
)

var wikiDir string
var tagDir string
var pubDir string

var specialDir []string

type basePage struct {
	Title string
	Nav   nav
}
type wikiPage struct {
	Body      template.HTML
	Tags      string
	TagArray  []string
	Created   string
	Modified  string
	Published bool
	basePage
}
type searchPage struct {
	basePage
	Results []QueryResults
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}
func getPDFFilename(folder, name string) string {
	return folder + name
}

func getWikiFilename(folder, name string) string {
	return folder + name + ".md"
}

func getWikiTagsFilename(name string) string {
	return tagDir + name
}
func getWikiPubFilename(name string) string {
	return pubDir + name
}
func (p *wikiPage) save(s storage) error {
	filename := getWikiFilename(wikiDir, p.Title)
	err := s.storeFile(filename, []byte(p.Body))
	if err != nil {
		return err
	}

	tagsfile := getWikiTagsFilename(p.Title)
	err = s.storeFile(tagsfile, []byte(p.Tags))
	if err != nil {
		return err
	}

	log.Printf("Pub flag %v\n", p.Published)
	if p.Published {
		pubfile := getWikiPubFilename(p.Title)
		log.Printf("Saving %v\n", pubfile)
		err = s.storeFile(pubfile, nil)
		if err != nil {
			return err
		}

	} else {
		// Need to delete the pub file if it exists
	}

	return nil
}

func convertMarkdown(page *wikiPage, err error) (*wikiPage, error) {
	if err != nil {
		return page, err
	}
	md := markdown.New(markdown.HTML(true))
	page.Body = template.HTML(md.RenderToString([]byte(page.Body)))
	return page, nil

}
func loadPage(p *wikiPage) (*wikiPage, error) {
	filename := getWikiFilename(wikiDir, p.Title)

	file, err := os.Open(filename)
	if err != nil {
		log.Println(err)
		return p, err
	}
	defer file.Close()

	body, err := ioutil.ReadAll(file)
	if err != nil {
		log.Println(err)
		return p, err
	}
	p.Body = template.HTML(body)

	info, err := file.Stat()
	if err != nil {
		log.Println(err)
		return p, err
	}

	p.Modified = info.ModTime().String()

	tags, err := ioutil.ReadFile(getWikiTagsFilename(p.Title))
	if err == nil {
		p.Tags = string(tags)
		p.TagArray = strings.Split(p.Tags, ",")
	}

	pubfilename := getWikiPubFilename(p.Title)

	pubfile, err := os.Open(pubfilename)
	if err == nil {
		p.Published = true
		pubfile.Close()
	}

	return p, nil
}

func checkForPDF(p *wikiPage) (*wikiPage, error) {
	filename := getPDFFilename(wikiDir, p.Title)

	file, err := os.Open(filename)
	if err != nil {
		log.Printf("Failed to open %v, %v\n", p.Title, err.Error())
		return p, err
	}
	defer file.Close()

	p.Body = template.HTML(fmt.Sprintf("%v", p.Title, p.Title))
	return p, nil
}

func viewHandler(w http.ResponseWriter, r *http.Request, p *wikiPage) {
	p, err := convertMarkdown(loadPage(p))
	if err != nil {
		p, err = checkForPDF(p)
		if err != nil {
			http.Redirect(w, r, "/wiki/edit/"+p.Title, http.StatusFound)
			return
		}
	} else {
		p.Body = template.HTML(parseWikiWords([]byte(p.Body)))
	}

	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, p *wikiPage) {
	p, _ = loadPage(p)
	renderTemplate(w, "edit", p)
}

func searchHandler(fn navFunc) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		term := r.URL.Query().Get("term") // Get the search term
		if len(term) == 0 {
			http.NotFound(w, r)
			return
		}

		results := ParseQueryResults(SearchWikis(wikiDir, term))
		p := &searchPage{Results: results, basePage: basePage{Title: "Search", Nav: fn(nil)}}

		renderTemplate(w, "search", p)
	}
}

func redirectHandler(c Config) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		host := r.Host
		var port string
		hostparts := strings.Split(host, ":")
		if len(hostparts) == 2 {
			host = hostparts[0]
			port = strconv.Itoa(c.HTTPSPort)
		}
		target := "https://" + host
		if len(port) > 0 {
			target += ":" + port

		}
		target += r.URL.Path
		if len(r.URL.RawQuery) > 0 {
			target += "?" + r.URL.RawQuery
		}
		http.Redirect(w, r, target, http.StatusTemporaryRedirect)

	}
}

func homeHandler(page string, fn navFunc, s storage) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		renderTemplate(w, page, fn(s))
	}

}

func saveHandler(w http.ResponseWriter, r *http.Request, wiki string, s storage) string {
	body := r.FormValue("body")
	log.Printf("Checkbox is : %v", r.FormValue("wikipub"))
	p := wikiPage{basePage: basePage{Title: wiki}, Body: template.HTML(body), Tags: r.FormValue("wikitags")}
	if r.FormValue("wikipub") == "on" {
		p.Published = true
	}

	err := p.save(s)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return ""
	}
	http.Redirect(w, r, "/wiki/view/"+p.Title, http.StatusFound)

	return r.FormValue("wikitags")
}

var templates = template.Must(template.ParseFiles(
	"views/edit.html",
	"views/view.html",
	"views/pub.html",
	"views/pubhome.html",
	"views/login.html",
	"views/home.html",
	"views/search.html",
	"views/index.html",
	"views/footer.html",
	"views/leftnav.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {
	err := templates.ExecuteTemplate(w, tmpl+".html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

var validPath = regexp.MustCompile("^/wiki/(edit|save|view|search)/([a-zA-Z0-9\\.\\-_ /]*)$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, *wikiPage), navfn navFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		wword := r.URL.Query().Get("wword") // Get the wiki word param if available
		if len(wword) == 0 {
			log.Printf("Path is : %v", r.URL.Path)
			m := validPath.FindStringSubmatch(r.URL.Path)
			if m == nil {
				http.NotFound(w, r)
				return
			}
			wword = m[2]
		}
		p := &wikiPage{basePage: basePage{Title: wword, Nav: navfn(nil)}}
		fn(w, r, p)
	}
}

func processSave(fn func(http.ResponseWriter, *http.Request, string, storage) string, s storage) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r, m[2], s)

	}
}

func parseWikiWords(target []byte) []byte {
	var wikiWord = regexp.MustCompile(`\{\{([^\}]+)\}\}`)

	return wikiWord.ReplaceAll(target, []byte("$1"))
}

func loggingHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		t1 := time.Now()
		next.ServeHTTP(w, r)
		t2 := time.Now()
		log.Printf("[%s] %q %v\n", r.Method, r.URL.String(), t2.Sub(t1))
	}
	return http.HandlerFunc(fn)
}

func main() {
	specialDir = []string{"tags", "pub"}
	config, err := LoadConfig("config.json")
	if err != nil {
		log.Fatal(err)
	}

	if config.Logfile != "" {
		f, err := os.OpenFile(config.Logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			checkErr(err)
		}
		defer f.Close()

		log.SetOutput(f)
	}

	config.LoadCookieKey()

	auth := NewAuth(*config, persistUsers)

	wikiDir = config.WikiDir
	if !strings.HasSuffix(wikiDir, "/") {
		wikiDir = wikiDir + "/"
	}
	tagDir = wikiDir + "tags/" // Make sure this doesnt double up the / in the path...
	pubDir = wikiDir + "pub/"  // Make sure this doesnt double up the / in the path...

	os.Mkdir(config.WikiDir, 0755)
	os.Mkdir(config.WikiDir+"tags", 0755)

	authHandlers := alice.New(loggingHandler, auth.validate)
	noauthHandlers := alice.New(loggingHandler)

	httpmux := http.NewServeMux()
	httpsmux := httpmux
	// setup wiki on https
	if config.UseHttps {
		httpsmux = http.NewServeMux()
	}

	fstore := fileStorage{}

	httpsmux.Handle("/wiki", authHandlers.ThenFunc(homeHandler("home", getNav, fstore)))
	httpsmux.Handle("/wiki/login/", noauthHandlers.ThenFunc(auth.loginHandler))
	httpsmux.Handle("/wiki/register/", noauthHandlers.ThenFunc(auth.registerHandler))
	httpsmux.Handle("/wiki/logout/", authHandlers.ThenFunc(logoutHandler))
	httpsmux.Handle("/wiki/search/", authHandlers.ThenFunc(searchHandler(getNav)))
	httpsmux.Handle("/wiki/view/", authHandlers.ThenFunc(makeHandler(viewHandler, getNav)))
	httpsmux.Handle("/wiki/edit/", authHandlers.ThenFunc(makeHandler(editHandler, getNav)))
	httpsmux.Handle("/wiki/save/", authHandlers.ThenFunc(processSave(saveHandler, fstore)))
	httpsmux.Handle("/wiki/raw/", http.StripPrefix("/wiki/raw/", http.FileServer(http.Dir(wikiDir))))
	httpsmux.Handle("/pub/", noauthHandlers.ThenFunc(makePubHandler(pubHandler, getNav)))
	httpsmux.Handle("/pub", noauthHandlers.ThenFunc(homeHandler("pubhome", getPubNav, fstore)))

	if config.UseHttps {
		// Any routes that duplicate the http routing are only done here
		httpsmux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
		go http.ListenAndServeTLS(
			":"+strconv.Itoa(config.HTTPSPort),
			config.CertPath,
			config.KeyPath,
			httpsmux)

		httpmux.HandleFunc("/wiki", redirectHandler(*config))
	} else {
	}

	// Listen for normal traffic against root
	httpmux.Handle("/", http.FileServer(http.Dir("wwwroot")))
	httpmux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	err = http.ListenAndServe(":"+strconv.Itoa(config.HTTPPort), httpmux)
	checkErr(err)

}
<commit_msg>Add support for linking to headings<commit_after>package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"

	"log"

	"fmt"
	"strings"

	"time"

	"strconv"

	"github.com/gawth/markdown"
	"github.com/justinas/alice"
)

var wikiDir string
var tagDir string
var pubDir string

var specialDir []string

type basePage struct {
	Title string
	Nav   nav
}
type wikiPage struct {
	Body      template.HTML
	Tags      string
	TagArray  []string
	Created   string
	Modified  string
	Published bool
	basePage
}
type searchPage struct {
	basePage
	Results []QueryResults
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}
func getPDFFilename(folder, name string) string {
	return folder + name
}

func getWikiFilename(folder, name string) string {
	return folder + name + ".md"
}

func getWikiTagsFilename(name string) string {
	return tagDir + name
}
func getWikiPubFilename(name string) string {
	return pubDir + name
}
func (p *wikiPage) save(s storage) error {
	filename := getWikiFilename(wikiDir, p.Title)
	err := s.storeFile(filename, []byte(p.Body))
	if err != nil {
		return err
	}

	tagsfile := getWikiTagsFilename(p.Title)
	err = s.storeFile(tagsfile, []byte(p.Tags))
	if err != nil {
		return err
	}

	log.Printf("Pub flag %v\n", p.Published)
	if p.Published {
		pubfile := getWikiPubFilename(p.Title)
		log.Printf("Saving %v\n", pubfile)
		err = s.storeFile(pubfile, nil)
		if err != nil {
			return err
		}

	} else {
		// Need to delete the pub file if it exists
	}

	return nil
}

func convertMarkdown(page *wikiPage, err error) (*wikiPage, error) {
	if err != nil {
		return page, err
	}
	md := markdown.New(markdown.HTML(true))
	page.Body = template.HTML(md.RenderToString([]byte(page.Body)))
	return page, nil

}
func loadPage(p *wikiPage) (*wikiPage, error) {
	filename := getWikiFilename(wikiDir, p.Title)

	file, err := os.Open(filename)
	if err != nil {
		log.Println(err)
		return p, err
	}
	defer file.Close()

	body, err := ioutil.ReadAll(file)
	if err != nil {
		log.Println(err)
		return p, err
	}
	p.Body = template.HTML(body)

	info, err := file.Stat()
	if err != nil {
		log.Println(err)
		return p, err
	}

	p.Modified = info.ModTime().String()

	tags, err := ioutil.ReadFile(getWikiTagsFilename(p.Title))
	if err == nil {
		p.Tags = string(tags)
		p.TagArray = strings.Split(p.Tags, ",")
	}

	pubfilename := getWikiPubFilename(p.Title)

	pubfile, err := os.Open(pubfilename)
	if err == nil {
		p.Published = true
		pubfile.Close()
	}

	return p, nil
}

func checkForPDF(p *wikiPage) (*wikiPage, error) {
	filename := getPDFFilename(wikiDir, p.Title)

	file, err := os.Open(filename)
	if err != nil {
		log.Printf("Failed to open %v, %v\n", p.Title, err.Error())
		return p, err
	}
	defer file.Close()

	p.Body = template.HTML(fmt.Sprintf("%v", p.Title, p.Title))
	return p, nil
}

func viewHandler(w http.ResponseWriter, r *http.Request, p *wikiPage) {
	p, err := convertMarkdown(loadPage(p))
	if err != nil {
		p, err = checkForPDF(p)
		if err != nil {
			http.Redirect(w, r, "/wiki/edit/"+p.Title, http.StatusFound)
			return
		}
	} else {
		p.Body = template.HTML(parseWikiWords([]byte(p.Body)))
	}

	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, p *wikiPage) {
	p, _ = loadPage(p)
	renderTemplate(w, "edit", p)
}

func searchHandler(fn navFunc) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		term := r.URL.Query().Get("term") // Get the search term
		if len(term) == 0 {
			http.NotFound(w, r)
			return
		}

		results := ParseQueryResults(SearchWikis(wikiDir, term))
		p := &searchPage{Results: results, basePage: basePage{Title: "Search", Nav: fn(nil)}}

		renderTemplate(w, "search", p)
	}
}

func redirectHandler(c Config) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		host := r.Host
		var port string
		hostparts := strings.Split(host, ":")
		if len(hostparts) == 2 {
			host = hostparts[0]
			port = strconv.Itoa(c.HTTPSPort)
		}
		target := "https://" + host
		if len(port) > 0 {
			target += ":" + port

		}
		target += r.URL.Path
		if len(r.URL.RawQuery) > 0 {
			target += "?" + r.URL.RawQuery
		}
		http.Redirect(w, r, target, http.StatusTemporaryRedirect)

	}
}

func homeHandler(page string, fn navFunc, s storage) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		renderTemplate(w, page, fn(s))
	}

}

func saveHandler(w http.ResponseWriter, r *http.Request, wiki string, s storage) string {
	body := r.FormValue("body")
	log.Printf("Checkbox is : %v", r.FormValue("wikipub"))
	p := wikiPage{basePage: basePage{Title: wiki}, Body: template.HTML(body), Tags: r.FormValue("wikitags")}
	if r.FormValue("wikipub") == "on" {
		p.Published = true
	}

	err := p.save(s)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return ""
	}
	http.Redirect(w, r, "/wiki/view/"+p.Title, http.StatusFound)

	return r.FormValue("wikitags")
}

var templates = template.Must(template.ParseFiles(
	"views/edit.html",
	"views/view.html",
	"views/pub.html",
	"views/pubhome.html",
	"views/login.html",
	"views/home.html",
	"views/search.html",
	"views/index.html",
	"views/footer.html",
	"views/leftnav.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {
	err := templates.ExecuteTemplate(w, tmpl+".html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

var validPath = regexp.MustCompile("^/wiki/(edit|save|view|search)/([a-zA-Z0-9\\.\\-_ /]*)$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, *wikiPage), navfn navFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		wword := r.URL.Query().Get("wword") // Get the wiki word param if available
		if len(wword) == 0 {
			log.Printf("Path is : %v", r.URL.Path)
			m := validPath.FindStringSubmatch(r.URL.Path)
			if m == nil {
				http.NotFound(w, r)
				return
			}
			wword = m[2]
		}
		p := &wikiPage{basePage: basePage{Title: wword, Nav: navfn(nil)}}
		fn(w, r, p)
	}
}

func processSave(fn func(http.ResponseWriter, *http.Request, string, storage) string, s storage) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r, m[2], s)

	}
}

func parseWikiWords(target []byte) []byte {
	var wikiWord = regexp.MustCompile(`\{\{([^\}^#]+)[#]*(.*)\}\}`)

	return wikiWord.ReplaceAll(target, []byte("$1"))
}

func loggingHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		t1 := time.Now()
		next.ServeHTTP(w, r)
		t2 := time.Now()
		log.Printf("[%s] %q %v\n", r.Method, r.URL.String(), t2.Sub(t1))
	}
	return http.HandlerFunc(fn)
}

func main() {
	specialDir = []string{"tags", "pub"}
	config, err := LoadConfig("config.json")
	if err != nil {
		log.Fatal(err)
	}

	if config.Logfile != "" {
		f, err := os.OpenFile(config.Logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			checkErr(err)
		}
		defer f.Close()

		log.SetOutput(f)
	}

	config.LoadCookieKey()

	auth := NewAuth(*config, persistUsers)

	wikiDir = config.WikiDir
	if !strings.HasSuffix(wikiDir, "/") {
		wikiDir = wikiDir + "/"
	}
	tagDir = wikiDir + "tags/" // Make sure this doesnt double up the / in the path...
	pubDir = wikiDir + "pub/"  // Make sure this doesnt double up the / in the path...

	os.Mkdir(config.WikiDir, 0755)
	os.Mkdir(config.WikiDir+"tags", 0755)

	authHandlers := alice.New(loggingHandler, auth.validate)
	noauthHandlers := alice.New(loggingHandler)

	httpmux := http.NewServeMux()
	httpsmux := httpmux
	// setup wiki on https
	if config.UseHttps {
		httpsmux = http.NewServeMux()
	}

	fstore := fileStorage{}

	httpsmux.Handle("/wiki", authHandlers.ThenFunc(homeHandler("home", getNav, fstore)))
	httpsmux.Handle("/wiki/login/", noauthHandlers.ThenFunc(auth.loginHandler))
	httpsmux.Handle("/wiki/register/", noauthHandlers.ThenFunc(auth.registerHandler))
	httpsmux.Handle("/wiki/logout/", authHandlers.ThenFunc(logoutHandler))
	httpsmux.Handle("/wiki/search/", authHandlers.ThenFunc(searchHandler(getNav)))
	httpsmux.Handle("/wiki/view/", authHandlers.ThenFunc(makeHandler(viewHandler, getNav)))
	httpsmux.Handle("/wiki/edit/", authHandlers.ThenFunc(makeHandler(editHandler, getNav)))
	httpsmux.Handle("/wiki/save/", authHandlers.ThenFunc(processSave(saveHandler, fstore)))
	httpsmux.Handle("/wiki/raw/", http.StripPrefix("/wiki/raw/", http.FileServer(http.Dir(wikiDir))))
	httpsmux.Handle("/pub/", noauthHandlers.ThenFunc(makePubHandler(pubHandler, getNav)))
	httpsmux.Handle("/pub", noauthHandlers.ThenFunc(homeHandler("pubhome", getPubNav, fstore)))

	if config.UseHttps {
		// Any routes that duplicate the http routing are only done here
		httpsmux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
		go http.ListenAndServeTLS(
			":"+strconv.Itoa(config.HTTPSPort),
			config.CertPath,
			config.KeyPath,
			httpsmux)

		httpmux.HandleFunc("/wiki", redirectHandler(*config))
	} else {
	}

	// Listen for normal traffic against root
	httpmux.Handle("/", http.FileServer(http.Dir("wwwroot")))
	httpmux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	err = http.ListenAndServe(":"+strconv.Itoa(config.HTTPPort), httpmux)
	checkErr(err)

}
<|endoftext|>


<commit_before>package xlst

import (
	"errors"
	"io"
	"regexp"

	"github.com/aymerick/raymond"
	"github.com/tealeg/xlsx"
)

var (
	rgx = regexp.MustCompile(`\{\{\s*(\w+)\.\w+\s*\}\}`)
)

// Xlst Represents template struct
type Xlst struct {
	file   *xlsx.File
	report *xlsx.File
}

// New() creates new Xlst struct and returns pointer to it
func New() *Xlst {
	return &Xlst{}
}

// Render() renders report and stores it in a struct
func (m *Xlst) Render(ctx map[string]interface{}) error {
	report := xlsx.NewFile()
	for i, sheet := range m.file.Sheets {
		report.AddSheet(sheet.Name)
		cloneSheet(sheet, report.Sheets[i])
		for _, row := range sheet.Rows {
			prop := getListProp(row)
			if prop == "" {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
				continue
			}

			if !isArray(ctx, prop) {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
				continue
			}

			arr := ctx[prop].([]interface{})
			arrBackup := ctx[prop]
			for i := range arr {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				ctx[prop] = arr[i]
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
			}
			ctx[prop] = arrBackup
		}
	}
	m.report = report

	return nil
}

// ReadTemplate() reads template from disk and stores it in a struct
func (m *Xlst) ReadTemplate(path string) error {
	file, err := xlsx.OpenFile(path)
	if err != nil {
		return err
	}
	m.file = file
	return nil
}

// Save() saves generated report to disk
func (m *Xlst) Save(path string) error {
	if m.report == nil {
		return errors.New("Report was not generated")
	}
	return m.report.Save(path)
}

// Write() writes generated report to provided writer
func (m *Xlst) Write(writer io.Writer) error {
	if m.report == nil {
		return errors.New("Report was not generated")
	}
	return m.report.Write(writer)
}

func cloneCell(from, to *xlsx.Cell) {
	to.Value = from.Value
	to.SetStyle(from.GetStyle())
	to.HMerge = from.HMerge
	to.VMerge = from.VMerge
	to.Hidden = from.Hidden
}

func cloneRow(from, to *xlsx.Row) {
	to.Height = from.Height
	for _, cell := range from.Cells {
		newCell := to.AddCell()
		cloneCell(cell, newCell)
	}
}

func renderCell(cell *xlsx.Cell, ctx interface{}) error {
	template, err := raymond.Parse(cell.Value)
	if err != nil {
		return err
	}
	out, err := template.Exec(ctx)
	if err != nil {
		return err
	}
	cell.Value = out
	return nil
}

func cloneSheet(from, to *xlsx.Sheet) {
	for _, col := range from.Cols {
		newCol := xlsx.Col{}
		newCol.SetStyle(col.GetStyle())
		newCol.Width = col.Width
		newCol.Hidden = col.Hidden
		newCol.Collapsed = col.Collapsed
		newCol.Min = col.Min
		newCol.Max = col.Max
		to.Cols = append(to.Cols, &newCol)
	}
}

func isArray(in map[string]interface{}, prop string) bool {
	val, ok := in[prop]
	if !ok {
		return false
	}
	arr, ok := val.([]interface{})
	return ok && arr != nil
}

func getListProp(in *xlsx.Row) string {
	for _, cell := range in.Cells {
		if cell.Value == "" {
			continue
		}
		if match := rgx.FindAllStringSubmatch(cell.Value, -1); match != nil {
			return match[0][1]
		}
	}
	return ""
}

func renderRow(in *xlsx.Row, ctx interface{}) error {
	for _, cell := range in.Cells {
		err := renderCell(cell, ctx)
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Fix for slices<commit_after>package xlst

import (
	"errors"
	"io"
	"reflect"
	"regexp"

	"github.com/aymerick/raymond"
	"github.com/tealeg/xlsx"
)

var (
	rgx = regexp.MustCompile(`\{\{\s*(\w+)\.\w+\s*\}\}`)
)

// Xlst Represents template struct
type Xlst struct {
	file   *xlsx.File
	report *xlsx.File
}

// New() creates new Xlst struct and returns pointer to it
func New() *Xlst {
	return &Xlst{}
}

// Render() renders report and stores it in a struct
func (m *Xlst) Render(ctx map[string]interface{}) error {
	report := xlsx.NewFile()
	for i, sheet := range m.file.Sheets {
		report.AddSheet(sheet.Name)
		cloneSheet(sheet, report.Sheets[i])
		for _, row := range sheet.Rows {
			prop := getListProp(row)
			if prop == "" {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
				continue
			}
			if !isArray(ctx, prop) {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
				continue
			}

			arr := reflect.ValueOf(ctx[prop])
			arrBackup := ctx[prop]
			for i := 0; i < arr.Len(); i++ {
				newRow := report.Sheets[0].AddRow()
				cloneRow(row, newRow)
				ctx[prop] = arr.Index(i).Interface()
				err := renderRow(newRow, ctx)
				if err != nil {
					return err
				}
			}
			ctx[prop] = arrBackup
		}
	}
	m.report = report

	return nil
}

// ReadTemplate() reads template from disk and stores it in a struct
func (m *Xlst) ReadTemplate(path string) error {
	file, err := xlsx.OpenFile(path)
	if err != nil {
		return err
	}
	m.file = file
	return nil
}

// Save() saves generated report to disk
func (m *Xlst) Save(path string) error {
	if m.report == nil {
		return errors.New("Report was not generated")
	}
	return m.report.Save(path)
}

// Write() writes generated report to provided writer
func (m *Xlst) Write(writer io.Writer) error {
	if m.report == nil {
		return errors.New("Report was not generated")
	}
	return m.report.Write(writer)
}

func cloneCell(from, to *xlsx.Cell) {
	to.Value = from.Value
	to.SetStyle(from.GetStyle())
	to.HMerge = from.HMerge
	to.VMerge = from.VMerge
	to.Hidden = from.Hidden
}

func cloneRow(from, to *xlsx.Row) {
	to.Height = from.Height
	for _, cell := range from.Cells {
		newCell := to.AddCell()
		cloneCell(cell, newCell)
	}
}

func renderCell(cell *xlsx.Cell, ctx interface{}) error {
	template, err := raymond.Parse(cell.Value)
	if err != nil {
		return err
	}
	out, err := template.Exec(ctx)
	if err != nil {
		return err
	}
	cell.Value = out
	return nil
}

func cloneSheet(from, to *xlsx.Sheet) {
	for _, col := range from.Cols {
		newCol := xlsx.Col{}
		newCol.SetStyle(col.GetStyle())
		newCol.Width = col.Width
		newCol.Hidden = col.Hidden
		newCol.Collapsed = col.Collapsed
		newCol.Min = col.Min
		newCol.Max = col.Max
		to.Cols = append(to.Cols, &newCol)
	}
}

func isArray(in map[string]interface{}, prop string) bool {
	val, ok := in[prop]
	if !ok {
		return false
	}
	switch reflect.TypeOf(val).Kind() {
	case reflect.Array, reflect.Slice:
		return true
	}
	return false
}

func getListProp(in *xlsx.Row) string {
	for _, cell := range in.Cells {
		if cell.Value == "" {
			continue
		}
		if match := rgx.FindAllStringSubmatch(cell.Value, -1); match != nil {
			return match[0][1]
		}
	}
	return ""
}

func renderRow(in *xlsx.Row, ctx interface{}) error {
	for _, cell := range in.Cells {
		err := renderCell(cell, ctx)
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package xorm

import (
	"errors"
	"fmt"
	"os"
	"reflect"
	"runtime"
	"sync"
	"time"

	"github.com/go-xorm/core"
)

const (
	Version string = "0.4.1"
)

func regDrvsNDialects() bool {
	providedDrvsNDialects := map[string]struct {
		dbType     core.DbType
		getDriver  func() core.Driver
		getDialect func() core.Dialect
	}{
		"mssql":    {"mssql", func() core.Driver { return &odbcDriver{} }, func() core.Dialect { return &mssql{} }},
		"odbc":     {"mssql", func() core.Driver { return &odbcDriver{} }, func() core.Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access
		"mysql":    {"mysql", func() core.Driver { return &mysqlDriver{} }, func() core.Dialect { return &mysql{} }},
		"mymysql":  {"mysql", func() core.Driver { return &mymysqlDriver{} }, func() core.Dialect { return &mysql{} }},
		"postgres": {"postgres", func() core.Driver { return &pqDriver{} }, func() core.Dialect { return &postgres{} }},
		"sqlite3":  {"sqlite3", func() core.Driver { return &sqlite3Driver{} }, func() core.Dialect { return &sqlite3{} }},
		"oci8":     {"oracle", func() core.Driver { return &oci8Driver{} }, func() core.Dialect { return &oracle{} }},
		"goracle":  {"oracle", func() core.Driver { return &goracleDriver{} }, func() core.Dialect { return &oracle{} }},
	}

	for driverName, v := range providedDrvsNDialects {
		if driver := core.QueryDriver(driverName); driver == nil {
			core.RegisterDriver(driverName, v.getDriver())
			core.RegisterDialect(v.dbType, v.getDialect())
		}
	}
	return true
}

func close(engine *Engine) {
	engine.Close()
}

// new a db manager according to the parameter. Currently support four
// drivers
func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
	regDrvsNDialects()
	driver := core.QueryDriver(driverName)
	if driver == nil {
		return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName))
	}

	uri, err := driver.Parse(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	dialect := core.QueryDialect(uri.DbType)
	if dialect == nil {
		return nil, errors.New(fmt.Sprintf("Unsupported dialect type: %v", uri.DbType))
	}

	db, err := core.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	err = dialect.Init(db, uri, driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	engine := &Engine{
		db:            db,
		dialect:       dialect,
		Tables:        make(map[reflect.Type]*core.Table),
		mutex:         &sync.RWMutex{},
		TagIdentifier: "xorm",
		Logger:        NewSimpleLogger(os.Stdout),
		TZLocation:    time.Local,
	}

	engine.SetMapper(core.NewCacheMapper(new(core.SnakeMapper)))

	//engine.Filters = dialect.Filters()
	//engine.Cacher = NewLRUCacher()
	//err = engine.SetPool(NewSysConnectPool())

	runtime.SetFinalizer(engine, close)
	return engine, err
}

// clone an engine
func (engine *Engine) Clone() (*Engine, error) {
	return NewEngine(engine.dialect.DriverName(), engine.dialect.DataSourceName())
}
<commit_msg>little improvement<commit_after>package xorm

import (
	"errors"
	"fmt"
	"os"
	"reflect"
	"runtime"
	"sync"
	"time"

	"github.com/go-xorm/core"
)

const (
	Version string = "0.4.1"
)

func regDrvsNDialects() bool {
	providedDrvsNDialects := map[string]struct {
		dbType     core.DbType
		getDriver  func() core.Driver
		getDialect func() core.Dialect
	}{
		"mssql":    {"mssql", func() core.Driver { return &odbcDriver{} }, func() core.Dialect { return &mssql{} }},
		"odbc":     {"mssql", func() core.Driver { return &odbcDriver{} }, func() core.Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access
		"mysql":    {"mysql", func() core.Driver { return &mysqlDriver{} }, func() core.Dialect { return &mysql{} }},
		"mymysql":  {"mysql", func() core.Driver { return &mymysqlDriver{} }, func() core.Dialect { return &mysql{} }},
		"postgres": {"postgres", func() core.Driver { return &pqDriver{} }, func() core.Dialect { return &postgres{} }},
		"sqlite3":  {"sqlite3", func() core.Driver { return &sqlite3Driver{} }, func() core.Dialect { return &sqlite3{} }},
		"oci8":     {"oracle", func() core.Driver { return &oci8Driver{} }, func() core.Dialect { return &oracle{} }},
		"goracle":  {"oracle", func() core.Driver { return &goracleDriver{} }, func() core.Dialect { return &oracle{} }},
	}

	for driverName, v := range providedDrvsNDialects {
		if driver := core.QueryDriver(driverName); driver == nil {
			core.RegisterDriver(driverName, v.getDriver())
			core.RegisterDialect(v.dbType, v.getDialect())
		}
	}
	return true
}

func close(engine *Engine) {
	engine.Close()
}

// new a db manager according to the parameter. Currently support four
// drivers
func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
	regDrvsNDialects()
	driver := core.QueryDriver(driverName)
	if driver == nil {
		return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName))
	}

	uri, err := driver.Parse(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	dialect := core.QueryDialect(uri.DbType)
	if dialect == nil {
		return nil, errors.New(fmt.Sprintf("Unsupported dialect type: %v", uri.DbType))
	}

	db, err := core.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	err = dialect.Init(db, uri, driverName, dataSourceName)
	if err != nil {
		return nil, err
	}

	engine := &Engine{
		db:            db,
		dialect:       dialect,
		Tables:        make(map[reflect.Type]*core.Table),
		mutex:         &sync.RWMutex{},
		TagIdentifier: "xorm",
		Logger:        NewSimpleLogger(os.Stdout),
		TZLocation:    time.Local,
	}

	engine.SetMapper(core.NewCacheMapper(new(core.SnakeMapper)))

	runtime.SetFinalizer(engine, close)

	return engine, nil
}

// clone an engine
func (engine *Engine) Clone() (*Engine, error) {
	return NewEngine(engine.dialect.DriverName(), engine.dialect.DataSourceName())
}
<|endoftext|>


<commit_before>// vim: tabstop=2 shiftwidth=2

package main

import (
	"fmt"
	"github.com/luksen/maildir"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

const (
	version         string = "0.2a"
	dayLength       int    = 24 * 60 * 60 // Day in seconds
	maxFragLength          = 10230
	maxChainLength         = 10
	maxCopies              = 5
	base64LineWrap         = 72
	rfc5322date            = "Mon, 2 Jan 2006 15:04:05 -0700"
	shortdate              = "2 Jan 2006"
	headerBytes            = 256 // An entire header slot
	encHeadBytes           = 160 // The encrypted component of a header
	encDataBytes           = 64  // Exit / Intermediate header component
	headersBytes           = headerBytes * maxChainLength
	encHeadersBytes        = headersBytes - headerBytes
	bodyBytes              = 10240
	messageBytes           = headersBytes + bodyBytes
)

var (
	Trace *log.Logger
	Info  *log.Logger
	Warn  *log.Logger
	Error *log.Logger
)

func logInit(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warnHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"Trace: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"Info: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warn = log.New(warnHandle,
		"Warn: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"Error: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func main() {
	var err error
	flags()
	switch strings.ToLower(cfg.Remailer.Loglevel) {
	case "trace":
		logInit(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
	case "info":
		logInit(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
	case "warn":
		logInit(ioutil.Discard, ioutil.Discard, os.Stdout, os.Stderr)
	case "error":
		logInit(ioutil.Discard, ioutil.Discard, ioutil.Discard, os.Stderr)
	default:
		fmt.Fprintf(os.Stderr, "Unknown loglevel: %s\n", cfg.Remailer.Loglevel)
	}
	if flag_client {
		mixprep()
		poolOutboundSend()
	} else if flag_stdin {
		dir := maildir.Dir(cfg.Files.Maildir)
		newmsg, err := dir.NewDelivery()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		stdin, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		newmsg.Write(stdin)
		newmsg.Close()
	} else if flag_remailer {
		err = loopServer()
		if err != nil {
			panic(err)
		}
	} else if flag_dummy {
		injectDummy()
	} else if flag_send {
		poolOutboundSend()
	}
}
<commit_msg>Increase payload size to match Mixmaster's<commit_after>// vim: tabstop=2 shiftwidth=2

package main

import (
	"fmt"
	"github.com/luksen/maildir"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

const (
	version         string = "0.2a"
	dayLength       int    = 24 * 60 * 60 // Day in seconds
	maxFragLength          = 10230
	maxChainLength         = 10
	maxCopies              = 5
	base64LineWrap         = 72
	rfc5322date            = "Mon, 2 Jan 2006 15:04:05 -0700"
	shortdate              = "2 Jan 2006"
	headerBytes            = 256 // An entire header slot
	encHeadBytes           = 160 // The encrypted component of a header
	encDataBytes           = 64  // Exit / Intermediate header component
	headersBytes           = headerBytes * maxChainLength
	encHeadersBytes        = headersBytes - headerBytes
	bodyBytes              = 17920
	messageBytes           = headersBytes + bodyBytes
)

var (
	Trace *log.Logger
	Info  *log.Logger
	Warn  *log.Logger
	Error *log.Logger
)

func logInit(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warnHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"Trace: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"Info: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warn = log.New(warnHandle,
		"Warn: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"Error: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func main() {
	var err error
	flags()
	switch strings.ToLower(cfg.Remailer.Loglevel) {
	case "trace":
		logInit(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
	case "info":
		logInit(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
	case "warn":
		logInit(ioutil.Discard, ioutil.Discard, os.Stdout, os.Stderr)
	case "error":
		logInit(ioutil.Discard, ioutil.Discard, ioutil.Discard, os.Stderr)
	default:
		fmt.Fprintf(os.Stderr, "Unknown loglevel: %s\n", cfg.Remailer.Loglevel)
	}
	if flag_client {
		mixprep()
		poolOutboundSend()
	} else if flag_stdin {
		dir := maildir.Dir(cfg.Files.Maildir)
		newmsg, err := dir.NewDelivery()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		stdin, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		newmsg.Write(stdin)
		newmsg.Close()
	} else if flag_remailer {
		err = loopServer()
		if err != nil {
			panic(err)
		}
	} else if flag_dummy {
		injectDummy()
	} else if flag_send {
		poolOutboundSend()
	}
}
<|endoftext|>


<commit_before>package main

import(
	"fmt"
	"Golly/parser"
	"strconv"
)

type baseType int
const(
	Int baseType = iota
	Float
	Char
	Symbol
	List
	FuncDef
	VarDef
)

type FunctionObj struct{
	Type TypeObj
	Parems []string
	Body []ListCell
}

type singleType struct{
	Inputs []string
	Outputs []string
	Order int8
}

type TypeObj struct{
	Name string
	Types []singleType
}

type EnvBinding struct{
	Name string
	Binding ListCell
}

type SysEnvironment struct{
	 Bindings map[string]EnvBinding
}

type Environment struct{
	Bindings []EnvBinding
	Parent *Environment
	System *SysEnvironment
}

func (env Environment) findBinding(name string, recur, checkSystem bool) *EnvBinding{
	if checkSystem{
		if binding, ok := env.System.Bindings[name]; ok {
			return &binding
		}
	}
	for i, binding := range env.Bindings{
		if binding.Name == name{
			return &env.Bindings[i]
		}
	}
	if recur{
		if env.Parent == nil{
			return nil
		}else{
			return env.Parent.findBinding(name, true, false)
		}
	}
	return nil
}

func (env *Environment) addBinding(recur bool) *EnvBinding{
	if recur{
		if env.Parent == nil{
			env.Bindings = append(env.Bindings, EnvBinding{})
			return &((env.Bindings)[len(env.Bindings)])
		}else{
			return env.Parent.addBinding(true)
		}
	}else{
		env.Bindings = append(env.Bindings, EnvBinding{})
		return &((env.Bindings)[len(env.Bindings)])
	}
}

type ListCell struct{
	TypeName string
	Value interface{}
	Mutable bool
}

type CellList struct{
	Cells []ListCell
	Environment []EnvBinding
}

func evalNumToken(num *Parser.Token, lineNum int, caller string)(ListCell){
	newValue := ListCell{}
			if (*num).LitType == Parser.FixNum{
				floatval, err := strconv.ParseFloat((*num).Value, 32)
				if err != nil{
					errMsg := fmt.Sprintf("Error: cannot parse string %v to float in %v at line %v.\n", (*num).Value, caller, lineNum)
					panic(errMsg)
				}else{
					newValue.Value = floatval
					newValue.TypeName = "float"
				}
			}else if (*num).LitType == Parser.FixNum{
				intval, err := strconv.Atoi((*num).Value)
				if err != nil{
					errMsg := fmt.Sprintf("Error: cannot parse string %v to int in %v at line %v.\n", (*num).Value, caller, lineNum)
					panic(errMsg)
				}else{
					newValue.Value = intval
					newValue.TypeName = "int"
				}
			}
	return newValue
}

func evalIdToken(identifierName *Parser.Token, env *Environment, lineNum int, caller string)(interface{}){
	var newValue interface{}
	valueReferenced := env.findBinding((*identifierName).Value, true, true)
			if valueReferenced == nil{
				errMsg := fmt.Sprintf("Error: attempting to evalute var %v in %v at line %v, but that var is unbound.\n", (*identifierName).Value, caller, lineNum)
				panic(errMsg)
			}else{
				newValue = valueReferenced.Binding
			}
	return newValue
}
func bindVars(list *Parser.Token, env Environment, lineNum int, global, mut bool, caller string)Environment{
	for i := 0; i < len(list.ListVals); i++{
		val := &list.ListVals[i]
		if val.Type != Parser.IdToken{
			errMsg := fmt.Sprintf("Error: attempting to assign to a non-identifier in %v at line %v.\n", caller, lineNum)
			panic(errMsg)
		}
		prevBinding := env.findBinding(val.Value, global, true)
		var newBinding *EnvBinding
		if prevBinding != nil{
			if !(*prevBinding).Binding.Mutable{
				errMsg := fmt.Sprintf("Error: attempting to assign to an immutable identifier in %v at line %v.\n", caller, lineNum)
				panic(errMsg)
			}else{
				newBinding = prevBinding
			}
		}else{
			newBinding = env.addBinding(global)
		}
		if i >= len(list.ListVals){
			errMsg := fmt.Sprintf("Error: nothing to assign to %v in %v at line %v.\n", val.Value, caller, lineNum)
			panic(errMsg)
		}
		nextVal := &list.ListVals[i+1]
		newBinding.Name = val.Value
		newValue := ListCell{TypeName: "undecided", Mutable: mut}
		typeNameAnnotated := ""
		switch (*nextVal).Type {
		case Parser.LiteralToken:
			newValue = evalNumToken(nextVal,lineNum,caller)
		case Parser.DefToken:
			errMsg := fmt.Sprintf("Error: attempting to assign reserved name %v to %v in %v at line %v.\n", (*nextVal).Value, val.Value, caller, lineNum)
			panic(errMsg)
		case Parser.IdToken:
			potentialNewValue := env.findBinding(nextVal.Value, true, true)
			if potentialNewValue != nil{
				newValue.Value = potentialNewValue
			}else{
				errMsg := fmt.Sprintf("Error: attempting to assign identifier %v to %v in %v at line %v, but %v is unbound.\n", (*nextVal).Value, val.Value, caller, lineNum, (*nextVal).Value)
				panic(errMsg)
			}
		case Parser.ListToken:
			newValue.Value = evalListToken(nextVal)
		case Parser.TypeAnnToken:
			if i >= len(list.ListVals)+1{
				errMsg := fmt.Sprintf("Error: no type provided in assignment to %v in %v at line %v.\n", val.Value, caller, lineNum)
				panic(errMsg)
			}
			nextValType := &list.ListVals[i+2]
			newValueType := ListCell{}
			newNameFound := false
			switch (*nextValType).Type {
			case Parser.LiteralToken:
				errMsg := fmt.Sprintf("Error: attempting use a numeric literal as the type for %v in %v at line %v.\n", val.Value, caller, lineNum)
				panic(errMsg)
			case Parser.DefToken:
				errMsg := fmt.Sprintf("Error: attempting use a reserved name as the type for %v in %v at line %v.\n", val.Value, caller, lineNum)
				panic(errMsg)
			case Parser.IdToken:
				potentialNewValueType := env.findBinding(nextValType.Value, true, true)
				if potentialNewValueType != nil{
					if potentialNewValueType.Binding.TypeName != "type"{
						errMsg := fmt.Sprintf("Error: attempting to assign something that is not a type, but a %v, to %v in %v at line %v.\n", potentialNewValueType.Binding.TypeName, val.Value, caller, lineNum)
						panic(errMsg)
					}else{
						newNameFound = true
						newValueType = potentialNewValueType.Binding
					}
				}else{
					errMsg := fmt.Sprintf("Error: attempting to assign identifier %v to %v in %v at line %v, but %v is unbound.\n", 	(*nextVal).Value, val.Value, caller, lineNum, (*nextVal).Value)
					panic(errMsg)
				}
			case Parser.ListToken:
				newValueType = evalListToken(nextVal)
				if newValueType.TypeName != "type"{
					errMsg := fmt.Sprintf("Error: attempting to assign something that is not a type, but a %v, to %v in %v at line %v.\n", newValueType.TypeName, val.Value, caller, lineNum)
					panic(errMsg)
				}else{
					newNameFound = true
				}
			case Parser.TypeAnnToken:
				errMsg := fmt.Sprintf("Error: misplaced type annotation marker in %v at line %v.\n", val.Value, caller, lineNum)
				panic(errMsg)
			}
			typeName := nextValType.Value
			if newNameFound{
				if foundTypeActual, ok := newValueType.Value.(TypeObj); ok {
					typeName = foundTypeActual.Name
				}else{
					errMsg := fmt.Sprintf("Error: cell claiming to be a type actually contains something else, in %v at line %v.\n", caller, lineNum)
					panic(errMsg)
				}
			}
			namesBinding := env.findBinding(typeName, true, true)
			if namesBinding.Binding.TypeName == "type"{
				typeNameAnnotated = typeName
			}else{
				errMsg := fmt.Sprintf("Error: attempting to assign type %v to %v in %v at line %v, but that type is not bound.\n", typeName, val.Value, caller, lineNum)
				panic(errMsg)
			}
		}
		if newValue.TypeName != "undecided" && newValue.TypeName != typeNameAnnotated{
			errMsg := fmt.Sprintf("Error: attempting to assign type %v to %v in %v at line %v, but it is already of type %v.\n", typeNameAnnotated, val.Value, caller, lineNum, newValue.TypeName)
			panic(errMsg)
		}else if typeNameAnnotated != ""{
			newValue.TypeName = typeNameAnnotated
		}
		newBinding.Binding = newValue
	}
	return env
}

func evalListToken(list *Parser.Token)(ListCell){
	firstVal := &list.ListVals[0]
//	initCellList := CellList{}
	initEnvironment := Environment{}
	switch firstVal.Type{
	case Parser.LiteralToken:
		errMsg := fmt.Sprintf("Error: attempting to evaluate a literal, %v, at line %v.\n", firstVal.Value, firstVal.LineNum)
		panic(errMsg)
	case Parser.DefToken:
		defKind := &firstVal.Value
		if len(list.ListVals) < 3{
			errMsg := fmt.Sprintf("Error: too few arguments to %v at line %v.\n", defKind, firstVal.LineNum)
			panic(errMsg)
		}else if list.ListVals[1].Type != Parser.ListToken{
			errMsg := fmt.Sprintf("Error: first argument (%v) to %v at line %v is not a list.\n",list.ListVals[1].Value, defKind, firstVal.LineNum)
			panic(errMsg)
		}else if list.ListVals[2].Type != Parser.ListToken{
			errMsg := fmt.Sprintf("Error: second argument (%v) to %v  at line %v is not a list.\n",list.ListVals[2].Value, defKind, firstVal.LineNum)
			panic(errMsg)
		}else if len(list.ListVals) > 3{
			errMsg := fmt.Sprintf("Error: too many arguments to %v at line %v.\n",defKind, firstVal.LineNum)
			panic(errMsg)
		}
		initEnvironment = bindVars(&list.ListVals[1], initEnvironment, firstVal.LineNum, true, true, "let")

	}
	return ListCell{}
}

func main(){
	//types := []string{"Int", "Float", "Char", "Symbol", "List"}
	input := `(let (a 1) (b 2))`
	res := Parser.Lex(&input)
	tokens := Parser.ParseList(res, 0)
	for _, tok := range tokens.ListVals{
		fmt.Println(tok)
	}
	evalListToken(&tokens.ListVals[0])
}
<commit_msg>Refactored parser.<commit_after>package main

import (
	"Golly/parser"
	"fmt"
	"strconv"
)

type baseType int

const (
	Int baseType = iota
	Float
	Char
	Symbol
	List
	FuncDef
	VarDef
)

type FunctionObj struct {
	Type   TypeObj
	Parems []string
	Body   []ListCell
}

type singleType struct {
	Inputs  []string
	Outputs []string
	Order   int8
}

type TypeObj struct {
	Name  string
	Types []singleType
}

type EnvBinding struct {
	Name    string
	Binding ListCell
}

type SysEnvironment struct {
	Bindings map[string]EnvBinding
}

type Environment struct {
	Bindings []EnvBinding
	Parent   *Environment
	System   *SysEnvironment
}

func (env Environment) findBinding(name string, recur, checkSystem bool) *EnvBinding {
	if checkSystem {
		if binding, ok := env.System.Bindings[name]; ok {
			return &binding
		}
	}
	for i, binding := range env.Bindings {
		if binding.Name == name {
			return &env.Bindings[i]
		}
	}
	if recur {
		if env.Parent == nil {
			return nil
		} else {
			return env.Parent.findBinding(name, true, false)
		}
	}
	return nil
}

func (env *Environment) addBinding(recur bool) *EnvBinding {
	if recur {
		if env.Parent == nil {
			env.Bindings = append(env.Bindings, EnvBinding{})
			return &((env.Bindings)[len(env.Bindings)])
		} else {
			return env.Parent.addBinding(true)
		}
	} else {
		env.Bindings = append(env.Bindings, EnvBinding{})
		return &((env.Bindings)[len(env.Bindings)])
	}
}

type ListCell struct {
	TypeName string
	Value    interface{}
	Mutable  bool
}

type CellList struct {
	Cells       []ListCell
	Environment []EnvBinding
}

func evalNumToken(num *Parser.Token, lineNum int, caller string) ListCell {
	newValue := ListCell{}
	if (*num).LitType == Parser.FixNum {
		floatval, err := strconv.ParseFloat((*num).Value, 32)
		if err != nil {
			errMsg := fmt.Sprintf("Error: cannot parse string %v to float in %v at line %v.\n", (*num).Value, caller, lineNum)
			panic(errMsg)
		} else {
			newValue.Value = floatval
			newValue.TypeName = "float"
		}
	} else if (*num).LitType == Parser.FixNum {
		intval, err := strconv.Atoi((*num).Value)
		if err != nil {
			errMsg := fmt.Sprintf("Error: cannot parse string %v to int in %v at line %v.\n", (*num).Value, caller, lineNum)
			panic(errMsg)
		} else {
			newValue.Value = intval
			newValue.TypeName = "int"
		}
	}
	return newValue
}

func evalIdToken(identifierName *Parser.Token, env *Environment, lineNum int, caller string) interface{} {
	var newValue interface{}
	valueReferenced := env.findBinding((*identifierName).Value, true, true)
	if valueReferenced == nil {
		errMsg := fmt.Sprintf("Error: attempting to evalute var %v in %v at line %v, but that var is unbound.\n", (*identifierName).Value, caller, lineNum)
		panic(errMsg)
	} else {
		newValue = valueReferenced.Binding
	}
	return newValue
}

func parseType(identifierToBindTo *Parser.Token, potentialType *Parser.Token, env *Environment, lineNum int, caller string) (ListCell, bool) {
	newNameFound := false
	newValueType := ListCell{}
	switch (*potentialType).Type {
	case Parser.LiteralToken:
		errMsg := fmt.Sprintf("Error: attempting use a numeric literal as the type for %v in %v at line %v.\n", identifierToBindTo.Value, caller, lineNum)
		panic(errMsg)
	case Parser.DefToken:
		errMsg := fmt.Sprintf("Error: attempting use a reserved name as the type for %v in %v at line %v.\n", identifierToBindTo.Value, caller, lineNum)
		panic(errMsg)
	case Parser.IdToken:
		potentialNewTypeValue := env.findBinding(potentialType.Value, true, true)
		if potentialNewTypeValue != nil {
			if potentialNewTypeValue.Binding.TypeName != "type" {
				errMsg := fmt.Sprintf("Error: attempting to assign something that is not a type, but a %v, to %v in %v at line %v.\n", potentialNewTypeValue.Binding.TypeName, identifierToBindTo.Value, caller, lineNum)
				panic(errMsg)
			} else {
				newNameFound = true
				newValueType = potentialNewTypeValue.Binding
			}
		} else {
			errMsg := fmt.Sprintf("Error: attempting to assign identifier %v to %v in %v at line %v, but %v is unbound.\n", (*potentialType).Value, (*identifierToBindTo).Value, caller, lineNum, (*potentialType).Value)
			panic(errMsg)
		}
	case Parser.ListToken:
		newValueType = evalListToken(potentialType)
		if newValueType.TypeName != "type" {
			errMsg := fmt.Sprintf("Error: attempting to assign something that is not a type, but a %v, to %v in %v at line %v.\n", newValueType.TypeName, (*identifierToBindTo).Value, caller, lineNum)
			panic(errMsg)
		} else {
			newNameFound = true
		}
	case Parser.TypeAnnToken:
		errMsg := fmt.Sprintf("Error: misplaced type annotation marker in %v at line %v.\n", caller, lineNum)
		panic(errMsg)
	}
	return newValueType, newNameFound
}

func bindVars(list *Parser.Token, env Environment, lineNum int, global, mut bool, caller string) Environment {
	for i := 0; i < len(list.ListVals); i++ {
		howManyIndicesToJumpForward := 2
		val := &list.ListVals[i]
		if val.Type != Parser.IdToken {
			errMsg := fmt.Sprintf("Error: attempting to assign to a non-identifier in %v at line %v.\n", caller, lineNum)
			panic(errMsg)
		}
		prevBinding := env.findBinding(val.Value, global, true)
		var newBinding *EnvBinding
		if prevBinding != nil {
			if !(*prevBinding).Binding.Mutable {
				errMsg := fmt.Sprintf("Error: attempting to assign to an immutable identifier in %v at line %v.\n", caller, lineNum)
				panic(errMsg)
			} else {
				newBinding = prevBinding
			}
		} else {
			newBinding = env.addBinding(global)
		}
		if i >= len(list.ListVals) {
			errMsg := fmt.Sprintf("Error: nothing to assign to %v in %v at line %v.\n", val.Value, caller, lineNum)
			panic(errMsg)
		}
		nextVal := &list.ListVals[i+1]
		newBinding.Name = val.Value
		newValue := ListCell{TypeName: "undecided", Mutable: mut}
		typeNameAnnotated := ""
		switch (*nextVal).Type {
		case Parser.LiteralToken:
			newValue = evalNumToken(nextVal, lineNum, caller)
		case Parser.DefToken:
			errMsg := fmt.Sprintf("Error: attempting to assign reserved name %v to %v in %v at line %v.\n", (*nextVal).Value, val.Value, caller, lineNum)
			panic(errMsg)
		case Parser.IdToken:
			potentialNewValue := env.findBinding(nextVal.Value, true, true)
			if potentialNewValue != nil {
				newValue.Value = potentialNewValue
			} else {
				errMsg := fmt.Sprintf("Error: attempting to assign identifier %v to %v in %v at line %v, but %v is unbound.\n", (*nextVal).Value, val.Value, caller, lineNum, (*nextVal).Value)
				panic(errMsg)
			}
		case Parser.ListToken:
			newValue.Value = evalListToken(nextVal)
		case Parser.TypeAnnToken:
			if i >= len(list.ListVals)+1 {
				errMsg := fmt.Sprintf("Error: no type provided in assignment to %v in %v at line %v.\n", val.Value, caller, lineNum)
				panic(errMsg)
			}
			nextValType := &list.ListVals[i+2]
			newValueType, newNameFound := parseType(val, nextValType, &env, lineNum, caller)

			typeName := nextValType.Value
			if newNameFound {
				if foundTypeActual, ok := newValueType.Value.(TypeObj); ok {
					typeName = foundTypeActual.Name
				} else {
					errMsg := fmt.Sprintf("Error: cell claiming to be a type actually contains something else, in %v at line %v.\n", caller, lineNum)
					panic(errMsg)
				}
			}
			namesBinding := env.findBinding(typeName, true, true)
			if namesBinding.Binding.TypeName == "type" {
				typeNameAnnotated = typeName
				howManyIndicesToJumpForward = 4
			} else {
				errMsg := fmt.Sprintf("Error: attempting to assign type %v to %v in %v at line %v, but that type is not bound.\n", typeName, val.Value, caller, lineNum)
				panic(errMsg)
			}
		}
		if newValue.TypeName != "undecided" && newValue.TypeName != typeNameAnnotated {
			errMsg := fmt.Sprintf("Error: attempting to assign type %v to %v in %v at line %v, but it is already of type %v.\n", typeNameAnnotated, val.Value, caller, lineNum, newValue.TypeName)
			panic(errMsg)
		} else if typeNameAnnotated != "" {
			newValue.TypeName = typeNameAnnotated
		}
		newBinding.Binding = newValue
		i += howManyIndicesToJumpForward
		continue
	}
	return env
}

func evalListToken(list *Parser.Token) ListCell {
	firstVal := &list.ListVals[0]
	//	initCellList := CellList{}
	initEnvironment := Environment{}
	switch firstVal.Type {
	case Parser.LiteralToken:
		errMsg := fmt.Sprintf("Error: attempting to evaluate a literal, %v, at line %v.\n", firstVal.Value, firstVal.LineNum)
		panic(errMsg)
	case Parser.DefToken:
		defKind := &firstVal.Value
		if len(list.ListVals) < 3 {
			errMsg := fmt.Sprintf("Error: too few arguments to %v at line %v.\n", defKind, firstVal.LineNum)
			panic(errMsg)
		} else if list.ListVals[1].Type != Parser.ListToken {
			errMsg := fmt.Sprintf("Error: first argument (%v) to %v at line %v is not a list.\n", list.ListVals[1].Value, defKind, firstVal.LineNum)
			panic(errMsg)
		} else if list.ListVals[2].Type != Parser.ListToken {
			errMsg := fmt.Sprintf("Error: second argument (%v) to %v  at line %v is not a list.\n", list.ListVals[2].Value, defKind, firstVal.LineNum)
			panic(errMsg)
		} else if len(list.ListVals) > 3 {
			errMsg := fmt.Sprintf("Error: too many arguments to %v at line %v.\n", defKind, firstVal.LineNum)
			panic(errMsg)
		}
		initEnvironment = bindVars(&list.ListVals[1], initEnvironment, firstVal.LineNum, true, true, "let")

	}
	return ListCell{}
}

func main() {
	//types := []string{"Int", "Float", "Char", "Symbol", "List"}
	input := `(let (a 1) (b 2))`
	res := Parser.Lex(&input)
	tokens := Parser.ParseList(res, 0)
	for _, tok := range tokens.ListVals {
		fmt.Println(tok)
	}
	evalListToken(&tokens.ListVals[0])
}
<|endoftext|>


<commit_before>package domain

import "time"

// Trace represents a full trace of a request
// comprised of a number of frames
type Trace []Frame

// FrameType represents an Enum of types of Frames which Phosphor can record
type FrameType int32

const (
	// Calls
	Req     = FrameType(1) // Client Request dispatch
	Rsp     = FrameType(2) // Client Response received
	In      = FrameType(3) // Server Request received
	Out     = FrameType(4) // Server Response dispatched
	Timeout = FrameType(5) // Client timed out waiting

	// Developer initiated annotations
	Annotation = FrameType(6)
)

// A Frame represents the smallest individually fired component of a trace
// These can be assembled into spans, and entire traces of a request to our systems
type Frame struct {
	TraceId      string // Global Trace Identifier
	SpanId       string // Identifier for this span, non unique - eg. RPC calls would have 4 frames with this id
	ParentSpanId string // Parent span - eg. nested RPC calls

	Timestamp time.Time     // Timestamp the event occured, can only be compared on the same machine
	Duration  time.Duration // Optional: duration of the event, eg. RPC call

	Hostname    string // Hostname this event originated from
	Origin      string // Fully qualified name of the message origin
	Destination string // Optional: Fully qualified name of the message destination

	EventType EventType // The type of Event

	Payload     string            // The payload, eg. RPC body, or Annotation
	PayloadSize int32             // Bytes of payload
	KeyValue    map[string]string // Key value debug information
}
<commit_msg>Also store unknown frame types<commit_after>package domain

import "time"

// Trace represents a full trace of a request
// comprised of a number of frames
type Trace []Frame

// FrameType represents an Enum of types of Frames which Phosphor can record
type FrameType int32

const (
	UnknownFrameType = FrameType(0) // No idea...

	// Calls
	Req     = FrameType(1) // Client Request dispatch
	Rsp     = FrameType(2) // Client Response received
	In      = FrameType(3) // Server Request received
	Out     = FrameType(4) // Server Response dispatched
	Timeout = FrameType(5) // Client timed out waiting

	// Developer initiated annotations
	Annotation = FrameType(6)
)

// A Frame represents the smallest individually fired component of a trace
// These can be assembled into spans, and entire traces of a request to our systems
type Frame struct {
	TraceId      string // Global Trace Identifier
	SpanId       string // Identifier for this span, non unique - eg. RPC calls would have 4 frames with this id
	ParentSpanId string // Parent span - eg. nested RPC calls

	Timestamp time.Time     // Timestamp the event occured, can only be compared on the same machine
	Duration  time.Duration // Optional: duration of the event, eg. RPC call

	Hostname    string // Hostname this event originated from
	Origin      string // Fully qualified name of the message origin
	Destination string // Optional: Fully qualified name of the message destination

	FrameType FrameType // The type of Frame

	Payload     string            // The payload, eg. RPC body, or Annotation
	PayloadSize int32             // Bytes of payload
	KeyValue    map[string]string // Key value debug information
}
<|endoftext|>


<commit_before>package redlot

import (
	"bytes"
	"testing"
)

func TestEncodeHashKey(t *testing.T) {
	name := []byte("name")
	key := []byte("key")
	expect := []byte{0x68, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x03, 0x6b, 0x65, 0x79}
	encoded := encodeHashKey(name, key)
	if !bytes.Equal(expect, encoded) {
		t.Logf("\nexcept: \n\t %v \nencoded: \n\t %v\n", expect, encoded)
		t.Fail()
	}
}

func TestDecodeHashKey(t *testing.T) {
	raw := []byte{0x68, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x03, 0x6b, 0x65, 0x79}
	name, key := decodeHashKey(raw)
	t.Logf("\nexcept: \n\t 0x6e 0x61 0x6d 0x65 \t 0x6b 0x65 0x79 \ndecoded: \n\t % #x \t % #x\n", name, key)
	if !bytes.Equal(name, []byte("name")) || !bytes.Equal(key, []byte("key")) {
		t.Logf("\nexcept: \n\t name \t key \ndecoded: \n\t %v \t %v\n", name, key)
		t.Fail()
	}
}

func TestEncodeHsizeKey(t *testing.T) {
	name := []byte("name")
	expect := []byte{0x48, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65}
	encoded := encodeHsizeKey(name)
	if !bytes.Equal(expect, encoded) {
		t.Logf("\nexcept: \n\t %v \nencoded: \n\t %v\n", expect, encoded)
		t.Fail()
	}
}

func TestDecodeHsizeKey(t *testing.T) {
	raw := []byte{0x48, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65}
	name := decodeHsizeKey(raw)
	if !bytes.Equal([]byte("name"), name) {
		t.Logf("\nexcept: \n\t 0x6e 0x61 0x6d 0x65 \ndecoded: \n\t % #x\n", name)
		t.Fail()
	}
}

func TestHashFuncsArgs(t *testing.T) {
	zeroByte := make([][]byte, 0)
	oneByte := make([][]byte, 1)
	twoBytes := make([][]byte, 2)
	threeBytes := make([][]byte, 3)
	// fourByte := make([][]byte, 4)

	// one args methods
	if _, e := Hsize(zeroByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hgetall(zeroByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hclear(zeroByte); e != errNosArgs {
		t.Fail()
	}

	// two args methods
	if _, e := Hget(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hdel(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hexists(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := MultiHget(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := MultiHdel(oneByte); e != errNosArgs {
		t.Fail()
	}

	// theree args methods
	if _, e := Hset(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hincr(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hlist(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hrlist(twoBytes); e != errNosArgs {
		t.Fail()
	}

	// four args methods
	if _, e := Hkeys(threeBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hscan(threeBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hrscan(threeBytes); e != errNosArgs {
		t.Fail()
	}

}
<commit_msg>Test hash size incr method.<commit_after>package redlot

import (
	"bytes"
	"testing"
)

func TestEncodeHashKey(t *testing.T) {
	name := []byte("name")
	key := []byte("key")
	expect := []byte{0x68, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x03, 0x6b, 0x65, 0x79}
	encoded := encodeHashKey(name, key)
	if !bytes.Equal(expect, encoded) {
		t.Logf("\nexcept: \n\t %v \nencoded: \n\t %v\n", expect, encoded)
		t.Fail()
	}
}

func TestDecodeHashKey(t *testing.T) {
	raw := []byte{0x68, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x03, 0x6b, 0x65, 0x79}
	name, key := decodeHashKey(raw)
	t.Logf("\nexcept: \n\t 0x6e 0x61 0x6d 0x65 \t 0x6b 0x65 0x79 \ndecoded: \n\t % #x \t % #x\n", name, key)
	if !bytes.Equal(name, []byte("name")) || !bytes.Equal(key, []byte("key")) {
		t.Logf("\nexcept: \n\t name \t key \ndecoded: \n\t %v \t %v\n", name, key)
		t.Fail()
	}
}

func TestEncodeHsizeKey(t *testing.T) {
	name := []byte("name")
	expect := []byte{0x48, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65}
	encoded := encodeHsizeKey(name)
	if !bytes.Equal(expect, encoded) {
		t.Logf("\nexcept: \n\t %v \nencoded: \n\t %v\n", expect, encoded)
		t.Fail()
	}
}

func TestDecodeHsizeKey(t *testing.T) {
	raw := []byte{0x48, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65}
	name := decodeHsizeKey(raw)
	if !bytes.Equal([]byte("name"), name) {
		t.Logf("\nexcept: \n\t 0x6e 0x61 0x6d 0x65 \ndecoded: \n\t % #x\n", name)
		t.Fail()
	}
}

func TestHashFuncsArgs(t *testing.T) {
	zeroByte := make([][]byte, 0)
	oneByte := make([][]byte, 1)
	twoBytes := make([][]byte, 2)
	threeBytes := make([][]byte, 3)
	// fourByte := make([][]byte, 4)

	// one args methods
	if _, e := Hsize(zeroByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hgetall(zeroByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hclear(zeroByte); e != errNosArgs {
		t.Fail()
	}

	// two args methods
	if _, e := Hget(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hdel(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hexists(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := MultiHget(oneByte); e != errNosArgs {
		t.Fail()
	}
	if _, e := MultiHdel(oneByte); e != errNosArgs {
		t.Fail()
	}

	// theree args methods
	if _, e := Hset(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hincr(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hlist(twoBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hrlist(twoBytes); e != errNosArgs {
		t.Fail()
	}

	// four args methods
	if _, e := Hkeys(threeBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hscan(threeBytes); e != errNosArgs {
		t.Fail()
	}
	if _, e := Hrscan(threeBytes); e != errNosArgs {
		t.Fail()
	}

}

func TestHashSizeIncr(t *testing.T) {
	name := []byte("hash")
	key := []byte("key")

	db.Delete(encodeHashKey(name, key), nil)
	db.Delete(encodeHsizeKey(name), nil)

	hashSizeIncr(name, key)

	if b, err := db.Get(encodeHsizeKey(name), nil); bytesToUint32(b) != 1 || err != nil {
		t.Logf("expect hisize is 1, but get: %d\n", bytesToUint32(b))
		t.Fail()
	}

}
<|endoftext|>


<commit_before>package registry

import (
	"fmt"
	"path"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"

	"github.com/coreos/coreinit/job"
	"github.com/coreos/coreinit/machine"
)

const (
	offerPrefix = "offer"
)

func (r *Registry) CreateJobOffer(jo *job.JobOffer) {
	key := path.Join(keyPrefix, offerPrefix, jo.Job.Name, "object")
	json, _ := marshal(jo)
	r.etcd.Set(key, json, 0)
}

func (r *Registry) ClaimJobOffer(jobName string, m *machine.Machine, ttl time.Duration) bool {
	key := path.Join(keyPrefix, offerPrefix, jobName)
	_, err := r.etcd.Get(key, false, true)
	if err != nil {
		return false
	}

	return r.acquireLeadership(fmt.Sprintf("offer-%s", jobName), m.BootId, ttl)
}

func (r *Registry) ResolveJobOffer(jobName string) {
	key := path.Join(keyPrefix, offerPrefix, jobName)
	r.etcd.Delete(key, true)
}

func (r *Registry) SubmitJobBid(jb *job.JobBid) {
	key := path.Join(keyPrefix, offerPrefix, jb.JobName, "bids", jb.MachineName)
	//TODO: Use a TTL
	r.etcd.Set(key, "", 0)
}

func (self *EventStream) filterEventJobOffered(resp *etcd.Response) *Event {
	if resp.Action != "set" {
		return nil
	}

	dir, base := path.Split(resp.Node.Key)

	if base != "object" {
		return nil
	}

	dir = path.Dir(strings.TrimSuffix(dir, "/"))
	prefix := path.Base(strings.TrimSuffix(dir, "/"))

	if prefix != offerPrefix {
		return nil
	}

	var jo job.JobOffer
	//TODO: handle error from unmarshal
	unmarshal(resp.Node.Value, &jo)

	return &Event{"EventJobOffered", jo, nil}
}

func filterEventJobBidSubmitted(resp *etcd.Response) *Event {
	if resp.Action != "set" {
		return nil
	}

	dir, machName := path.Split(resp.Node.Key)
	dir, prefix := path.Split(strings.TrimSuffix(dir, "/"))

	if prefix != "bids" {
		return nil
	}

	dir, jobName := path.Split(strings.TrimSuffix(dir, "/"))
	prefix = path.Base(strings.TrimSuffix(dir, "/"))

	if prefix != offerPrefix {
		return nil
	}

	jb := job.NewBid(jobName, machName)
	return &Event{"EventJobBidSubmitted", *jb, nil}
}
<commit_msg>chore(logging): moar logging!<commit_after>package registry

import (
	"fmt"
	"path"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"
	log "github.com/golang/glog"

	"github.com/coreos/coreinit/job"
	"github.com/coreos/coreinit/machine"
)

const (
	offerPrefix = "offer"
)

func (r *Registry) CreateJobOffer(jo *job.JobOffer) {
	key := path.Join(keyPrefix, offerPrefix, jo.Job.Name, "object")
	json, _ := marshal(jo)
	r.etcd.Set(key, json, 0)
}

func (r *Registry) ClaimJobOffer(jobName string, m *machine.Machine, ttl time.Duration) bool {
	key := path.Join(keyPrefix, offerPrefix, jobName)
	_, err := r.etcd.Get(key, false, true)
	if err != nil {
		return false
	}

	return r.acquireLeadership(fmt.Sprintf("offer-%s", jobName), m.BootId, ttl)
}

func (r *Registry) ResolveJobOffer(jobName string) {
	key := path.Join(keyPrefix, offerPrefix, jobName)
	_, err := r.etcd.Delete(key, true)
	if err == nil {
		log.V(2).Infof("Successfully resolved JobOffer(%s)", jobName)
	} else {
		log.V(2).Infof("Failed to resolve JobOffer(%s): %s", jobName, err.Error())
	}
}

func (r *Registry) SubmitJobBid(jb *job.JobBid) {
	key := path.Join(keyPrefix, offerPrefix, jb.JobName, "bids", jb.MachineName)
	//TODO: Use a TTL
	r.etcd.Set(key, "", 0)
}

func (self *EventStream) filterEventJobOffered(resp *etcd.Response) *Event {
	if resp.Action != "set" {
		return nil
	}

	dir, base := path.Split(resp.Node.Key)

	if base != "object" {
		return nil
	}

	dir = path.Dir(strings.TrimSuffix(dir, "/"))
	prefix := path.Base(strings.TrimSuffix(dir, "/"))

	if prefix != offerPrefix {
		return nil
	}

	var jo job.JobOffer
	//TODO: handle error from unmarshal
	unmarshal(resp.Node.Value, &jo)

	return &Event{"EventJobOffered", jo, nil}
}

func filterEventJobBidSubmitted(resp *etcd.Response) *Event {
	if resp.Action != "set" {
		return nil
	}

	dir, machName := path.Split(resp.Node.Key)
	dir, prefix := path.Split(strings.TrimSuffix(dir, "/"))

	if prefix != "bids" {
		return nil
	}

	dir, jobName := path.Split(strings.TrimSuffix(dir, "/"))
	prefix = path.Base(strings.TrimSuffix(dir, "/"))

	if prefix != offerPrefix {
		return nil
	}

	jb := job.NewBid(jobName, machName)
	return &Event{"EventJobBidSubmitted", *jb, nil}
}
<|endoftext|>


<commit_before>// Outgoing Relay Handler
//
// Handles an outgoing message.
// It serves as a relay that a worker can dial and have the
// relay handle delivering the message.

package handler

import (
	"fmt"
	"io/ioutil"
	"net"
)

// Read from the Session buffer and send to a handler function
func ReadOutgoing(conn net.Conn) {
	// close connection on exit
	defer conn.Close()

	result, err := ioutil.ReadAll(conn)
	checkError(err)

	err = sendMessage(result)
	checkError(err)
}

func sendMessage(result []byte) error {
	// Lookup Receiving Node
	node := "127.0.0.1:7834"

	tcpAddr, err := net.ResolveTCPAddr("tcp4", node)
	if err != nil {
		return err
	}

	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return err
	}
	defer conn.Close()

	_, err = conn.Write(result)
	if err != nil {
		return err
	}

	return nil
}

func checkError(err error) {
	if err != nil {
		fmt.Printf("Fatal error: %s", err.Error())
	}
}
<commit_msg>use ip addresses as domains to test sending<commit_after>// Outgoing Relay Handler
//
// Handles an outgoing message.
// It serves as a relay that a worker can dial and have the
// relay handle delivering the message.

package handler

import (
	"fmt"
	"github.com/msgbox/message"
	"io/ioutil"
	"net"
	"strings"
)

// Read from the Session buffer and send to a handler function
func ReadOutgoing(conn net.Conn) {
	// close connection on exit
	defer conn.Close()

	result, err := ioutil.ReadAll(conn)
	checkError(err)

	err = sendMessage(result)
	checkError(err)
}

func sendMessage(result []byte) error {
	// Lookup Receiving Node
	node := lookupAddress(result)

	conn, err := net.DialTCP("tcp", nil, node)
	if err != nil {
		return err
	}
	defer conn.Close()

	_, err = conn.Write(result)
	if err != nil {
		return err
	}

	return nil
}

// Get it working with with IP addresses for now
func lookupAddress(data []byte) *net.TCPAddr {
	port := ":7834" // Hardcoded for now
	msg := messages.Parse(data)
	receiver := msg.GetReceiver()
	addr := strings.Split(receiver, "@")
	tcpAddr, err := net.ResolveTCPAddr("tcp4", addr[1]+port)
	checkError(err)
	return tcpAddr
}

func checkError(err error) {
	if err != nil {
		fmt.Printf("Fatal error: %s", err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The gocui 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 (
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/jroimartin/gocui"
)

const delta = 0.1

type HelpWidget struct {
	name string
	x, y int
	w, h int
	body string
}

func NewHelpWidget(name string, x, y int, body string) *HelpWidget {
	lines := strings.Split(body, "\n")

	w := 0
	for _, l := range lines {
		if len(l) > w {
			w = len(l)
		}
	}
	h := len(lines) + 1
	w = w + 1

	return &HelpWidget{name: name, x: x, y: y, w: w, h: h, body: body}
}

func (w *HelpWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+w.h)
	if err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		fmt.Fprint(v, w.body)
	}
	return nil
}

type StatusbarWidget struct {
	name string
	x, y int
	w    int
	val  float32
}

func NewStatusbarWidget(name string, x, y, w int) *StatusbarWidget {
	return &StatusbarWidget{name: name, x: x, y: y, w: w}
}

func (w *StatusbarWidget) SetVal(val float32) error {
	if val < 0 || val > 1+delta/2 {
		return errors.New("invalid value")
	}
	w.val = val
	return nil
}

func (w *StatusbarWidget) Val() float32 {
	return w.val
}

func (w *StatusbarWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
	if err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
	}
	v.Clear()
	val := int(w.val * float32(w.w-1))
	fmt.Fprint(v, strings.Repeat("▒", val))
	return nil
}

type ButtonWidget struct {
	name    string
	x, y    int
	w       int
	label   string
	handler func(g *gocui.Gui, v *gocui.View) error
}

func NewButtonWidget(name string, x, y int, label string, handler func(g *gocui.Gui, v *gocui.View) error) *ButtonWidget {
	return &ButtonWidget{name: name, x: x, y: y, w: len(label) + 1, label: label, handler: handler}
}

func (w *ButtonWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
	if err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		if _, err := g.SetCurrentView(w.name); err != nil {
			return err
		}
		if err := g.SetKeybinding(w.name, gocui.KeyEnter, gocui.ModNone, w.handler); err != nil {
			return err
		}
		fmt.Fprint(v, w.label)
	}
	return nil
}

func main() {
	g, err := gocui.NewGui()
	if err != nil {
		log.Panicln(err)
	}
	defer g.Close()

	g.Highlight = true
	g.SelFgColor = gocui.ColorRed

	help := NewHelpWidget("help", 1, 1, helpText)
	status := NewStatusbarWidget("status", 1, 6, 50)
	butdown := NewButtonWidget("butdown", 52, 6, "DOWN", statusDown(status))
	butup := NewButtonWidget("butup", 58, 6, "UP", statusUp(status))
	g.SetManager(help, status, butdown, butup)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		log.Panicln(err)
	}
	if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, toggleButton); err != nil {
		log.Panicln(err)
	}

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		log.Panicln(err)
	}
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

func toggleButton(g *gocui.Gui, v *gocui.View) error {
	nextview := "butdown"
	if v == nil || v.Name() == "butdown" {
		nextview = "butup"
	}
	_, err := g.SetCurrentView(nextview)
	return err
}

func statusUp(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
	return func(g *gocui.Gui, v *gocui.View) error {
		return statusSet(status, delta)
	}
}

func statusDown(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
	return func(g *gocui.Gui, v *gocui.View) error {
		return statusSet(status, -delta)
	}
}

func statusSet(sw *StatusbarWidget, inc float32) error {
	val := sw.Val() + inc
	if val < 0 || val > 1+delta/2 {
		return nil
	}
	return sw.SetVal(val)
}

const helpText = `KEYBINDINGS
Tab: Move between buttons
^C: Exit`
<commit_msg>_examples/widgets.go: Minor refactoring<commit_after>// Copyright 2014 The gocui 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 (
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/jroimartin/gocui"
)

const delta = 0.1

type HelpWidget struct {
	name string
	x, y int
	w, h int
	body string
}

func NewHelpWidget(name string, x, y int, body string) *HelpWidget {
	lines := strings.Split(body, "\n")

	w := 0
	for _, l := range lines {
		if len(l) > w {
			w = len(l)
		}
	}
	h := len(lines) + 1
	w = w + 1

	return &HelpWidget{name: name, x: x, y: y, w: w, h: h, body: body}
}

func (w *HelpWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+w.h)
	if err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		fmt.Fprint(v, w.body)
	}
	return nil
}

type StatusbarWidget struct {
	name string
	x, y int
	w    int
	val  float32
}

func NewStatusbarWidget(name string, x, y, w int) *StatusbarWidget {
	return &StatusbarWidget{name: name, x: x, y: y, w: w}
}

func (w *StatusbarWidget) SetVal(val float32) error {
	if val < 0 || val > 1+delta/2 {
		return errors.New("invalid value")
	}
	w.val = val
	return nil
}

func (w *StatusbarWidget) Val() float32 {
	return w.val
}

func (w *StatusbarWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
	if err != nil && err != gocui.ErrUnknownView {
		return err
	}
	v.Clear()
	val := int(w.val * float32(w.w-1))
	fmt.Fprint(v, strings.Repeat("▒", val))
	return nil
}

type ButtonWidget struct {
	name    string
	x, y    int
	w       int
	label   string
	handler func(g *gocui.Gui, v *gocui.View) error
}

func NewButtonWidget(name string, x, y int, label string, handler func(g *gocui.Gui, v *gocui.View) error) *ButtonWidget {
	return &ButtonWidget{name: name, x: x, y: y, w: len(label) + 1, label: label, handler: handler}
}

func (w *ButtonWidget) Layout(g *gocui.Gui) error {
	v, err := g.SetView(w.name, w.x, w.y, w.x+w.w, w.y+2)
	if err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		if _, err := g.SetCurrentView(w.name); err != nil {
			return err
		}
		if err := g.SetKeybinding(w.name, gocui.KeyEnter, gocui.ModNone, w.handler); err != nil {
			return err
		}
		fmt.Fprint(v, w.label)
	}
	return nil
}

func main() {
	g, err := gocui.NewGui()
	if err != nil {
		log.Panicln(err)
	}
	defer g.Close()

	g.Highlight = true
	g.SelFgColor = gocui.ColorRed

	help := NewHelpWidget("help", 1, 1, helpText)
	status := NewStatusbarWidget("status", 1, 6, 50)
	butdown := NewButtonWidget("butdown", 52, 6, "DOWN", statusDown(status))
	butup := NewButtonWidget("butup", 58, 6, "UP", statusUp(status))
	g.SetManager(help, status, butdown, butup)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		log.Panicln(err)
	}
	if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, toggleButton); err != nil {
		log.Panicln(err)
	}

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		log.Panicln(err)
	}
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

func toggleButton(g *gocui.Gui, v *gocui.View) error {
	nextview := "butdown"
	if v == nil || v.Name() == "butdown" {
		nextview = "butup"
	}
	_, err := g.SetCurrentView(nextview)
	return err
}

func statusUp(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
	return func(g *gocui.Gui, v *gocui.View) error {
		return statusSet(status, delta)
	}
}

func statusDown(status *StatusbarWidget) func(g *gocui.Gui, v *gocui.View) error {
	return func(g *gocui.Gui, v *gocui.View) error {
		return statusSet(status, -delta)
	}
}

func statusSet(sw *StatusbarWidget, inc float32) error {
	val := sw.Val() + inc
	if val < 0 || val > 1+delta/2 {
		return nil
	}
	return sw.SetVal(val)
}

const helpText = `KEYBINDINGS
Tab: Move between buttons
^C: Exit`
<|endoftext|>


<commit_before>package report

import (
	"math"
	"time"

	"github.com/ugorji/go/codec"
)

// Metrics is a string->metric map.
type Metrics map[string]Metric

// Lookup the metric for the given key
func (m Metrics) Lookup(key string) (Metric, bool) {
	v, ok := m[key]
	return v, ok
}

// Merge merges two sets maps into a fresh set, performing set-union merges as
// appropriate.
func (m Metrics) Merge(other Metrics) Metrics {
	result := m.Copy()
	for k, v := range other {
		if rv, ok := result[k]; ok {
			result[k] = rv.Merge(v)
		} else {
			result[k] = v.Copy()
		}
	}
	return result
}

// Copy returns a value copy of the sets map.
func (m Metrics) Copy() Metrics {
	result := Metrics{}
	for k, v := range m {
		result[k] = v
	}
	return result
}

// Metric is a list of timeseries data with some metadata. Clients must use the
// Add method to add values.  Metrics are immutable.
type Metric struct {
	Samples     []Sample
	Min, Max    float64
	First, Last time.Time
}

// Sample is a single datapoint of a metric.
type Sample struct {
	Timestamp time.Time `json:"date"`
	Value     float64   `json:"value"`
}

// MakeSingletonMetric makes a metric with a single value
func MakeSingletonMetric(t time.Time, v float64) Metric {
	return Metric{
		Samples: []Sample{{t, v}},
		Min:     v,
		Max:     v,
		First:   t,
		Last:    t,
	}

}

// MakeMetric makes a new Metric from unique samples incrementally ordered in
// time.
func MakeMetric(samples []Sample) Metric {
	if len(samples) < 1 {
		return Metric{}
	}

	var (
		min = samples[0].Value
		max = samples[0].Value
	)

	for i := 1; i < len(samples); i++ {
		if samples[i].Value < min {
			min = samples[i].Value
		} else if samples[i].Value > max {
			max = samples[i].Value
		}
	}

	return Metric{
		Samples: samples,
		Min:     min,
		Max:     max,
		First:   samples[0].Timestamp,
		Last:    samples[len(samples)-1].Timestamp,
	}
}

// Copy returns a copy of the Metric.
func (m Metric) Copy() Metric {
	c := m
	if c.Samples != nil {
		c.Samples = make([]Sample, len(m.Samples))
		copy(c.Samples, m.Samples)
	}
	return c
}

// WithMax returns a fresh copy of m, with Max set to max
func (m Metric) WithMax(max float64) Metric {
	return Metric{
		Samples: m.Samples,
		Max:     max,
		Min:     m.Min,
		First:   m.First,
		Last:    m.Last,
	}
}

// Len returns the number of samples in the metric.
func (m Metric) Len() int {
	return len(m.Samples)
}

func first(t1, t2 time.Time) time.Time {
	if t2.IsZero() || (!t1.IsZero() && t1.Before(t2)) {
		return t1
	}
	return t2
}

func last(t1, t2 time.Time) time.Time {
	if t2.IsZero() || (!t1.IsZero() && t1.After(t2)) {
		return t1
	}
	return t2
}

// Merge combines the two Metrics and returns a new result.
func (m Metric) Merge(other Metric) Metric {

	// Optimize the empty and non-overlapping case since they are very common
	switch {
	case len(m.Samples) == 0:
		return other.Copy()
	case len(other.Samples) == 0:
		return m.Copy()
	case other.First.After(m.Last):
		samplesOut := make([]Sample, len(m.Samples)+len(other.Samples))
		copy(samplesOut, m.Samples)
		copy(samplesOut[len(m.Samples):], other.Samples)
		return Metric{
			Samples: samplesOut,
			Max:     math.Max(m.Max, other.Max),
			Min:     math.Min(m.Min, other.Min),
			First:   m.First,
			Last:    other.Last,
		}
	case m.First.After(other.Last):
		samplesOut := make([]Sample, len(m.Samples)+len(other.Samples))
		copy(samplesOut, other.Samples)
		copy(samplesOut[len(other.Samples):], m.Samples)
		return Metric{
			Samples: samplesOut,
			Max:     math.Max(m.Max, other.Max),
			Min:     math.Min(m.Min, other.Min),
			First:   other.First,
			Last:    m.Last,
		}
	}

	// Merge two lists of Samples in O(n)
	samplesOut := make([]Sample, 0, len(m.Samples)+len(other.Samples))
	mI, otherI := 0, 0
	for {
		if otherI >= len(other.Samples) {
			samplesOut = append(samplesOut, m.Samples[mI:]...)
			break
		} else if mI >= len(m.Samples) {
			samplesOut = append(samplesOut, other.Samples[otherI:]...)
			break
		}

		if m.Samples[mI].Timestamp.Equal(other.Samples[otherI].Timestamp) {
			samplesOut = append(samplesOut, m.Samples[mI])
			mI++
			otherI++
		} else if m.Samples[mI].Timestamp.Before(other.Samples[otherI].Timestamp) {
			samplesOut = append(samplesOut, m.Samples[mI])
			mI++
		} else {
			samplesOut = append(samplesOut, other.Samples[otherI])
			otherI++
		}
	}

	return Metric{
		Samples: samplesOut,
		Max:     math.Max(m.Max, other.Max),
		Min:     math.Min(m.Min, other.Min),
		First:   first(m.First, other.First),
		Last:    last(m.Last, other.Last),
	}
}

// Div returns a new copy of the metric, with each value divided by n.
func (m Metric) Div(n float64) Metric {
	samplesOut := make([]Sample, len(m.Samples), len(m.Samples))

	for i := range m.Samples {
		samplesOut[i].Value = m.Samples[i].Value / n
		samplesOut[i].Timestamp = m.Samples[i].Timestamp
	}
	return Metric{
		Samples: samplesOut,
		Max:     m.Max / n,
		Min:     m.Min / n,
		First:   m.First,
		Last:    m.Last,
	}
}

// LastSample obtains the last sample of the metric
func (m Metric) LastSample() (Sample, bool) {
	if m.Samples == nil {
		return Sample{}, false
	}
	return m.Samples[len(m.Samples)-1], true
}

// WireMetrics is the on-the-wire representation of Metrics.
// Only needed for backwards compatibility with probes
// (time.Time is encoded in binary in MsgPack)
type WireMetrics struct {
	Samples []Sample `json:"samples,omitempty"`
	Min     float64  `json:"min"`
	Max     float64  `json:"max"`
	First   string   `json:"first,omitempty"`
	Last    string   `json:"last,omitempty"`
}

func renderTime(t time.Time) string {
	if t.IsZero() {
		return ""
	}
	return t.Format(time.RFC3339Nano)
}

func parseTime(s string) time.Time {
	t, _ := time.Parse(time.RFC3339Nano, s)
	return t
}

// ToIntermediate converts the metric to a representation suitable
// for serialization.
func (m Metric) ToIntermediate() WireMetrics {
	return WireMetrics{
		Samples: m.Samples,
		Max:     m.Max,
		Min:     m.Min,
		First:   renderTime(m.First),
		Last:    renderTime(m.Last),
	}
}

// FromIntermediate obtains the metric from a representation suitable
// for serialization.
func (m WireMetrics) FromIntermediate() Metric {
	return Metric{
		Samples: m.Samples,
		Max:     m.Max,
		Min:     m.Min,
		First:   parseTime(m.First),
		Last:    parseTime(m.Last),
	}
}

// CodecEncodeSelf implements codec.Selfer
func (m *Metric) CodecEncodeSelf(encoder *codec.Encoder) {
	in := m.ToIntermediate()
	encoder.Encode(in)
}

// CodecDecodeSelf implements codec.Selfer
func (m *Metric) CodecDecodeSelf(decoder *codec.Decoder) {
	in := WireMetrics{}
	if err := decoder.Decode(&in); err != nil {
		return
	}
	*m = in.FromIntermediate()
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (Metric) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*Metric) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}
<commit_msg>Preallocate metrics when copying<commit_after>package report

import (
	"math"
	"time"

	"github.com/ugorji/go/codec"
)

// Metrics is a string->metric map.
type Metrics map[string]Metric

// Lookup the metric for the given key
func (m Metrics) Lookup(key string) (Metric, bool) {
	v, ok := m[key]
	return v, ok
}

// Merge merges two sets maps into a fresh set, performing set-union merges as
// appropriate.
func (m Metrics) Merge(other Metrics) Metrics {
	result := m.Copy()
	for k, v := range other {
		if rv, ok := result[k]; ok {
			result[k] = rv.Merge(v)
		} else {
			result[k] = v.Copy()
		}
	}
	return result
}

// Copy returns a value copy of the sets map.
func (m Metrics) Copy() Metrics {
	result := make(Metrics, len(m))
	for k, v := range m {
		result[k] = v
	}
	return result
}

// Metric is a list of timeseries data with some metadata. Clients must use the
// Add method to add values.  Metrics are immutable.
type Metric struct {
	Samples     []Sample
	Min, Max    float64
	First, Last time.Time
}

// Sample is a single datapoint of a metric.
type Sample struct {
	Timestamp time.Time `json:"date"`
	Value     float64   `json:"value"`
}

// MakeSingletonMetric makes a metric with a single value
func MakeSingletonMetric(t time.Time, v float64) Metric {
	return Metric{
		Samples: []Sample{{t, v}},
		Min:     v,
		Max:     v,
		First:   t,
		Last:    t,
	}

}

// MakeMetric makes a new Metric from unique samples incrementally ordered in
// time.
func MakeMetric(samples []Sample) Metric {
	if len(samples) < 1 {
		return Metric{}
	}

	var (
		min = samples[0].Value
		max = samples[0].Value
	)

	for i := 1; i < len(samples); i++ {
		if samples[i].Value < min {
			min = samples[i].Value
		} else if samples[i].Value > max {
			max = samples[i].Value
		}
	}

	return Metric{
		Samples: samples,
		Min:     min,
		Max:     max,
		First:   samples[0].Timestamp,
		Last:    samples[len(samples)-1].Timestamp,
	}
}

// Copy returns a copy of the Metric.
func (m Metric) Copy() Metric {
	c := m
	if c.Samples != nil {
		c.Samples = make([]Sample, len(m.Samples))
		copy(c.Samples, m.Samples)
	}
	return c
}

// WithMax returns a fresh copy of m, with Max set to max
func (m Metric) WithMax(max float64) Metric {
	return Metric{
		Samples: m.Samples,
		Max:     max,
		Min:     m.Min,
		First:   m.First,
		Last:    m.Last,
	}
}

// Len returns the number of samples in the metric.
func (m Metric) Len() int {
	return len(m.Samples)
}

func first(t1, t2 time.Time) time.Time {
	if t2.IsZero() || (!t1.IsZero() && t1.Before(t2)) {
		return t1
	}
	return t2
}

func last(t1, t2 time.Time) time.Time {
	if t2.IsZero() || (!t1.IsZero() && t1.After(t2)) {
		return t1
	}
	return t2
}

// Merge combines the two Metrics and returns a new result.
func (m Metric) Merge(other Metric) Metric {

	// Optimize the empty and non-overlapping case since they are very common
	switch {
	case len(m.Samples) == 0:
		return other.Copy()
	case len(other.Samples) == 0:
		return m.Copy()
	case other.First.After(m.Last):
		samplesOut := make([]Sample, len(m.Samples)+len(other.Samples))
		copy(samplesOut, m.Samples)
		copy(samplesOut[len(m.Samples):], other.Samples)
		return Metric{
			Samples: samplesOut,
			Max:     math.Max(m.Max, other.Max),
			Min:     math.Min(m.Min, other.Min),
			First:   m.First,
			Last:    other.Last,
		}
	case m.First.After(other.Last):
		samplesOut := make([]Sample, len(m.Samples)+len(other.Samples))
		copy(samplesOut, other.Samples)
		copy(samplesOut[len(other.Samples):], m.Samples)
		return Metric{
			Samples: samplesOut,
			Max:     math.Max(m.Max, other.Max),
			Min:     math.Min(m.Min, other.Min),
			First:   other.First,
			Last:    m.Last,
		}
	}

	// Merge two lists of Samples in O(n)
	samplesOut := make([]Sample, 0, len(m.Samples)+len(other.Samples))
	mI, otherI := 0, 0
	for {
		if otherI >= len(other.Samples) {
			samplesOut = append(samplesOut, m.Samples[mI:]...)
			break
		} else if mI >= len(m.Samples) {
			samplesOut = append(samplesOut, other.Samples[otherI:]...)
			break
		}

		if m.Samples[mI].Timestamp.Equal(other.Samples[otherI].Timestamp) {
			samplesOut = append(samplesOut, m.Samples[mI])
			mI++
			otherI++
		} else if m.Samples[mI].Timestamp.Before(other.Samples[otherI].Timestamp) {
			samplesOut = append(samplesOut, m.Samples[mI])
			mI++
		} else {
			samplesOut = append(samplesOut, other.Samples[otherI])
			otherI++
		}
	}

	return Metric{
		Samples: samplesOut,
		Max:     math.Max(m.Max, other.Max),
		Min:     math.Min(m.Min, other.Min),
		First:   first(m.First, other.First),
		Last:    last(m.Last, other.Last),
	}
}

// Div returns a new copy of the metric, with each value divided by n.
func (m Metric) Div(n float64) Metric {
	samplesOut := make([]Sample, len(m.Samples), len(m.Samples))

	for i := range m.Samples {
		samplesOut[i].Value = m.Samples[i].Value / n
		samplesOut[i].Timestamp = m.Samples[i].Timestamp
	}
	return Metric{
		Samples: samplesOut,
		Max:     m.Max / n,
		Min:     m.Min / n,
		First:   m.First,
		Last:    m.Last,
	}
}

// LastSample obtains the last sample of the metric
func (m Metric) LastSample() (Sample, bool) {
	if m.Samples == nil {
		return Sample{}, false
	}
	return m.Samples[len(m.Samples)-1], true
}

// WireMetrics is the on-the-wire representation of Metrics.
// Only needed for backwards compatibility with probes
// (time.Time is encoded in binary in MsgPack)
type WireMetrics struct {
	Samples []Sample `json:"samples,omitempty"`
	Min     float64  `json:"min"`
	Max     float64  `json:"max"`
	First   string   `json:"first,omitempty"`
	Last    string   `json:"last,omitempty"`
}

func renderTime(t time.Time) string {
	if t.IsZero() {
		return ""
	}
	return t.Format(time.RFC3339Nano)
}

func parseTime(s string) time.Time {
	t, _ := time.Parse(time.RFC3339Nano, s)
	return t
}

// ToIntermediate converts the metric to a representation suitable
// for serialization.
func (m Metric) ToIntermediate() WireMetrics {
	return WireMetrics{
		Samples: m.Samples,
		Max:     m.Max,
		Min:     m.Min,
		First:   renderTime(m.First),
		Last:    renderTime(m.Last),
	}
}

// FromIntermediate obtains the metric from a representation suitable
// for serialization.
func (m WireMetrics) FromIntermediate() Metric {
	return Metric{
		Samples: m.Samples,
		Max:     m.Max,
		Min:     m.Min,
		First:   parseTime(m.First),
		Last:    parseTime(m.Last),
	}
}

// CodecEncodeSelf implements codec.Selfer
func (m *Metric) CodecEncodeSelf(encoder *codec.Encoder) {
	in := m.ToIntermediate()
	encoder.Encode(in)
}

// CodecDecodeSelf implements codec.Selfer
func (m *Metric) CodecDecodeSelf(decoder *codec.Decoder) {
	in := WireMetrics{}
	if err := decoder.Decode(&in); err != nil {
		return
	}
	*m = in.FromIntermediate()
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (Metric) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*Metric) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}
<|endoftext|>


<commit_before>package main

var etcdTemplate = `apiVersion: v1
kind: Pod
metadata:
  name: etcd
spec:
  hostNetwork: true
    containers:
      - name: "etcd"
        image: "{{.Image}}"
        args:
          - "--name={{.Name}}"
          - "--advertise-client-urls={{.AdvertiseClientUrls}}"
          - "--listen-client-urls=http://0.0.0.0:2379"
          - "--listen-peer-urls=http://0.0.0.0:2380"
          - "--data-dir=/var/lib/etcd/data"
          - "--wal-dir=/var/lib/etcd/wal"
          - "--election-timeout=1000"
          - "--heartbeat-interval=100"
          - "--snapshot-count=10000"
          - "--max-snapshots=5"
          - "--max-wals=5"
          - "--initial-advertise-peer-urls={{.InitialAdvertisePeerUrls}}"
          - "--initial-cluster={{.InitialCluster}}"
          - "--initial-cluster-state=new"
          - "--initial-cluster-token={{.ClusterToken}}"
        ports:
          - name: client
            containerPort: 2379
            protocol: "TCP"
          - name: peer
            containerPort: 2380
            protocol: "TCP"
        resources:
          limits:
            cpu: "1000m"
            memory: "256Mi"
        volumeMounts:
          - name: "etcd-data"
            mountPath: /var/lib/etcd/data
          - name: "etcd-wal"
            mountPath: /var/lib/etcd/wal
    volumes:{{if eq .CloudProvider "gce"}}
      - name: "etcd-wal"
        gcePersistentDisk:
          pdName: {{.WalVolumeId}}
          fsType: ext4
      - name: "etcd-data"
        gcePersistentDisk:
          pdName: {{.DataVolumeId}}
          fsType: ext4{{else}}
      - name: "etcd-wal"
        awsElasticBlockStore:
          volumeID: {{.WalVolumeId}}
          fsType: ext4
      - name: "etcd-data"
        awsElasticBlockStore:
          volumeID: {{.DataVolumeId}}
          fsType: ext4{{end}}
`
<commit_msg>fix etcd pod template<commit_after>package main

var etcdTemplate = `apiVersion: v1
kind: Pod
metadata:
  name: etcd
spec:
  hostNetwork: true
  containers:
    - name: "etcd"
      image: "{{.Image}}"
      args:
        - "--name={{.Name}}"
        - "--advertise-client-urls={{.AdvertiseClientUrls}}"
        - "--listen-client-urls=http://0.0.0.0:2379"
        - "--listen-peer-urls=http://0.0.0.0:2380"
        - "--data-dir=/var/lib/etcd/data"
        - "--wal-dir=/var/lib/etcd/wal"
        - "--election-timeout=1000"
        - "--heartbeat-interval=100"
        - "--snapshot-count=10000"
        - "--max-snapshots=5"
        - "--max-wals=5"
        - "--initial-advertise-peer-urls={{.InitialAdvertisePeerUrls}}"
        - "--initial-cluster={{.InitialCluster}}"
        - "--initial-cluster-state=new"
        - "--initial-cluster-token={{.ClusterToken}}"
      ports:
        - name: client
          containerPort: 2379
          protocol: "TCP"
        - name: peer
          containerPort: 2380
          protocol: "TCP"
      resources:
        limits:
          cpu: "1000m"
          memory: "256Mi"
      volumeMounts:
        - name: "etcd-data"
          mountPath: /var/lib/etcd/data
        - name: "etcd-wal"
          mountPath: /var/lib/etcd/wal
  volumes:{{if eq .CloudProvider "gce"}}
    - name: "etcd-wal"
      gcePersistentDisk:
        pdName: {{.WalVolumeId}}
        fsType: ext4
    - name: "etcd-data"
      gcePersistentDisk:
        pdName: {{.DataVolumeId}}
        fsType: ext4{{else}}
    - name: "etcd-wal"
      awsElasticBlockStore:
        volumeID: {{.WalVolumeId}}
        fsType: ext4
    - name: "etcd-data"
      awsElasticBlockStore:
        volumeID: {{.DataVolumeId}}
        fsType: ext4{{end}}
`
<|endoftext|>