<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Magnús Örn Gylfason
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package itk

import (
	"github.com/mg/i"
)

// Compose this structure in your iterator to wrap a Forward iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped Forward iterator.
type WForward struct {
	value  func() interface{}
	err    func() error
	seterr func(error)
	next   func() error
	atEnd  func() bool
}

// Wrap a Forward iterator. If ITR is your iterator type and F is
// the iterator your wish to wrap, the usage is
//
// ITR.WForward= *(WrapForward(F))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to F.Value() by
// WForward. To guard against a chain of useless forwards, the
// WrapForward checks if F is a WForward iterator. If so, it simply
// copies the values of the mehtods from F so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the F iterator wrapped.
func WrapForward(itr i.Forward) *WForward {
	wf := WForward{}
	if wrapped, ok := itr.(*WForward); ok {
		wf.value = wrapped.value
		wf.err = wrapped.err
		wf.seterr = wrapped.seterr
		wf.next = wrapped.next
		wf.atEnd = wrapped.atEnd
	} else {
		wf.value = itr.Value
		wf.err = itr.Error
		wf.seterr = itr.SetError
		wf.next = itr.Next
		wf.atEnd = itr.AtEnd
	}
	return &wf
}

// Forwards the call to the Value() method of the wrapped iterator.
func (wf *WForward) Value() interface{} {
	return wf.value()
}

// Forwards the call to the Error() method of the wrapped iterator.
func (wf *WForward) Error() error {
	return wf.err()
}

// Forwards the call to the SetError() method of the wrapped iterator.
func (wf *WForward) SetError(err error) {
	wf.seterr(err)
}

// Forwards the call to the Next() method of the wrapped iterator.
func (wf *WForward) Next() error {
	return wf.next()
}

// Forwards the call to the AtEnd() method of the wrapped iterator.
func (wf *WForward) AtEnd() bool {
	return wf.atEnd()
}

// Compose this structure in your iterator to wrap a BiDirectional iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped BiDirectional iterator.
type WBiDirectional struct {
	WForward
	prev    func() error
	atStart func() bool
}

// Wrap a BiDirectional iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBiDirectional= *(WrapBiDirectional(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WBiDirectional. To guard against a chain of useless forwards, the
// WrapBiDirectional checks if B is a WBiDirectional iterator. If so,
// it simply copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBiDirectional(itr i.BiDirectional) *WBiDirectional {
	wbd := WBiDirectional{}
	wbd.WForward = *(WrapForward(itr))

	if wrapped, ok := itr.(*WBiDirectional); ok {
		wbd.prev = wrapped.prev
		wbd.atStart = wrapped.atStart
	} else {
		wbd.prev = itr.Prev
		wbd.atStart = itr.AtStart
	}

	return &wbd
}

// Forwards the call to the Prev() method of the wrapped iterator.
func (wbd *WBiDirectional) Prev() error {
	return wbd.prev()
}

// Forwards the call to the AtStart() method of the wrapped iterator.
func (wbd *WBiDirectional) AtStart() bool {
	return wbd.atStart()
}

// Compose this structure in your iterator to wrap a BoundedAtStart iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped BoundedAtStart iterator.
type WBoundedAtStart struct {
	WForward
	first func() error
}

// Wrap a BoundedAtStart iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBoundedAtStart= *(WrapBoundedAtStart(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WFBoundedAtStart. To guard against a chain of useless forwards, the
// WrapBoundedAtStart checks if B is a WBoundedAtStart iterator. If so,
// it simply copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBoundedAtStart(itr i.BoundedAtStart) *WBoundedAtStart {
	wbas := WBoundedAtStart{}
	wbas.WForward = *(WrapForward(itr))

	if wrapped, ok := itr.(*WBoundedAtStart); ok {
		wbas.first = wrapped.first
	} else {
		wbas.first = itr.First
	}

	return &wbas
}

// Forwards the call to the First() method of the wrapped iterator.
func (wbas *WBoundedAtStart) First() error {
	return wbas.first()
}

// Compose this structure in your iterator to wrap a Bounded iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped Bounded iterator.
type WBounded struct {
	WBiDirectional
	first func() error
	last  func() error
}

// Wrap a Bounded iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBounded= *(WrapBounded(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WBounded. To guard against a chain of useless forwards, the
// WrapBounded checks if B is a WBounded iterator. If so, it simply
// copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBounded(itr i.Bounded) *WBounded {
	wb := WBounded{}
	wb.WBiDirectional = *(WrapBiDirectional(itr))

	if wrapped, ok := itr.(*WBounded); ok {
		wb.first = wrapped.first
		wb.last = wrapped.last
	} else {
		wb.first = itr.First
		wb.last = itr.Last
	}

	return &wb
}

// Forwards the call to the First() method of the wrapped iterator.
func (wb *WBounded) First() error {
	return wb.first()
}

// Forwards the call to the Last() method of the wrapped iterator.
func (wb *WBounded) Last() error {
	return wb.last()
}

// Compose this structure in your iterator to wrap a RandomAccess iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped RandomAccess iterator.
type WRandomAccess struct {
	WBounded
	goTo   func(int) error
	length func() int
}

// Wrap a RandomAccess iterator. If ITR is your iterator type and R is
// the iterator your wish to wrap, the usage is
//
// ITR.WRandomAccess= *(WrapRandomAccess(R))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to R.Value() by
// WRandomAccess. To guard against a chain of useless forwards, the
// WrapRandomAccess checks if R is a WRandomAccess iterator. If so, it simply
// copies the values of the mehtods from R so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the R iterator wrapped.
func WrapRandomAccess(itr i.RandomAccess) *WRandomAccess {
	wra := WRandomAccess{}
	wra.WBounded = *(WrapBounded(itr))

	if wrapped, ok := itr.(*WRandomAccess); ok {
		wra.goTo = wrapped.goTo
		wra.length = wrapped.length
	} else {
		wra.goTo = itr.Goto
		wra.length = itr.Len
	}

	return &wra
}

// Forwards the call to the Goto() method of the wrapped iterator.
func (wra *WRandomAccess) Goto(idx int) error {
	return wra.goTo(idx)
}

// Forwards the call to the Len() method of the wrapped iterator.
func (wra *WRandomAccess) Len() int {
	return wra.length()
}
<commit_msg>itk.Wrap: provide optimization functionality<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Magnús Örn Gylfason
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package itk

import (
	"github.com/mg/i"
	"reflect"
)

// Gives access to wrapped methods
type wrappedForward interface {
	getValueMethod() func() interface{}
	getErrorMethod() func() error
	getSetErrorMethod() func(error)
	getNextMethod() func() error
	getAtEndMethod() func() bool
}

// Compose this structure in your iterator to wrap a Forward iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped Forward iterator.
type WForward struct {
	value  func() interface{}
	err    func() error
	seterr func(error)
	next   func() error
	atEnd  func() bool
}

// Wrap a Forward iterator. If ITR is your iterator type and F is
// the iterator your wish to wrap, the usage is
//
// ITR.WForward= *(WrapForward(F))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to F.Value() by
// WForward. To guard against a chain of useless forwards, the
// WrapForward checks if F is a WForward iterator. If so, it simply
// copies the values of the mehtods from F so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the F iterator wrapped.
func WrapForward(itr i.Forward) *WForward {
	wf := WForward{}

	t := reflect.TypeOf(itr)
	isWrapper := false
	if t.Kind() == reflect.Ptr {
		_, isWrapper = t.Elem().FieldByName("WForward")
	} else {
		_, isWrapper = t.FieldByName("WForward")
	}
	if isWrapper {
		wrapped, _ := itr.(wrappedForward)
		if _, ok := t.MethodByName("Value"); !ok {
			wf.value = wrapped.getValueMethod()
		} else {
			wf.value = itr.Value
		}
		if _, ok := t.MethodByName("Error"); !ok {
			wf.err = wrapped.getErrorMethod()
		} else {
			wf.err = itr.Error
		}
		if _, ok := t.MethodByName("SetError"); !ok {
			wf.seterr = wrapped.getSetErrorMethod()
		} else {
			wf.seterr = itr.SetError
		}
		if _, ok := t.MethodByName("Next"); !ok {
			wf.next = wrapped.getNextMethod()
		} else {
			wf.next = itr.Next
		}
		if _, ok := t.MethodByName("AtEnd"); !ok {
			wf.atEnd = wrapped.getAtEndMethod()
		} else {
			wf.atEnd = itr.AtEnd
		}
	} else {
		wf.value = itr.Value
		wf.err = itr.Error
		wf.seterr = itr.SetError
		wf.next = itr.Next
		wf.atEnd = itr.AtEnd
	}
	return &wf
}

// Forwards the call to the Value() method of the wrapped iterator.
func (wf *WForward) Value() interface{} {
	return wf.value()
}

// Forwards the call to the Error() method of the wrapped iterator.
func (wf *WForward) Error() error {
	return wf.err()
}

// Forwards the call to the SetError() method of the wrapped iterator.
func (wf *WForward) SetError(err error) {
	wf.seterr(err)
}

// Forwards the call to the Next() method of the wrapped iterator.
func (wf *WForward) Next() error {
	return wf.next()
}

// Forwards the call to the AtEnd() method of the wrapped iterator.
func (wf *WForward) AtEnd() bool {
	return wf.atEnd()
}

// Methods to access wrapped functions
func (wf *WForward) getValueMethod() func() interface{} {
	return wf.value
}

func (wf *WForward) getErrorMethod() func() error {
	return wf.err
}

func (wf *WForward) getSetErrorMethod() func(error) {
	return wf.seterr
}

func (wf *WForward) getNextMethod() func() error {
	return wf.next
}

func (wf *WForward) getAtEndMethod() func() bool {
	return wf.atEnd
}

// Gives access to wrapped methods
type wrappedBiDirectional interface {
	getPrevMethod() func() error
	getAtStartMethod() func() bool
}

// Compose this structure in your iterator to wrap a BiDirectional iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped BiDirectional iterator.
type WBiDirectional struct {
	WForward
	prev    func() error
	atStart func() bool
}

// Wrap a BiDirectional iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBiDirectional= *(WrapBiDirectional(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WBiDirectional. To guard against a chain of useless forwards, the
// WrapBiDirectional checks if B is a WBiDirectional iterator. If so,
// it simply copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBiDirectional(itr i.BiDirectional) *WBiDirectional {
	wbd := WBiDirectional{}
	wbd.WForward = *(WrapForward(itr))

	t := reflect.TypeOf(itr)
	isWrapper := false
	if t.Kind() == reflect.Ptr {
		_, isWrapper = t.Elem().FieldByName("WBiDirectional")
	} else {
		_, isWrapper = t.FieldByName("WBiDirectional")
	}
	if isWrapper {
		wrapped, _ := itr.(wrappedBiDirectional)
		if _, ok := t.MethodByName("Prev"); !ok {
			wbd.prev = wrapped.getPrevMethod()
		} else {
			wbd.prev = itr.Prev
		}
		if _, ok := t.MethodByName("AtStart"); !ok {
			wbd.atStart = wrapped.getAtStartMethod()
		} else {
			wbd.atStart = itr.AtStart
		}
	} else {
		wbd.prev = itr.Prev
		wbd.atStart = itr.AtStart
	}

	return &wbd
}

// Forwards the call to the Prev() method of the wrapped iterator.
func (wbd *WBiDirectional) Prev() error {
	return wbd.prev()
}

// Forwards the call to the AtStart() method of the wrapped iterator.
func (wbd *WBiDirectional) AtStart() bool {
	return wbd.atStart()
}

// Methods to access wrapped functions
func (wbd *WBiDirectional) getPrevMethod() func() error {
	return wbd.prev
}

func (wbd *WBiDirectional) getAtStartMethod() func() bool {
	return wbd.atStart
}

// Gives access to wrapped methods
type wrappedBondedAtStart interface {
	getFirstMethod() func() error
}

// Compose this structure in your iterator to wrap a BoundedAtStart iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped BoundedAtStart iterator.
type WBoundedAtStart struct {
	WForward
	first func() error
}

// Wrap a BoundedAtStart iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBoundedAtStart= *(WrapBoundedAtStart(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WFBoundedAtStart. To guard against a chain of useless forwards, the
// WrapBoundedAtStart checks if B is a WBoundedAtStart iterator. If so,
// it simply copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBoundedAtStart(itr i.BoundedAtStart) *WBoundedAtStart {
	wbas := WBoundedAtStart{}
	wbas.WForward = *(WrapForward(itr))

	t := reflect.TypeOf(itr)
	isWrapper := false
	if t.Kind() == reflect.Ptr {
		_, isWrapper = t.Elem().FieldByName("WBoundedAtStart")
	} else {
		_, isWrapper = t.FieldByName("WBoundedAtStart")
	}
	if isWrapper {
		wrapped, _ := itr.(wrappedBondedAtStart)
		if _, ok := t.MethodByName("First"); !ok {
			wbas.first = wrapped.getFirstMethod()
		} else {
			wbas.first = itr.First
		}
	} else {
		wbas.first = itr.First
	}

	return &wbas
}

// Forwards the call to the First() method of the wrapped iterator.
func (wbas *WBoundedAtStart) First() error {
	return wbas.first()
}

// Methods to access wrapped functions
func (wbas *WBoundedAtStart) getFirstMethod() func() error {
	return wbas.first
}

// Gives access to wrapped methods
type wrappedBonded interface {
	getFirstMethod() func() error
	getLastMethod() func() error
}

// Compose this structure in your iterator to wrap a Bounded iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped Bounded iterator.
type WBounded struct {
	WBiDirectional
	first func() error
	last  func() error
}

// Wrap a Bounded iterator. If ITR is your iterator type and B is
// the iterator your wish to wrap, the usage is
//
// ITR.WBounded= *(WrapBounded(B))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to B.Value() by
// WBounded. To guard against a chain of useless forwards, the
// WrapBounded checks if B is a WBounded iterator. If so, it simply
// copies the values of the mehtods from B so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the B iterator wrapped.
func WrapBounded(itr i.Bounded) *WBounded {
	wb := WBounded{}
	wb.WBiDirectional = *(WrapBiDirectional(itr))

	t := reflect.TypeOf(itr)
	isWrapper := false
	if t.Kind() == reflect.Ptr {
		_, isWrapper = t.Elem().FieldByName("WBounded")
	} else {
		_, isWrapper = t.FieldByName("WBounded")
	}
	if isWrapper {
		wrapped, _ := itr.(wrappedBonded)
		if _, ok := t.MethodByName("First"); !ok {
			wb.first = wrapped.getFirstMethod()
		} else {
			wb.first = itr.First
		}
		if _, ok := t.MethodByName("Last"); !ok {
			wb.last = wrapped.getLastMethod()
		} else {
			wb.last = itr.Last
		}
	} else {
		wb.first = itr.First
		wb.last = itr.Last
	}

	return &wb
}

// Forwards the call to the First() method of the wrapped iterator.
func (wb *WBounded) First() error {
	return wb.first()
}

// Forwards the call to the Last() method of the wrapped iterator.
func (wb *WBounded) Last() error {
	return wb.last()
}

// Methods to access wrapped functions
func (wb *WBounded) getFirstMethod() func() error {
	return wb.first
}

func (wb *WBounded) getLastMethod() func() error {
	return wb.last
}

// Gives access to wrapped methods
type wrappedRandomAccess interface {
	getGoToMethod() func(int) error
	getLenMethod() func() int
}

// Compose this structure in your iterator to wrap a RandomAccess iterator
// within your own iterator. It contains function pointers that point
// to all the methods of the wrapped RandomAccess iterator.
type WRandomAccess struct {
	WBounded
	goTo   func(int) error
	length func() int
}

// Wrap a RandomAccess iterator. If ITR is your iterator type and R is
// the iterator your wish to wrap, the usage is
//
// ITR.WRandomAccess= *(WrapRandomAccess(R))
//
// Now if you don't e.g. provide an implementation for the Value()
// method, a call to ITR.Value() will be forwarded to R.Value() by
// WRandomAccess. To guard against a chain of useless forwards, the
// WrapRandomAccess checks if R is a WRandomAccess iterator. If so, it simply
// copies the values of the mehtods from R so any calls to e.g.
// ITR.Value() will result in a direct call of the Value() method
// the R iterator wrapped.
func WrapRandomAccess(itr i.RandomAccess) *WRandomAccess {
	wra := WRandomAccess{}
	wra.WBounded = *(WrapBounded(itr))

	t := reflect.TypeOf(itr)
	isWrapper := false
	if t.Kind() == reflect.Ptr {
		_, isWrapper = t.Elem().FieldByName("WRandomAccess")
	} else {
		_, isWrapper = t.FieldByName("WRandomAccess")
	}
	if isWrapper {
		wrapped, _ := itr.(wrappedRandomAccess)
		if _, ok := t.MethodByName("GoTo"); !ok {
			wra.goTo = wrapped.getGoToMethod()
		} else {
			wra.goTo = itr.Goto
		}
		if _, ok := t.MethodByName("Len"); !ok {
			wra.length = wrapped.getLenMethod()
		} else {
			wra.length = itr.Len
		}
	} else {
		wra.goTo = itr.Goto
		wra.length = itr.Len
	}

	return &wra
}

// Forwards the call to the Goto() method of the wrapped iterator.
func (wra *WRandomAccess) Goto(idx int) error {
	return wra.goTo(idx)
}

// Forwards the call to the Len() method of the wrapped iterator.
func (wra *WRandomAccess) Len() int {
	return wra.length()
}

// Methods to access wrapped functions
func (wra *WRandomAccess) getGoToMethod() func(int) error {
	return wra.goTo
}

func (wra *WRandomAccess) getLenMethod() func() int {
	return wra.length
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"github.com/gizak/termui"
)

func dashboard(startTime time.Time, stopTheCrawler chan bool) {
	if err := termui.Init(); err != nil {
		panic(err)
	}
	defer termui.Close()

	var snapshots []Snapshot

	logWindow := termui.NewList()
	logWindow.ItemFgColor = termui.ColorYellow
	logWindow.BorderLabel = "Log"
	logWindow.Height = 22
	logWindow.Y = 0

	totalBytesDownloaded := termui.NewPar("")
	totalBytesDownloaded.Height = 3
	totalBytesDownloaded.TextFgColor = termui.ColorWhite
	totalBytesDownloaded.BorderLabel = "Data downloaded"
	totalBytesDownloaded.BorderFg = termui.ColorCyan

	totalNumberOfRequests := termui.NewPar("")
	totalNumberOfRequests.Height = 3
	totalNumberOfRequests.TextFgColor = termui.ColorWhite
	totalNumberOfRequests.BorderLabel = "URLs crawled"
	totalNumberOfRequests.BorderFg = termui.ColorCyan

	requestsPerSecond := termui.NewPar("")
	requestsPerSecond.Height = 3
	requestsPerSecond.TextFgColor = termui.ColorWhite
	requestsPerSecond.BorderLabel = "URLs/second"
	requestsPerSecond.BorderFg = termui.ColorCyan

	averageResponseTime := termui.NewPar("")
	averageResponseTime.Height = 3
	averageResponseTime.TextFgColor = termui.ColorWhite
	averageResponseTime.BorderLabel = "Average response time"
	averageResponseTime.BorderFg = termui.ColorCyan

	numberOfWorkers := termui.NewPar("")
	numberOfWorkers.Height = 3
	numberOfWorkers.TextFgColor = termui.ColorWhite
	numberOfWorkers.BorderLabel = "Number of workers"
	numberOfWorkers.BorderFg = termui.ColorCyan

	averageSizeInBytes := termui.NewPar("")
	averageSizeInBytes.Height = 3
	averageSizeInBytes.TextFgColor = termui.ColorWhite
	averageSizeInBytes.BorderLabel = "Average request size"
	averageSizeInBytes.BorderFg = termui.ColorCyan

	numberOfErrors := termui.NewPar("")
	numberOfErrors.Height = 3
	numberOfErrors.TextFgColor = termui.ColorWhite
	numberOfErrors.BorderLabel = "Number of 4xx errors"
	numberOfErrors.BorderFg = termui.ColorCyan

	elapsedTime := termui.NewPar("")
	elapsedTime.Height = 3
	elapsedTime.TextFgColor = termui.ColorWhite
	elapsedTime.BorderLabel = "Elapsed time"
	elapsedTime.BorderFg = termui.ColorCyan

	debugMessages := termui.NewList()
	debugMessages.ItemFgColor = termui.ColorYellow
	debugMessages.BorderLabel = "Debug"
	debugMessages.Height = 6
	debugMessages.Y = 0

	draw := func() {

		snapshot := stats.LastSnapshot()

		// capture the latest snapshot
		snapshots = append(snapshots, snapshot)

		// log messages
		logWindow.Items = stats.LastLogMessages(20)

		// total number of requests
		totalNumberOfRequests.Text = fmt.Sprintf("%d", snapshot.TotalNumberOfRequests())

		// total number of bytes downloaded
		totalBytesDownloaded.Text = formatBytes(snapshot.TotalSizeInBytes())

		// requests per second
		requestsPerSecond.Text = fmt.Sprintf("%.1f", snapshot.RequestsPerSecond())

		// average response time
		averageResponseTime.Text = fmt.Sprintf("%s", snapshot.AverageResponseTime())

		// number of workers
		numberOfWorkers.Text = fmt.Sprintf("%d", snapshot.NumberOfWorkers())

		// average request size
		averageSizeInBytes.Text = formatBytes(snapshot.AverageSizeInBytes())

		// number of errors
		numberOfErrors.Text = fmt.Sprintf("%d", snapshot.NumberOfErrors())

		// debug messages
		debugMessages.Items = errorMessages

		// time since first snapshot
		timeSinceStart := time.Now().Sub(startTime)
		elapsedTime.Text = fmt.Sprintf("%s", timeSinceStart)

		termui.Render(termui.Body)
	}

	termui.Body.AddRows(
		termui.NewRow(
			termui.NewCol(12, 0, logWindow),
		),
		termui.NewRow(
			termui.NewCol(3, 0, totalBytesDownloaded),
			termui.NewCol(3, 0, totalNumberOfRequests),
			termui.NewCol(3, 0, requestsPerSecond),
			termui.NewCol(3, 0, averageResponseTime),
		),
		termui.NewRow(
			termui.NewCol(3, 0, numberOfWorkers),
			termui.NewCol(3, 0, numberOfErrors),
			termui.NewCol(3, 0, averageSizeInBytes),
			termui.NewCol(3, 0, elapsedTime),
		),
		termui.NewRow(
			termui.NewCol(12, 0, debugMessages),
		),
	)

	termui.Body.Align()

	termui.Render(termui.Body)

	termui.Handle("/sys/wnd/resize", func(e termui.Event) {
		termui.Body.Width = termui.TermWidth()
		termui.Body.Align()
		termui.Clear()
		termui.Render(termui.Body)
	})

	termui.Handle("/sys/kbd/q", func(termui.Event) {
		stopTheCrawler <- true

		termui.StopLoop()
	})

	termui.Handle("/timer/1s", func(e termui.Event) {
		draw()
	})

	termui.Loop()
}
<commit_msg>Use a different font color for the debug window than for the log window<commit_after>package main

import (
	"fmt"
	"time"

	"github.com/gizak/termui"
)

func dashboard(startTime time.Time, stopTheCrawler chan bool) {
	if err := termui.Init(); err != nil {
		panic(err)
	}
	defer termui.Close()

	var snapshots []Snapshot

	logWindow := termui.NewList()
	logWindow.ItemFgColor = termui.ColorYellow
	logWindow.BorderLabel = "Log"
	logWindow.Height = 22
	logWindow.Y = 0

	totalBytesDownloaded := termui.NewPar("")
	totalBytesDownloaded.Height = 3
	totalBytesDownloaded.TextFgColor = termui.ColorWhite
	totalBytesDownloaded.BorderLabel = "Data downloaded"
	totalBytesDownloaded.BorderFg = termui.ColorCyan

	totalNumberOfRequests := termui.NewPar("")
	totalNumberOfRequests.Height = 3
	totalNumberOfRequests.TextFgColor = termui.ColorWhite
	totalNumberOfRequests.BorderLabel = "URLs crawled"
	totalNumberOfRequests.BorderFg = termui.ColorCyan

	requestsPerSecond := termui.NewPar("")
	requestsPerSecond.Height = 3
	requestsPerSecond.TextFgColor = termui.ColorWhite
	requestsPerSecond.BorderLabel = "URLs/second"
	requestsPerSecond.BorderFg = termui.ColorCyan

	averageResponseTime := termui.NewPar("")
	averageResponseTime.Height = 3
	averageResponseTime.TextFgColor = termui.ColorWhite
	averageResponseTime.BorderLabel = "Average response time"
	averageResponseTime.BorderFg = termui.ColorCyan

	numberOfWorkers := termui.NewPar("")
	numberOfWorkers.Height = 3
	numberOfWorkers.TextFgColor = termui.ColorWhite
	numberOfWorkers.BorderLabel = "Number of workers"
	numberOfWorkers.BorderFg = termui.ColorCyan

	averageSizeInBytes := termui.NewPar("")
	averageSizeInBytes.Height = 3
	averageSizeInBytes.TextFgColor = termui.ColorWhite
	averageSizeInBytes.BorderLabel = "Average request size"
	averageSizeInBytes.BorderFg = termui.ColorCyan

	numberOfErrors := termui.NewPar("")
	numberOfErrors.Height = 3
	numberOfErrors.TextFgColor = termui.ColorWhite
	numberOfErrors.BorderLabel = "Number of 4xx errors"
	numberOfErrors.BorderFg = termui.ColorCyan

	elapsedTime := termui.NewPar("")
	elapsedTime.Height = 3
	elapsedTime.TextFgColor = termui.ColorWhite
	elapsedTime.BorderLabel = "Elapsed time"
	elapsedTime.BorderFg = termui.ColorCyan

	debugMessages := termui.NewList()
	debugMessages.ItemFgColor = termui.ColorWhite
	debugMessages.BorderLabel = "Debug"
	debugMessages.Height = 6
	debugMessages.Y = 0

	draw := func() {

		snapshot := stats.LastSnapshot()

		// capture the latest snapshot
		snapshots = append(snapshots, snapshot)

		// log messages
		logWindow.Items = stats.LastLogMessages(20)

		// total number of requests
		totalNumberOfRequests.Text = fmt.Sprintf("%d", snapshot.TotalNumberOfRequests())

		// total number of bytes downloaded
		totalBytesDownloaded.Text = formatBytes(snapshot.TotalSizeInBytes())

		// requests per second
		requestsPerSecond.Text = fmt.Sprintf("%.1f", snapshot.RequestsPerSecond())

		// average response time
		averageResponseTime.Text = fmt.Sprintf("%s", snapshot.AverageResponseTime())

		// number of workers
		numberOfWorkers.Text = fmt.Sprintf("%d", snapshot.NumberOfWorkers())

		// average request size
		averageSizeInBytes.Text = formatBytes(snapshot.AverageSizeInBytes())

		// number of errors
		numberOfErrors.Text = fmt.Sprintf("%d", snapshot.NumberOfErrors())

		// debug messages
		debugMessages.Items = errorMessages

		// time since first snapshot
		timeSinceStart := time.Now().Sub(startTime)
		elapsedTime.Text = fmt.Sprintf("%s", timeSinceStart)

		termui.Render(termui.Body)
	}

	termui.Body.AddRows(
		termui.NewRow(
			termui.NewCol(12, 0, logWindow),
		),
		termui.NewRow(
			termui.NewCol(3, 0, totalBytesDownloaded),
			termui.NewCol(3, 0, totalNumberOfRequests),
			termui.NewCol(3, 0, requestsPerSecond),
			termui.NewCol(3, 0, averageResponseTime),
		),
		termui.NewRow(
			termui.NewCol(3, 0, numberOfWorkers),
			termui.NewCol(3, 0, numberOfErrors),
			termui.NewCol(3, 0, averageSizeInBytes),
			termui.NewCol(3, 0, elapsedTime),
		),
		termui.NewRow(
			termui.NewCol(12, 0, debugMessages),
		),
	)

	termui.Body.Align()

	termui.Render(termui.Body)

	termui.Handle("/sys/wnd/resize", func(e termui.Event) {
		termui.Body.Width = termui.TermWidth()
		termui.Body.Align()
		termui.Clear()
		termui.Render(termui.Body)
	})

	termui.Handle("/sys/kbd/q", func(termui.Event) {
		stopTheCrawler <- true

		termui.StopLoop()
	})

	termui.Handle("/timer/1s", func(e termui.Event) {
		draw()
	})

	termui.Loop()
}
<|endoftext|>


<commit_before>package grafana

import "time"

type DashboardID uint64

type Dashboard struct {
	ID           DashboardID `json:"id"`
	Editable     bool        `json:"editable"`
	GraphTooltip uint8       `json:"graphTooltip"`
	HideControls bool        `json:"hideControls"`
	Rows         []*Row      `json:"rows"`
	Slug         string      `json:"slug"`
	Style        string      `json:"style"`
	Timezone     string      `json:"timezone"`
	Title        string      `json:"title"`
	tags         []string
	Meta         *DashboardMeta
}

type DashboardMeta struct {
	Slug    string `json:"slug"`
	Type    string `json:"type"`
	Version int    `json:"version"`

	CanEdit bool `json:"canEdit"`
	CanSave bool `json:"canSave"`
	CanStar bool `json:"canStar"`

	Created   time.Time `json:"created"`
	CreatedBy string    `json:"createdBy"`
	Expires   time.Time `json:"expires"`
	Updated   time.Time `json:"updated"`
	UpdatedBy string    `json:"updatedBy"`
}

// Tags is a getter for Dashboard tags field
func (d *Dashboard) Tags() []string {
	return d.tags
}

// SetTags sets new tags to dashboard
func (d *Dashboard) SetTags(tags ...string) {
	newTags := []string{}

	uniqTags := make(map[string]bool)
	for _, tag := range tags {
		uniqTags[tag] = true
	}

	for tag := range uniqTags {
		newTags = append(newTags, tag)
	}

	d.tags = newTags
}

// AddTags adds given tags to dashboard. This method keeps uniqueness of tags.
func (d *Dashboard) AddTags(tags ...string) {
	tagFound := make(map[string]bool, len(d.tags))
	for _, tag := range d.tags {
		tagFound[tag] = true
	}

	for _, tag := range tags {
		if _, ok := tagFound[tag]; ok {
			continue
		}
		d.tags = append(d.tags, tag)
	}
}

// RemoveTags removes given tags from dashboard. Does nothing if tag is not found.
func (d *Dashboard) RemoveTags(tags ...string) {
	tagIndex := make(map[string]int, len(d.tags))
	for i, tag := range d.tags {
		tagIndex[tag] = i
	}

	for _, tag := range tags {
		if i, ok := tagIndex[tag]; ok {
			d.tags = append(d.tags[:i], d.tags[i+1:]...)
		}
	}
}

type Row struct {
	Collapse bool     `json:"collapse"`
	Editable bool     `json:"editable"`
	Height   string   `json:"height"`
	Title    string   `json:"title"`
	Panels   []*Panel `json:"panels"`
}

type Panel struct {
}
<commit_msg>Make SetTags respectful to order<commit_after>package grafana

import "time"

type DashboardID uint64

type Dashboard struct {
	ID           DashboardID `json:"id"`
	Editable     bool        `json:"editable"`
	GraphTooltip uint8       `json:"graphTooltip"`
	HideControls bool        `json:"hideControls"`
	Rows         []*Row      `json:"rows"`
	Slug         string      `json:"slug"`
	Style        string      `json:"style"`
	Timezone     string      `json:"timezone"`
	Title        string      `json:"title"`
	tags         []string
	Meta         *DashboardMeta
}

type DashboardMeta struct {
	Slug    string `json:"slug"`
	Type    string `json:"type"`
	Version int    `json:"version"`

	CanEdit bool `json:"canEdit"`
	CanSave bool `json:"canSave"`
	CanStar bool `json:"canStar"`

	Created   time.Time `json:"created"`
	CreatedBy string    `json:"createdBy"`
	Expires   time.Time `json:"expires"`
	Updated   time.Time `json:"updated"`
	UpdatedBy string    `json:"updatedBy"`
}

// Tags is a getter for Dashboard tags field
func (d *Dashboard) Tags() []string {
	return d.tags
}

// SetTags sets new tags to dashboard
func (d *Dashboard) SetTags(tags ...string) {
	newTags := []string{}
	uniqTags := make(map[string]bool)
	for _, tag := range tags {
		if _, ok := uniqTags[tag]; ok {
			continue
		}

		uniqTags[tag] = true
		newTags = append(newTags, tag)
	}

	d.tags = newTags
}

// AddTags adds given tags to dashboard. This method keeps uniqueness of tags.
func (d *Dashboard) AddTags(tags ...string) {
	tagFound := make(map[string]bool, len(d.tags))
	for _, tag := range d.tags {
		tagFound[tag] = true
	}

	for _, tag := range tags {
		if _, ok := tagFound[tag]; ok {
			continue
		}
		d.tags = append(d.tags, tag)
	}
}

// RemoveTags removes given tags from dashboard. Does nothing if tag is not found.
func (d *Dashboard) RemoveTags(tags ...string) {
	tagIndex := make(map[string]int, len(d.tags))
	for i, tag := range d.tags {
		tagIndex[tag] = i
	}

	for _, tag := range tags {
		if i, ok := tagIndex[tag]; ok {
			d.tags = append(d.tags[:i], d.tags[i+1:]...)
		}
	}
}

type Row struct {
	Collapse bool     `json:"collapse"`
	Editable bool     `json:"editable"`
	Height   string   `json:"height"`
	Title    string   `json:"title"`
	Panels   []*Panel `json:"panels"`
}

type Panel struct {
}
<|endoftext|>


<commit_before>package influxdb

import (
	"context"
	"net/url"
	"sort"
	"time"
)

// ErrDashboardNotFound is the error msg for a missing dashboard.
const ErrDashboardNotFound = "dashboard not found"

// ErrCellNotFound is the error msg for a missing cell.
const ErrCellNotFound = "cell not found"

// ops for dashboard service.
const (
	OpFindDashboardByID       = "FindDashboardByID"
	OpFindDashboards          = "FindDashboards"
	OpCreateDashboard         = "CreateDashboard"
	OpUpdateDashboard         = "UpdateDashboard"
	OpAddDashboardCell        = "AddDashboardCell"
	OpRemoveDashboardCell     = "RemoveDashboardCell"
	OpUpdateDashboardCell     = "UpdateDashboardCell"
	OpGetDashboardCellView    = "GetDashboardCellView"
	OpUpdateDashboardCellView = "UpdateDashboardCellView"
	OpDeleteDashboard         = "DeleteDashboard"
	OpReplaceDashboardCells   = "ReplaceDashboardCells"
)

// DashboardService represents a service for managing dashboard data.
type DashboardService interface {
	// FindDashboardByID returns a single dashboard by ID.
	FindDashboardByID(ctx context.Context, id ID) (*Dashboard, error)

	// FindDashboards returns a list of dashboards that match filter and the total count of matching dashboards.
	// Additional options provide pagination & sorting.
	FindDashboards(ctx context.Context, filter DashboardFilter, opts FindOptions) ([]*Dashboard, int, error)

	// CreateDashboard creates a new dashboard and sets b.ID with the new identifier.
	CreateDashboard(ctx context.Context, b *Dashboard) error

	// UpdateDashboard updates a single dashboard with changeset.
	// Returns the new dashboard state after update.
	UpdateDashboard(ctx context.Context, id ID, upd DashboardUpdate) (*Dashboard, error)

	// AddDashboardCell adds a cell to a dashboard.
	AddDashboardCell(ctx context.Context, id ID, c *Cell, opts AddDashboardCellOptions) error

	// RemoveDashboardCell removes a dashbaord.
	RemoveDashboardCell(ctx context.Context, dashboardID, cellID ID) error

	// UpdateDashboardCell replaces the dashboard cell with the provided ID.
	UpdateDashboardCell(ctx context.Context, dashboardID, cellID ID, upd CellUpdate) (*Cell, error)

	// GetDashboardCellView retrieves a dashboard cells view.
	GetDashboardCellView(ctx context.Context, dashboardID, cellID ID) (*View, error)

	// UpdateDashboardCellView retrieves a dashboard cells view.
	UpdateDashboardCellView(ctx context.Context, dashboardID, cellID ID, upd ViewUpdate) (*View, error)

	// DeleteDashboard removes a dashboard by ID.
	DeleteDashboard(ctx context.Context, id ID) error

	// ReplaceDashboardCells replaces all cells in a dashboard
	ReplaceDashboardCells(ctx context.Context, id ID, c []*Cell) error
}

// Dashboard represents all visual and query data for a dashboard.
type Dashboard struct {
	ID             ID            `json:"id,omitempty"`
	OrganizationID ID            `json:"orgID,omitempty"`
	Name           string        `json:"name"`
	Description    string        `json:"description"`
	Cells          []*Cell       `json:"cells"`
	Meta           DashboardMeta `json:"meta"`
}

// DashboardMeta contains meta information about dashboards
type DashboardMeta struct {
	CreatedAt time.Time `json:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt"`
}

// DefaultDashboardFindOptions are the default find options for dashboards
var DefaultDashboardFindOptions = FindOptions{
	SortBy: "ID",
}

// SortDashboards sorts a slice of dashboards by a field.
func SortDashboards(by string, ds []*Dashboard) {
	var sorter func(i, j int) bool
	switch by {
	case "CreatedAt":
		sorter = func(i, j int) bool {
			return ds[j].Meta.CreatedAt.After(ds[i].Meta.CreatedAt)
		}
	case "UpdatedAt":
		sorter = func(i, j int) bool {
			return ds[j].Meta.UpdatedAt.After(ds[i].Meta.UpdatedAt)
		}
	case "Name":
		sorter = func(i, j int) bool {
			return ds[i].Name < ds[j].Name
		}
	default:
		sorter = func(i, j int) bool {
			return ds[i].ID < ds[j].ID
		}
	}

	sort.Slice(ds, sorter)
}

// Cell holds positional information about a cell on dashboard and a reference to a cell.
type Cell struct {
	ID ID    `json:"id,omitempty"`
	X  int32 `json:"x"`
	Y  int32 `json:"y"`
	W  int32 `json:"w"`
	H  int32 `json:"h"`
}

// DashboardFilter is a filter for dashboards.
type DashboardFilter struct {
	IDs            []*ID
	OrganizationID *ID
	Organization   *string
}

// QueryParams turns a dashboard filter into query params
func (f DashboardFilter) QueryParams() url.Values {
	qp := url.Values{}
	for _, id := range f.IDs {
		if id != nil {
			qp.Add("id", id.String())
		}
	}

	if f.OrganizationID != nil {
		qp.Add("orgID", f.OrganizationID.String())
	}

	return qp
}

// DashboardUpdate is the patch structure for a dashboard.
type DashboardUpdate struct {
	Name        *string `json:"name"`
	Description *string `json:"description"`
}

// Apply applies an update to a dashboard.
func (u DashboardUpdate) Apply(d *Dashboard) error {
	if u.Name != nil {
		d.Name = *u.Name
	}

	if u.Description != nil {
		d.Description = *u.Description
	}

	return nil
}

// Valid returns an error if the dashboard update is invalid.
func (u DashboardUpdate) Valid() *Error {
	if u.Name == nil && u.Description == nil {
		return &Error{
			Code: EInvalid,
			Msg:  "must update at least one attribute",
		}
	}

	return nil
}

// AddDashboardCellOptions are options for adding a dashboard.
type AddDashboardCellOptions struct {
	View *View
}

// CellUpdate is the patch structure for a cell.
type CellUpdate struct {
	X *int32 `json:"x"`
	Y *int32 `json:"y"`
	W *int32 `json:"w"`
	H *int32 `json:"h"`
}

// Apply applies an update to a Cell.
func (u CellUpdate) Apply(c *Cell) error {
	if u.X != nil {
		c.X = *u.X
	}

	if u.Y != nil {
		c.Y = *u.Y
	}

	if u.W != nil {
		c.W = *u.W
	}

	if u.H != nil {
		c.H = *u.H
	}

	return nil
}

// Valid returns an error if the cell update is invalid.
func (u CellUpdate) Valid() *Error {
	if u.H == nil && u.W == nil && u.Y == nil && u.X == nil {
		return &Error{
			Code: EInvalid,
			Msg:  "must update at least one attribute",
		}
	}

	return nil
}
<commit_msg>fix(platform): dashboard filter must implement paging filter<commit_after>package influxdb

import (
	"context"
	"net/url"
	"sort"
	"time"
)

// ErrDashboardNotFound is the error msg for a missing dashboard.
const ErrDashboardNotFound = "dashboard not found"

// ErrCellNotFound is the error msg for a missing cell.
const ErrCellNotFound = "cell not found"

// ops for dashboard service.
const (
	OpFindDashboardByID       = "FindDashboardByID"
	OpFindDashboards          = "FindDashboards"
	OpCreateDashboard         = "CreateDashboard"
	OpUpdateDashboard         = "UpdateDashboard"
	OpAddDashboardCell        = "AddDashboardCell"
	OpRemoveDashboardCell     = "RemoveDashboardCell"
	OpUpdateDashboardCell     = "UpdateDashboardCell"
	OpGetDashboardCellView    = "GetDashboardCellView"
	OpUpdateDashboardCellView = "UpdateDashboardCellView"
	OpDeleteDashboard         = "DeleteDashboard"
	OpReplaceDashboardCells   = "ReplaceDashboardCells"
)

// DashboardService represents a service for managing dashboard data.
type DashboardService interface {
	// FindDashboardByID returns a single dashboard by ID.
	FindDashboardByID(ctx context.Context, id ID) (*Dashboard, error)

	// FindDashboards returns a list of dashboards that match filter and the total count of matching dashboards.
	// Additional options provide pagination & sorting.
	FindDashboards(ctx context.Context, filter DashboardFilter, opts FindOptions) ([]*Dashboard, int, error)

	// CreateDashboard creates a new dashboard and sets b.ID with the new identifier.
	CreateDashboard(ctx context.Context, b *Dashboard) error

	// UpdateDashboard updates a single dashboard with changeset.
	// Returns the new dashboard state after update.
	UpdateDashboard(ctx context.Context, id ID, upd DashboardUpdate) (*Dashboard, error)

	// AddDashboardCell adds a cell to a dashboard.
	AddDashboardCell(ctx context.Context, id ID, c *Cell, opts AddDashboardCellOptions) error

	// RemoveDashboardCell removes a dashbaord.
	RemoveDashboardCell(ctx context.Context, dashboardID, cellID ID) error

	// UpdateDashboardCell replaces the dashboard cell with the provided ID.
	UpdateDashboardCell(ctx context.Context, dashboardID, cellID ID, upd CellUpdate) (*Cell, error)

	// GetDashboardCellView retrieves a dashboard cells view.
	GetDashboardCellView(ctx context.Context, dashboardID, cellID ID) (*View, error)

	// UpdateDashboardCellView retrieves a dashboard cells view.
	UpdateDashboardCellView(ctx context.Context, dashboardID, cellID ID, upd ViewUpdate) (*View, error)

	// DeleteDashboard removes a dashboard by ID.
	DeleteDashboard(ctx context.Context, id ID) error

	// ReplaceDashboardCells replaces all cells in a dashboard
	ReplaceDashboardCells(ctx context.Context, id ID, c []*Cell) error
}

// Dashboard represents all visual and query data for a dashboard.
type Dashboard struct {
	ID             ID            `json:"id,omitempty"`
	OrganizationID ID            `json:"orgID,omitempty"`
	Name           string        `json:"name"`
	Description    string        `json:"description"`
	Cells          []*Cell       `json:"cells"`
	Meta           DashboardMeta `json:"meta"`
}

// DashboardMeta contains meta information about dashboards
type DashboardMeta struct {
	CreatedAt time.Time `json:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt"`
}

// DefaultDashboardFindOptions are the default find options for dashboards
var DefaultDashboardFindOptions = FindOptions{
	SortBy: "ID",
}

// SortDashboards sorts a slice of dashboards by a field.
func SortDashboards(opts FindOptions, ds []*Dashboard) {
	var sorter func(i, j int) bool
	switch opts.SortBy {
	case "CreatedAt":
		sorter = func(i, j int) bool {
			return ds[j].Meta.CreatedAt.After(ds[i].Meta.CreatedAt)
		}
	case "UpdatedAt":
		sorter = func(i, j int) bool {
			return ds[j].Meta.UpdatedAt.After(ds[i].Meta.UpdatedAt)
		}
	case "Name":
		sorter = func(i, j int) bool {
			return ds[i].Name < ds[j].Name
		}
	default:
		sorter = func(i, j int) bool {
			if opts.Descending {
				return ds[i].ID > ds[j].ID
			}
			return ds[i].ID < ds[j].ID
		}
	}

	sort.Slice(ds, sorter)
}

// Cell holds positional information about a cell on dashboard and a reference to a cell.
type Cell struct {
	ID ID    `json:"id,omitempty"`
	X  int32 `json:"x"`
	Y  int32 `json:"y"`
	W  int32 `json:"w"`
	H  int32 `json:"h"`
}

// DashboardFilter is a filter for dashboards.
type DashboardFilter struct {
	IDs            []*ID
	OrganizationID *ID
	Organization   *string
}

// QueryParams turns a dashboard filter into query params
//
// It implements PagingFilter.
func (f DashboardFilter) QueryParams() map[string][]string {
	qp := url.Values{}
	for _, id := range f.IDs {
		if id != nil {
			qp.Add("id", id.String())
		}
	}

	if f.OrganizationID != nil {
		qp.Add("orgID", f.OrganizationID.String())
	}

	if f.Organization != nil {
		qp.Add("org", *f.Organization)
	}

	return qp
}

// DashboardUpdate is the patch structure for a dashboard.
type DashboardUpdate struct {
	Name        *string `json:"name"`
	Description *string `json:"description"`
}

// Apply applies an update to a dashboard.
func (u DashboardUpdate) Apply(d *Dashboard) error {
	if u.Name != nil {
		d.Name = *u.Name
	}

	if u.Description != nil {
		d.Description = *u.Description
	}

	return nil
}

// Valid returns an error if the dashboard update is invalid.
func (u DashboardUpdate) Valid() *Error {
	if u.Name == nil && u.Description == nil {
		return &Error{
			Code: EInvalid,
			Msg:  "must update at least one attribute",
		}
	}

	return nil
}

// AddDashboardCellOptions are options for adding a dashboard.
type AddDashboardCellOptions struct {
	View *View
}

// CellUpdate is the patch structure for a cell.
type CellUpdate struct {
	X *int32 `json:"x"`
	Y *int32 `json:"y"`
	W *int32 `json:"w"`
	H *int32 `json:"h"`
}

// Apply applies an update to a Cell.
func (u CellUpdate) Apply(c *Cell) error {
	if u.X != nil {
		c.X = *u.X
	}

	if u.Y != nil {
		c.Y = *u.Y
	}

	if u.W != nil {
		c.W = *u.W
	}

	if u.H != nil {
		c.H = *u.H
	}

	return nil
}

// Valid returns an error if the cell update is invalid.
func (u CellUpdate) Valid() *Error {
	if u.H == nil && u.W == nil && u.Y == nil && u.X == nil {
		return &Error{
			Code: EInvalid,
			Msg:  "must update at least one attribute",
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package data

import (
	"math"
)

type Data struct {
	Tag              string
	Attributes       []float64
	Distances        []float64
	Classification   int
	ClosestCentroids []*Data
}

func New(attr []float64, numClass int, tag string) *Data {
	return &Data{
		Tag:              tag,
		Attributes:       attr,
		Distances:        make([]float64, numClass),
		Classification:   0,
		ClosestCentroids: make([]*Data, 0),
	}
}

func (data *Data) updateDistances(centroids []*Data) {
	for i, centroid := range centroids {
		sumOfSquares := 0.0
		for j := range centroid.Attributes {
			sumOfSquares += math.Pow(data.Attributes[j]-centroid.Attributes[j], 2)
		}
		distance := math.Sqrt(sumOfSquares)
		data.Distances[i] = distance
	}
}

func (data *Data) UpdateClassification(centroids []*Data) {
	data.updateDistances(centroids)

	closestCentroids := make([]int, 0)
	for centroidId, distance := range data.Distances {
		if len(closestCentroids) == 0 {
			closestCentroids = append(closestCentroids, centroidId)
		} else {
			for i, compareId := range closestCentroids {
				// Kolla distansen för varje som hittas
				currentDistance := data.Distances[compareId]
				if distance < currentDistance {
					// Insert BEGIN
					closestCentroids = append(closestCentroids, 0)
					copy(closestCentroids[i+1:], closestCentroids[i:])
					closestCentroids[i] = centroidId
					// Insert END
					break
				}
			}
		}
	}
	for _, closeCentroidId := range closestCentroids {
		data.ClosestCentroids = append(data.ClosestCentroids, centroids[closeCentroidId])
	}
	/*
		for i, distance := range data.Distances {
			if distance < minDistance {
				minDistance = distance
				data.Classification = i
				data.Tag = centroids[i].Tag
			}
		}
	*/
}

func (data *Data) Waverage(item *Data, weigth float64) {
	for i := range data.Attributes {
		data.Attributes[i] = data.Attributes[i]*(1.0-weigth) + item.Attributes[i]*weigth
	}
}
<commit_msg>Removed old comments<commit_after>package data

import (
	"math"
)

type Data struct {
	Tag              string
	Attributes       []float64
	Distances        []float64
	Classification   int
	ClosestCentroids []*Data
}

func New(attr []float64, numClass int, tag string) *Data {
	return &Data{
		Tag:              tag,
		Attributes:       attr,
		Distances:        make([]float64, numClass),
		Classification:   0,
		ClosestCentroids: make([]*Data, 0),
	}
}

func (data *Data) updateDistances(centroids []*Data) {
	for i, centroid := range centroids {
		sumOfSquares := 0.0
		for j := range centroid.Attributes {
			sumOfSquares += math.Pow(data.Attributes[j]-centroid.Attributes[j], 2)
		}
		distance := math.Sqrt(sumOfSquares)
		data.Distances[i] = distance
	}
}

func (data *Data) UpdateClassification(centroids []*Data) {
	data.updateDistances(centroids)

	closestCentroids := make([]int, 0)
	for centroidId, distance := range data.Distances {
		if len(closestCentroids) == 0 {
			closestCentroids = append(closestCentroids, centroidId)
		} else {
			for i, compareId := range closestCentroids {
				currentDistance := data.Distances[compareId]
				if distance < currentDistance {

					// The following three lines is a slice insert
					closestCentroids = append(closestCentroids, 0)
					copy(closestCentroids[i+1:], closestCentroids[i:])
					closestCentroids[i] = centroidId

					break
				}
			}
		}
	}
	for _, closeCentroidId := range closestCentroids {
		data.ClosestCentroids = append(data.ClosestCentroids, centroids[closeCentroidId])
	}
}

func (data *Data) Waverage(item *Data, weigth float64) {
	for i := range data.Attributes {
		data.Attributes[i] = data.Attributes[i]*(1.0-weigth) + item.Attributes[i]*weigth
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 the u-root 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

/*
dd is modeled after dd. Each step in the chain is a goroutine that
reads a block and writes a block.
There are two always-the goroutines, in and out. They're actually
the same thing save they have, maybe, different block sizes.
*/
import (
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
)

type passer func(r io.Reader, w io.Writer, ibs, obs int)

var (
	ibs     = flag.Int("ibs", 1, "Default input block size")
	obs     = flag.Int("obs", 1, "Default output block size")
	skip = flag.Int("skip", 0, "skip n bytes before reading")
	seek = flag.Int("seek", 0, "seek output when writing")
	count = flag.Int("count", max.MaxUInt, "Max output of data to copy")
	inName  = flag.String("if", "", "Input file")
	outName = flag.String("of", "", "Output file")
)

func pass(r io.Reader, w io.WriteCloser, ibs, obs int) {
	b := make([]byte, ibs)
	defer w.Close()
	for {
		bs := 0
		for bs < ibs {
			n, err := r.Read(b[bs:])
			if err != nil && err != io.EOF {
				return
			}
			if n == 0 {
				break
			}
			bs += n
		}
		if bs == 0 {
			return
		}
		tot := 0
		for tot < bs {
			nn, err := w.Write(b[tot : tot+obs])
			if err != nil {
				fmt.Fprintf(os.Stderr, "pass: %v\n", err)
				return
			}
			if nn == 0 {
				return
			}
			tot += nn
		}
	}
}

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "%v", err)
	os.Exit(1)
}

// rather than, in essence, recreating all the apparatus of flag.xxxx with the if= bits,
// including dup checking, conversion, etc. we just convert the arguments and then
// run flag.Parse. Gross, but hey, it works.
func main() {
<<<<<<< HEAD
	var err error
	flag.Parse()
	for _, v := range flag.Args() {
		l := strings.SplitN(v, "=", 2)
		switch l[0] {
		case "if":
			inFile, err = os.Open(l[1])
		case "of":
			outFile, err = os.OpenFile(l[1], os.O_CREATE|os.O_WRONLY, 0600)
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	}
=======
	inFile := os.Stdin
	outFile := os.Stdout
	var err error
	// EVERYTHING in dd follows x=y. So blindly split and convert and sleep well.
	arg := []string{}
	for _, v := range os.Args {
		l := strings.SplitN(v, "=", 2)
		l[0] = "-" + l[0]
		arg = append(arg, l...)
	}
	os.Args = arg
	flag.Parse()
	if *inName != "" {
		inFile, err = os.Open(*inName)
		if err != nil {
			fatal(err)
		}
	}
	if *outName != "" {
		outFile, err = os.OpenFile(*outName, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			fatal(err)
		}
	}

>>>>>>> Take dd a bit further: if= and of=
	r, w := io.Pipe()
	go pass(inFile, w, *ibs, *ibs)
	pass(r, outFile, *obs, *obs)
}
<commit_msg>Fix some merge issues.<commit_after>// Copyright 2013 the u-root 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

/*
dd is modeled after dd. Each step in the chain is a goroutine that
reads a block and writes a block.
There are two always-the goroutines, in and out. They're actually
the same thing save they have, maybe, different block sizes.
*/
import (
	"flag"
	"fmt"
	"io"
	"math"
	"os"
	"strings"
)

type passer func(r io.Reader, w io.Writer, ibs, obs int)

var (
	ibs     = flag.Int("ibs", 1, "Default input block size")
	obs     = flag.Int("obs", 1, "Default output block size")
	skip = flag.Int("skip", 0, "skip n bytes before reading")
	seek = flag.Int("seek", 0, "seek output when writing")
	count = flag.Int64("count", math.MaxInt64, "Max output of data to copy")
	inName  = flag.String("if", "", "Input file")
	outName = flag.String("of", "", "Output file")
)

func pass(r io.Reader, w io.WriteCloser, ibs, obs int) {
	b := make([]byte, ibs)
	defer w.Close()
	for {
		bs := 0
		for bs < ibs {
			n, err := r.Read(b[bs:])
			if err != nil && err != io.EOF {
				return
			}
			if n == 0 {
				break
			}
			bs += n
		}
		if bs == 0 {
			return
		}
		tot := 0
		for tot < bs {
			nn, err := w.Write(b[tot : tot+obs])
			if err != nil {
				fmt.Fprintf(os.Stderr, "pass: %v\n", err)
				return
			}
			if nn == 0 {
				return
			}
			tot += nn
		}
	}
}

func fatal(err error) {
	fmt.Fprintf(os.Stderr, "%v", err)
	os.Exit(1)
}

// rather than, in essence, recreating all the apparatus of flag.xxxx with the if= bits,
// including dup checking, conversion, etc. we just convert the arguments and then
// run flag.Parse. Gross, but hey, it works.
func main() {
	inFile := os.Stdin
	outFile := os.Stdout
	var err error
	// EVERYTHING in dd follows x=y. So blindly split and convert and sleep well.
	arg := []string{}
	for _, v := range os.Args {
		l := strings.SplitN(v, "=", 2)
		l[0] = "-" + l[0]
		arg = append(arg, l...)
	}
	os.Args = arg
	flag.Parse()
	if *inName != "" {
		inFile, err = os.Open(*inName)
		if err != nil {
			fatal(err)
		}
	}
	if *outName != "" {
		outFile, err = os.OpenFile(*outName, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			fatal(err)
		}
	}

	r, w := io.Pipe()
	go pass(inFile, w, *ibs, *ibs)
	pass(r, outFile, *obs, *obs)
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014-2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
)

var (
	listen = flag.String("l", ":8080", "Host and port to listen to")
)

type httpHandler struct {
	Clubs []CommunityClub
}

func (h httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		h.handleGet(w, r)
	case "POST":
		h.handlePost(w, r)
	default:
		http.Error(w, "unsupported action", http.StatusBadRequest)
	}
}

func (h *httpHandler) handleGet(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "GET")
}

func (h *httpHandler) handlePost(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "POST")
}

func main() {
	flag.Parse()
	handler := httpHandler{
		Clubs: getCommunityClubs(),
	}
	log.Printf("listen = %s", *listen)
	http.Handle("/", handler)
	log.Println("Up and running!")
	log.Fatal(http.ListenAndServe(*listen, nil))
}
<commit_msg>Open endpoint<commit_after>/* Copyright (c) 2014-2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"
)

var (
	listen = flag.String("l", ":8080", "Host and port to listen to")
)

type httpHandler struct {
	Clubs []CommunityClub
}

func (h httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		h.handleGet(w, r)
	case "POST":
		h.handlePost(w, r)
	default:
		http.Error(w, "unsupported action", http.StatusBadRequest)
	}
}

func (h *httpHandler) handleGet(w http.ResponseWriter, r *http.Request) {
	switch strings.ToLower(r.URL.Path) {
	case "/clubs":
		e := json.NewEncoder(w)
		e.Encode(&h.Clubs)
	default:
		http.Error(w, "unknown endpoint", http.StatusBadRequest)
	}
}

func (h *httpHandler) handlePost(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "POST")
}

func main() {
	flag.Parse()
	handler := httpHandler{
		Clubs: getCommunityClubs(),
	}
	log.Printf("listen = %s", *listen)
	http.Handle("/", handler)
	log.Println("Up and running!")
	log.Fatal(http.ListenAndServe(*listen, nil))
}
<|endoftext|>


<commit_before>// +build darwin
// This file is compiled only on mac. It contains paths used by the mac
// browser bundle.
// http://golang.org/pkg/go/build/#hdr-Build_Constraints

package main

const (
	// The TorBrowser.app.meek-http-helper directory is a special case for
	// the mac bundle. It is a copy of TorBrowser.app that has a modified
	// Info.plist file so that it doesn't show a dock icon.
	firefoxPath        = "../Data/TorBrowser.app.meek-http-helper/Contents/MacOS/firefox"
	firefoxProfilePath = "../Data/Browser/profile.meek-http-helper"
)
<commit_msg>Put the headless TorBrowser.app under PluggableTransports.<commit_after>// +build darwin
// This file is compiled only on mac. It contains paths used by the mac
// browser bundle.
// http://golang.org/pkg/go/build/#hdr-Build_Constraints

package main

const (
	// The TorBrowser.app.meek-http-helper directory is a special case for
	// the mac bundle. It is a copy of TorBrowser.app that has a modified
	// Info.plist file so that it doesn't show a dock icon.
	firefoxPath        = "PluggableTransports/TorBrowser.app.meek-http-helper/Contents/MacOS/firefox"
	firefoxProfilePath = "../Data/Browser/profile.meek-http-helper"
)
<|endoftext|>


<commit_before>package server

import (
	"errors"
	"fmt"

	"github.com/google/go-attestation/attest"
	tpmpb "github.com/google/go-tpm-tools/proto"
	"github.com/google/go-tpm/tpm2"
)

// ParseAndVerifyEventLog parses a raw event log and replays the parsed event
// log against the given PCR values. It returns the events verified
// particular PCR indexes/digests and an error if the replay for any PCR
// index does not match the provided value.
//
// It is the caller's responsibility to call server.Verify with those PCRs,
// a trusted public key, and a quote using the private part of the trusted key
// to ensure that the PCRs are generated by a known TPM.
func ParseAndVerifyEventLog(rawEventLog []byte, pcrs *tpmpb.Pcrs) ([]attest.Event, error) {
	attestPcrs, err := convertToAttestPcrs(pcrs)
	if err != nil {
		return nil, fmt.Errorf("received bad PCR proto: %v", err)
	}
	eventLog, err := attest.ParseEventLog(rawEventLog)
	if err != nil {
		return nil, fmt.Errorf("failed to parse event log: %v", err)
	}
	return eventLog.Verify(attestPcrs)
}

func convertToAttestPcrs(pcrProto *tpmpb.Pcrs) ([]attest.PCR, error) {
	if len(pcrProto.GetPcrs()) == 0 {
		return nil, errors.New("no PCRs to convert")
	}
	hash := tpm2.Algorithm(pcrProto.GetHash())
	cryptoHash, err := hash.Hash()
	if err != nil {
		return nil, err
	}

	attestPcrs := make([]attest.PCR, len(pcrProto.GetPcrs()))
	for index, digest := range pcrProto.GetPcrs() {
		attestPcrs = append(attestPcrs, attest.PCR{
			Index:     int(index),
			Digest:    digest,
			DigestAlg: cryptoHash,
		})
	}
	return attestPcrs, nil
}
<commit_msg>server/eventlog: Correctly use make<commit_after>package server

import (
	"errors"
	"fmt"

	"github.com/google/go-attestation/attest"
	tpmpb "github.com/google/go-tpm-tools/proto"
	"github.com/google/go-tpm/tpm2"
)

// ParseAndVerifyEventLog parses a raw event log and replays the parsed event
// log against the given PCR values. It returns the events verified
// particular PCR indexes/digests and an error if the replay for any PCR
// index does not match the provided value.
//
// It is the caller's responsibility to call server.Verify with those PCRs,
// a trusted public key, and a quote using the private part of the trusted key
// to ensure that the PCRs are generated by a known TPM.
func ParseAndVerifyEventLog(rawEventLog []byte, pcrs *tpmpb.Pcrs) ([]attest.Event, error) {
	attestPcrs, err := convertToAttestPcrs(pcrs)
	if err != nil {
		return nil, fmt.Errorf("received bad PCR proto: %v", err)
	}
	eventLog, err := attest.ParseEventLog(rawEventLog)
	if err != nil {
		return nil, fmt.Errorf("failed to parse event log: %v", err)
	}
	return eventLog.Verify(attestPcrs)
}

func convertToAttestPcrs(pcrProto *tpmpb.Pcrs) ([]attest.PCR, error) {
	if len(pcrProto.GetPcrs()) == 0 {
		return nil, errors.New("no PCRs to convert")
	}
	hash := tpm2.Algorithm(pcrProto.GetHash())
	cryptoHash, err := hash.Hash()
	if err != nil {
		return nil, err
	}

	attestPcrs := make([]attest.PCR, 0, len(pcrProto.GetPcrs()))
	for index, digest := range pcrProto.GetPcrs() {
		attestPcrs = append(attestPcrs, attest.PCR{
			Index:     int(index),
			Digest:    digest,
			DigestAlg: cryptoHash,
		})
	}
	return attestPcrs, nil
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/dag"
)

// RootModuleName is the name given to the root module implicitly.
const RootModuleName = "root"

// RootModulePath is the path for the root module.
var RootModulePath = []string{RootModuleName}

// Graph represents the graph that Terraform uses to represent resources
// and their dependencies. Each graph represents only one module, but it
// can contain further modules, which themselves have their own graph.
type Graph struct {
	// Graph is the actual DAG. This is embedded so you can call the DAG
	// methods directly.
	dag.AcyclicGraph

	// Path is the path in the module tree that this Graph represents.
	// The root is represented by a single element list containing
	// RootModuleName
	Path []string

	// annotations are the annotations that are added to vertices. Annotations
	// are arbitrary metadata taht is used for various logic. Annotations
	// should have unique keys that are referenced via constants.
	annotations map[dag.Vertex]map[string]interface{}

	// dependableMap is a lookaside table for fast lookups for connecting
	// dependencies by their GraphNodeDependable value to avoid O(n^3)-like
	// situations and turn them into O(1) with respect to the number of new
	// edges.
	dependableMap map[string]dag.Vertex

	once sync.Once
}

// Annotations returns the annotations that are configured for the
// given vertex. The map is guaranteed to be non-nil but may be empty.
//
// The returned map may be modified to modify the annotations of the
// vertex.
func (g *Graph) Annotations(v dag.Vertex) map[string]interface{} {
	g.once.Do(g.init)

	// If this vertex isn't in the graph, then just return an empty map
	if !g.HasVertex(v) {
		return map[string]interface{}{}
	}

	// Get the map, if it doesn't exist yet then initialize it
	m, ok := g.annotations[v]
	if !ok {
		m = make(map[string]interface{})
		g.annotations[v] = m
	}

	return m
}

// Add is the same as dag.Graph.Add.
func (g *Graph) Add(v dag.Vertex) dag.Vertex {
	g.once.Do(g.init)

	// Call upwards to add it to the actual graph
	g.Graph.Add(v)

	// If this is a depend-able node, then store the lookaside info
	if dv, ok := v.(GraphNodeDependable); ok {
		for _, n := range dv.DependableName() {
			g.dependableMap[n] = v
		}
	}

	// If this initializes annotations, then do that
	if av, ok := v.(GraphNodeAnnotationInit); ok {
		as := g.Annotations(v)
		for k, v := range av.AnnotationInit() {
			as[k] = v
		}
	}

	return v
}

// Remove is the same as dag.Graph.Remove
func (g *Graph) Remove(v dag.Vertex) dag.Vertex {
	g.once.Do(g.init)

	// If this is a depend-able node, then remove the lookaside info
	if dv, ok := v.(GraphNodeDependable); ok {
		for _, n := range dv.DependableName() {
			delete(g.dependableMap, n)
		}
	}

	// Remove the annotations
	delete(g.annotations, v)

	// Call upwards to remove it from the actual graph
	return g.Graph.Remove(v)
}

// Replace is the same as dag.Graph.Replace
func (g *Graph) Replace(o, n dag.Vertex) bool {
	g.once.Do(g.init)

	// Go through and update our lookaside to point to the new vertex
	for k, v := range g.dependableMap {
		if v == o {
			if _, ok := n.(GraphNodeDependable); ok {
				g.dependableMap[k] = n
			} else {
				delete(g.dependableMap, k)
			}
		}
	}

	// Move the annotation if it exists
	if m, ok := g.annotations[o]; ok {
		g.annotations[n] = m
		delete(g.annotations, o)
	}

	return g.Graph.Replace(o, n)
}

// ConnectDependent connects a GraphNodeDependent to all of its
// GraphNodeDependables. It returns the list of dependents it was
// unable to connect to.
func (g *Graph) ConnectDependent(raw dag.Vertex) []string {
	v, ok := raw.(GraphNodeDependent)
	if !ok {
		return nil
	}

	return g.ConnectTo(v, v.DependentOn())
}

// ConnectDependents goes through the graph, connecting all the
// GraphNodeDependents to GraphNodeDependables. This is safe to call
// multiple times.
//
// To get details on whether dependencies could be found/made, the more
// specific ConnectDependent should be used.
func (g *Graph) ConnectDependents() {
	for _, v := range g.Vertices() {
		if dv, ok := v.(GraphNodeDependent); ok {
			g.ConnectDependent(dv)
		}
	}
}

// ConnectFrom creates an edge by finding the source from a DependableName
// and connecting it to the specific vertex.
func (g *Graph) ConnectFrom(source string, target dag.Vertex) {
	g.once.Do(g.init)

	if source := g.dependableMap[source]; source != nil {
		g.Connect(dag.BasicEdge(source, target))
	}
}

// ConnectTo connects a vertex to a raw string of targets that are the
// result of DependableName, and returns the list of targets that are missing.
func (g *Graph) ConnectTo(v dag.Vertex, targets []string) []string {
	g.once.Do(g.init)

	var missing []string
	for _, t := range targets {
		if dest := g.dependableMap[t]; dest != nil {
			g.Connect(dag.BasicEdge(v, dest))
		} else {
			missing = append(missing, t)
		}
	}

	return missing
}

// Dependable finds the vertices in the graph that have the given dependable
// names and returns them.
func (g *Graph) Dependable(n string) dag.Vertex {
	// TODO: do we need this?
	return nil
}

// Walk walks the graph with the given walker for callbacks. The graph
// will be walked with full parallelism, so the walker should expect
// to be called in concurrently.
func (g *Graph) Walk(walker GraphWalker) error {
	return g.walk(walker)
}

func (g *Graph) init() {
	if g.annotations == nil {
		g.annotations = make(map[dag.Vertex]map[string]interface{})
	}

	if g.dependableMap == nil {
		g.dependableMap = make(map[string]dag.Vertex)
	}
}

func (g *Graph) walk(walker GraphWalker) error {
	// The callbacks for enter/exiting a graph
	ctx := walker.EnterPath(g.Path)
	defer walker.ExitPath(g.Path)

	// Get the path for logs
	path := strings.Join(ctx.Path(), ".")

	// Walk the graph.
	var walkFn dag.WalkFunc
	walkFn = func(v dag.Vertex) (rerr error) {
		log.Printf("[DEBUG] vertex %s.%s: walking", path, dag.VertexName(v))

		walker.EnterVertex(v)
		defer func() { walker.ExitVertex(v, rerr) }()

		// vertexCtx is the context that we use when evaluating. This
		// is normally the context of our graph but can be overridden
		// with a GraphNodeSubPath impl.
		vertexCtx := ctx
		if pn, ok := v.(GraphNodeSubPath); ok && len(pn.Path()) > 0 {
			vertexCtx = walker.EnterPath(normalizeModulePath(pn.Path()))
			defer walker.ExitPath(pn.Path())
		}

		// If the node is eval-able, then evaluate it.
		if ev, ok := v.(GraphNodeEvalable); ok {
			tree := ev.EvalTree()
			if tree == nil {
				panic(fmt.Sprintf(
					"%s.%s (%T): nil eval tree", path, dag.VertexName(v), v))
			}

			// Allow the walker to change our tree if needed. Eval,
			// then callback with the output.
			log.Printf("[DEBUG] vertex %s.%s: evaluating", path, dag.VertexName(v))
			tree = walker.EnterEvalTree(v, tree)
			output, err := Eval(tree, vertexCtx)
			if rerr = walker.ExitEvalTree(v, output, err); rerr != nil {
				return
			}
		}

		// If the node is dynamically expanded, then expand it
		if ev, ok := v.(GraphNodeDynamicExpandable); ok {
			log.Printf(
				"[DEBUG] vertex '%s.%s': expanding/walking dynamic subgraph",
				path,
				dag.VertexName(v))
			g, err := ev.DynamicExpand(vertexCtx)
			if err != nil {
				rerr = err
				return
			}
			if g != nil {
				// Walk the subgraph
				if rerr = g.walk(walker); rerr != nil {
					return
				}
			}
		}

		// If the node has a subgraph, then walk the subgraph
		if sn, ok := v.(GraphNodeSubgraph); ok {
			log.Printf(
				"[DEBUG] vertex '%s.%s': walking subgraph",
				path,
				dag.VertexName(v))

			if rerr = sn.Subgraph().walk(walker); rerr != nil {
				return
			}
		}

		return nil
	}

	return g.AcyclicGraph.Walk(walkFn)
}

// GraphNodeAnnotationInit is an interface that allows a node to
// initialize it's annotations.
//
// AnnotationInit will be called _once_ when the node is added to a
// graph for the first time and is expected to return it's initial
// annotations.
type GraphNodeAnnotationInit interface {
	AnnotationInit() map[string]interface{}
}

// GraphNodeDependable is an interface which says that a node can be
// depended on (an edge can be placed between this node and another) according
// to the well-known name returned by DependableName.
//
// DependableName can return multiple names it is known by.
type GraphNodeDependable interface {
	DependableName() []string
}

// GraphNodeDependent is an interface which says that a node depends
// on another GraphNodeDependable by some name. By implementing this
// interface, Graph.ConnectDependents() can be called multiple times
// safely and efficiently.
type GraphNodeDependent interface {
	DependentOn() []string
}
<commit_msg>update CHANGELOG<commit_after>package terraform

import (
	"fmt"
	"log"
	"strings"
	"sync"

	"github.com/hashicorp/terraform/dag"
)

// RootModuleName is the name given to the root module implicitly.
const RootModuleName = "root"

// RootModulePath is the path for the root module.
var RootModulePath = []string{RootModuleName}

// Graph represents the graph that Terraform uses to represent resources
// and their dependencies. Each graph represents only one module, but it
// can contain further modules, which themselves have their own graph.
type Graph struct {
	// Graph is the actual DAG. This is embedded so you can call the DAG
	// methods directly.
	dag.AcyclicGraph

	// Path is the path in the module tree that this Graph represents.
	// The root is represented by a single element list containing
	// RootModuleName
	Path []string

	// annotations are the annotations that are added to vertices. Annotations
	// are arbitrary metadata taht is used for various logic. Annotations
	// should have unique keys that are referenced via constants.
	annotations map[dag.Vertex]map[string]interface{}

	// dependableMap is a lookaside table for fast lookups for connecting
	// dependencies by their GraphNodeDependable value to avoid O(n^3)-like
	// situations and turn them into O(1) with respect to the number of new
	// edges.
	dependableMap map[string]dag.Vertex

	once sync.Once
}

// Annotations returns the annotations that are configured for the
// given vertex. The map is guaranteed to be non-nil but may be empty.
//
// The returned map may be modified to modify the annotations of the
// vertex.
func (g *Graph) Annotations(v dag.Vertex) map[string]interface{} {
	g.once.Do(g.init)

	// If this vertex isn't in the graph, then just return an empty map
	if !g.HasVertex(v) {
		return map[string]interface{}{}
	}

	// Get the map, if it doesn't exist yet then initialize it
	m, ok := g.annotations[v]
	if !ok {
		m = make(map[string]interface{})
		g.annotations[v] = m
	}

	return m
}

// Add is the same as dag.Graph.Add.
func (g *Graph) Add(v dag.Vertex) dag.Vertex {
	g.once.Do(g.init)

	// Call upwards to add it to the actual graph
	g.Graph.Add(v)

	// If this is a depend-able node, then store the lookaside info
	if dv, ok := v.(GraphNodeDependable); ok {
		for _, n := range dv.DependableName() {
			g.dependableMap[n] = v
		}
	}

	// If this initializes annotations, then do that
	if av, ok := v.(GraphNodeAnnotationInit); ok {
		as := g.Annotations(v)
		for k, v := range av.AnnotationInit() {
			as[k] = v
		}
	}

	return v
}

// Remove is the same as dag.Graph.Remove
func (g *Graph) Remove(v dag.Vertex) dag.Vertex {
	g.once.Do(g.init)

	// If this is a depend-able node, then remove the lookaside info
	if dv, ok := v.(GraphNodeDependable); ok {
		for _, n := range dv.DependableName() {
			delete(g.dependableMap, n)
		}
	}

	// Remove the annotations
	delete(g.annotations, v)

	// Call upwards to remove it from the actual graph
	return g.Graph.Remove(v)
}

// Replace is the same as dag.Graph.Replace
func (g *Graph) Replace(o, n dag.Vertex) bool {
	g.once.Do(g.init)

	// Go through and update our lookaside to point to the new vertex
	for k, v := range g.dependableMap {
		if v == o {
			if _, ok := n.(GraphNodeDependable); ok {
				g.dependableMap[k] = n
			} else {
				delete(g.dependableMap, k)
			}
		}
	}

	// Move the annotation if it exists
	if m, ok := g.annotations[o]; ok {
		g.annotations[n] = m
		delete(g.annotations, o)
	}

	return g.Graph.Replace(o, n)
}

// ConnectDependent connects a GraphNodeDependent to all of its
// GraphNodeDependables. It returns the list of dependents it was
// unable to connect to.
func (g *Graph) ConnectDependent(raw dag.Vertex) []string {
	v, ok := raw.(GraphNodeDependent)
	if !ok {
		return nil
	}

	return g.ConnectTo(v, v.DependentOn())
}

// ConnectDependents goes through the graph, connecting all the
// GraphNodeDependents to GraphNodeDependables. This is safe to call
// multiple times.
//
// To get details on whether dependencies could be found/made, the more
// specific ConnectDependent should be used.
func (g *Graph) ConnectDependents() {
	for _, v := range g.Vertices() {
		if dv, ok := v.(GraphNodeDependent); ok {
			g.ConnectDependent(dv)
		}
	}
}

// ConnectFrom creates an edge by finding the source from a DependableName
// and connecting it to the specific vertex.
func (g *Graph) ConnectFrom(source string, target dag.Vertex) {
	g.once.Do(g.init)

	if source := g.dependableMap[source]; source != nil {
		g.Connect(dag.BasicEdge(source, target))
	}
}

// ConnectTo connects a vertex to a raw string of targets that are the
// result of DependableName, and returns the list of targets that are missing.
func (g *Graph) ConnectTo(v dag.Vertex, targets []string) []string {
	g.once.Do(g.init)

	var missing []string
	for _, t := range targets {
		if dest := g.dependableMap[t]; dest != nil {
			g.Connect(dag.BasicEdge(v, dest))
		} else {
			missing = append(missing, t)
		}
	}

	return missing
}

// Dependable finds the vertices in the graph that have the given dependable
// names and returns them.
func (g *Graph) Dependable(n string) dag.Vertex {
	// TODO: do we need this?
	return nil
}

// Walk walks the graph with the given walker for callbacks. The graph
// will be walked with full parallelism, so the walker should expect
// to be called in concurrently.
func (g *Graph) Walk(walker GraphWalker) error {
	return g.walk(walker)
}

func (g *Graph) init() {
	if g.annotations == nil {
		g.annotations = make(map[dag.Vertex]map[string]interface{})
	}

	if g.dependableMap == nil {
		g.dependableMap = make(map[string]dag.Vertex)
	}
}

func (g *Graph) walk(walker GraphWalker) error {
	// The callbacks for enter/exiting a graph
	ctx := walker.EnterPath(g.Path)
	defer walker.ExitPath(g.Path)

	// Get the path for logs
	path := strings.Join(ctx.Path(), ".")

	// Walk the graph.
	var walkFn dag.WalkFunc
	walkFn = func(v dag.Vertex) (rerr error) {
		log.Printf("[DEBUG] vertex %s.%s: walking", path, dag.VertexName(v))

		walker.EnterVertex(v)
		defer func() { walker.ExitVertex(v, rerr) }()

		// vertexCtx is the context that we use when evaluating. This
		// is normally the context of our graph but can be overridden
		// with a GraphNodeSubPath impl.
		vertexCtx := ctx
		if pn, ok := v.(GraphNodeSubPath); ok && len(pn.Path()) > 0 {
			vertexCtx = walker.EnterPath(normalizeModulePath(pn.Path()))
			defer walker.ExitPath(pn.Path())
		}

		// If the node is eval-able, then evaluate it.
		if ev, ok := v.(GraphNodeEvalable); ok {
			tree := ev.EvalTree()
			if tree == nil {
				panic(fmt.Sprintf(
					"%s.%s (%T): nil eval tree", path, dag.VertexName(v), v))
			}

			// Allow the walker to change our tree if needed. Eval,
			// then callback with the output.
			log.Printf("[DEBUG] vertex '%s.%s': evaluating", path, dag.VertexName(v))
			tree = walker.EnterEvalTree(v, tree)
			output, err := Eval(tree, vertexCtx)
			if rerr = walker.ExitEvalTree(v, output, err); rerr != nil {
				return
			}
		}

		// If the node is dynamically expanded, then expand it
		if ev, ok := v.(GraphNodeDynamicExpandable); ok {
			log.Printf(
				"[DEBUG] vertex '%s.%s': expanding/walking dynamic subgraph",
				path,
				dag.VertexName(v))
			g, err := ev.DynamicExpand(vertexCtx)
			if err != nil {
				rerr = err
				return
			}
			if g != nil {
				// Walk the subgraph
				if rerr = g.walk(walker); rerr != nil {
					return
				}
			}
		}

		// If the node has a subgraph, then walk the subgraph
		if sn, ok := v.(GraphNodeSubgraph); ok {
			log.Printf(
				"[DEBUG] vertex '%s.%s': walking subgraph",
				path,
				dag.VertexName(v))

			if rerr = sn.Subgraph().walk(walker); rerr != nil {
				return
			}
		}

		return nil
	}

	return g.AcyclicGraph.Walk(walkFn)
}

// GraphNodeAnnotationInit is an interface that allows a node to
// initialize it's annotations.
//
// AnnotationInit will be called _once_ when the node is added to a
// graph for the first time and is expected to return it's initial
// annotations.
type GraphNodeAnnotationInit interface {
	AnnotationInit() map[string]interface{}
}

// GraphNodeDependable is an interface which says that a node can be
// depended on (an edge can be placed between this node and another) according
// to the well-known name returned by DependableName.
//
// DependableName can return multiple names it is known by.
type GraphNodeDependable interface {
	DependableName() []string
}

// GraphNodeDependent is an interface which says that a node depends
// on another GraphNodeDependable by some name. By implementing this
// interface, Graph.ConnectDependents() can be called multiple times
// safely and efficiently.
type GraphNodeDependent interface {
	DependentOn() []string
}
<|endoftext|>


<commit_before>package pretty

import (
	"encoding/hex"
	"fmt"
	"io"
	"strconv"

	. "github.com/polydawn/refmt/tok"
)

func NewEncoder(wr io.Writer) *Encoder {
	return &Encoder{
		wr:    wr,
		stack: make([]phase, 0, 10),
	}
}

func (d *Encoder) Reset() {
	d.stack = d.stack[0:0]
	d.current = phase_anyExpectValue
}

/*
	A pretty.Encoder is a TokenSink that emits pretty-printed stuff.

	The default behavior is color coded with ANSI escape sequences, so it's
	snazzy looking on your terminal.
*/
type Encoder struct {
	wr io.Writer

	// Stack, tracking how many array and map opens are outstanding.
	// (Values are only 'phase_mapExpectKeyOrEnd' and 'phase_arrExpectValueOrEnd'.)
	stack   []phase
	current phase // shortcut to value at end of stack

	// Spare memory, for use in operations on leaf nodes (e.g. temp space for an int serialization).
	scratch [64]byte
}

type phase int

const (
	phase_anyExpectValue phase = iota
	phase_mapExpectKeyOrEnd
	phase_mapExpectValue
	phase_arrExpectValueOrEnd
)

func (d *Encoder) Step(tok *Token) (done bool, err error) {
	switch d.current {
	case phase_anyExpectValue:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value")
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of value")
		default:
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return true, nil
		}
	case phase_mapExpectKeyOrEnd:
		switch tok.Type {
		case TMapOpen:
			return true, fmt.Errorf("unexpected mapOpen; expected start of key or end of map")
		case TArrOpen:
			return true, fmt.Errorf("unexpected arrOpen; expected start of key or end of map")
		case TMapClose:
			d.emitMapClose(tok)
			return d.popPhase()
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of key or end of map")
		default:
			switch tok.Type {
			case TString, TInt, TUint:
				d.wr.Write(indentWord(len(d.stack)))
				d.emitValue(tok)
				d.wr.Write(wordColon)
				d.current = phase_mapExpectValue
				return false, nil
			default:
				return true, fmt.Errorf("unexpected token of type %T; expected map key", *tok)
			}
		}
	case phase_mapExpectValue:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value")
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of value")
		default:
			d.current = phase_mapExpectKeyOrEnd
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return false, nil
		}
	case phase_arrExpectValueOrEnd:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value or end of array")
		case TArrClose:
			d.emitArrClose(tok)
			return d.popPhase()
		default:
			d.wr.Write(indentWord(len(d.stack)))
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return false, nil
		}
	default:
		panic("Unreachable")
	}
}

func (d *Encoder) pushPhase(p phase) {
	d.current = p
	d.stack = append(d.stack, d.current)
}

// Pop a phase from the stack; return 'true' if stack now empty.
func (d *Encoder) popPhase() (bool, error) {
	n := len(d.stack) - 1
	if n == 0 {
		return true, nil
	}
	if n < 0 { // the state machines are supposed to have already errored better
		panic("prettyEncoder stack overpopped")
	}
	d.current = d.stack[n-1]
	d.stack = d.stack[0:n]
	return false, nil
}

func (d *Encoder) emitMapOpen(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	d.wr.Write(wordMapOpenPt1)
	if tok.Length < 0 {
		d.wr.Write(wordUnknownLen)
	} else {
		d.wr.Write([]byte(strconv.Itoa(tok.Length)))
	}
	d.wr.Write(wordMapOpenPt2)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitMapClose(tok *Token) {
	d.wr.Write(indentWord(len(d.stack) - 1))
	d.wr.Write(wordMapClose)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitArrOpen(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	d.wr.Write(wordArrOpenPt1)
	if tok.Length < 0 {
		d.wr.Write(wordUnknownLen)
	} else {
		d.wr.Write([]byte(strconv.Itoa(tok.Length)))
	}
	d.wr.Write(wordArrOpenPt2)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitArrClose(tok *Token) {
	d.wr.Write(indentWord(len(d.stack) - 1))
	d.wr.Write(wordArrClose)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitValue(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	switch tok.Type {
	case TNull:
		d.wr.Write(wordNull)
	case TString:
		d.emitString(tok.Str)
	case TBytes:
		dst := make([]byte, hex.EncodedLen(len(tok.Bytes)))
		hex.Encode(dst, tok.Bytes)
		d.wr.Write(dst)
	case TBool:
		switch tok.Bool {
		case true:
			d.wr.Write(wordTrue)
		case false:
			d.wr.Write(wordFalse)
		}
	case TInt:
		b := strconv.AppendInt(d.scratch[:0], tok.Int, 10)
		d.wr.Write(b)
	case TFloat64:
		b := strconv.AppendFloat(d.scratch[:0], tok.Float64, 'f', 6, 64)
		d.wr.Write(b)
	default:
		panic(fmt.Errorf("TODO finish more pretty.Encoder primitives support: unhandled token %s", tok))
	}
}

func (d *Encoder) writeByte(b byte) {
	d.scratch[0] = b
	d.wr.Write(d.scratch[0:1])
}
<commit_msg>pretty encoding for uints<commit_after>package pretty

import (
	"encoding/hex"
	"fmt"
	"io"
	"strconv"

	. "github.com/polydawn/refmt/tok"
)

func NewEncoder(wr io.Writer) *Encoder {
	return &Encoder{
		wr:    wr,
		stack: make([]phase, 0, 10),
	}
}

func (d *Encoder) Reset() {
	d.stack = d.stack[0:0]
	d.current = phase_anyExpectValue
}

/*
	A pretty.Encoder is a TokenSink that emits pretty-printed stuff.

	The default behavior is color coded with ANSI escape sequences, so it's
	snazzy looking on your terminal.
*/
type Encoder struct {
	wr io.Writer

	// Stack, tracking how many array and map opens are outstanding.
	// (Values are only 'phase_mapExpectKeyOrEnd' and 'phase_arrExpectValueOrEnd'.)
	stack   []phase
	current phase // shortcut to value at end of stack

	// Spare memory, for use in operations on leaf nodes (e.g. temp space for an int serialization).
	scratch [64]byte
}

type phase int

const (
	phase_anyExpectValue phase = iota
	phase_mapExpectKeyOrEnd
	phase_mapExpectValue
	phase_arrExpectValueOrEnd
)

func (d *Encoder) Step(tok *Token) (done bool, err error) {
	switch d.current {
	case phase_anyExpectValue:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value")
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of value")
		default:
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return true, nil
		}
	case phase_mapExpectKeyOrEnd:
		switch tok.Type {
		case TMapOpen:
			return true, fmt.Errorf("unexpected mapOpen; expected start of key or end of map")
		case TArrOpen:
			return true, fmt.Errorf("unexpected arrOpen; expected start of key or end of map")
		case TMapClose:
			d.emitMapClose(tok)
			return d.popPhase()
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of key or end of map")
		default:
			switch tok.Type {
			case TString, TInt, TUint:
				d.wr.Write(indentWord(len(d.stack)))
				d.emitValue(tok)
				d.wr.Write(wordColon)
				d.current = phase_mapExpectValue
				return false, nil
			default:
				return true, fmt.Errorf("unexpected token of type %T; expected map key", *tok)
			}
		}
	case phase_mapExpectValue:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value")
		case TArrClose:
			return true, fmt.Errorf("unexpected arrClose; expected start of value")
		default:
			d.current = phase_mapExpectKeyOrEnd
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return false, nil
		}
	case phase_arrExpectValueOrEnd:
		switch tok.Type {
		case TMapOpen:
			d.pushPhase(phase_mapExpectKeyOrEnd)
			d.emitMapOpen(tok)
			return false, nil
		case TArrOpen:
			d.pushPhase(phase_arrExpectValueOrEnd)
			d.emitArrOpen(tok)
			return false, nil
		case TMapClose:
			return true, fmt.Errorf("unexpected mapClose; expected start of value or end of array")
		case TArrClose:
			d.emitArrClose(tok)
			return d.popPhase()
		default:
			d.wr.Write(indentWord(len(d.stack)))
			d.emitValue(tok)
			d.wr.Write(wordBreak)
			return false, nil
		}
	default:
		panic("Unreachable")
	}
}

func (d *Encoder) pushPhase(p phase) {
	d.current = p
	d.stack = append(d.stack, d.current)
}

// Pop a phase from the stack; return 'true' if stack now empty.
func (d *Encoder) popPhase() (bool, error) {
	n := len(d.stack) - 1
	if n == 0 {
		return true, nil
	}
	if n < 0 { // the state machines are supposed to have already errored better
		panic("prettyEncoder stack overpopped")
	}
	d.current = d.stack[n-1]
	d.stack = d.stack[0:n]
	return false, nil
}

func (d *Encoder) emitMapOpen(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	d.wr.Write(wordMapOpenPt1)
	if tok.Length < 0 {
		d.wr.Write(wordUnknownLen)
	} else {
		d.wr.Write([]byte(strconv.Itoa(tok.Length)))
	}
	d.wr.Write(wordMapOpenPt2)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitMapClose(tok *Token) {
	d.wr.Write(indentWord(len(d.stack) - 1))
	d.wr.Write(wordMapClose)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitArrOpen(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	d.wr.Write(wordArrOpenPt1)
	if tok.Length < 0 {
		d.wr.Write(wordUnknownLen)
	} else {
		d.wr.Write([]byte(strconv.Itoa(tok.Length)))
	}
	d.wr.Write(wordArrOpenPt2)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitArrClose(tok *Token) {
	d.wr.Write(indentWord(len(d.stack) - 1))
	d.wr.Write(wordArrClose)
	d.wr.Write(wordBreak)
}

func (d *Encoder) emitValue(tok *Token) {
	if tok.Tagged {
		d.wr.Write(wordTag)
		d.wr.Write([]byte(strconv.Itoa(tok.Tag)))
		d.wr.Write(wordTagClose)
	}
	switch tok.Type {
	case TNull:
		d.wr.Write(wordNull)
	case TString:
		d.emitString(tok.Str)
	case TBytes:
		dst := make([]byte, hex.EncodedLen(len(tok.Bytes)))
		hex.Encode(dst, tok.Bytes)
		d.wr.Write(dst)
	case TBool:
		switch tok.Bool {
		case true:
			d.wr.Write(wordTrue)
		case false:
			d.wr.Write(wordFalse)
		}
	case TInt:
		b := strconv.AppendInt(d.scratch[:0], tok.Int, 10)
		d.wr.Write(b)
	case TUint:
		b := strconv.AppendUint(d.scratch[:0], tok.Uint, 10)
		d.wr.Write(b)
	case TFloat64:
		b := strconv.AppendFloat(d.scratch[:0], tok.Float64, 'f', 6, 64)
		d.wr.Write(b)
	default:
		panic(fmt.Errorf("TODO finish more pretty.Encoder primitives support: unhandled token %s", tok))
	}
}

func (d *Encoder) writeByte(b byte) {
	d.scratch[0] = b
	d.wr.Write(d.scratch[0:1])
}
<|endoftext|>