<commit_before>package server

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
)

type Pattern struct {
	Blocks      []BlockLedger      `json:"blocks"`
	Connections []ConnectionLedger `json:"connections"`
	Groups      []Group            `json:"groups"`
}

type Node interface {
	GetID() int
	GetParent() *Group
	SetParent(*Group)
}

type Group struct {
	Id       int    `json:"id"`
	Label    string `json:"label"`
	Children []int  `json:"children"`
	Parent   *Group `json:"-"`
}

func (g *Group) GetID() int {
	return g.Id
}

func (g *Group) GetParent() *Group {
	return g.Parent
}

func (g *Group) SetParent(group *Group) {
	g.Parent = group
}

func (s *Server) ListGroups() []Group {
	groups := []Group{}
	for _, g := range s.groups {
		groups = append(groups, *g)
	}
	return groups
}

func (s *Server) GroupIndexHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(s.ListGroups()); err != nil {
		panic(err)
	}
}

func (s *Server) DetachChild(g Node) error {
	parent := g.GetParent()
	if parent == nil {
		return errors.New("no parent to detach from")
	}

	id := g.GetID()

	child := -1
	for i, v := range parent.Children {
		if v == id {
			child = i
		}
	}

	if child == -1 {
		return errors.New("could not remove child from group: child does not exist")
	}

	parent.Children = append(parent.Children[:child], parent.Children[child+1:]...)

	update := struct {
		Id    int `json:"id"`
		Child int `json:"child"`
	}{
		parent.GetID(), g.GetID(),
	}

	s.websocketBroadcast(Update{Action: DELETE, Type: GROUP_CHILD, Data: update})
	return nil
}

func (s *Server) AddChildToGroup(id int, n Node) error {
	newParent, ok := s.groups[id]
	if !ok {
		return errors.New("group not found")
	}

	nid := n.GetID()
	for _, v := range newParent.Children {
		if v == nid {
			return errors.New("node already child of this group")
		}
	}

	newParent.Children = append(newParent.Children, nid)
	if n.GetParent() != nil {
		err := s.DetachChild(n)
		if err != nil {
			return err
		}
	}

	n.SetParent(newParent)

	update := struct {
		Id    int `json:"id"`
		Child int `json:"child"`
	}{
		id, nid,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: GROUP_CHILD, Data: update})
	return nil
}

// CreateGroupHandler responds to a POST request to instantiate a new group and add it to the Server.
// Moves all of the specified children out of the parent's group and into the new group.
func (s *Server) GroupCreateHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var g struct {
		Group    int    `json:"group"`
		Children []int  `json:"children"`
		Label    string `json:"label"`
	}

	err = json.Unmarshal(body, &g)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read JSON"})
		return
	}

	s.Lock()
	defer s.Unlock()

	newGroup := &Group{
		Children: g.Children,
		Label:    g.Label,
		Id:       s.GetNextID(),
	}

	if newGroup.Children == nil {
		newGroup.Children = []int{}
	}

	for _, c := range newGroup.Children {
		_, okb := s.blocks[c]
		_, okg := s.groups[c]
		if !okb && !okg {
			w.WriteHeader(http.StatusBadRequest)
			writeJSON(w, Error{"could not create group: invalid children"})
			return
		}
	}

	s.groups[newGroup.Id] = newGroup
	s.websocketBroadcast(Update{Action: CREATE, Type: GROUP, Data: newGroup})

	err = s.AddChildToGroup(g.Group, newGroup)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	for _, c := range newGroup.Children {
		if cb, ok := s.blocks[c]; ok {
			err = s.AddChildToGroup(newGroup.Id, cb)
		}
		if cg, ok := s.groups[c]; ok {
			err = s.AddChildToGroup(newGroup.Id, cg)
		}
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			writeJSON(w, Error{err.Error()})
			return
		}
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) DeleteGroup(id int) error {
	group, ok := s.groups[id]
	if !ok {
		return errors.New("could not find group to delete")
	}

	for _, c := range group.Children {
		if _, ok := s.blocks[c]; ok {
			err := s.DeleteBlock(c)
			if err != nil {
				return err
			}
		} else if _, ok := s.groups[c]; ok {
			err := s.DeleteGroup(c)
			if err != nil {
				return err
			}
		}
	}

	update := struct {
		Id int `json:"id"`
	}{
		id,
	}
	s.DetachChild(group)
	delete(s.groups, id)
	s.websocketBroadcast(Update{Action: DELETE, Type: GROUP, Data: update})
	return nil
}

func (s *Server) GroupDeleteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.DeleteGroup(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}
func (s *Server) GroupHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) GroupExportHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()
	p, err := s.ExportGroup(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	writeJSON(w, p)
}

func (s *Server) ExportGroup(id int) (*Pattern, error) {
	p := &Pattern{}
	g, ok := s.groups[id]
	if !ok {
		return nil, errors.New("could not find group to export")
	}

	p.Groups = append(p.Groups, *g)
	for _, c := range s.connections {
		in := false
		out := false
		for _, bid := range g.Children {
			b, ok := s.blocks[bid]
			if !ok {
				continue
			}
			if b.Id == c.Source.Id {
				in = true
			}
			if b.Id == c.Target.Id {
				out = true
			}
		}
		if in && out {
			p.Connections = append(p.Connections, *c)
		}
	}

	for _, c := range g.Children {
		b, ok := s.blocks[c]
		if !ok {
			g, err := s.ExportGroup(c)
			if err != nil {
				return nil, err
			}

			p.Blocks = append(p.Blocks, g.Blocks...)
			p.Groups = append(p.Groups, g.Groups...)
			p.Connections = append(p.Connections, g.Connections...)
			continue
		}
		p.Blocks = append(p.Blocks, *b)
	}

	return p, nil
}

func (s *Server) GroupImportHandler(w http.ResponseWriter, r *http.Request) {

}
func (s *Server) GroupModifyLabelHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	var l string
	err = json.Unmarshal(body, &l)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.Lock()
	defer s.Unlock()

	g, ok := s.groups[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no block found"})
		return
	}

	g.Label = l

	update := struct {
		Label string `json:"label"`
		Id    int    `json:"id"`
	}{
		l, id,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: GROUP, Data: update})

	w.WriteHeader(http.StatusNoContent)
}
func (s *Server) GroupModifyAllChildrenHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) GroupModifyChildHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	childs, ok := vars["node_id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	child, err := strconv.Atoi(childs)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	if id == child {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"cannot add group as member of itself"})
		return
	}

	s.Lock()
	defer s.Unlock()

	var n Node

	if _, ok := s.groups[id]; !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find id"})
		return
	}

	if b, ok := s.blocks[child]; ok {
		n = b
	}
	if g, ok := s.groups[child]; ok {
		n = g
	}

	if n == nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find id"})
		return
	}

	err = s.AddChildToGroup(id, n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) GroupPositionHandler(w http.ResponseWriter, r *http.Request) {
}
<commit_msg>starting import<commit_after>package server

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
)

type Pattern struct {
	Blocks      []BlockLedger      `json:"blocks"`
	Connections []ConnectionLedger `json:"connections"`
	Groups      []Group            `json:"groups"`
}

type Node interface {
	GetID() int
	GetParent() *Group
	SetParent(*Group)
}

type Group struct {
	Id       int    `json:"id"`
	Label    string `json:"label"`
	Children []int  `json:"children"`
	Parent   *Group `json:"-"`
}

func (g *Group) GetID() int {
	return g.Id
}

func (g *Group) GetParent() *Group {
	return g.Parent
}

func (g *Group) SetParent(group *Group) {
	g.Parent = group
}

func (s *Server) ListGroups() []Group {
	groups := []Group{}
	for _, g := range s.groups {
		groups = append(groups, *g)
	}
	return groups
}

func (s *Server) GroupIndexHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(s.ListGroups()); err != nil {
		panic(err)
	}
}

func (s *Server) DetachChild(g Node) error {
	parent := g.GetParent()
	if parent == nil {
		return errors.New("no parent to detach from")
	}

	id := g.GetID()

	child := -1
	for i, v := range parent.Children {
		if v == id {
			child = i
		}
	}

	if child == -1 {
		return errors.New("could not remove child from group: child does not exist")
	}

	parent.Children = append(parent.Children[:child], parent.Children[child+1:]...)

	update := struct {
		Id    int `json:"id"`
		Child int `json:"child"`
	}{
		parent.GetID(), g.GetID(),
	}

	s.websocketBroadcast(Update{Action: DELETE, Type: GROUP_CHILD, Data: update})
	return nil
}

func (s *Server) AddChildToGroup(id int, n Node) error {
	newParent, ok := s.groups[id]
	if !ok {
		return errors.New("group not found")
	}

	nid := n.GetID()
	for _, v := range newParent.Children {
		if v == nid {
			return errors.New("node already child of this group")
		}
	}

	newParent.Children = append(newParent.Children, nid)
	if n.GetParent() != nil {
		err := s.DetachChild(n)
		if err != nil {
			return err
		}
	}

	n.SetParent(newParent)

	update := struct {
		Id    int `json:"id"`
		Child int `json:"child"`
	}{
		id, nid,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: GROUP_CHILD, Data: update})
	return nil
}

// CreateGroupHandler responds to a POST request to instantiate a new group and add it to the Server.
// Moves all of the specified children out of the parent's group and into the new group.
func (s *Server) GroupCreateHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var g struct {
		Group    int    `json:"group"`
		Children []int  `json:"children"`
		Label    string `json:"label"`
	}

	err = json.Unmarshal(body, &g)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read JSON"})
		return
	}

	s.Lock()
	defer s.Unlock()

	newGroup := &Group{
		Children: g.Children,
		Label:    g.Label,
		Id:       s.GetNextID(),
	}

	if newGroup.Children == nil {
		newGroup.Children = []int{}
	}

	for _, c := range newGroup.Children {
		_, okb := s.blocks[c]
		_, okg := s.groups[c]
		if !okb && !okg {
			w.WriteHeader(http.StatusBadRequest)
			writeJSON(w, Error{"could not create group: invalid children"})
			return
		}
	}

	s.groups[newGroup.Id] = newGroup
	s.websocketBroadcast(Update{Action: CREATE, Type: GROUP, Data: newGroup})

	err = s.AddChildToGroup(g.Group, newGroup)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	for _, c := range newGroup.Children {
		if cb, ok := s.blocks[c]; ok {
			err = s.AddChildToGroup(newGroup.Id, cb)
		}
		if cg, ok := s.groups[c]; ok {
			err = s.AddChildToGroup(newGroup.Id, cg)
		}
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			writeJSON(w, Error{err.Error()})
			return
		}
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) DeleteGroup(id int) error {
	group, ok := s.groups[id]
	if !ok {
		return errors.New("could not find group to delete")
	}

	for _, c := range group.Children {
		if _, ok := s.blocks[c]; ok {
			err := s.DeleteBlock(c)
			if err != nil {
				return err
			}
		} else if _, ok := s.groups[c]; ok {
			err := s.DeleteGroup(c)
			if err != nil {
				return err
			}
		}
	}

	update := struct {
		Id int `json:"id"`
	}{
		id,
	}
	s.DetachChild(group)
	delete(s.groups, id)
	s.websocketBroadcast(Update{Action: DELETE, Type: GROUP, Data: update})
	return nil
}

func (s *Server) GroupDeleteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.DeleteGroup(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}
func (s *Server) GroupHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) GroupExportHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()
	p, err := s.ExportGroup(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	writeJSON(w, p)
}

func (s *Server) ExportGroup(id int) (*Pattern, error) {
	p := &Pattern{}
	g, ok := s.groups[id]
	if !ok {
		return nil, errors.New("could not find group to export")
	}

	p.Groups = append(p.Groups, *g)
	for _, c := range s.connections {
		in := false
		out := false
		for _, bid := range g.Children {
			b, ok := s.blocks[bid]
			if !ok {
				continue
			}
			if b.Id == c.Source.Id {
				in = true
			}
			if b.Id == c.Target.Id {
				out = true
			}
		}
		if in && out {
			p.Connections = append(p.Connections, *c)
		}
	}

	for _, c := range g.Children {
		b, ok := s.blocks[c]
		if !ok {
			g, err := s.ExportGroup(c)
			if err != nil {
				return nil, err
			}

			p.Blocks = append(p.Blocks, g.Blocks...)
			p.Groups = append(p.Groups, g.Groups...)
			p.Connections = append(p.Connections, g.Connections...)
			continue
		}
		p.Blocks = append(p.Blocks, *b)
	}

	return p, nil
}

func (s *Server) GroupImportHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	var p Pattern
	err = json.Unmarshal(body, &p)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.Lock()
	defer s.Unlock()

	err := s.ImportGroup(p)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}
}

func (s *Server) ImportGroup(p Pattern) error {
	ids := make(map[int]int)
	for _, b := range p.Blocks() {
		ids[b.Id] = s.GetNextID()
	}
	for _, g := range p.Groups() {
		ids[g.Id] = s.GetNextID()
	}
	for _, c := range p.Connections() {
		ids[c.Id] = s.GetNextID()
	}

	childNodes := make(map[int]struct{})
	for _, g := range p.Groups() {
		for _, c := range g.Children {
			childNodes[c] = struct{}{}
		}
	}

	parent := -1
	for _, c := range p.Groups() {
		_, ok := childNodes[c.Id]
		if !ok {
			parent = c.Id
			break
		}
	}

	if parent == -1 {
		return errors.New("there is no parent group in this pattern")
	}

}

func (s *Server) GroupModifyLabelHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	var l string
	err = json.Unmarshal(body, &l)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.Lock()
	defer s.Unlock()

	g, ok := s.groups[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no block found"})
		return
	}

	g.Label = l

	update := struct {
		Label string `json:"label"`
		Id    int    `json:"id"`
	}{
		l, id,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: GROUP, Data: update})

	w.WriteHeader(http.StatusNoContent)
}
func (s *Server) GroupModifyAllChildrenHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) GroupModifyChildHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	childs, ok := vars["node_id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	child, err := strconv.Atoi(childs)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	if id == child {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"cannot add group as member of itself"})
		return
	}

	s.Lock()
	defer s.Unlock()

	var n Node

	if _, ok := s.groups[id]; !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find id"})
		return
	}

	if b, ok := s.blocks[child]; ok {
		n = b
	}
	if g, ok := s.groups[child]; ok {
		n = g
	}

	if n == nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find id"})
		return
	}

	err = s.AddChildToGroup(id, n)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) GroupPositionHandler(w http.ResponseWriter, r *http.Request) {
}
<|endoftext|>


<commit_before>package openresty

import (
	"math"
	"strconv"
	"strings"
	"regexp"
)

var (
	versionPattern *regexp.Regexp
)

func init() {
	versionPattern = regexp.MustCompile(`([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?`)
}

func Name(version string) string {
	version = versionPattern.FindString(version)

	numbers := strings.Split(version, ".")
	size := len(numbers)
	sum := 0
	for i := 0; i < size; i++ {
		n, err := strconv.Atoi(numbers[i])
		if err != nil {
			return "ngx_openresty"
		}
		sum += int(math.Pow10(size-i-1)) * n
	}

	// the source distribution name of openresty is renamed in the 1.9.7.3 or later
	if sum > 1972 {
		return "openresty"
	}

	return "ngx_openresty"
}
<commit_msg>go fmt ./...<commit_after>package openresty

import (
	"math"
	"regexp"
	"strconv"
	"strings"
)

var (
	versionPattern *regexp.Regexp
)

func init() {
	versionPattern = regexp.MustCompile(`([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?`)
}

func Name(version string) string {
	version = versionPattern.FindString(version)

	numbers := strings.Split(version, ".")
	size := len(numbers)
	sum := 0
	for i := 0; i < size; i++ {
		n, err := strconv.Atoi(numbers[i])
		if err != nil {
			return "ngx_openresty"
		}
		sum += int(math.Pow10(size-i-1)) * n
	}

	// the source distribution name of openresty is renamed in the 1.9.7.3 or later
	if sum > 1972 {
		return "openresty"
	}

	return "ngx_openresty"
}
<|endoftext|>


<commit_before>package twosum

func TwoSum(array []int, target int) []int {
	var result []int
	for i, _ := range array {
		for j := i + 1; j < len(array); j++ {
			if array[i]+array[j] == target {
				result = append(result, i, j)
			}
		}
	}
	return result
}
<commit_msg>add detail<commit_after>/*Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution.

Example:
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].*/

package twosum

func TwoSum(array []int, target int) []int {
	var result []int
	for i, _ := range array {
		for j := i + 1; j < len(array); j++ {
			if array[i]+array[j] == target {
				result = append(result, i, j)
			}
		}
	}
	return result
}
<|endoftext|>


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

package vmath

import (
	"fmt"

	"github.com/go-gl/mathgl/mgl32"
)

type AABB struct {
	Min mgl32.Vec3
	Max mgl32.Vec3
}

func NewAABB(x1, y1, z1, x2, y2, z2 float32) AABB {
	return AABB{
		Min: mgl32.Vec3{x1, y1, z1},
		Max: mgl32.Vec3{x2, y2, z2},
	}
}

func (a AABB) RotateX(an, ox, oy, oz float32) AABB {
	mat := mgl32.Rotate3DX(an)
	o := mgl32.Vec3{ox, oy, oz}
	a.Max = mat.Mul3x1(a.Max.Sub(o)).Add(o)
	a.Min = mat.Mul3x1(a.Min.Sub(o)).Add(o)
	a.fixBounds()
	return a
}

func (a AABB) RotateY(an, ox, oy, oz float32) AABB {
	mat := mgl32.Rotate3DY(an)
	o := mgl32.Vec3{ox, oy, oz}
	a.Max = mat.Mul3x1(a.Max.Sub(o)).Add(o)
	a.Min = mat.Mul3x1(a.Min.Sub(o)).Add(o)
	a.fixBounds()
	return a
}

func (a *AABB) fixBounds() {
	for i := range a.Min {
		if a.Max[i] < a.Min[i] || a.Min[i] > a.Max[i] {
			a.Max[i], a.Min[i] = a.Min[i], a.Max[i]
		}
	}
}

func (a AABB) Intersects(o AABB) bool {
	return !(o.Min.X() >= a.Max.X() ||
		o.Max.X() <= a.Min.X() ||
		o.Min.Y() >= a.Max.Y() ||
		o.Max.Y() <= a.Min.Y() ||
		o.Min.Z() >= a.Max.Z() ||
		o.Max.Z() <= a.Min.Z())
}

func (a AABB) IntersectsLine(origin, dir mgl32.Vec3) bool {
	const right, left, middle = 0, 1, 2
	var (
		quadrant       [3]int
		candidatePlane [3]float32
		maxT           = [3]float32{-1, -1, -1}
	)
	inside := true
	for i := range origin {
		if origin[i] < a.Min[i] {
			quadrant[i] = left
			candidatePlane[i] = a.Min[i]
			inside = false
		} else if origin[i] > a.Max[i] {
			quadrant[i] = right
			candidatePlane[i] = a.Max[i]
			inside = false
		} else {
			quadrant[i] = middle
		}
	}
	if inside {
		return true
	}

	for i := range dir {
		if quadrant[i] != middle && dir[i] != 0 {
			maxT[i] = (candidatePlane[i] - origin[i]) / dir[i]
		}
	}
	whichPlane := 0
	for i := 1; i < 3; i++ {
		if maxT[whichPlane] < maxT[i] {
			whichPlane = i
		}
	}
	if maxT[whichPlane] < 0 {
		return false
	}

	for i := range origin {
		if whichPlane != i {
			coord := origin[i] + maxT[whichPlane]*dir[i]
			if coord < a.Min[i] || coord > a.Max[i] {
				return false
			}
		}
	}
	return true
}

func (a AABB) Shift(x, y, z float32) AABB {
	a.Min[0] += x
	a.Max[0] += x
	a.Min[1] += y
	a.Max[1] += y
	a.Min[2] += z
	a.Max[2] += z
	return a
}

func (a AABB) MoveOutOf(o AABB, dir mgl32.Vec3) AABB {
	if dir.X() != 0 {
		if dir.X() > 0 {
			ox := a.Max.X()
			a.Max[0] = o.Min.X() - 0.0001
			a.Min[0] += a.Max.X() - ox
		} else {
			ox := a.Min.X()
			a.Min[0] = o.Max.X() + 0.0001
			a.Max[0] += a.Min.X() - ox
		}
	}
	if dir.Y() != 0 {
		if dir.Y() > 0 {
			oy := a.Max.Y()
			a.Max[1] = o.Min.Y() - 0.0001
			a.Min[1] += a.Max.Y() - oy
		} else {
			oy := a.Min.Y()
			a.Min[1] = o.Max.Y() + 0.0001
			a.Max[1] += a.Min.Y() - oy
		}
	}

	if dir.Z() != 0 {
		if dir.Z() > 0 {
			oz := a.Max.Z()
			a.Max[2] = o.Min.Z() - 0.0001
			a.Min[2] += a.Max.Z() - oz
		} else {
			oz := a.Min.Z()
			a.Min[2] = o.Max.Z() + 0.0001
			a.Max[2] += a.Min.Z() - oz
		}
	}
	return a
}

func (a AABB) String() string {
	return fmt.Sprintf("[%v->%v]", a.Min, a.Max)
}
<commit_msg>type/vmath: add a Grow method<commit_after>// Copyright 2015 Matthew Collins
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vmath

import (
	"fmt"

	"github.com/go-gl/mathgl/mgl32"
)

type AABB struct {
	Min mgl32.Vec3
	Max mgl32.Vec3
}

func NewAABB(x1, y1, z1, x2, y2, z2 float32) AABB {
	return AABB{
		Min: mgl32.Vec3{x1, y1, z1},
		Max: mgl32.Vec3{x2, y2, z2},
	}
}

func (a AABB) RotateX(an, ox, oy, oz float32) AABB {
	mat := mgl32.Rotate3DX(an)
	o := mgl32.Vec3{ox, oy, oz}
	a.Max = mat.Mul3x1(a.Max.Sub(o)).Add(o)
	a.Min = mat.Mul3x1(a.Min.Sub(o)).Add(o)
	a.fixBounds()
	return a
}

func (a AABB) RotateY(an, ox, oy, oz float32) AABB {
	mat := mgl32.Rotate3DY(an)
	o := mgl32.Vec3{ox, oy, oz}
	a.Max = mat.Mul3x1(a.Max.Sub(o)).Add(o)
	a.Min = mat.Mul3x1(a.Min.Sub(o)).Add(o)
	a.fixBounds()
	return a
}

func (a *AABB) fixBounds() {
	for i := range a.Min {
		if a.Max[i] < a.Min[i] || a.Min[i] > a.Max[i] {
			a.Max[i], a.Min[i] = a.Min[i], a.Max[i]
		}
	}
}

func (a AABB) Intersects(o AABB) bool {
	return !(o.Min.X() >= a.Max.X() ||
		o.Max.X() <= a.Min.X() ||
		o.Min.Y() >= a.Max.Y() ||
		o.Max.Y() <= a.Min.Y() ||
		o.Min.Z() >= a.Max.Z() ||
		o.Max.Z() <= a.Min.Z())
}

func (a AABB) IntersectsLine(origin, dir mgl32.Vec3) bool {
	const right, left, middle = 0, 1, 2
	var (
		quadrant       [3]int
		candidatePlane [3]float32
		maxT           = [3]float32{-1, -1, -1}
	)
	inside := true
	for i := range origin {
		if origin[i] < a.Min[i] {
			quadrant[i] = left
			candidatePlane[i] = a.Min[i]
			inside = false
		} else if origin[i] > a.Max[i] {
			quadrant[i] = right
			candidatePlane[i] = a.Max[i]
			inside = false
		} else {
			quadrant[i] = middle
		}
	}
	if inside {
		return true
	}

	for i := range dir {
		if quadrant[i] != middle && dir[i] != 0 {
			maxT[i] = (candidatePlane[i] - origin[i]) / dir[i]
		}
	}
	whichPlane := 0
	for i := 1; i < 3; i++ {
		if maxT[whichPlane] < maxT[i] {
			whichPlane = i
		}
	}
	if maxT[whichPlane] < 0 {
		return false
	}

	for i := range origin {
		if whichPlane != i {
			coord := origin[i] + maxT[whichPlane]*dir[i]
			if coord < a.Min[i] || coord > a.Max[i] {
				return false
			}
		}
	}
	return true
}

func (a AABB) Shift(x, y, z float32) AABB {
	a.Min[0] += x
	a.Max[0] += x
	a.Min[1] += y
	a.Max[1] += y
	a.Min[2] += z
	a.Max[2] += z
	return a
}

func (a AABB) Grow(x, y, z float32) AABB {
	a.Min[0] -= x
	a.Max[0] -= x
	a.Min[1] -= y
	a.Max[1] += y
	a.Min[2] += z
	a.Max[2] += z
	return a
}

func (a AABB) MoveOutOf(o AABB, dir mgl32.Vec3) AABB {
	if dir.X() != 0 {
		if dir.X() > 0 {
			ox := a.Max.X()
			a.Max[0] = o.Min.X() - 0.0001
			a.Min[0] += a.Max.X() - ox
		} else {
			ox := a.Min.X()
			a.Min[0] = o.Max.X() + 0.0001
			a.Max[0] += a.Min.X() - ox
		}
	}
	if dir.Y() != 0 {
		if dir.Y() > 0 {
			oy := a.Max.Y()
			a.Max[1] = o.Min.Y() - 0.0001
			a.Min[1] += a.Max.Y() - oy
		} else {
			oy := a.Min.Y()
			a.Min[1] = o.Max.Y() + 0.0001
			a.Max[1] += a.Min.Y() - oy
		}
	}

	if dir.Z() != 0 {
		if dir.Z() > 0 {
			oz := a.Max.Z()
			a.Max[2] = o.Min.Z() - 0.0001
			a.Min[2] += a.Max.Z() - oz
		} else {
			oz := a.Min.Z()
			a.Min[2] = o.Max.Z() + 0.0001
			a.Max[2] += a.Min.Z() - oz
		}
	}
	return a
}

func (a AABB) String() string {
	return fmt.Sprintf("[%v->%v]", a.Min, a.Max)
}
<|endoftext|>


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

package flatpack_test

import (
	"encoding/json"
	"fmt"
	"reflect"
	"testing"

	"CodeCity/server/flatpack"
	"CodeCity/server/interpreter"
	"CodeCity/server/interpreter/data"
)

// FIXME: add a more general (and more comprehensive) example.

func Example() {
	intrp, _ := interpreter.NewFromJSON(fibonacci)
	for i := 0; i < 500 && intrp.Step(); i++ {
	}
	var f = flatpack.New()
	f.Pack("Interpreter", intrp)

	b, e := json.MarshalIndent(f, "", "  ")
	if e != nil {
		panic(e)
	}
	fmt.Printf("%s\n", string(b))
	// // Output:
}

func TestRoundTripInterpreter(t *testing.T) {
	// t.SkipNow()
	intrp, _ := interpreter.NewFromJSON(fibonacci)
	for i := 0; i < 500 && intrp.Step(); i++ {
	}
	var f = flatpack.New()
	f.Pack("Interpreter", intrp)
	f.Seal()

	b, e := json.MarshalIndent(f, "", "  ")
	if e != nil {
		t.Error(e)
	}
	var f2 *flatpack.Flatpack
	e = json.Unmarshal(b, &f2)
	if e != nil {
		t.Error(e)
	}

	if !reflect.DeepEqual(f, f2) {
		t.Errorf("%#v != %#v", f2, f)
	}
	// These versions might be more helpful in diagnosis:
	// if !reflect.DeepEqual(f.Labels, f2.Labels) {
	// 	t.Errorf("%#v != %#v", f2.Labels, f.Labels)
	// }
	// for i := 0; i < len(f.Values); i++ {
	// 	if f.Values[i].T != f2.Values[i].T {
	// 		t.Errorf("Values[%d].T == %#v (expected %#v)", i, f2.Values[i].T, f.Values[i].T)
	// 	}
	// 	if !reflect.DeepEqual(f.Values[i].V, f2.Values[i].V) {
	// 		t.Errorf("Values[%d].V == %#v (%[2]T) (expected %#v (%[3]T))", i, f2.Values[i].V, f.Values[i].V)
	// 	}
	// }

	intrp2 := f.Unpack("Interpreter").(*interpreter.Interpreter)
	intrp2.Run()
	if v := intrp2.Value(); v != data.Number(987) {
		t.Errorf("intrp2.Value() == %#v (expected %#v)", v, data.Number(987))
	}
}

// var fibonacci = function(n, output) {
//   var a = 1, b = 1, sum;
//   for (var i = 0; i < n; i++) {
//     output.push(a);
//     sum = a + b;
//     a = b;
//     b = sum;
//   }
// }
// fibonacci(16, result);
// result[15];
const fibonacci = `{"type":"Program","start":0,"end":206,"body":[{"type":"VariableDeclaration","start":0,"end":16,"declarations":[{"type":"VariableDeclarator","start":4,"end":15,"id":{"type":"Identifier","start":4,"end":10,"name":"result"},"init":{"type":"ArrayExpression","start":13,"end":15,"elements":[]}}],"kind":"var"},{"type":"FunctionDeclaration","start":17,"end":172,"id":{"type":"Identifier","start":26,"end":35,"name":"fibonacci"},"params":[{"type":"Identifier","start":36,"end":37,"name":"n"},{"type":"Identifier","start":39,"end":45,"name":"output"}],"body":{"type":"BlockStatement","start":47,"end":172,"body":[{"type":"VariableDeclaration","start":51,"end":73,"declarations":[{"type":"VariableDeclarator","start":55,"end":60,"id":{"type":"Identifier","start":55,"end":56,"name":"a"},"init":{"type":"Literal","start":59,"end":60,"value":1,"raw":"1"}},{"type":"VariableDeclarator","start":62,"end":67,"id":{"type":"Identifier","start":62,"end":63,"name":"b"},"init":{"type":"Literal","start":66,"end":67,"value":1,"raw":"1"}},{"type":"VariableDeclarator","start":69,"end":72,"id":{"type":"Identifier","start":69,"end":72,"name":"sum"},"init":null}],"kind":"var"},{"type":"ForStatement","start":76,"end":170,"init":{"type":"VariableDeclaration","start":81,"end":90,"declarations":[{"type":"VariableDeclarator","start":85,"end":90,"id":{"type":"Identifier","start":85,"end":86,"name":"i"},"init":{"type":"Literal","start":89,"end":90,"value":0,"raw":"0"}}],"kind":"var"},"test":{"type":"BinaryExpression","start":92,"end":97,"left":{"type":"Identifier","start":92,"end":93,"name":"i"},"operator":"<","right":{"type":"Identifier","start":96,"end":97,"name":"n"}},"update":{"type":"UpdateExpression","start":99,"end":102,"operator":"++","prefix":false,"argument":{"type":"Identifier","start":99,"end":100,"name":"i"}},"body":{"type":"BlockStatement","start":104,"end":170,"body":[{"type":"ExpressionStatement","start":110,"end":125,"expression":{"type":"CallExpression","start":110,"end":124,"callee":{"type":"MemberExpression","start":110,"end":121,"object":{"type":"Identifier","start":110,"end":116,"name":"output"},"property":{"type":"Identifier","start":117,"end":121,"name":"push"},"computed":false},"arguments":[{"type":"Identifier","start":122,"end":123,"name":"a"}]}},{"type":"ExpressionStatement","start":130,"end":142,"expression":{"type":"AssignmentExpression","start":130,"end":141,"operator":"=","left":{"type":"Identifier","start":130,"end":133,"name":"sum"},"right":{"type":"BinaryExpression","start":136,"end":141,"left":{"type":"Identifier","start":136,"end":137,"name":"a"},"operator":"+","right":{"type":"Identifier","start":140,"end":141,"name":"b"}}}},{"type":"ExpressionStatement","start":147,"end":153,"expression":{"type":"AssignmentExpression","start":147,"end":152,"operator":"=","left":{"type":"Identifier","start":147,"end":148,"name":"a"},"right":{"type":"Identifier","start":151,"end":152,"name":"b"}}},{"type":"ExpressionStatement","start":158,"end":166,"expression":{"type":"AssignmentExpression","start":158,"end":165,"operator":"=","left":{"type":"Identifier","start":158,"end":159,"name":"b"},"right":{"type":"Identifier","start":162,"end":165,"name":"sum"}}}]}}]}},{"type":"ExpressionStatement","start":173,"end":195,"expression":{"type":"CallExpression","start":173,"end":194,"callee":{"type":"Identifier","start":173,"end":182,"name":"fibonacci"},"arguments":[{"type":"Literal","start":183,"end":185,"value":16,"raw":"16"},{"type":"Identifier","start":187,"end":193,"name":"result"}]}},{"type":"ExpressionStatement","start":196,"end":206,"expression":{"type":"MemberExpression","start":196,"end":206,"object":{"type":"Identifier","start":196,"end":202,"name":"result"},"property":{"type":"Literal","start":203,"end":205,"value":15,"raw":"15"},"computed":true}}]}`
<commit_msg>Use RecEqual instead of DeepEqual<commit_after>/* Copyright 2017 Google Inc.
 * https://github.com/NeilFraser/CodeCity
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package flatpack_test

import (
	"encoding/json"
	"fmt"
	"testing"

	"CodeCity/server/flatpack"
	"CodeCity/server/interpreter"
	"CodeCity/server/interpreter/data"
	"CodeCity/server/testutil"
)

// FIXME: add a more general (and more comprehensive) example.

func Example() {
	intrp, _ := interpreter.NewFromJSON(fibonacci)
	for i := 0; i < 500 && intrp.Step(); i++ {
	}
	var f = flatpack.New()
	f.Pack("Interpreter", intrp)

	b, e := json.MarshalIndent(f, "", "  ")
	if e != nil {
		panic(e)
	}
	fmt.Printf("%s\n", string(b))
	// // Output:
}

func TestRoundTripInterpreter(t *testing.T) {
	// t.SkipNow()
	intrp, _ := interpreter.NewFromJSON(fibonacci)
	for i := 0; i < 500 && intrp.Step(); i++ {
	}
	var f = flatpack.New()
	f.Pack("Interpreter", intrp)
	f.Seal()

	b, e := json.MarshalIndent(f, "", "  ")
	if e != nil {
		t.Error(e)
	}
	var f2 *flatpack.Flatpack
	e = json.Unmarshal(b, &f2)
	if e != nil {
		t.Error(e)
	}

	if !testutil.RecEqual(f, f2, true) {
		t.Errorf("testutil.RecEqual(%#v, %#v, true) == false", f2, f)
	}
	// These versions might be more helpful in diagnosis:
	// if !reflect.DeepEqual(f.Labels, f2.Labels) {
	// 	t.Errorf("%#v != %#v", f2.Labels, f.Labels)
	// }
	// for i := 0; i < len(f.Values); i++ {
	// 	if f.Values[i].T != f2.Values[i].T {
	// 		t.Errorf("Values[%d].T == %#v (expected %#v)", i, f2.Values[i].T, f.Values[i].T)
	// 	}
	// 	if !reflect.DeepEqual(f.Values[i].V, f2.Values[i].V) {
	// 		t.Errorf("Values[%d].V == %#v (%[2]T) (expected %#v (%[3]T))", i, f2.Values[i].V, f.Values[i].V)
	// 	}
	// }

	intrp2 := f.Unpack("Interpreter").(*interpreter.Interpreter)
	intrp2.Run()
	if v := intrp2.Value(); v != data.Number(987) {
		t.Errorf("intrp2.Value() == %#v (expected %#v)", v, data.Number(987))
	}
}

// var fibonacci = function(n, output) {
//   var a = 1, b = 1, sum;
//   for (var i = 0; i < n; i++) {
//     output.push(a);
//     sum = a + b;
//     a = b;
//     b = sum;
//   }
// }
// fibonacci(16, result);
// result[15];
const fibonacci = `{"type":"Program","start":0,"end":206,"body":[{"type":"VariableDeclaration","start":0,"end":16,"declarations":[{"type":"VariableDeclarator","start":4,"end":15,"id":{"type":"Identifier","start":4,"end":10,"name":"result"},"init":{"type":"ArrayExpression","start":13,"end":15,"elements":[]}}],"kind":"var"},{"type":"FunctionDeclaration","start":17,"end":172,"id":{"type":"Identifier","start":26,"end":35,"name":"fibonacci"},"params":[{"type":"Identifier","start":36,"end":37,"name":"n"},{"type":"Identifier","start":39,"end":45,"name":"output"}],"body":{"type":"BlockStatement","start":47,"end":172,"body":[{"type":"VariableDeclaration","start":51,"end":73,"declarations":[{"type":"VariableDeclarator","start":55,"end":60,"id":{"type":"Identifier","start":55,"end":56,"name":"a"},"init":{"type":"Literal","start":59,"end":60,"value":1,"raw":"1"}},{"type":"VariableDeclarator","start":62,"end":67,"id":{"type":"Identifier","start":62,"end":63,"name":"b"},"init":{"type":"Literal","start":66,"end":67,"value":1,"raw":"1"}},{"type":"VariableDeclarator","start":69,"end":72,"id":{"type":"Identifier","start":69,"end":72,"name":"sum"},"init":null}],"kind":"var"},{"type":"ForStatement","start":76,"end":170,"init":{"type":"VariableDeclaration","start":81,"end":90,"declarations":[{"type":"VariableDeclarator","start":85,"end":90,"id":{"type":"Identifier","start":85,"end":86,"name":"i"},"init":{"type":"Literal","start":89,"end":90,"value":0,"raw":"0"}}],"kind":"var"},"test":{"type":"BinaryExpression","start":92,"end":97,"left":{"type":"Identifier","start":92,"end":93,"name":"i"},"operator":"<","right":{"type":"Identifier","start":96,"end":97,"name":"n"}},"update":{"type":"UpdateExpression","start":99,"end":102,"operator":"++","prefix":false,"argument":{"type":"Identifier","start":99,"end":100,"name":"i"}},"body":{"type":"BlockStatement","start":104,"end":170,"body":[{"type":"ExpressionStatement","start":110,"end":125,"expression":{"type":"CallExpression","start":110,"end":124,"callee":{"type":"MemberExpression","start":110,"end":121,"object":{"type":"Identifier","start":110,"end":116,"name":"output"},"property":{"type":"Identifier","start":117,"end":121,"name":"push"},"computed":false},"arguments":[{"type":"Identifier","start":122,"end":123,"name":"a"}]}},{"type":"ExpressionStatement","start":130,"end":142,"expression":{"type":"AssignmentExpression","start":130,"end":141,"operator":"=","left":{"type":"Identifier","start":130,"end":133,"name":"sum"},"right":{"type":"BinaryExpression","start":136,"end":141,"left":{"type":"Identifier","start":136,"end":137,"name":"a"},"operator":"+","right":{"type":"Identifier","start":140,"end":141,"name":"b"}}}},{"type":"ExpressionStatement","start":147,"end":153,"expression":{"type":"AssignmentExpression","start":147,"end":152,"operator":"=","left":{"type":"Identifier","start":147,"end":148,"name":"a"},"right":{"type":"Identifier","start":151,"end":152,"name":"b"}}},{"type":"ExpressionStatement","start":158,"end":166,"expression":{"type":"AssignmentExpression","start":158,"end":165,"operator":"=","left":{"type":"Identifier","start":158,"end":159,"name":"b"},"right":{"type":"Identifier","start":162,"end":165,"name":"sum"}}}]}}]}},{"type":"ExpressionStatement","start":173,"end":195,"expression":{"type":"CallExpression","start":173,"end":194,"callee":{"type":"Identifier","start":173,"end":182,"name":"fibonacci"},"arguments":[{"type":"Literal","start":183,"end":185,"value":16,"raw":"16"},{"type":"Identifier","start":187,"end":193,"name":"result"}]}},{"type":"ExpressionStatement","start":196,"end":206,"expression":{"type":"MemberExpression","start":196,"end":206,"object":{"type":"Identifier","start":196,"end":202,"name":"result"},"property":{"type":"Literal","start":203,"end":205,"value":15,"raw":"15"},"computed":true}}]}`
<|endoftext|>


<commit_before>// Package swarm implements a connection muxer with a pair of channels
// to synchronize all network communication.
package swarm

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"

	metrics "github.com/libp2p/go-libp2p/p2p/metrics"
	mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn"
	inet "github.com/libp2p/go-libp2p/p2p/net"
	conn "github.com/libp2p/go-libp2p/p2p/net/conn"
	filter "github.com/libp2p/go-libp2p/p2p/net/filter"
	addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr"

	ci "github.com/ipfs/go-libp2p-crypto"
	peer "github.com/ipfs/go-libp2p-peer"
	pstore "github.com/ipfs/go-libp2p-peerstore"
	transport "github.com/ipfs/go-libp2p-transport"
	logging "github.com/ipfs/go-log"
	ma "github.com/jbenet/go-multiaddr"
	ps "github.com/jbenet/go-peerstream"
	pst "github.com/jbenet/go-stream-muxer"
	"github.com/jbenet/goprocess"
	goprocessctx "github.com/jbenet/goprocess/context"
	psmss "github.com/whyrusleeping/go-smux-multistream"
	spdy "github.com/whyrusleeping/go-smux-spdystream"
	yamux "github.com/whyrusleeping/go-smux-yamux"
	mafilter "github.com/whyrusleeping/multiaddr-filter"
	ws "github.com/whyrusleeping/ws-transport"
	context "golang.org/x/net/context"
)

var log = logging.Logger("swarm2")

// PSTransport is the default peerstream transport that will be used by
// any libp2p swarms.
var PSTransport pst.Transport

func init() {
	msstpt := psmss.NewBlankTransport()

	ymxtpt := &yamux.Transport{
		AcceptBacklog:          8192,
		ConnectionWriteTimeout: time.Second * 10,
		KeepAliveInterval:      time.Second * 30,
		EnableKeepAlive:        true,
		MaxStreamWindowSize:    uint32(1024 * 512),
		LogOutput:              ioutil.Discard,
	}

	msstpt.AddTransport("/yamux/1.0.0", ymxtpt)
	msstpt.AddTransport("/spdy/3.1.0", spdy.Transport)

	// allow overriding of muxer preferences
	if prefs := os.Getenv("LIBP2P_MUX_PREFS"); prefs != "" {
		msstpt.OrderPreference = strings.Fields(prefs)
	}

	PSTransport = msstpt
}

// Swarm is a connection muxer, allowing connections to other peers to
// be opened and closed, while still using the same Chan for all
// communication. The Chan sends/receives Messages, which note the
// destination or source Peer.
//
// Uses peerstream.Swarm
type Swarm struct {
	swarm *ps.Swarm
	local peer.ID
	peers pstore.Peerstore
	connh ConnHandler

	dsync dialsync
	backf dialbackoff
	dialT time.Duration // mainly for tests

	dialer *conn.Dialer

	notifmu sync.RWMutex
	notifs  map[inet.Notifiee]ps.Notifiee

	transports []transport.Transport

	// filters for addresses that shouldnt be dialed
	Filters *filter.Filters

	// file descriptor rate limited
	fdRateLimit chan struct{}

	proc goprocess.Process
	ctx  context.Context
	bwc  metrics.Reporter

	limiter *dialLimiter
}

// NewSwarm constructs a Swarm, with a Chan.
func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr,
	local peer.ID, peers pstore.Peerstore, bwc metrics.Reporter) (*Swarm, error) {

	listenAddrs, err := filterAddrs(listenAddrs)
	if err != nil {
		return nil, err
	}

	wrap := func(c transport.Conn) transport.Conn {
		return mconn.WrapConn(bwc, c)
	}

	s := &Swarm{
		swarm:  ps.NewSwarm(PSTransport),
		local:  local,
		peers:  peers,
		ctx:    ctx,
		dialT:  DialTimeout,
		notifs: make(map[inet.Notifiee]ps.Notifiee),
		transports: []transport.Transport{
			transport.NewTCPTransport(),
			transport.NewUtpTransport(),
			new(ws.WebsocketTransport),
		},
		bwc:         bwc,
		fdRateLimit: make(chan struct{}, concurrentFdDials),
		Filters:     filter.NewFilters(),
		dialer:      conn.NewDialer(local, peers.PrivKey(local), wrap),
	}

	s.limiter = newDialLimiter(s.dialAddr)

	// configure Swarm
	s.proc = goprocessctx.WithContextAndTeardown(ctx, s.teardown)
	s.SetConnHandler(nil) // make sure to setup our own conn handler.

	err = s.setupInterfaces(listenAddrs)
	if err != nil {
		return nil, err
	}

	return s, nil
}

func NewBlankSwarm(ctx context.Context, id peer.ID, privkey ci.PrivKey) *Swarm {
	s := &Swarm{
		swarm:       ps.NewSwarm(PSTransport),
		local:       id,
		peers:       pstore.NewPeerstore(),
		ctx:         ctx,
		dialT:       DialTimeout,
		notifs:      make(map[inet.Notifiee]ps.Notifiee),
		fdRateLimit: make(chan struct{}, concurrentFdDials),
		Filters:     filter.NewFilters(),
		dialer:      conn.NewDialer(id, privkey, nil),
	}

	// configure Swarm
	s.limiter = newDialLimiter(s.dialAddr)
	s.proc = goprocessctx.WithContextAndTeardown(ctx, s.teardown)
	s.SetConnHandler(nil) // make sure to setup our own conn handler.

	return s
}

func (s *Swarm) AddTransport(t transport.Transport) {
	s.transports = append(s.transports, t)
}

func (s *Swarm) teardown() error {
	return s.swarm.Close()
}

// AddAddrFilter adds a multiaddr filter to the set of filters the swarm will
// use to determine which addresses not to dial to.
func (s *Swarm) AddAddrFilter(f string) error {
	m, err := mafilter.NewMask(f)
	if err != nil {
		return err
	}

	s.Filters.AddDialFilter(m)
	return nil
}

func filterAddrs(listenAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
	if len(listenAddrs) > 0 {
		filtered := addrutil.FilterUsableAddrs(listenAddrs)
		if len(filtered) < 1 {
			return nil, fmt.Errorf("swarm cannot use any addr in: %s", listenAddrs)
		}
		listenAddrs = filtered
	}

	return listenAddrs, nil
}

// Listen sets up listeners for all of the given addresses
func (s *Swarm) Listen(addrs ...ma.Multiaddr) error {
	addrs, err := filterAddrs(addrs)
	if err != nil {
		return err
	}

	return s.setupInterfaces(addrs)
}

// Process returns the Process of the swarm
func (s *Swarm) Process() goprocess.Process {
	return s.proc
}

// Context returns the context of the swarm
func (s *Swarm) Context() context.Context {
	return s.ctx
}

// Close stops the Swarm.
func (s *Swarm) Close() error {
	return s.proc.Close()
}

// StreamSwarm returns the underlying peerstream.Swarm
func (s *Swarm) StreamSwarm() *ps.Swarm {
	return s.swarm
}

// SetConnHandler assigns the handler for new connections.
// See peerstream. You will rarely use this. See SetStreamHandler
func (s *Swarm) SetConnHandler(handler ConnHandler) {

	// handler is nil if user wants to clear the old handler.
	if handler == nil {
		s.swarm.SetConnHandler(func(psconn *ps.Conn) {
			s.connHandler(psconn)
		})
		return
	}

	s.swarm.SetConnHandler(func(psconn *ps.Conn) {
		// sc is nil if closed in our handler.
		if sc := s.connHandler(psconn); sc != nil {
			// call the user's handler. in a goroutine for sync safety.
			go handler(sc)
		}
	})
}

// SetStreamHandler assigns the handler for new streams.
// See peerstream.
func (s *Swarm) SetStreamHandler(handler inet.StreamHandler) {
	s.swarm.SetStreamHandler(func(s *ps.Stream) {
		handler(wrapStream(s))
	})
}

// NewStreamWithPeer creates a new stream on any available connection to p
func (s *Swarm) NewStreamWithPeer(ctx context.Context, p peer.ID) (*Stream, error) {
	// if we have no connections, try connecting.
	if len(s.ConnectionsToPeer(p)) == 0 {
		log.Debug("Swarm: NewStreamWithPeer no connections. Attempting to connect...")
		if _, err := s.Dial(ctx, p); err != nil {
			return nil, err
		}
	}
	log.Debug("Swarm: NewStreamWithPeer...")

	// TODO: think about passing a context down to NewStreamWithGroup
	st, err := s.swarm.NewStreamWithGroup(p)
	return wrapStream(st), err
}

// StreamsWithPeer returns all the live Streams to p
func (s *Swarm) StreamsWithPeer(p peer.ID) []*Stream {
	return wrapStreams(ps.StreamsWithGroup(p, s.swarm.Streams()))
}

// ConnectionsToPeer returns all the live connections to p
func (s *Swarm) ConnectionsToPeer(p peer.ID) []*Conn {
	return wrapConns(ps.ConnsWithGroup(p, s.swarm.Conns()))
}

// Connections returns a slice of all connections.
func (s *Swarm) Connections() []*Conn {
	return wrapConns(s.swarm.Conns())
}

// CloseConnection removes a given peer from swarm + closes the connection
func (s *Swarm) CloseConnection(p peer.ID) error {
	conns := s.swarm.ConnsWithGroup(p) // boom.
	for _, c := range conns {
		c.Close()
	}
	return nil
}

// Peers returns a copy of the set of peers swarm is connected to.
func (s *Swarm) Peers() []peer.ID {
	conns := s.Connections()

	seen := make(map[peer.ID]struct{})
	peers := make([]peer.ID, 0, len(conns))
	for _, c := range conns {
		p := c.RemotePeer()
		if _, found := seen[p]; found {
			continue
		}

		seen[p] = struct{}{}
		peers = append(peers, p)
	}
	return peers
}

// LocalPeer returns the local peer swarm is associated to.
func (s *Swarm) LocalPeer() peer.ID {
	return s.local
}

// Backoff returns the dialbackoff object for this swarm.
func (s *Swarm) Backoff() *dialbackoff {
	return &s.backf
}

// notifyAll sends a signal to all Notifiees
func (s *Swarm) notifyAll(notify func(inet.Notifiee)) {
	s.notifmu.RLock()
	for f := range s.notifs {
		go notify(f)
	}
	s.notifmu.RUnlock()
}

// Notify signs up Notifiee to receive signals when events happen
func (s *Swarm) Notify(f inet.Notifiee) {
	// wrap with our notifiee, to translate function calls
	n := &ps2netNotifee{net: (*Network)(s), not: f}

	s.notifmu.Lock()
	s.notifs[f] = n
	s.notifmu.Unlock()

	// register for notifications in the peer swarm.
	s.swarm.Notify(n)
}

// StopNotify unregisters Notifiee fromr receiving signals
func (s *Swarm) StopNotify(f inet.Notifiee) {
	s.notifmu.Lock()
	n, found := s.notifs[f]
	if found {
		delete(s.notifs, f)
	}
	s.notifmu.Unlock()

	if found {
		s.swarm.StopNotify(n)
	}
}

type ps2netNotifee struct {
	net *Network
	not inet.Notifiee
}

func (n *ps2netNotifee) Connected(c *ps.Conn) {
	n.not.Connected(n.net, inet.Conn((*Conn)(c)))
}

func (n *ps2netNotifee) Disconnected(c *ps.Conn) {
	n.not.Disconnected(n.net, inet.Conn((*Conn)(c)))
}

func (n *ps2netNotifee) OpenedStream(s *ps.Stream) {
	n.not.OpenedStream(n.net, &Stream{stream: s})
}

func (n *ps2netNotifee) ClosedStream(s *ps.Stream) {
	n.not.ClosedStream(n.net, &Stream{stream: s})
}
<commit_msg>swarm: pass in stream muxer on construct<commit_after>// Package swarm implements a connection muxer with a pair of channels
// to synchronize all network communication.
package swarm

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"

	metrics "github.com/libp2p/go-libp2p/p2p/metrics"
	mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn"
	inet "github.com/libp2p/go-libp2p/p2p/net"
	conn "github.com/libp2p/go-libp2p/p2p/net/conn"
	filter "github.com/libp2p/go-libp2p/p2p/net/filter"
	addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr"

	ci "github.com/ipfs/go-libp2p-crypto"
	peer "github.com/ipfs/go-libp2p-peer"
	pstore "github.com/ipfs/go-libp2p-peerstore"
	transport "github.com/ipfs/go-libp2p-transport"
	logging "github.com/ipfs/go-log"
	ma "github.com/jbenet/go-multiaddr"
	ps "github.com/jbenet/go-peerstream"
	pst "github.com/jbenet/go-stream-muxer"
	"github.com/jbenet/goprocess"
	goprocessctx "github.com/jbenet/goprocess/context"
	psmss "github.com/whyrusleeping/go-smux-multistream"
	spdy "github.com/whyrusleeping/go-smux-spdystream"
	yamux "github.com/whyrusleeping/go-smux-yamux"
	mafilter "github.com/whyrusleeping/multiaddr-filter"
	ws "github.com/whyrusleeping/ws-transport"
	context "golang.org/x/net/context"
)

var log = logging.Logger("swarm2")

// PSTransport is the default peerstream transport that will be used by
// any libp2p swarms.
var PSTransport pst.Transport

func init() {
	msstpt := psmss.NewBlankTransport()

	ymxtpt := &yamux.Transport{
		AcceptBacklog:          8192,
		ConnectionWriteTimeout: time.Second * 10,
		KeepAliveInterval:      time.Second * 30,
		EnableKeepAlive:        true,
		MaxStreamWindowSize:    uint32(1024 * 512),
		LogOutput:              ioutil.Discard,
	}

	msstpt.AddTransport("/yamux/1.0.0", ymxtpt)
	msstpt.AddTransport("/spdy/3.1.0", spdy.Transport)

	// allow overriding of muxer preferences
	if prefs := os.Getenv("LIBP2P_MUX_PREFS"); prefs != "" {
		msstpt.OrderPreference = strings.Fields(prefs)
	}

	PSTransport = msstpt
}

// Swarm is a connection muxer, allowing connections to other peers to
// be opened and closed, while still using the same Chan for all
// communication. The Chan sends/receives Messages, which note the
// destination or source Peer.
//
// Uses peerstream.Swarm
type Swarm struct {
	swarm *ps.Swarm
	local peer.ID
	peers pstore.Peerstore
	connh ConnHandler

	dsync dialsync
	backf dialbackoff
	dialT time.Duration // mainly for tests

	dialer *conn.Dialer

	notifmu sync.RWMutex
	notifs  map[inet.Notifiee]ps.Notifiee

	transports []transport.Transport

	// filters for addresses that shouldnt be dialed
	Filters *filter.Filters

	// file descriptor rate limited
	fdRateLimit chan struct{}

	proc goprocess.Process
	ctx  context.Context
	bwc  metrics.Reporter

	limiter *dialLimiter
}

// NewSwarm constructs a Swarm, with a Chan.
func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr,
	local peer.ID, peers pstore.Peerstore, bwc metrics.Reporter) (*Swarm, error) {

	listenAddrs, err := filterAddrs(listenAddrs)
	if err != nil {
		return nil, err
	}

	wrap := func(c transport.Conn) transport.Conn {
		return mconn.WrapConn(bwc, c)
	}

	s := &Swarm{
		swarm:  ps.NewSwarm(PSTransport),
		local:  local,
		peers:  peers,
		ctx:    ctx,
		dialT:  DialTimeout,
		notifs: make(map[inet.Notifiee]ps.Notifiee),
		transports: []transport.Transport{
			transport.NewTCPTransport(),
			transport.NewUtpTransport(),
			new(ws.WebsocketTransport),
		},
		bwc:         bwc,
		fdRateLimit: make(chan struct{}, concurrentFdDials),
		Filters:     filter.NewFilters(),
		dialer:      conn.NewDialer(local, peers.PrivKey(local), wrap),
	}

	s.limiter = newDialLimiter(s.dialAddr)

	// configure Swarm
	s.proc = goprocessctx.WithContextAndTeardown(ctx, s.teardown)
	s.SetConnHandler(nil) // make sure to setup our own conn handler.

	err = s.setupInterfaces(listenAddrs)
	if err != nil {
		return nil, err
	}

	return s, nil
}

func NewBlankSwarm(ctx context.Context, id peer.ID, privkey ci.PrivKey, pstpt pst.Transport) *Swarm {
	s := &Swarm{
		swarm:       ps.NewSwarm(pstpt),
		local:       id,
		peers:       pstore.NewPeerstore(),
		ctx:         ctx,
		dialT:       DialTimeout,
		notifs:      make(map[inet.Notifiee]ps.Notifiee),
		fdRateLimit: make(chan struct{}, concurrentFdDials),
		Filters:     filter.NewFilters(),
		dialer:      conn.NewDialer(id, privkey, nil),
	}

	// configure Swarm
	s.limiter = newDialLimiter(s.dialAddr)
	s.proc = goprocessctx.WithContextAndTeardown(ctx, s.teardown)
	s.SetConnHandler(nil) // make sure to setup our own conn handler.

	return s
}

func (s *Swarm) AddTransport(t transport.Transport) {
	s.transports = append(s.transports, t)
}

func (s *Swarm) teardown() error {
	return s.swarm.Close()
}

// AddAddrFilter adds a multiaddr filter to the set of filters the swarm will
// use to determine which addresses not to dial to.
func (s *Swarm) AddAddrFilter(f string) error {
	m, err := mafilter.NewMask(f)
	if err != nil {
		return err
	}

	s.Filters.AddDialFilter(m)
	return nil
}

func filterAddrs(listenAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
	if len(listenAddrs) > 0 {
		filtered := addrutil.FilterUsableAddrs(listenAddrs)
		if len(filtered) < 1 {
			return nil, fmt.Errorf("swarm cannot use any addr in: %s", listenAddrs)
		}
		listenAddrs = filtered
	}

	return listenAddrs, nil
}

// Listen sets up listeners for all of the given addresses
func (s *Swarm) Listen(addrs ...ma.Multiaddr) error {
	addrs, err := filterAddrs(addrs)
	if err != nil {
		return err
	}

	return s.setupInterfaces(addrs)
}

// Process returns the Process of the swarm
func (s *Swarm) Process() goprocess.Process {
	return s.proc
}

// Context returns the context of the swarm
func (s *Swarm) Context() context.Context {
	return s.ctx
}

// Close stops the Swarm.
func (s *Swarm) Close() error {
	return s.proc.Close()
}

// StreamSwarm returns the underlying peerstream.Swarm
func (s *Swarm) StreamSwarm() *ps.Swarm {
	return s.swarm
}

// SetConnHandler assigns the handler for new connections.
// See peerstream. You will rarely use this. See SetStreamHandler
func (s *Swarm) SetConnHandler(handler ConnHandler) {

	// handler is nil if user wants to clear the old handler.
	if handler == nil {
		s.swarm.SetConnHandler(func(psconn *ps.Conn) {
			s.connHandler(psconn)
		})
		return
	}

	s.swarm.SetConnHandler(func(psconn *ps.Conn) {
		// sc is nil if closed in our handler.
		if sc := s.connHandler(psconn); sc != nil {
			// call the user's handler. in a goroutine for sync safety.
			go handler(sc)
		}
	})
}

// SetStreamHandler assigns the handler for new streams.
// See peerstream.
func (s *Swarm) SetStreamHandler(handler inet.StreamHandler) {
	s.swarm.SetStreamHandler(func(s *ps.Stream) {
		handler(wrapStream(s))
	})
}

// NewStreamWithPeer creates a new stream on any available connection to p
func (s *Swarm) NewStreamWithPeer(ctx context.Context, p peer.ID) (*Stream, error) {
	// if we have no connections, try connecting.
	if len(s.ConnectionsToPeer(p)) == 0 {
		log.Debug("Swarm: NewStreamWithPeer no connections. Attempting to connect...")
		if _, err := s.Dial(ctx, p); err != nil {
			return nil, err
		}
	}
	log.Debug("Swarm: NewStreamWithPeer...")

	// TODO: think about passing a context down to NewStreamWithGroup
	st, err := s.swarm.NewStreamWithGroup(p)
	return wrapStream(st), err
}

// StreamsWithPeer returns all the live Streams to p
func (s *Swarm) StreamsWithPeer(p peer.ID) []*Stream {
	return wrapStreams(ps.StreamsWithGroup(p, s.swarm.Streams()))
}

// ConnectionsToPeer returns all the live connections to p
func (s *Swarm) ConnectionsToPeer(p peer.ID) []*Conn {
	return wrapConns(ps.ConnsWithGroup(p, s.swarm.Conns()))
}

// Connections returns a slice of all connections.
func (s *Swarm) Connections() []*Conn {
	return wrapConns(s.swarm.Conns())
}

// CloseConnection removes a given peer from swarm + closes the connection
func (s *Swarm) CloseConnection(p peer.ID) error {
	conns := s.swarm.ConnsWithGroup(p) // boom.
	for _, c := range conns {
		c.Close()
	}
	return nil
}

// Peers returns a copy of the set of peers swarm is connected to.
func (s *Swarm) Peers() []peer.ID {
	conns := s.Connections()

	seen := make(map[peer.ID]struct{})
	peers := make([]peer.ID, 0, len(conns))
	for _, c := range conns {
		p := c.RemotePeer()
		if _, found := seen[p]; found {
			continue
		}

		seen[p] = struct{}{}
		peers = append(peers, p)
	}
	return peers
}

// LocalPeer returns the local peer swarm is associated to.
func (s *Swarm) LocalPeer() peer.ID {
	return s.local
}

// Backoff returns the dialbackoff object for this swarm.
func (s *Swarm) Backoff() *dialbackoff {
	return &s.backf
}

// notifyAll sends a signal to all Notifiees
func (s *Swarm) notifyAll(notify func(inet.Notifiee)) {
	s.notifmu.RLock()
	for f := range s.notifs {
		go notify(f)
	}
	s.notifmu.RUnlock()
}

// Notify signs up Notifiee to receive signals when events happen
func (s *Swarm) Notify(f inet.Notifiee) {
	// wrap with our notifiee, to translate function calls
	n := &ps2netNotifee{net: (*Network)(s), not: f}

	s.notifmu.Lock()
	s.notifs[f] = n
	s.notifmu.Unlock()

	// register for notifications in the peer swarm.
	s.swarm.Notify(n)
}

// StopNotify unregisters Notifiee fromr receiving signals
func (s *Swarm) StopNotify(f inet.Notifiee) {
	s.notifmu.Lock()
	n, found := s.notifs[f]
	if found {
		delete(s.notifs, f)
	}
	s.notifmu.Unlock()

	if found {
		s.swarm.StopNotify(n)
	}
}

type ps2netNotifee struct {
	net *Network
	not inet.Notifiee
}

func (n *ps2netNotifee) Connected(c *ps.Conn) {
	n.not.Connected(n.net, inet.Conn((*Conn)(c)))
}

func (n *ps2netNotifee) Disconnected(c *ps.Conn) {
	n.not.Disconnected(n.net, inet.Conn((*Conn)(c)))
}

func (n *ps2netNotifee) OpenedStream(s *ps.Stream) {
	n.not.OpenedStream(n.net, &Stream{stream: s})
}

func (n *ps2netNotifee) ClosedStream(s *ps.Stream) {
	n.not.ClosedStream(n.net, &Stream{stream: s})
}
<|endoftext|>


<commit_before>package keydbstore

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/dancannon/gorethink"
	"github.com/docker/notary/passphrase"
	"github.com/docker/notary/storage/rethinkdb"
	"github.com/docker/notary/trustmanager"
	"github.com/docker/notary/tuf/data"
	jose "github.com/dvsekhvalnov/jose2go"
)

// RethinkDBKeyStore persists and manages private keys on a RethinkDB database
type RethinkDBKeyStore struct {
	lock             *sync.Mutex
	sess             *gorethink.Session
	defaultPassAlias string
	retriever        passphrase.Retriever
	cachedKeys       map[string]data.PrivateKey
}

// RDBPrivateKey represents a PrivateKey in the rethink database
type RDBPrivateKey struct {
	rethinkdb.Timing
	KeyID           string `gorethink:"key_id"`
	EncryptionAlg   string `gorethink:"encryption_alg"`
	KeywrapAlg      string `gorethink:"keywrap_alg"`
	Algorithm       string `gorethink:"algorithm"`
	PassphraseAlias string `gorethink:"passphrase_alias"`
	Public          string `gorethink:"public"`
	Private         string `gorethink:"private"`
}

var privateKeys = rethinkdb.Table{
	Name:       RDBPrivateKey{}.TableName(),
	PrimaryKey: RDBPrivateKey{}.KeyID,
}

// TableName sets a specific table name for our RDBPrivateKey
func (g RDBPrivateKey) TableName() string {
	return "private_keys"
}

// NewRethinkDBKeyStore returns a new RethinkDBKeyStore backed by a RethinkDB database
func NewRethinkDBKeyStore(passphraseRetriever passphrase.Retriever, defaultPassAlias string, rethinkSession *gorethink.Session) *RethinkDBKeyStore {
	cachedKeys := make(map[string]data.PrivateKey)

	return &RethinkDBKeyStore{
		lock:             &sync.Mutex{},
		sess:             rethinkSession,
		defaultPassAlias: defaultPassAlias,
		retriever:        passphraseRetriever,
		cachedKeys:       cachedKeys,
	}
}

// Name returns a user friendly name for the storage location
func (rdb *RethinkDBKeyStore) Name() string {
	return "RethinkDB"
}

func (rdb RethinkDBKeyStore) dbName() string {
	return "notarysigner"
}

// AddKey stores the contents of a private key. Both role and gun are ignored,
// we always use Key IDs as name, and don't support aliases
func (rdb *RethinkDBKeyStore) AddKey(keyInfo trustmanager.KeyInfo, privKey data.PrivateKey) error {

	passphrase, _, err := rdb.retriever(privKey.ID(), rdb.defaultPassAlias, false, 1)
	if err != nil {
		return err
	}

	encryptedKey, err := jose.Encrypt(string(privKey.Private()), KeywrapAlg, EncryptionAlg, passphrase)
	if err != nil {
		return err
	}

	now := time.Now()
	rethinkPrivKey := RDBPrivateKey{
		Timing: rethinkdb.Timing{
			CreatedAt: now,
			UpdatedAt: now,
		},
		KeyID:           privKey.ID(),
		EncryptionAlg:   EncryptionAlg,
		KeywrapAlg:      KeywrapAlg,
		PassphraseAlias: rdb.defaultPassAlias,
		Algorithm:       privKey.Algorithm(),
		Public:          string(privKey.Public()),
		Private:         encryptedKey}

	// Add encrypted private key to the database
	_, err = gorethink.DB(rdb.dbName()).Table(rethinkPrivKey.TableName()).Insert(rethinkPrivKey).RunWrite(rdb.sess)
	if err != nil {
		return fmt.Errorf("failed to add private key to database: %s", privKey.ID())
	}

	// Add the private key to our cache
	rdb.lock.Lock()
	defer rdb.lock.Unlock()
	rdb.cachedKeys[privKey.ID()] = privKey

	return nil
}

// GetKey returns the PrivateKey given a KeyID
func (rdb *RethinkDBKeyStore) GetKey(name string) (data.PrivateKey, string, error) {
	rdb.lock.Lock()
	defer rdb.lock.Unlock()
	cachedKeyEntry, ok := rdb.cachedKeys[name]
	if ok {
		return cachedKeyEntry, "", nil
	}

	// Retrieve the RethinkDB private key from the database
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("key_id").Eq(name)).Run(rdb.sess)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}

	// Get the passphrase to use for this key
	passphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return nil, "", err
	}

	// Decrypt private bytes from the gorm key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	// Add the key to cache
	rdb.cachedKeys[privKey.ID()] = privKey

	return privKey, "", nil
}

// GetKeyInfo always returns empty and an error. This method is here to satisfy the KeyStore interface
func (rdb RethinkDBKeyStore) GetKeyInfo(name string) (trustmanager.KeyInfo, error) {
	return trustmanager.KeyInfo{}, fmt.Errorf("GetKeyInfo currently not supported for RethinkDBKeyStore, as it does not track roles or GUNs")
}

// ListKeys always returns nil. This method is here to satisfy the KeyStore interface
func (rdb RethinkDBKeyStore) ListKeys() map[string]trustmanager.KeyInfo {
	return nil
}

// RemoveKey removes the key from the table
func (rdb RethinkDBKeyStore) RemoveKey(keyID string) error {
	rdb.lock.Lock()
	defer rdb.lock.Unlock()

	delete(rdb.cachedKeys, keyID)

	// Delete the key from the database
	dbPrivateKey := RDBPrivateKey{KeyID: keyID}
	_, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("key_id").Eq(keyID)).Delete().RunWrite(rdb.sess)
	if err != nil {
		return fmt.Errorf("unable to delete private key from database: %s", err.Error())
	}

	return nil
}

// RotateKeyPassphrase rotates the key-encryption-key
func (rdb RethinkDBKeyStore) RotateKeyPassphrase(name, newPassphraseAlias string) error {
	// Retrieve the RethinkDB private key from the database
	dbPrivateKey := RDBPrivateKey{KeyID: name}
	res, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Get(dbPrivateKey).Run(rdb.sess)
	if err != nil {
		return trustmanager.ErrKeyNotFound{}
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err != nil {
		return trustmanager.ErrKeyNotFound{}
	}

	// Get the current passphrase to use for this key
	passphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return err
	}

	// Decrypt private bytes from the rethinkDB key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return err
	}

	// Get the new passphrase to use for this key
	newPassphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, newPassphraseAlias, false, 1)
	if err != nil {
		return err
	}

	// Re-encrypt the private bytes with the new passphrase
	newEncryptedKey, err := jose.Encrypt(decryptedPrivKey, KeywrapAlg, EncryptionAlg, newPassphrase)
	if err != nil {
		return err
	}

	// Update the database object
	dbPrivateKey.Private = newEncryptedKey
	dbPrivateKey.PassphraseAlias = newPassphraseAlias
	if _, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Get(RDBPrivateKey{KeyID: name}).Update(dbPrivateKey).RunWrite(rdb.sess); err != nil {
		return err
	}

	return nil
}

// ExportKey is currently unimplemented and will always return an error
func (rdb RethinkDBKeyStore) ExportKey(keyID string) ([]byte, error) {
	return nil, errors.New("Exporting from a RethinkDBKeyStore is not supported.")
}

// Bootstrap sets up the database and tables
func (rdb RethinkDBKeyStore) Bootstrap() error {
	return rethinkdb.SetupDB(rdb.sess, rdb.dbName(), []rethinkdb.Table{
		privateKeys,
	})
}

// CheckHealth verifies that DB exists and is query-able
func (rdb RethinkDBKeyStore) CheckHealth() error {
	var tableOk bool
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName()).TableList().Contains(dbPrivateKey.TableName()).Run(rdb.sess)
	if err != nil {
		return err
	}
	defer res.Close()
	err = res.One(tableOk)
	if err != nil || !tableOk {
		return fmt.Errorf(
			"Cannot access table: %s", dbPrivateKey.TableName())
	}
	return nil
}
<commit_msg>Fix signer rethink health check query<commit_after>package keydbstore

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/dancannon/gorethink"
	"github.com/docker/notary/passphrase"
	"github.com/docker/notary/storage/rethinkdb"
	"github.com/docker/notary/trustmanager"
	"github.com/docker/notary/tuf/data"
	"github.com/docker/notary/tuf/utils"
	jose "github.com/dvsekhvalnov/jose2go"
)

// RethinkDBKeyStore persists and manages private keys on a RethinkDB database
type RethinkDBKeyStore struct {
	lock             *sync.Mutex
	sess             *gorethink.Session
	defaultPassAlias string
	retriever        passphrase.Retriever
	cachedKeys       map[string]data.PrivateKey
}

// RDBPrivateKey represents a PrivateKey in the rethink database
type RDBPrivateKey struct {
	rethinkdb.Timing
	KeyID           string `gorethink:"key_id"`
	EncryptionAlg   string `gorethink:"encryption_alg"`
	KeywrapAlg      string `gorethink:"keywrap_alg"`
	Algorithm       string `gorethink:"algorithm"`
	PassphraseAlias string `gorethink:"passphrase_alias"`
	Public          string `gorethink:"public"`
	Private         string `gorethink:"private"`
}

var privateKeys = rethinkdb.Table{
	Name:       RDBPrivateKey{}.TableName(),
	PrimaryKey: RDBPrivateKey{}.KeyID,
}

// TableName sets a specific table name for our RDBPrivateKey
func (g RDBPrivateKey) TableName() string {
	return "private_keys"
}

// NewRethinkDBKeyStore returns a new RethinkDBKeyStore backed by a RethinkDB database
func NewRethinkDBKeyStore(passphraseRetriever passphrase.Retriever, defaultPassAlias string, rethinkSession *gorethink.Session) *RethinkDBKeyStore {
	cachedKeys := make(map[string]data.PrivateKey)

	return &RethinkDBKeyStore{
		lock:             &sync.Mutex{},
		sess:             rethinkSession,
		defaultPassAlias: defaultPassAlias,
		retriever:        passphraseRetriever,
		cachedKeys:       cachedKeys,
	}
}

// Name returns a user friendly name for the storage location
func (rdb *RethinkDBKeyStore) Name() string {
	return "RethinkDB"
}

func (rdb RethinkDBKeyStore) dbName() string {
	return "notarysigner"
}

// AddKey stores the contents of a private key. Both role and gun are ignored,
// we always use Key IDs as name, and don't support aliases
func (rdb *RethinkDBKeyStore) AddKey(keyInfo trustmanager.KeyInfo, privKey data.PrivateKey) error {

	passphrase, _, err := rdb.retriever(privKey.ID(), rdb.defaultPassAlias, false, 1)
	if err != nil {
		return err
	}

	encryptedKey, err := jose.Encrypt(string(privKey.Private()), KeywrapAlg, EncryptionAlg, passphrase)
	if err != nil {
		return err
	}

	now := time.Now()
	rethinkPrivKey := RDBPrivateKey{
		Timing: rethinkdb.Timing{
			CreatedAt: now,
			UpdatedAt: now,
		},
		KeyID:           privKey.ID(),
		EncryptionAlg:   EncryptionAlg,
		KeywrapAlg:      KeywrapAlg,
		PassphraseAlias: rdb.defaultPassAlias,
		Algorithm:       privKey.Algorithm(),
		Public:          string(privKey.Public()),
		Private:         encryptedKey}

	// Add encrypted private key to the database
	_, err = gorethink.DB(rdb.dbName()).Table(rethinkPrivKey.TableName()).Insert(rethinkPrivKey).RunWrite(rdb.sess)
	if err != nil {
		return fmt.Errorf("failed to add private key to database: %s", privKey.ID())
	}

	// Add the private key to our cache
	rdb.lock.Lock()
	defer rdb.lock.Unlock()
	rdb.cachedKeys[privKey.ID()] = privKey

	return nil
}

// GetKey returns the PrivateKey given a KeyID
func (rdb *RethinkDBKeyStore) GetKey(name string) (data.PrivateKey, string, error) {
	rdb.lock.Lock()
	defer rdb.lock.Unlock()
	cachedKeyEntry, ok := rdb.cachedKeys[name]
	if ok {
		return cachedKeyEntry, "", nil
	}

	// Retrieve the RethinkDB private key from the database
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("key_id").Eq(name)).Run(rdb.sess)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}

	// Get the passphrase to use for this key
	passphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return nil, "", err
	}

	// Decrypt private bytes from the gorm key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	// Add the key to cache
	rdb.cachedKeys[privKey.ID()] = privKey

	return privKey, "", nil
}

// GetKeyInfo always returns empty and an error. This method is here to satisfy the KeyStore interface
func (rdb RethinkDBKeyStore) GetKeyInfo(name string) (trustmanager.KeyInfo, error) {
	return trustmanager.KeyInfo{}, fmt.Errorf("GetKeyInfo currently not supported for RethinkDBKeyStore, as it does not track roles or GUNs")
}

// ListKeys always returns nil. This method is here to satisfy the KeyStore interface
func (rdb RethinkDBKeyStore) ListKeys() map[string]trustmanager.KeyInfo {
	return nil
}

// RemoveKey removes the key from the table
func (rdb RethinkDBKeyStore) RemoveKey(keyID string) error {
	rdb.lock.Lock()
	defer rdb.lock.Unlock()

	delete(rdb.cachedKeys, keyID)

	// Delete the key from the database
	dbPrivateKey := RDBPrivateKey{KeyID: keyID}
	_, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("key_id").Eq(keyID)).Delete().RunWrite(rdb.sess)
	if err != nil {
		return fmt.Errorf("unable to delete private key from database: %s", err.Error())
	}

	return nil
}

// RotateKeyPassphrase rotates the key-encryption-key
func (rdb RethinkDBKeyStore) RotateKeyPassphrase(name, newPassphraseAlias string) error {
	// Retrieve the RethinkDB private key from the database
	dbPrivateKey := RDBPrivateKey{KeyID: name}
	res, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Get(dbPrivateKey).Run(rdb.sess)
	if err != nil {
		return trustmanager.ErrKeyNotFound{}
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err != nil {
		return trustmanager.ErrKeyNotFound{}
	}

	// Get the current passphrase to use for this key
	passphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return err
	}

	// Decrypt private bytes from the rethinkDB key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return err
	}

	// Get the new passphrase to use for this key
	newPassphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, newPassphraseAlias, false, 1)
	if err != nil {
		return err
	}

	// Re-encrypt the private bytes with the new passphrase
	newEncryptedKey, err := jose.Encrypt(decryptedPrivKey, KeywrapAlg, EncryptionAlg, newPassphrase)
	if err != nil {
		return err
	}

	// Update the database object
	dbPrivateKey.Private = newEncryptedKey
	dbPrivateKey.PassphraseAlias = newPassphraseAlias
	if _, err := gorethink.DB(rdb.dbName()).Table(dbPrivateKey.TableName()).Get(RDBPrivateKey{KeyID: name}).Update(dbPrivateKey).RunWrite(rdb.sess); err != nil {
		return err
	}

	return nil
}

// ExportKey is currently unimplemented and will always return an error
func (rdb RethinkDBKeyStore) ExportKey(keyID string) ([]byte, error) {
	return nil, errors.New("Exporting from a RethinkDBKeyStore is not supported.")
}

// Bootstrap sets up the database and tables
func (rdb RethinkDBKeyStore) Bootstrap() error {
	return rethinkdb.SetupDB(rdb.sess, rdb.dbName(), []rethinkdb.Table{
		privateKeys,
	})
}

// CheckHealth verifies that DB exists and is query-able
func (rdb RethinkDBKeyStore) CheckHealth() error {
	var tables []string
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName()).TableList().Run(rdb.sess)
	if err != nil {
		return err
	}
	defer res.Close()
	err = res.All(&tables)
	if err != nil || !utils.StrSliceContains(tables, dbPrivateKey.TableName()) {
		return fmt.Errorf(
			"Cannot access table: %s", dbPrivateKey.TableName())
	}
	return nil
}
<|endoftext|>


<commit_before>package ui

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"log"
	"time"

	"github.com/ninjasphere/go-gestic"
	"github.com/ninjasphere/sphere-go-led-controller/fonts/O4b03b"
)

type ColorPane struct {
	image  *image.RGBA
	color  func() color.Color
	draw   func()
	bounds func() image.Rectangle
}

func NewColorPane(in color.Color) *ColorPane {
	pane := &ColorPane{
		color: func() color.Color {
			return in
		},
		image: image.NewRGBA(image.Rect(0, 0, width, height)),
	}
	pane.draw = func() {
		draw.Draw(pane.image, pane.bounds(), &image.Uniform{pane.color()}, image.ZP, draw.Src)
	}
	pane.bounds = func() image.Rectangle {
		return pane.image.Bounds()
	}
	return pane
}

func NewFadingColorPane(in color.Color, d time.Duration) *ColorPane {

	pane := NewColorPane(in)
	start := time.Now()
	pane.color = func() color.Color {
		n := time.Now().Sub(start)
		ratio := 1.0
		if n < d {
			ratio = float64(n) / float64(d)
		}
		r, g, b, a := in.RGBA()
		return color.RGBA{
			R: uint8(uint16((1.0-ratio)*float64(r)) >> 8),
			G: uint8(uint16((1.0-ratio)*float64(g)) >> 8),
			B: uint8(uint16((1.0-ratio)*float64(b)) >> 8),
			A: uint8(a),
		}
	}
	return pane
}
	}
}

func (p *ColorPane) Gesture(gesture *gestic.GestureData) {

}

func (p *ColorPane) Render() (*image.RGBA, error) {
	p.draw()
	return p.image, nil
}

func (p *ColorPane) IsDirty() bool {
	return false
}

type TextScrollPane struct {
	text      string
	textWidth int
	position  int
	start     time.Time
}

func NewTextScrollPane(text string) *TextScrollPane {

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	width := O4b03b.Font.DrawString(img, 0, 0, text, color.Black)
	log.Printf("Text '%s' width: %d", text, width)

	return &TextScrollPane{
		text:      text,
		textWidth: width,
		position:  17,
		start:     time.Now(),
	}
}

func (p *TextScrollPane) Gesture(gesture *gestic.GestureData) {

}

func (p *TextScrollPane) Render() (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	p.position = p.position - 1
	if p.position < -p.textWidth {
		p.position = 17
	}

	log.Printf("Rendering text '%s' at position %d", p.text, p.position)

	O4b03b.Font.DrawString(img, p.position, 0, p.text, color.White)

	elapsed := time.Now().Sub(p.start)

	elapsedSeconds := int(elapsed.Seconds())

	O4b03b.Font.DrawString(img, 0, 5, "Hey! :)", color.RGBA{0, 255, 255, 255})

	O4b03b.Font.DrawString(img, 0, 11, "02", color.RGBA{255, 0, 0, 255})

	O4b03b.Font.DrawString(img, 9, 11, fmt.Sprintf("%0d", elapsedSeconds), color.RGBA{255, 0, 0, 255})

	O4b03b.Font.DrawString(img, 8, 11, ":", color.RGBA{255, 255, 255, 255})

	return img, nil
}

func (p *TextScrollPane) IsDirty() bool {
	return true
}

type PairingCodePane struct {
	text      string
	textWidth int
}

func NewPairingCodePane(text string) *PairingCodePane {

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	width := O4b03b.Font.DrawString(img, 0, 0, text, color.Black)
	log.Printf("Text '%s' width: %d", text, width)

	return &PairingCodePane{
		text:      text,
		textWidth: width,
	}
}

func (p *PairingCodePane) Gesture(gesture *gestic.GestureData) {

}

func (p *PairingCodePane) Render() (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	log.Printf("Rendering text '%s'")

	start := 8 - int((float64(p.textWidth) / float64(2)))

	O4b03b.Font.DrawString(img, start, 4, p.text, color.White)

	return img, nil
}

func (p *PairingCodePane) IsDirty() bool {
	return true
}
<commit_msg>An implementation of a color pane that shrinks as it fades.<commit_after>package ui

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"log"
	"time"

	"github.com/ninjasphere/go-gestic"
	"github.com/ninjasphere/sphere-go-led-controller/fonts/O4b03b"
)

type ColorPane struct {
	image  *image.RGBA
	color  func() color.Color
	draw   func()
	bounds func() image.Rectangle
}

func NewColorPane(in color.Color) *ColorPane {
	pane := &ColorPane{
		color: func() color.Color {
			return in
		},
		image: image.NewRGBA(image.Rect(0, 0, width, height)),
	}
	pane.draw = func() {
		draw.Draw(pane.image, pane.bounds(), &image.Uniform{pane.color()}, image.ZP, draw.Src)
	}
	pane.bounds = func() image.Rectangle {
		return pane.image.Bounds()
	}
	return pane
}

func NewFadingColorPane(in color.Color, d time.Duration) *ColorPane {

	pane := NewColorPane(in)
	start := time.Now()
	pane.color = func() color.Color {
		n := time.Now().Sub(start)
		ratio := 1.0
		if n < d {
			ratio = float64(n) / float64(d)
		}
		r, g, b, a := in.RGBA()
		return color.RGBA{
			R: uint8(uint16((1.0-ratio)*float64(r)) >> 8),
			G: uint8(uint16((1.0-ratio)*float64(g)) >> 8),
			B: uint8(uint16((1.0-ratio)*float64(b)) >> 8),
			A: uint8(a),
		}
	}
	return pane
}

// creates a pane that fades and shrinks towards the center as time progresses
func NewFadingShrinkingColorPane(in color.Color, d time.Duration) *ColorPane {

	pane := NewFadingColorPane(in, d)
	basicDraw := pane.draw
	start := time.Now()
	black := color.RGBA{
		R: 0,
		G: 0,
		B: 0,
		A: 0,
	}

	pane.bounds = func() image.Rectangle {
		n := time.Now().Sub(start)
		dim := 0
		if d > n && d > 0 {
			dim = int(float64(d-n) * 8.0 / float64(d))
		}
		rect := image.Rectangle{
			Min: image.Point{
				X: 8 - dim,
				Y: 8 - dim,
			},
			Max: image.Point{
				X: 8 + dim,
				Y: 8 + dim,
			},
		}
		return rect
	}

	pane.draw = func() {
		draw.Draw(pane.image, pane.image.Bounds(), &image.Uniform{black}, image.ZP, draw.Src)
		basicDraw()
	}

	return pane
}

func (p *ColorPane) Gesture(gesture *gestic.GestureData) {

}

func (p *ColorPane) Render() (*image.RGBA, error) {
	p.draw()
	return p.image, nil
}

func (p *ColorPane) IsDirty() bool {
	return false
}

type TextScrollPane struct {
	text      string
	textWidth int
	position  int
	start     time.Time
}

func NewTextScrollPane(text string) *TextScrollPane {

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	width := O4b03b.Font.DrawString(img, 0, 0, text, color.Black)
	log.Printf("Text '%s' width: %d", text, width)

	return &TextScrollPane{
		text:      text,
		textWidth: width,
		position:  17,
		start:     time.Now(),
	}
}

func (p *TextScrollPane) Gesture(gesture *gestic.GestureData) {

}

func (p *TextScrollPane) Render() (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	p.position = p.position - 1
	if p.position < -p.textWidth {
		p.position = 17
	}

	log.Printf("Rendering text '%s' at position %d", p.text, p.position)

	O4b03b.Font.DrawString(img, p.position, 0, p.text, color.White)

	elapsed := time.Now().Sub(p.start)

	elapsedSeconds := int(elapsed.Seconds())

	O4b03b.Font.DrawString(img, 0, 5, "Hey! :)", color.RGBA{0, 255, 255, 255})

	O4b03b.Font.DrawString(img, 0, 11, "02", color.RGBA{255, 0, 0, 255})

	O4b03b.Font.DrawString(img, 9, 11, fmt.Sprintf("%0d", elapsedSeconds), color.RGBA{255, 0, 0, 255})

	O4b03b.Font.DrawString(img, 8, 11, ":", color.RGBA{255, 255, 255, 255})

	return img, nil
}

func (p *TextScrollPane) IsDirty() bool {
	return true
}

type PairingCodePane struct {
	text      string
	textWidth int
}

func NewPairingCodePane(text string) *PairingCodePane {

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	width := O4b03b.Font.DrawString(img, 0, 0, text, color.Black)
	log.Printf("Text '%s' width: %d", text, width)

	return &PairingCodePane{
		text:      text,
		textWidth: width,
	}
}

func (p *PairingCodePane) Gesture(gesture *gestic.GestureData) {

}

func (p *PairingCodePane) Render() (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	log.Printf("Rendering text '%s'")

	start := 8 - int((float64(p.textWidth) / float64(2)))

	O4b03b.Font.DrawString(img, start, 4, p.text, color.White)

	return img, nil
}

func (p *PairingCodePane) IsDirty() bool {
	return true
}
<|endoftext|>


<commit_before>package crawler

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	cfg "github.com/elastic/filebeat/config"
	"github.com/elastic/filebeat/input"
	. "github.com/elastic/filebeat/input"
	"github.com/elastic/libbeat/logp"
)

type Registrar struct {
	// Path to the Registry File
	registryFile string
	// Map with all file paths inside and the corresponding state
	State map[string]*FileState
	// Channel used by the prospector and crawler to send FileStates to be persisted
	Persist chan *input.FileState
	running bool
	Channel chan []*FileEvent
}

func NewRegistrar(registryFile string) (*Registrar, error) {

	r := &Registrar{
		registryFile: registryFile,
	}
	err := r.Init()

	return r, err
}

func (r *Registrar) Init() error {
	// Init state
	r.Persist = make(chan *FileState)
	r.State = make(map[string]*FileState)
	r.Channel = make(chan []*FileEvent, 1)

	// Set to default in case it is not set
	if r.registryFile == "" {
		r.registryFile = cfg.DefaultRegistryFile
	}

	// Make sure the directory where we store the registryFile exists
	absPath, err := filepath.Abs(r.registryFile)
	if err != nil {
		return fmt.Errorf("Failed to get the absolute path for %s: %v", r.registryFile, err)
	}
	err = os.MkdirAll(filepath.Dir(absPath), 0755)
	if err != nil {
		return fmt.Errorf("Failed to created folder %s: %v", filepath.Dir(absPath), err)
	}

	logp.Debug("registrar", "Registry file set to: %s", r.registryFile)

	return nil
}

// loadState fetches the previous reading state from the configure RegistryFile file
// The default file is .filebeat file which is stored in the same path as the binary is running
func (r *Registrar) LoadState() {

	if existing, e := os.Open(r.registryFile); e == nil {
		defer existing.Close()
		wd := ""
		if wd, e = os.Getwd(); e != nil {
			logp.Warn("WARNING: os.Getwd retuned unexpected error %s -- ignoring", e.Error())
		}
		logp.Info("Loading registrar data from %s/%s", wd, r.registryFile)

		decoder := json.NewDecoder(existing)
		decoder.Decode(&r.State)
	}
}

func (r *Registrar) Run() {
	logp.Debug("registrar", "Starting Registrar")

	r.running = true

	// Writes registry
	defer r.writeRegistry()

	for events := range r.Channel {
		logp.Debug("registrar", "Registrar: processing %d events", len(events))
		// Take the last event found for each file source
		for _, event := range events {

			if !r.running {
				break
			}

			// skip stdin
			if *event.Source == "-" {
				continue
			}

			r.State[*event.Source] = event.GetState()
		}

		if e := r.writeRegistry(); e != nil {
			// REVU: but we should panic, or something, right?
			logp.Err("Update of registry returned error: %v. Continuing..", e)
		}

		if !r.running {
			break
		}
	}
	logp.Debug("registrar", "Ending Registrar")
}

func (r *Registrar) Stop() {
	r.running = false
	close(r.Channel)
	r.writeRegistry()
}

func (r *Registrar) GetFileState(path string) (*FileState, bool) {
	state, exist := r.State[path]
	return state, exist
}

// writeRegistry Writes the new json registry file  to disk
func (r *Registrar) writeRegistry() error {
	logp.Debug("registrar", "Write registry file: %s", r.registryFile)

	tempfile := r.registryFile + ".new"
	file, e := os.Create(tempfile)
	if e != nil {
		logp.Err("Failed to create tempfile (%s) for writing: %s", tempfile, e)
		return e
	}

	encoder := json.NewEncoder(file)
	encoder.Encode(r.State)

	// Directly close file because of windows
	file.Close()

	return SafeFileRotate(r.registryFile, tempfile)
}

func (r *Registrar) fetchState(filePath string, fileInfo os.FileInfo) (int64, bool) {

	// Check if there is a state for this file
	lastState, isFound := r.GetFileState(filePath)

	if isFound && input.IsSameFile(filePath, fileInfo) {
		// We're resuming - throw the last state back downstream so we resave it
		// And return the offset - also force harvest in case the file is old and we're about to skip it
		r.Persist <- lastState
		return lastState.Offset, true
	}

	if previous := r.getPreviousFile(filePath, fileInfo); previous != "" {
		// File has rotated between shutdown and startup
		// We return last state downstream, with a modified event source with the new file name
		// And return the offset - also force harvest in case the file is old and we're about to skip it
		logp.Debug("prospector", "Detected rename of a previously harvested file: %s -> %s", previous, filePath)

		lastState, _ := r.GetFileState(previous)
		lastState.Source = &filePath
		r.Persist <- lastState
		return lastState.Offset, true
	}

	if isFound {
		logp.Debug("prospector", "Not resuming rotated file: %s", filePath)
	}

	// New file so just start from an automatic position
	return 0, false
}

// getPreviousFile checks in the registrar if there is the newFile already exist with a different name
// In case an old file is found, the path to the file is returned
func (r *Registrar) getPreviousFile(newFilePath string, newFileInfo os.FileInfo) string {

	newState := input.GetOSFileState(&newFileInfo)

	for oldFilePath, oldState := range r.State {

		// Skipping when path the same
		if oldFilePath == newFilePath {
			continue
		}

		// Compare states
		if newState.IsSame(oldState.FileStateOS) {
			return oldFilePath

		}
	}

	return ""
}
<commit_msg>signal filebeat registrar to shutdown<commit_after>package crawler

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	cfg "github.com/elastic/filebeat/config"
	"github.com/elastic/filebeat/input"
	. "github.com/elastic/filebeat/input"
	"github.com/elastic/libbeat/logp"
)

type Registrar struct {
	// Path to the Registry File
	registryFile string
	// Map with all file paths inside and the corresponding state
	State map[string]*FileState
	// Channel used by the prospector and crawler to send FileStates to be persisted
	Persist chan *input.FileState
	running bool

	Channel chan []*FileEvent
	done    chan struct{}
}

func NewRegistrar(registryFile string) (*Registrar, error) {

	r := &Registrar{
		registryFile: registryFile,
		done:         make(chan struct{}),
	}
	err := r.Init()

	return r, err
}

func (r *Registrar) Init() error {
	// Init state
	r.Persist = make(chan *FileState)
	r.State = make(map[string]*FileState)
	r.Channel = make(chan []*FileEvent, 1)

	// Set to default in case it is not set
	if r.registryFile == "" {
		r.registryFile = cfg.DefaultRegistryFile
	}

	// Make sure the directory where we store the registryFile exists
	absPath, err := filepath.Abs(r.registryFile)
	if err != nil {
		return fmt.Errorf("Failed to get the absolute path for %s: %v", r.registryFile, err)
	}
	err = os.MkdirAll(filepath.Dir(absPath), 0755)
	if err != nil {
		return fmt.Errorf("Failed to created folder %s: %v", filepath.Dir(absPath), err)
	}

	logp.Debug("registrar", "Registry file set to: %s", r.registryFile)

	return nil
}

// loadState fetches the previous reading state from the configure RegistryFile file
// The default file is .filebeat file which is stored in the same path as the binary is running
func (r *Registrar) LoadState() {

	if existing, e := os.Open(r.registryFile); e == nil {
		defer existing.Close()
		wd := ""
		if wd, e = os.Getwd(); e != nil {
			logp.Warn("WARNING: os.Getwd retuned unexpected error %s -- ignoring", e.Error())
		}
		logp.Info("Loading registrar data from %s/%s", wd, r.registryFile)

		decoder := json.NewDecoder(existing)
		decoder.Decode(&r.State)
	}
}

func (r *Registrar) Run() {
	logp.Debug("registrar", "Starting Registrar")

	r.running = true

	// Writes registry on shutdown
	defer r.writeRegistry()

	for {
		var events []*FileEvent
		select {
		case <-r.done:
			logp.Debug("registrar", "Ending Registrar")
			return
		case events = <-r.Channel:
		}

		logp.Debug("registrar", "Registrar: processing %d events", len(events))

		// Take the last event found for each file source
		for _, event := range events {
			if !r.running {
				break
			}

			// skip stdin
			if *event.Source == "-" {
				continue
			}

			r.State[*event.Source] = event.GetState()
		}

		if e := r.writeRegistry(); e != nil {
			// REVU: but we should panic, or something, right?
			logp.Err("Update of registry returned error: %v. Continuing..", e)
		}
	}
}

func (r *Registrar) Stop() {
	r.running = false
	close(r.done)
	// Note: don't block using waitGroup, cause this method is run by async signal handler
}

func (r *Registrar) GetFileState(path string) (*FileState, bool) {
	state, exist := r.State[path]
	return state, exist
}

// writeRegistry Writes the new json registry file  to disk
func (r *Registrar) writeRegistry() error {
	logp.Debug("registrar", "Write registry file: %s", r.registryFile)

	tempfile := r.registryFile + ".new"
	file, e := os.Create(tempfile)
	if e != nil {
		logp.Err("Failed to create tempfile (%s) for writing: %s", tempfile, e)
		return e
	}

	encoder := json.NewEncoder(file)
	encoder.Encode(r.State)

	// Directly close file because of windows
	file.Close()

	return SafeFileRotate(r.registryFile, tempfile)
}

func (r *Registrar) fetchState(filePath string, fileInfo os.FileInfo) (int64, bool) {

	// Check if there is a state for this file
	lastState, isFound := r.GetFileState(filePath)

	if isFound && input.IsSameFile(filePath, fileInfo) {
		// We're resuming - throw the last state back downstream so we resave it
		// And return the offset - also force harvest in case the file is old and we're about to skip it
		r.Persist <- lastState
		return lastState.Offset, true
	}

	if previous := r.getPreviousFile(filePath, fileInfo); previous != "" {
		// File has rotated between shutdown and startup
		// We return last state downstream, with a modified event source with the new file name
		// And return the offset - also force harvest in case the file is old and we're about to skip it
		logp.Debug("prospector", "Detected rename of a previously harvested file: %s -> %s", previous, filePath)

		lastState, _ := r.GetFileState(previous)
		lastState.Source = &filePath
		r.Persist <- lastState
		return lastState.Offset, true
	}

	if isFound {
		logp.Debug("prospector", "Not resuming rotated file: %s", filePath)
	}

	// New file so just start from an automatic position
	return 0, false
}

// getPreviousFile checks in the registrar if there is the newFile already exist with a different name
// In case an old file is found, the path to the file is returned
func (r *Registrar) getPreviousFile(newFilePath string, newFileInfo os.FileInfo) string {

	newState := input.GetOSFileState(&newFileInfo)

	for oldFilePath, oldState := range r.State {

		// Skipping when path the same
		if oldFilePath == newFilePath {
			continue
		}

		// Compare states
		if newState.IsSame(oldState.FileStateOS) {
			return oldFilePath

		}
	}

	return ""
}
<|endoftext|>