<commit_before>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     February 27, 2018
;       related version of root zone:     2018022701
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<commit_msg>auto-update<commit_after>package dnsr

var root = `
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC
;       under anonymous FTP as
;           file                /domain/named.cache
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:     March 07, 2018
;       related version of root zone:     2018030701
;
; FORMERLY NS.INTERNIC.NET
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
;
; FORMERLY NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
;
; FORMERLY C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
;
; FORMERLY TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
;
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
;
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
;
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
;
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
;
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
;
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
;
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file`
<|endoftext|>


<commit_before>package game

import (
	"errors"
	"strconv"
	"strings"

	"github.com/ghthor/engine/net/protocol"
	"github.com/ghthor/engine/rpg2d"
	"github.com/ghthor/engine/rpg2d/coord"
	"github.com/ghthor/engine/rpg2d/entity"
	"github.com/ghthor/engine/sim/stime"
)

type actorCmd struct {
	timeIssued stime.Time
	cmd        string
	params     string
}

type moveRequest struct {
	stime.Time
	coord.Direction
}

type actorCmdRequest struct {
	*moveRequest
}

type actorConn struct {
	// Comm interface to muxer used by WriteInput() method
	submitCmd chan<- actorCmd

	// Comm interface to muxer used by getEntity() method
	readCmdReq <-chan *actorCmdRequest

	// Comm interface to muxer used by SendState() method
	sendState chan<- *rpg2d.WorldState

	// Comm interface to muxer used by stopIO() method
	stop chan<- chan<- struct{}

	// External connection used to publish the world state
	protocol.Conn

	lastState rpg2d.WorldState
}

func newActorConn(conn protocol.Conn) actorConn {
	return actorConn{Conn: conn}
}

// Object stored in the quad tree
type actorEntity struct {
	id int64

	name string

	cell   coord.Cell
	facing coord.Direction

	pathAction     *coord.PathAction
	lastMoveAction coord.MoveAction
}

type actorEntityState struct {
	EntityId int64 `json:"id"`

	Name string `json:"name"`

	Facing string     `json:"facing"`
	Cell   coord.Cell `json:"cell"`
	bounds coord.Bounds

	PathAction *coord.PathActionJson `json:"pathAction"`
}

type actor struct {
	actorEntity
	actorConn

	actorCmdRequest
}

func (a *actor) Entity() entity.Entity { return &a.actorEntity }
func (e actorEntity) Id() int64        { return e.id }
func (e actorEntity) Cell() coord.Cell { return e.cell }
func (e actorEntity) Bounds() coord.Bounds {
	bounds := coord.Bounds{
		e.cell,
		e.cell,
	}

	if e.pathAction != nil {
		bounds = coord.JoinBounds(bounds, e.pathAction.Bounds())
	}

	return bounds
}

func (e actorEntity) ToState() entity.State {
	var pathAction *coord.PathActionJson

	if e.pathAction != nil {
		pa := e.pathAction.Json()
		pathAction = &pa
	}

	return actorEntityState{
		EntityId: e.id,

		Name: e.name,

		Cell:   e.cell,
		Facing: e.facing.String(),

		bounds: e.Bounds(),

		PathAction: pathAction,
	}
}

func (e actorEntityState) Id() int64            { return e.EntityId }
func (e actorEntityState) Bounds() coord.Bounds { return e.bounds }
func (e actorEntityState) IsDifferentFrom(other entity.State) (different bool) {
	o := other.(actorEntityState)

	switch {
	case e.Facing != o.Facing:
		return true
	case e.PathAction != nil && o.PathAction != nil:
		if *e.PathAction != *o.PathAction {
			return true
		}
	case e.bounds != o.bounds:
		return true
	}

	return false
}

func (a *actorConn) startIO() {
	// Setup communication channels
	cmdCh := make(chan actorCmd)
	cmdReqCh := make(chan *actorCmdRequest)
	outputCh := make(chan *rpg2d.WorldState)
	stopCh := make(chan chan<- struct{})

	// Set the channels accessible to the outside world
	a.submitCmd = cmdCh
	a.readCmdReq = cmdReqCh
	a.sendState = outputCh
	a.stop = stopCh

	// Establish the channel endpoints used inside the go routine
	var newCmd <-chan actorCmd
	var sendCmdReq chan<- *actorCmdRequest
	var newState <-chan *rpg2d.WorldState
	var stopReq <-chan chan<- struct{}

	newCmd = cmdCh
	sendCmdReq = cmdReqCh
	newState = outputCh
	stopReq = stopCh

	go func() {
		var hasStopped chan<- struct{}

		// Buffer of 1 used to store the most recently
		// received actor cmd from the network.
		var cmdReq *actorCmdRequest

		updateCmdReqWith := func(c actorCmd) {
			if cmdReq == nil {
				cmdReq = &actorCmdRequest{}
			}

			switch c.cmd {
			case "move":
				// TODO This is a shit place to be having an error to deal with
				// TODO It needs to be dealt with at the packet handler level
				d, _ := coord.NewDirectionWithString(c.params)

				cmdReq.moveRequest = &moveRequest{
					Time:      stime.Time(c.timeIssued),
					Direction: d,
				}
			case "moveCancel":
				d, _ := coord.NewDirectionWithString(c.params)
				if cmdReq.moveRequest != nil {
					if cmdReq.moveRequest.Direction == d {
						cmdReq.moveRequest = nil
					}
				}
			}
		}

	unlocked:
		// # This select prioritizes the following events.
		// ## 2 potential events to respond to
		// 1. ReadCmdRequest() method requests the actor command request
		// 2. stopIO() method has been called
		select {
		case sendCmdReq <- cmdReq:
			// Transition: unlocked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: unlocked -> exit
			goto exit
		default:
		}

		// ## 3 potential events to respond to
		// 1. SubmitInput() method has been called with a new command
		// 2. ReadCmdRequest() method requests the actor command request
		// 3. stopIO() method has been called
		select {
		case c := <-newCmd:
			updateCmdReqWith(c)

			// Transition: unlocked -> unlocked
			goto unlocked

		case sendCmdReq <- cmdReq:
			// Transition: unlocked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: unlocked -> exit
			goto exit
		}

		panic("unclosed case in unlocked state select")

	locked:
		// Accepting and processing input commands is now on hold

		// ## 3 potential events to respond to
		// 1. WriteState() method has been called with a new world state
		// 2. ReadCmdRequest() method requests the actor command request.. again!
		// 3. stopIO() method has been called
		select {
		case state := <-newState:
			if state != nil {
				a.SendJson("update", state)
			}

			// Reset the cmdReq object
			cmdReq = nil

			// Transition: locked -> unlocked
			goto unlocked

		case sendCmdReq <- cmdReq:
			// Transition: locked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: locked -> exit
			goto exit
		}

		panic("unclosed case in locked state select")
	exit:
		hasStopped <- struct{}{}
	}()
}

func (c actorConn) SubmitCmd(cmd, params string) error {
	parts := strings.Split(cmd, "=")

	if len(parts) != 2 {
		return errors.New("invalid command")
	}

	timeIssued, err := strconv.ParseInt(parts[1], 10, 64)
	if err != nil {
		return err
	}

	c.submitCmd <- actorCmd{
		timeIssued: stime.Time(timeIssued),
		cmd:        parts[0],
		params:     params,
	}

	return nil
}

func (c actorConn) ReadCmdRequest() *actorCmdRequest {
	return <-c.readCmdReq
}

// Culls the world state to the actor's viewport
func (a *actor) WriteState(state rpg2d.WorldState) {
	c := a.Cell()

	state = state.Cull(coord.Bounds{
		c.Add(-26, 26),
		c.Add(26, -26),
	})

	a.actorConn.WriteState(state)
}

// Diffs the world state so only the changes are sent
func (a *actorConn) WriteState(state rpg2d.WorldState) {
	diff := a.lastState.Diff(state)
	a.lastState = state

	// Will need this when I start comparing for terrain type changes
	// a.lastState.Prepare()

	if len(diff.Entities) > 0 || len(diff.Removed) > 0 || diff.TerrainMap != nil {
		diff.Prepare()
		a.sendState <- &diff
	} else {
		a.sendState <- nil
	}
}

func (a actorConn) stopIO() {
	hasStopped := make(chan struct{})

	a.stop <- hasStopped
	<-hasStopped
}
<commit_msg>Improved documentation for WriteState pipeline<commit_after>package game

import (
	"errors"
	"strconv"
	"strings"

	"github.com/ghthor/engine/net/protocol"
	"github.com/ghthor/engine/rpg2d"
	"github.com/ghthor/engine/rpg2d/coord"
	"github.com/ghthor/engine/rpg2d/entity"
	"github.com/ghthor/engine/sim/stime"
)

type actorCmd struct {
	timeIssued stime.Time
	cmd        string
	params     string
}

type moveRequest struct {
	stime.Time
	coord.Direction
}

type actorCmdRequest struct {
	*moveRequest
}

type actorConn struct {
	// Comm interface to muxer used by WriteInput() method
	submitCmd chan<- actorCmd

	// Comm interface to muxer used by getEntity() method
	readCmdReq <-chan *actorCmdRequest

	// Comm interface to muxer used by SendState() method
	sendState chan<- *rpg2d.WorldState

	// Comm interface to muxer used by stopIO() method
	stop chan<- chan<- struct{}

	// External connection used to publish the world state
	protocol.Conn

	lastState rpg2d.WorldState
}

func newActorConn(conn protocol.Conn) actorConn {
	return actorConn{Conn: conn}
}

// Object stored in the quad tree
type actorEntity struct {
	id int64

	name string

	cell   coord.Cell
	facing coord.Direction

	pathAction     *coord.PathAction
	lastMoveAction coord.MoveAction
}

type actorEntityState struct {
	EntityId int64 `json:"id"`

	Name string `json:"name"`

	Facing string     `json:"facing"`
	Cell   coord.Cell `json:"cell"`
	bounds coord.Bounds

	PathAction *coord.PathActionJson `json:"pathAction"`
}

type actor struct {
	actorEntity
	actorConn

	actorCmdRequest
}

func (a *actor) Entity() entity.Entity { return &a.actorEntity }
func (e actorEntity) Id() int64        { return e.id }
func (e actorEntity) Cell() coord.Cell { return e.cell }
func (e actorEntity) Bounds() coord.Bounds {
	bounds := coord.Bounds{
		e.cell,
		e.cell,
	}

	if e.pathAction != nil {
		bounds = coord.JoinBounds(bounds, e.pathAction.Bounds())
	}

	return bounds
}

func (e actorEntity) ToState() entity.State {
	var pathAction *coord.PathActionJson

	if e.pathAction != nil {
		pa := e.pathAction.Json()
		pathAction = &pa
	}

	return actorEntityState{
		EntityId: e.id,

		Name: e.name,

		Cell:   e.cell,
		Facing: e.facing.String(),

		bounds: e.Bounds(),

		PathAction: pathAction,
	}
}

func (e actorEntityState) Id() int64            { return e.EntityId }
func (e actorEntityState) Bounds() coord.Bounds { return e.bounds }
func (e actorEntityState) IsDifferentFrom(other entity.State) (different bool) {
	o := other.(actorEntityState)

	switch {
	case e.Facing != o.Facing:
		return true
	case e.PathAction != nil && o.PathAction != nil:
		if *e.PathAction != *o.PathAction {
			return true
		}
	case e.bounds != o.bounds:
		return true
	}

	return false
}

func (a *actorConn) startIO() {
	// Setup communication channels
	cmdCh := make(chan actorCmd)
	cmdReqCh := make(chan *actorCmdRequest)
	outputCh := make(chan *rpg2d.WorldState)
	stopCh := make(chan chan<- struct{})

	// Set the channels accessible to the outside world
	a.submitCmd = cmdCh
	a.readCmdReq = cmdReqCh
	a.sendState = outputCh
	a.stop = stopCh

	// Establish the channel endpoints used inside the go routine
	var newCmd <-chan actorCmd
	var sendCmdReq chan<- *actorCmdRequest
	var newState <-chan *rpg2d.WorldState
	var stopReq <-chan chan<- struct{}

	newCmd = cmdCh
	sendCmdReq = cmdReqCh
	newState = outputCh
	stopReq = stopCh

	go func() {
		var hasStopped chan<- struct{}

		// Buffer of 1 used to store the most recently
		// received actor cmd from the network.
		var cmdReq *actorCmdRequest

		updateCmdReqWith := func(c actorCmd) {
			if cmdReq == nil {
				cmdReq = &actorCmdRequest{}
			}

			switch c.cmd {
			case "move":
				// TODO This is a shit place to be having an error to deal with
				// TODO It needs to be dealt with at the packet handler level
				d, _ := coord.NewDirectionWithString(c.params)

				cmdReq.moveRequest = &moveRequest{
					Time:      stime.Time(c.timeIssued),
					Direction: d,
				}
			case "moveCancel":
				d, _ := coord.NewDirectionWithString(c.params)
				if cmdReq.moveRequest != nil {
					if cmdReq.moveRequest.Direction == d {
						cmdReq.moveRequest = nil
					}
				}
			}
		}

	unlocked:
		// # This select prioritizes the following events.
		// ## 2 potential events to respond to
		// 1. ReadCmdRequest() method requests the actor command request
		// 2. stopIO() method has been called
		select {
		case sendCmdReq <- cmdReq:
			// Transition: unlocked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: unlocked -> exit
			goto exit
		default:
		}

		// ## 3 potential events to respond to
		// 1. SubmitInput() method has been called with a new command
		// 2. ReadCmdRequest() method requests the actor command request
		// 3. stopIO() method has been called
		select {
		case c := <-newCmd:
			updateCmdReqWith(c)

			// Transition: unlocked -> unlocked
			goto unlocked

		case sendCmdReq <- cmdReq:
			// Transition: unlocked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: unlocked -> exit
			goto exit
		}

		panic("unclosed case in unlocked state select")

	locked:
		// Accepting and processing input commands is now on hold

		// ## 3 potential events to respond to
		// 1. WriteState() method has been called with a new world state
		// 2. ReadCmdRequest() method requests the actor command request.. again!
		// 3. stopIO() method has been called
		select {
		case state := <-newState:
			if state != nil {
				a.SendJson("update", state)
			}

			// Reset the cmdReq object
			cmdReq = nil

			// Transition: locked -> unlocked
			goto unlocked

		case sendCmdReq <- cmdReq:
			// Transition: locked -> locked
			goto locked

		case hasStopped = <-stopReq:
			// Transition: locked -> exit
			goto exit
		}

		panic("unclosed case in locked state select")
	exit:
		hasStopped <- struct{}{}
	}()
}

func (c actorConn) SubmitCmd(cmd, params string) error {
	parts := strings.Split(cmd, "=")

	if len(parts) != 2 {
		return errors.New("invalid command")
	}

	timeIssued, err := strconv.ParseInt(parts[1], 10, 64)
	if err != nil {
		return err
	}

	c.submitCmd <- actorCmd{
		timeIssued: stime.Time(timeIssued),
		cmd:        parts[0],
		params:     params,
	}

	return nil
}

func (c actorConn) ReadCmdRequest() *actorCmdRequest {
	return <-c.readCmdReq
}

// Culls the world state to the actor's viewport.
// Is called before actorConn.WriteState()
func (a *actor) WriteState(state rpg2d.WorldState) {
	c := a.Cell()

	state = state.Cull(coord.Bounds{
		c.Add(-26, 26),
		c.Add(26, -26),
	})

	a.actorConn.WriteState(state)
}

// Diffs the world state so only the changes are sent.
// Is called after actor.WriteState(). Expects the state
// to have been culled already.
func (a *actorConn) WriteState(state rpg2d.WorldState) {
	diff := a.lastState.Diff(state)
	a.lastState = state

	// Will need this when I start comparing for terrain type changes
	// a.lastState.Prepare()

	if len(diff.Entities) > 0 || len(diff.Removed) > 0 || diff.TerrainMap != nil {
		diff.Prepare()
		a.sendState <- &diff
	} else {
		a.sendState <- nil
	}
}

func (a actorConn) stopIO() {
	hasStopped := make(chan struct{})

	a.stop <- hasStopped
	<-hasStopped
}
<|endoftext|>


<commit_before>/*
Package api holds the models for the API Definition. On this package you can also find the
default errors, handlers, loaders and repositories.
 */
package api
<commit_msg>Formated<commit_after>/*
Package api holds the models for the API Definition. On this package you can also find the
default errors, handlers, loaders and repositories.
*/
package api
<|endoftext|>


<commit_before>/*
Copyright 2021 Intel Corporation

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 sst

import (
	"fmt"
	stdlog "log"
	"os"

	grclog "github.com/intel/goresctrl/pkg/log"
	"github.com/intel/goresctrl/pkg/utils"
)

// SstPackageInfo contains status of Intel Speed Select Technologies (SST)
// for one CPU package
type SstPackageInfo struct {
	// Gereric PP info
	PPSupported    bool
	PPLocked       bool
	PPVersion      int
	PPCurrentLevel int
	PPMaxLevel     int

	// Information about the currently active PP level
	CPSupported bool
	CPEnabled   bool
	CPPriority  CPPriorityType
	BFSupported bool
	BFEnabled   bool
	BFCores     utils.IDSet
	TFSupported bool
	TFEnabled   bool

	ClosInfo [NumClos]SstClosInfo
}

// NumClos is the number of CLOSes suported by SST-CP
const NumClos = 4

// SstClosInfo contains parameters of one CLOS of SST-CP
type SstClosInfo struct {
	EPP                  int
	ProportionalPriority int
	MinFreq              int
	MaxFreq              int
	DesiredFreq          int
}

// CPPriorityType denotes the type CLOS priority ordering used in SST-CP
type CPPriorityType int

const (
	Proportional CPPriorityType = 0
	Ordered      CPPriorityType = 1
)

const isstDevPath = "/dev/isst_interface"

var sstlog grclog.Logger = grclog.NewLoggerWrapper(stdlog.New(os.Stderr, "[ sst ] ", 0))

// SstSupported returns true if Intel Speed Select Technologies (SST) is supported
// by the system and can be interfaced via the Linux kernel device
func SstSupported() bool {
	if _, err := os.Stat(isstDevPath); err != nil {
		if !os.IsNotExist(err) {
			sstlog.Warnf("failed to access sst device %q: %v", isstDevPath, err)
		} else {
			sstlog.Debugf("sst device %q does not exist", isstDevPath)
		}
		return false
	}
	return true
}

// GetPackageInfo returns information of the SST configuration of one cpu
// package.
func GetPackageInfo(pkgId utils.ID) (SstPackageInfo, error) {
	info := SstPackageInfo{}

	// Get topology information from sysfs
	packages, err := getOnlineCpuPackages()
	if err != nil {
		return info, fmt.Errorf("failed to determine cpu topology: %w", err)
	}
	pkg, ok := packages[pkgId]
	if !ok {
		return info, fmt.Errorf("cpu package %d not present", pkgId)
	}
	cpu := pkg.cpus[0] // We just need to pass one logical cpu from the pkg as an arg

	var rsp uint32

	// Read perf-profile feature info
	if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_LEVELS_INFO, 0); err != nil {
		return info, fmt.Errorf("failed to read SST PP info: %v", err)
	}
	info.PPSupported = getBits(rsp, 31, 31) != 0
	info.PPLocked = getBits(rsp, 24, 24) != 0
	info.PPCurrentLevel = int(getBits(rsp, 16, 23))
	info.PPMaxLevel = int(getBits(rsp, 8, 15))
	info.PPVersion = int(getBits(rsp, 0, 7))

	// Forget about older hw with partial/convoluted support
	if info.PPVersion < 3 {
		sstlog.Infof("SST PP version %d (less than 3), giving up...")
		return info, nil
	}

	// Read the status of currently active perf-profile
	if info.PPSupported {
		if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_CONTROL, uint32(info.PPCurrentLevel)); err != nil {
			return info, fmt.Errorf("failed to read SST CP status: %v", err)
		}

		info.BFSupported = isBitSet(rsp, 1)
		info.BFEnabled = isBitSet(rsp, 17)

		info.TFSupported = isBitSet(rsp, 0)
		info.TFEnabled = isBitSet(rsp, 16)

	}

	// Read base-frequency info
	if info.BFSupported {
		info.BFCores = utils.IDSet{}

		punitCoreIDs := make(map[utils.ID]utils.IDSet, len(pkg.cpus))
		var maxPunitCore utils.ID
		for _, id := range pkg.cpus {
			pc, err := punitCPU(id)
			if err != nil {
				return info, err
			}
			punitCore := pc >> 1
			if _, ok := punitCoreIDs[punitCore]; !ok {
				punitCoreIDs[punitCore] = utils.IDSet{}
			}
			punitCoreIDs[punitCore].Add(id)
			if punitCore > maxPunitCore {
				maxPunitCore = punitCore
			}
		}

		// Read out core masks in batches of 32 (32 bits per response)
		for i := 0; i <= int(maxPunitCore)/32; i++ {
			if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_CORE_MASK_INFO, uint32(info.PPCurrentLevel+(i<<8))); err != nil {
				return info, fmt.Errorf("failed to read SST BF core mask (#%d): %v", i, err)
			}
			for bit := 0; bit < 32; bit++ {
				if isBitSet(rsp, uint32(bit)) {
					info.BFCores.Add(punitCoreIDs[utils.ID(i*32+bit)].Members()...)
				}
			}
		}
	}

	// Read core-power feature info
	if rsp, err = sendMboxCmd(cpu, READ_PM_CONFIG, PM_FEATURE, 0); err != nil {
		return info, fmt.Errorf("failed to read SST CP info: %v", err)
	}

	info.CPSupported = isBitSet(rsp, 0)
	info.CPEnabled = isBitSet(rsp, 16)

	if info.CPSupported {
		if rsp, err = sendMboxCmd(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0); err != nil {
			return info, fmt.Errorf("failed to read SST CP status: %v", err)
		}

		closEnabled := isBitSet(rsp, 1)
		if closEnabled != info.CPEnabled {
			sstlog.Warnf("SST firmware returned conflicting CP enabled status %v vs. %v", info.CPEnabled, closEnabled)
		}
		info.CPEnabled = closEnabled
		info.CPPriority = CPPriorityType(getBits(rsp, 2, 2))

		for i := uint32(0); i < NumClos; i++ {
			if rsp, err = sendMMIOCmd(cpu, (i<<2)+PM_CLOS_OFFSET); err != nil {
				return info, fmt.Errorf("failed to read SST CLOS #%d info: %v", i, err)
			}
			info.ClosInfo[i] = SstClosInfo{
				EPP:                  int(getBits(rsp, 0, 3)),
				ProportionalPriority: int(getBits(rsp, 4, 7)),
				MinFreq:              int(getBits(rsp, 8, 15)),
				MaxFreq:              int(getBits(rsp, 16, 23)),
				DesiredFreq:          int(getBits(rsp, 24, 31)),
			}
		}
	}

	return info, nil
}

func getCPUClosID(cpu utils.ID) (int, error) {
	p, err := punitCPU(cpu)
	if err != nil {
		return -1, err
	}
	punitCore := uint32(p) >> 1

	rsp, err := sendMMIOCmd(cpu, (punitCore<<2)+PQR_ASSOC_OFFSET)
	if err != nil {
		return 0, fmt.Errorf("failed to read CLOS number of cpu %d: %v", cpu, err)
	}
	return int(getBits(rsp, 16, 17)), nil
}

func getCPUClosIDs(cpus []utils.ID) ([]int, error) {
	ret := make([]int, len(cpus))
	for i, cpu := range cpus {
		id, err := getCPUClosID(cpu)
		if err != nil {
			return ret, err
		}
		ret[i] = id
	}
	return ret, nil
}

func getBits(val, i, j uint32) uint32 {
	lsb := i
	msb := j
	if i > j {
		lsb = j
		msb = i
	}
	return (val >> lsb) & ((1 << (msb - lsb + 1)) - 1)
}

func isBitSet(val, n uint32) bool {
	return val&(1<<n) != 0
}
<commit_msg>sst: export GetCPUClosID<commit_after>/*
Copyright 2021 Intel Corporation

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 sst

import (
	"fmt"
	stdlog "log"
	"os"

	grclog "github.com/intel/goresctrl/pkg/log"
	"github.com/intel/goresctrl/pkg/utils"
)

// SstPackageInfo contains status of Intel Speed Select Technologies (SST)
// for one CPU package
type SstPackageInfo struct {
	// Gereric PP info
	PPSupported    bool
	PPLocked       bool
	PPVersion      int
	PPCurrentLevel int
	PPMaxLevel     int

	// Information about the currently active PP level
	CPSupported bool
	CPEnabled   bool
	CPPriority  CPPriorityType
	BFSupported bool
	BFEnabled   bool
	BFCores     utils.IDSet
	TFSupported bool
	TFEnabled   bool

	ClosInfo [NumClos]SstClosInfo
}

// NumClos is the number of CLOSes suported by SST-CP
const NumClos = 4

// SstClosInfo contains parameters of one CLOS of SST-CP
type SstClosInfo struct {
	EPP                  int
	ProportionalPriority int
	MinFreq              int
	MaxFreq              int
	DesiredFreq          int
}

// CPPriorityType denotes the type CLOS priority ordering used in SST-CP
type CPPriorityType int

const (
	Proportional CPPriorityType = 0
	Ordered      CPPriorityType = 1
)

const isstDevPath = "/dev/isst_interface"

var sstlog grclog.Logger = grclog.NewLoggerWrapper(stdlog.New(os.Stderr, "[ sst ] ", 0))

// SstSupported returns true if Intel Speed Select Technologies (SST) is supported
// by the system and can be interfaced via the Linux kernel device
func SstSupported() bool {
	if _, err := os.Stat(isstDevPath); err != nil {
		if !os.IsNotExist(err) {
			sstlog.Warnf("failed to access sst device %q: %v", isstDevPath, err)
		} else {
			sstlog.Debugf("sst device %q does not exist", isstDevPath)
		}
		return false
	}
	return true
}

// GetPackageInfo returns information of the SST configuration of one cpu
// package.
func GetPackageInfo(pkgId utils.ID) (SstPackageInfo, error) {
	info := SstPackageInfo{}

	// Get topology information from sysfs
	packages, err := getOnlineCpuPackages()
	if err != nil {
		return info, fmt.Errorf("failed to determine cpu topology: %w", err)
	}
	pkg, ok := packages[pkgId]
	if !ok {
		return info, fmt.Errorf("cpu package %d not present", pkgId)
	}
	cpu := pkg.cpus[0] // We just need to pass one logical cpu from the pkg as an arg

	var rsp uint32

	// Read perf-profile feature info
	if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_LEVELS_INFO, 0); err != nil {
		return info, fmt.Errorf("failed to read SST PP info: %v", err)
	}
	info.PPSupported = getBits(rsp, 31, 31) != 0
	info.PPLocked = getBits(rsp, 24, 24) != 0
	info.PPCurrentLevel = int(getBits(rsp, 16, 23))
	info.PPMaxLevel = int(getBits(rsp, 8, 15))
	info.PPVersion = int(getBits(rsp, 0, 7))

	// Forget about older hw with partial/convoluted support
	if info.PPVersion < 3 {
		sstlog.Infof("SST PP version %d (less than 3), giving up...")
		return info, nil
	}

	// Read the status of currently active perf-profile
	if info.PPSupported {
		if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_CONTROL, uint32(info.PPCurrentLevel)); err != nil {
			return info, fmt.Errorf("failed to read SST CP status: %v", err)
		}

		info.BFSupported = isBitSet(rsp, 1)
		info.BFEnabled = isBitSet(rsp, 17)

		info.TFSupported = isBitSet(rsp, 0)
		info.TFEnabled = isBitSet(rsp, 16)

	}

	// Read base-frequency info
	if info.BFSupported {
		info.BFCores = utils.IDSet{}

		punitCoreIDs := make(map[utils.ID]utils.IDSet, len(pkg.cpus))
		var maxPunitCore utils.ID
		for _, id := range pkg.cpus {
			pc, err := punitCPU(id)
			if err != nil {
				return info, err
			}
			punitCore := pc >> 1
			if _, ok := punitCoreIDs[punitCore]; !ok {
				punitCoreIDs[punitCore] = utils.IDSet{}
			}
			punitCoreIDs[punitCore].Add(id)
			if punitCore > maxPunitCore {
				maxPunitCore = punitCore
			}
		}

		// Read out core masks in batches of 32 (32 bits per response)
		for i := 0; i <= int(maxPunitCore)/32; i++ {
			if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_CORE_MASK_INFO, uint32(info.PPCurrentLevel+(i<<8))); err != nil {
				return info, fmt.Errorf("failed to read SST BF core mask (#%d): %v", i, err)
			}
			for bit := 0; bit < 32; bit++ {
				if isBitSet(rsp, uint32(bit)) {
					info.BFCores.Add(punitCoreIDs[utils.ID(i*32+bit)].Members()...)
				}
			}
		}
	}

	// Read core-power feature info
	if rsp, err = sendMboxCmd(cpu, READ_PM_CONFIG, PM_FEATURE, 0); err != nil {
		return info, fmt.Errorf("failed to read SST CP info: %v", err)
	}

	info.CPSupported = isBitSet(rsp, 0)
	info.CPEnabled = isBitSet(rsp, 16)

	if info.CPSupported {
		if rsp, err = sendMboxCmd(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0); err != nil {
			return info, fmt.Errorf("failed to read SST CP status: %v", err)
		}

		closEnabled := isBitSet(rsp, 1)
		if closEnabled != info.CPEnabled {
			sstlog.Warnf("SST firmware returned conflicting CP enabled status %v vs. %v", info.CPEnabled, closEnabled)
		}
		info.CPEnabled = closEnabled
		info.CPPriority = CPPriorityType(getBits(rsp, 2, 2))

		for i := uint32(0); i < NumClos; i++ {
			if rsp, err = sendMMIOCmd(cpu, (i<<2)+PM_CLOS_OFFSET); err != nil {
				return info, fmt.Errorf("failed to read SST CLOS #%d info: %v", i, err)
			}
			info.ClosInfo[i] = SstClosInfo{
				EPP:                  int(getBits(rsp, 0, 3)),
				ProportionalPriority: int(getBits(rsp, 4, 7)),
				MinFreq:              int(getBits(rsp, 8, 15)),
				MaxFreq:              int(getBits(rsp, 16, 23)),
				DesiredFreq:          int(getBits(rsp, 24, 31)),
			}
		}
	}

	return info, nil
}

// GetCPUClosID returns the SST-CP CLOS id that a cpu is associated with.
func GetCPUClosID(cpu utils.ID) (int, error) {
	p, err := punitCPU(cpu)
	if err != nil {
		return -1, err
	}
	punitCore := uint32(p) >> 1

	rsp, err := sendMMIOCmd(cpu, (punitCore<<2)+PQR_ASSOC_OFFSET)
	if err != nil {
		return 0, fmt.Errorf("failed to read CLOS number of cpu %d: %v", cpu, err)
	}
	return int(getBits(rsp, 16, 17)), nil
}

func getBits(val, i, j uint32) uint32 {
	lsb := i
	msb := j
	if i > j {
		lsb = j
		msb = i
	}
	return (val >> lsb) & ((1 << (msb - lsb + 1)) - 1)
}

func isBitSet(val, n uint32) bool {
	return val&(1<<n) != 0
}
<|endoftext|>


<commit_before>package web

import (
	"fmt"
	"os"

	"github.com/graphql-go/graphql"
	"github.com/graphql-go/handler"
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
)

var Schema graphql.Schema

func Run() error {
	var err error
	Schema, err = BuildSchema()
	if err != nil {
		return err
	}

	e := echo.New()

	// Configure middleware
	// Heroku has its own logging
	if os.Getenv("DYNO") == "" {
		e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
			Format: "time=${time_rfc3339} method=${method} path=${path} host=${host} status=${status} bytes_in=${bytes_in} bytes_out=${bytes_out}\n",
		}))
	}
	e.Use(middleware.Recover())
	e.Static("/", "public")
	e.File("/graphiql", "public/graphiql.html")

	h := handler.New(&handler.Config{
		Schema: &Schema,
		Pretty: true,
	})

	e.Any("/graphql", standard.WrapHandler(h))

	// Run the server
	addr := fmt.Sprintf(":%s", os.Getenv("PORT"))

	err = e.Run(standard.New(addr))
	return err
}
<commit_msg>Add lets encrypt<commit_after>package web

import (
	"errors"
	"fmt"
	"net/http"
	"os"

	"github.com/graphql-go/graphql"
	"github.com/graphql-go/handler"
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
)

var Schema graphql.Schema

func Run() error {
	var err error
	Schema, err = BuildSchema()
	if err != nil {
		return err
	}

	e := echo.New()

	// Configure middleware
	// Heroku has its own logging
	if os.Getenv("DYNO") == "" {
		e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
			Format: "time=${time_rfc3339} method=${method} path=${path} host=${host} status=${status} bytes_in=${bytes_in} bytes_out=${bytes_out}\n",
		}))
	}
	e.Use(middleware.Recover())
	e.Static("/", "public")
	e.Get("/.well-known/acme-challenge/:challenge", letsEncrypt)
	e.File("/graphiql", "public/graphiql.html")

	h := handler.New(&handler.Config{
		Schema: &Schema,
		Pretty: true,
	})

	e.Any("/graphql", standard.WrapHandler(h))

	// Run the server
	addr := fmt.Sprintf(":%s", os.Getenv("PORT"))

	err = e.Run(standard.New(addr))
	return err
}

func letsEncrypt(c echo.Context) error {
	challenge := os.Getenv("LETS_ENCRYPT_CHALLENGE")
	param := c.Param("challenge")
	if param == challenge {
		return c.String(http.StatusOK, os.Getenv("LETS_ENCRYPT_KEY"))
	}
	return errors.New("Let's Encrypt challenge did not match")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

func init() {
	Topics = append(Topics, TopicSet{
		{
			Name:        "build",
			Description: "These commands are used to build the CLI. They are not intended to be used otherwise.",
			Hidden:      true,
			Commands: CommandSet{
				{
					Topic:       "build",
					Command:     "plugins",
					Description: "installs core plugins",
					Run: func(ctx *Context) {
						pjson, err := readJSON(filepath.Join(corePlugins.Path, "package.json"))
						must(err)
						plugins := []string{}
						for name, v := range pjson["dependencies"].(map[string]interface{}) {
							plugins = append(plugins, name+"@"+v.(string))
						}
						must(corePlugins.installPackages(plugins...))
						for _, plugin := range plugins {
							plugin, err := corePlugins.ParsePlugin(strings.Split(plugin, "@")[0])
							must(err)
							corePlugins.addToCache(plugin)
						}
					},
				},
				{
					Topic:       "build",
					Command:     "manifest",
					Description: "builds manifest.json to upload to S3",
					Flags: []Flag{
						{Name: "dir", Char: "d", Required: true, HasValue: true},
						{Name: "version", Char: "v", Required: true, HasValue: true},
						{Name: "channel", Char: "c", Required: true, HasValue: true},
						{Name: "targets", Char: "t", Required: true, HasValue: true},
					},
					Run: func(ctx *Context) {
						manifest := &Manifest{
							ReleasedAt: time.Now().UTC().Format("2006-01-02T15:04:05Z0700"),
							Version:    ctx.Flags["version"].(string),
							Channel:    ctx.Flags["channel"].(string),
							Builds:     map[string]*Build{},
						}
						files := strings.Split(ctx.Flags["targets"].(string), ",")
						re := regexp.MustCompile(`heroku-v\d+\.\d+\.\d+-\w+-(\w+)-(\w+)\.tar.xz`)
						for _, file := range files {
							filename := filepath.Base(file)
							info := re.FindStringSubmatch(filename)
							f, err := os.Open(file)
							must(err)
							fi, err := f.Stat()
							must(err)
							os := info[1]
							arch := info[2]
							sha256, err := fileSha256(file)
							must(err)
							manifest.Builds[os+"-"+arch] = &Build{
								URL:    "https://cli-assets.heroku.com/branches/" + manifest.Channel + "/" + manifest.Version + "/" + filename,
								Sha256: sha256,
								Bytes:  fi.Size(),
							}
						}
						data, err := json.MarshalIndent(manifest, "", "  ")
						must(err)
						Println(string(data))
					},
				},
			},
		},
	}...)
}

// Manifest is the manifest.json for releases
type Manifest struct {
	ReleasedAt string            `json:"released_at"`
	Version    string            `json:"version"`
	Channel    string            `json:"channel"`
	Builds     map[string]*Build `json:"builds"`
}

// Build is a part of a Manifest
type Build struct {
	URL    string `json:"url"`
	Sha1   string `json:"sha1"`
	Sha256 string `json:"sha256"`
	Bytes  int64  `json:"bytes"`
}
<commit_msg>remove sha1 field<commit_after>package main

import (
	"encoding/json"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

func init() {
	Topics = append(Topics, TopicSet{
		{
			Name:        "build",
			Description: "These commands are used to build the CLI. They are not intended to be used otherwise.",
			Hidden:      true,
			Commands: CommandSet{
				{
					Topic:       "build",
					Command:     "plugins",
					Description: "installs core plugins",
					Run: func(ctx *Context) {
						pjson, err := readJSON(filepath.Join(corePlugins.Path, "package.json"))
						must(err)
						plugins := []string{}
						for name, v := range pjson["dependencies"].(map[string]interface{}) {
							plugins = append(plugins, name+"@"+v.(string))
						}
						must(corePlugins.installPackages(plugins...))
						for _, plugin := range plugins {
							plugin, err := corePlugins.ParsePlugin(strings.Split(plugin, "@")[0])
							must(err)
							corePlugins.addToCache(plugin)
						}
					},
				},
				{
					Topic:       "build",
					Command:     "manifest",
					Description: "builds manifest.json to upload to S3",
					Flags: []Flag{
						{Name: "dir", Char: "d", Required: true, HasValue: true},
						{Name: "version", Char: "v", Required: true, HasValue: true},
						{Name: "channel", Char: "c", Required: true, HasValue: true},
						{Name: "targets", Char: "t", Required: true, HasValue: true},
					},
					Run: func(ctx *Context) {
						manifest := &Manifest{
							ReleasedAt: time.Now().UTC().Format("2006-01-02T15:04:05Z0700"),
							Version:    ctx.Flags["version"].(string),
							Channel:    ctx.Flags["channel"].(string),
							Builds:     map[string]*Build{},
						}
						files := strings.Split(ctx.Flags["targets"].(string), ",")
						re := regexp.MustCompile(`heroku-v\d+\.\d+\.\d+-\w+-(\w+)-(\w+)\.tar.xz`)
						for _, file := range files {
							filename := filepath.Base(file)
							info := re.FindStringSubmatch(filename)
							f, err := os.Open(file)
							must(err)
							fi, err := f.Stat()
							must(err)
							os := info[1]
							arch := info[2]
							sha256, err := fileSha256(file)
							must(err)
							manifest.Builds[os+"-"+arch] = &Build{
								URL:    "https://cli-assets.heroku.com/branches/" + manifest.Channel + "/" + manifest.Version + "/" + filename,
								Sha256: sha256,
								Bytes:  fi.Size(),
							}
						}
						data, err := json.MarshalIndent(manifest, "", "  ")
						must(err)
						Println(string(data))
					},
				},
			},
		},
	}...)
}

// Manifest is the manifest.json for releases
type Manifest struct {
	ReleasedAt string            `json:"released_at"`
	Version    string            `json:"version"`
	Channel    string            `json:"channel"`
	Builds     map[string]*Build `json:"builds"`
}

// Build is a part of a Manifest
type Build struct {
	URL    string `json:"url"`
	Sha256 string `json:"sha256"`
	Bytes  int64  `json:"bytes"`
}
<|endoftext|>


<commit_before>package gb

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

// Build builds each of pkgs in succession. If pkg is a command, then the results of build include
// linking the final binary into pkg.Context.Bindir().
func Build(pkgs ...*Package) error {
	targets := make(map[string]PkgTarget)
	roots := make([]Target, 0, len(pkgs))
	for _, pkg := range pkgs {
		target := buildPackage(targets, pkg)
		if pkg.isMain() {
			target = Ld(pkg, target.(PkgTarget))
		}
		roots = append(roots, target)
	}
	for _, root := range roots {
		if err := root.Result(); err != nil {
			return err
		}
	}
	return nil
}

// buildPackage returns a Target repesenting the results of compiling
// pkg and its dependencies.
func buildPackage(targets map[string]PkgTarget, pkg *Package) Target {
	if target, ok := targets[pkg.ImportPath]; ok {
		// already compiled
		return target
	}
	Debugf("buildPackage: %v", pkg.ImportPath)

	deps := buildDependencies(targets, pkg)
	target := Compile(pkg, deps...)
	targets[pkg.ImportPath] = target
	return target
}

// buildDependencies returns a []Target representing the results of
// compiling the dependencies of pkg.
func buildDependencies(targets map[string]PkgTarget, pkg *Package) []Target {
	var deps []Target
	for _, i := range pkg.Imports() {
		deps = append(deps, buildPackage(targets, i))
	}
	return deps
}

// Compile returns a Target representing all the steps required to build a go package.
func Compile(pkg *Package, deps ...Target) PkgTarget {
	if !pkg.Stale {
		return cachedPackage(pkg)
	}
	var gofiles []string
	gofiles = append(gofiles, pkg.GoFiles...)
	var objs []ObjTarget
	if len(pkg.CgoFiles) > 0 {
		return errTarget{
			fmt.Errorf("%v: cgo not supported, see https://github.com/constabulary/gb/issues/12", pkg.ImportPath),
		}
	}
	objs = append(objs, Gc(pkg, gofiles, deps...))
	for _, sfile := range pkg.SFiles {
		objs = append(objs, Asm(pkg, sfile))
	}
	if pkg.Complete() {
		return Install(pkg, objs[0].(PkgTarget))
	}
	return Install(pkg, Pack(pkg, objs...))
}

// ObjTarget represents a compiled Go object (.5, .6, etc)
type ObjTarget interface {
	Target

	// Objfile is the name of the file that is produced if the target is successful.
	Objfile() string
}

type gc struct {
	target
	pkg     *Package
	gofiles []string
}

func (g *gc) String() string {
	return fmt.Sprintf("compile %v", g.pkg)
}

func (g *gc) compile() error {
	t0 := time.Now()
	if g.pkg.Scope != "test" {
		// only log compilation message if not in test scope
		Infof(g.pkg.ImportPath)
	}
	includes := g.pkg.ctx.IncludePaths()
	importpath := g.pkg.ImportPath
	if g.pkg.Scope == "test" && g.pkg.ExtraIncludes != "" {
		// TODO(dfc) gross
		includes = append([]string{g.pkg.ExtraIncludes}, includes...)
	}
	for i := range g.gofiles {
		g.gofiles[i], _ = filepath.Rel(g.pkg.ctx.Projectdir(), filepath.Join(g.pkg.Dir, g.gofiles[i]))
	}
	err := g.pkg.ctx.tc.Gc(includes, importpath, g.pkg.ctx.Projectdir(), g.Objfile(), g.gofiles, g.pkg.Complete())
	g.pkg.ctx.Record("compile", time.Since(t0))
	return err
}

func (g *gc) Objfile() string {
	return objfile(g.pkg)
}

func (g *gc) Pkgfile() string {
	return g.Objfile()
}

type objpkgtarget interface {
	ObjTarget
	Pkgfile() string // implements PkgTarget
}

// Gc returns a Target representing the result of compiling a set of gofiles with the Context specified gc Compiler.
func Gc(pkg *Package, gofiles []string, deps ...Target) objpkgtarget {
	gc := gc{
		pkg:     pkg,
		gofiles: gofiles,
	}
	gc.target = newTarget(gc.compile, deps...)
	return &gc
}

// PkgTarget represents a Target that produces a pkg (.a) file.
type PkgTarget interface {
	Target

	// Pkgfile returns the name of the file that is produced by the Target if successful.
	Pkgfile() string
}

type pack struct {
	c   chan error
	pkg *Package
}

func (p *pack) Result() error {
	err := <-p.c
	p.c <- err
	return err
}

func (p *pack) pack(objs ...ObjTarget) {
	afiles := make([]string, 0, len(objs))
	for _, obj := range objs {
		err := obj.Result()
		if err != nil {
			p.c <- err
			return
		}
		// pkg.a (compiled Go code) is always first
		afiles = append(afiles, obj.Objfile())
	}
	t0 := time.Now()
	err := p.pkg.ctx.tc.Pack(afiles...)
	p.pkg.ctx.Record("pack", time.Since(t0))
	p.c <- err
}

func (p *pack) Pkgfile() string {
	return objfile(p.pkg)
}

// Pack returns a Target representing the result of packing a
// set of Context specific object files into an archive.
func Pack(pkg *Package, deps ...ObjTarget) PkgTarget {
	if len(deps) < 2 {
		return errTarget{
			fmt.Errorf("Pack requires at least two arguments: %v", deps)}
	}
	pack := pack{
		c:   make(chan error, 1),
		pkg: pkg,
	}
	go pack.pack(deps...)
	return &pack
}

type asm struct {
	target
	pkg   *Package
	sfile string
}

func (a *asm) String() string {
	return fmt.Sprintf("asm %v", a.sfile)
}

func (a *asm) Objfile() string {
	return filepath.Join(a.pkg.ctx.workdir, a.pkg.ImportPath, stripext(a.sfile)+".6")
}

func (a *asm) asm() error {
	t0 := time.Now()
	err := a.pkg.ctx.tc.Asm(a.pkg.Dir, a.Objfile(), filepath.Join(a.pkg.Dir, a.sfile))
	a.pkg.ctx.Record("asm", time.Since(t0))
	return err
}

// Asm returns a Target representing the result of assembling
// sfile with the Context specified asssembler.
func Asm(pkg *Package, sfile string) ObjTarget {
	asm := asm{
		pkg:   pkg,
		sfile: sfile,
	}
	asm.target = newTarget(asm.asm)
	return &asm
}

type ld struct {
	target
	pkg   *Package
	afile PkgTarget
}

func (l *ld) link() error {
	t0 := time.Now()
	target := binfile(l.pkg)
	if err := mkdir(filepath.Dir(target)); err != nil {
		return err
	}

	includes := l.pkg.ctx.IncludePaths()
	if l.pkg.Scope == "test" && l.pkg.ExtraIncludes != "" {
		// TODO(dfc) gross
		includes = append([]string{l.pkg.ExtraIncludes}, includes...)
		target += ".test"
	}
	err := l.pkg.ctx.tc.Ld(includes, l.pkg.ctx.ldflags, target, l.afile.Pkgfile())
	l.pkg.ctx.Record("link", time.Since(t0))
	return err
}

// Ld returns a Target representing the result of linking a
// Package into a command with the Context provided linker.
func Ld(pkg *Package, afile PkgTarget) Target {
	ld := ld{
		pkg:   pkg,
		afile: afile,
	}
	ld.target = newTarget(ld.link, afile)
	return &ld
}

func stripext(path string) string {
	ext := filepath.Ext(path)
	return path[:len(ext)]
}

// objfile returns the name of the object file for this package
func objfile(pkg *Package) string {
	return filepath.Join(objdir(pkg), objname(pkg))
}

// objdir returns the destination for object files compiled for this Package.
func objdir(pkg *Package) string {
	switch pkg.Scope {
	case "test":
		ip := strings.TrimSuffix(filepath.FromSlash(pkg.ImportPath), "_test")
		return filepath.Join(pkg.ctx.workdir, ip, "_test", filepath.Dir(filepath.FromSlash(pkg.ImportPath)))
	default:
		return filepath.Join(pkg.ctx.workdir, filepath.Dir(filepath.FromSlash(pkg.ImportPath)))
	}
}

func objname(pkg *Package) string {
	switch pkg.Name {
	case "main":
		return filepath.Join(filepath.Base(filepath.FromSlash(pkg.ImportPath)), "main.a")
	default:
		return filepath.Base(filepath.FromSlash(pkg.ImportPath)) + ".a"
	}
}

func binfile(pkg *Package) string {
	var target string
	switch pkg.Scope {
	case "test":
		target = filepath.Join(pkg.ctx.workdir, filepath.FromSlash(pkg.ImportPath), "_test", binname(pkg))
	default:
		target = filepath.Join(pkg.ctx.Bindir(), binname(pkg))
	}
	if pkg.ctx.GOOS == "windows" {
		target += ".exe"
	}
	return target
}

func binname(pkg *Package) string {
	switch {
	case pkg.Name == "main":
		return filepath.Base(filepath.FromSlash(pkg.ImportPath))
	case pkg.Scope == "test":
		return pkg.Name
	default:
		panic("binname called with non main package: " + pkg.ImportPath)
	}
}
<commit_msg>Fix TestStripext<commit_after>package gb

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

// Build builds each of pkgs in succession. If pkg is a command, then the results of build include
// linking the final binary into pkg.Context.Bindir().
func Build(pkgs ...*Package) error {
	targets := make(map[string]PkgTarget)
	roots := make([]Target, 0, len(pkgs))
	for _, pkg := range pkgs {
		target := buildPackage(targets, pkg)
		if pkg.isMain() {
			target = Ld(pkg, target.(PkgTarget))
		}
		roots = append(roots, target)
	}
	for _, root := range roots {
		if err := root.Result(); err != nil {
			return err
		}
	}
	return nil
}

// buildPackage returns a Target repesenting the results of compiling
// pkg and its dependencies.
func buildPackage(targets map[string]PkgTarget, pkg *Package) Target {
	if target, ok := targets[pkg.ImportPath]; ok {
		// already compiled
		return target
	}
	Debugf("buildPackage: %v", pkg.ImportPath)

	deps := buildDependencies(targets, pkg)
	target := Compile(pkg, deps...)
	targets[pkg.ImportPath] = target
	return target
}

// buildDependencies returns a []Target representing the results of
// compiling the dependencies of pkg.
func buildDependencies(targets map[string]PkgTarget, pkg *Package) []Target {
	var deps []Target
	for _, i := range pkg.Imports() {
		deps = append(deps, buildPackage(targets, i))
	}
	return deps
}

// Compile returns a Target representing all the steps required to build a go package.
func Compile(pkg *Package, deps ...Target) PkgTarget {
	if !pkg.Stale {
		return cachedPackage(pkg)
	}
	var gofiles []string
	gofiles = append(gofiles, pkg.GoFiles...)
	var objs []ObjTarget
	if len(pkg.CgoFiles) > 0 {
		return errTarget{
			fmt.Errorf("%v: cgo not supported, see https://github.com/constabulary/gb/issues/12", pkg.ImportPath),
		}
	}
	objs = append(objs, Gc(pkg, gofiles, deps...))
	for _, sfile := range pkg.SFiles {
		objs = append(objs, Asm(pkg, sfile))
	}
	if pkg.Complete() {
		return Install(pkg, objs[0].(PkgTarget))
	}
	return Install(pkg, Pack(pkg, objs...))
}

// ObjTarget represents a compiled Go object (.5, .6, etc)
type ObjTarget interface {
	Target

	// Objfile is the name of the file that is produced if the target is successful.
	Objfile() string
}

type gc struct {
	target
	pkg     *Package
	gofiles []string
}

func (g *gc) String() string {
	return fmt.Sprintf("compile %v", g.pkg)
}

func (g *gc) compile() error {
	t0 := time.Now()
	if g.pkg.Scope != "test" {
		// only log compilation message if not in test scope
		Infof(g.pkg.ImportPath)
	}
	includes := g.pkg.ctx.IncludePaths()
	importpath := g.pkg.ImportPath
	if g.pkg.Scope == "test" && g.pkg.ExtraIncludes != "" {
		// TODO(dfc) gross
		includes = append([]string{g.pkg.ExtraIncludes}, includes...)
	}
	for i := range g.gofiles {
		g.gofiles[i], _ = filepath.Rel(g.pkg.ctx.Projectdir(), filepath.Join(g.pkg.Dir, g.gofiles[i]))
	}
	err := g.pkg.ctx.tc.Gc(includes, importpath, g.pkg.ctx.Projectdir(), g.Objfile(), g.gofiles, g.pkg.Complete())
	g.pkg.ctx.Record("compile", time.Since(t0))
	return err
}

func (g *gc) Objfile() string {
	return objfile(g.pkg)
}

func (g *gc) Pkgfile() string {
	return g.Objfile()
}

type objpkgtarget interface {
	ObjTarget
	Pkgfile() string // implements PkgTarget
}

// Gc returns a Target representing the result of compiling a set of gofiles with the Context specified gc Compiler.
func Gc(pkg *Package, gofiles []string, deps ...Target) objpkgtarget {
	gc := gc{
		pkg:     pkg,
		gofiles: gofiles,
	}
	gc.target = newTarget(gc.compile, deps...)
	return &gc
}

// PkgTarget represents a Target that produces a pkg (.a) file.
type PkgTarget interface {
	Target

	// Pkgfile returns the name of the file that is produced by the Target if successful.
	Pkgfile() string
}

type pack struct {
	c   chan error
	pkg *Package
}

func (p *pack) Result() error {
	err := <-p.c
	p.c <- err
	return err
}

func (p *pack) pack(objs ...ObjTarget) {
	afiles := make([]string, 0, len(objs))
	for _, obj := range objs {
		err := obj.Result()
		if err != nil {
			p.c <- err
			return
		}
		// pkg.a (compiled Go code) is always first
		afiles = append(afiles, obj.Objfile())
	}
	t0 := time.Now()
	err := p.pkg.ctx.tc.Pack(afiles...)
	p.pkg.ctx.Record("pack", time.Since(t0))
	p.c <- err
}

func (p *pack) Pkgfile() string {
	return objfile(p.pkg)
}

// Pack returns a Target representing the result of packing a
// set of Context specific object files into an archive.
func Pack(pkg *Package, deps ...ObjTarget) PkgTarget {
	if len(deps) < 2 {
		return errTarget{
			fmt.Errorf("Pack requires at least two arguments: %v", deps)}
	}
	pack := pack{
		c:   make(chan error, 1),
		pkg: pkg,
	}
	go pack.pack(deps...)
	return &pack
}

type asm struct {
	target
	pkg   *Package
	sfile string
}

func (a *asm) String() string {
	return fmt.Sprintf("asm %v", a.sfile)
}

func (a *asm) Objfile() string {
	return filepath.Join(a.pkg.ctx.workdir, a.pkg.ImportPath, stripext(a.sfile)+".6")
}

func (a *asm) asm() error {
	t0 := time.Now()
	err := a.pkg.ctx.tc.Asm(a.pkg.Dir, a.Objfile(), filepath.Join(a.pkg.Dir, a.sfile))
	a.pkg.ctx.Record("asm", time.Since(t0))
	return err
}

// Asm returns a Target representing the result of assembling
// sfile with the Context specified asssembler.
func Asm(pkg *Package, sfile string) ObjTarget {
	asm := asm{
		pkg:   pkg,
		sfile: sfile,
	}
	asm.target = newTarget(asm.asm)
	return &asm
}

type ld struct {
	target
	pkg   *Package
	afile PkgTarget
}

func (l *ld) link() error {
	t0 := time.Now()
	target := binfile(l.pkg)
	if err := mkdir(filepath.Dir(target)); err != nil {
		return err
	}

	includes := l.pkg.ctx.IncludePaths()
	if l.pkg.Scope == "test" && l.pkg.ExtraIncludes != "" {
		// TODO(dfc) gross
		includes = append([]string{l.pkg.ExtraIncludes}, includes...)
		target += ".test"
	}
	err := l.pkg.ctx.tc.Ld(includes, l.pkg.ctx.ldflags, target, l.afile.Pkgfile())
	l.pkg.ctx.Record("link", time.Since(t0))
	return err
}

// Ld returns a Target representing the result of linking a
// Package into a command with the Context provided linker.
func Ld(pkg *Package, afile PkgTarget) Target {
	ld := ld{
		pkg:   pkg,
		afile: afile,
	}
	ld.target = newTarget(ld.link, afile)
	return &ld
}

func stripext(path string) string {
	ext := filepath.Ext(path)
	return path[:len(path)-len(ext)]
}

// objfile returns the name of the object file for this package
func objfile(pkg *Package) string {
	return filepath.Join(objdir(pkg), objname(pkg))
}

// objdir returns the destination for object files compiled for this Package.
func objdir(pkg *Package) string {
	switch pkg.Scope {
	case "test":
		ip := strings.TrimSuffix(filepath.FromSlash(pkg.ImportPath), "_test")
		return filepath.Join(pkg.ctx.workdir, ip, "_test", filepath.Dir(filepath.FromSlash(pkg.ImportPath)))
	default:
		return filepath.Join(pkg.ctx.workdir, filepath.Dir(filepath.FromSlash(pkg.ImportPath)))
	}
}

func objname(pkg *Package) string {
	switch pkg.Name {
	case "main":
		return filepath.Join(filepath.Base(filepath.FromSlash(pkg.ImportPath)), "main.a")
	default:
		return filepath.Base(filepath.FromSlash(pkg.ImportPath)) + ".a"
	}
}

func binfile(pkg *Package) string {
	var target string
	switch pkg.Scope {
	case "test":
		target = filepath.Join(pkg.ctx.workdir, filepath.FromSlash(pkg.ImportPath), "_test", binname(pkg))
	default:
		target = filepath.Join(pkg.ctx.Bindir(), binname(pkg))
	}
	if pkg.ctx.GOOS == "windows" {
		target += ".exe"
	}
	return target
}

func binname(pkg *Package) string {
	switch {
	case pkg.Name == "main":
		return filepath.Base(filepath.FromSlash(pkg.ImportPath))
	case pkg.Scope == "test":
		return pkg.Name
	default:
		panic("binname called with non main package: " + pkg.ImportPath)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2015-2017 Hilko Bengen <bengen@hilluzination.de>
// All rights reserved.
//
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

package yara

/*
#include <yara.h>

// rule_identifier is a union accessor function.
static const char* rule_identifier(YR_RULE* r) {
	return r->identifier;
}

// rule_namespace is a union accessor function.
static const char* rule_namespace(YR_RULE* r) {
	return r->ns->name;
}

// rule_tags returns pointers to the tag names associated with a rule,
// using YARA's own implementation
static void rule_tags(YR_RULE* r, const char *tags[], int *n) {
	const char *tag;
	int i = 0;
	yr_rule_tags_foreach(r, tag) {
		if (i < *n)
			tags[i] = tag;
		i++;
	};
	*n = i;
	return;
}

// rule_tags returns pointers to the meta variables associated with a
// rule, using YARA's own implementation
static void rule_metas(YR_RULE* r, const YR_META *metas[], int *n) {
	const YR_META *meta;
	int i = 0;
	yr_rule_metas_foreach(r, meta) {
		if (i < *n)
			metas[i] = meta;
		i++;
	};
	*n = i;
	return;
}

// meta_get is an accessor function for unions that are not directly
// accessible from Go because CGO does not understand them.
static void meta_get(YR_META *m, const char** identifier, char** string) {
	*identifier = m->identifier;
	*string = m->string;
	return;
}

// rule_strings returns pointers to the matching strings associated
// with a rule, using YARA's own implementation.
static void rule_strings(YR_RULE* r, const YR_STRING *strings[], int *n) {
	const YR_STRING *string;
	int i = 0;
	yr_rule_strings_foreach(r, string) {
		if (i < *n)
			strings[i] = string;
		i++;
	}
	*n = i;
	return;
}

// string_identifier is a union accessor function.
static const char* string_identifier(YR_STRING* s) {
	return s->identifier;
}

// string_matches
static void string_matches(YR_STRING* s, const YR_MATCH *matches[], int *n) {
	const YR_MATCH *match;
	int i = 0;
	yr_string_matches_foreach(s, match) {
		if (i < *n)
			matches[i] = match;
		i++;
	};
	*n = i;
	return;
}

*/
import "C"

// Rule represents a single rule as part of a ruleset
type Rule struct{ cptr *C.YR_RULE }

// Identifier returns the rule's name.
func (r *Rule) Identifier() string {
	return C.GoString(C.rule_identifier(r.cptr))
}

// Namespace returns the rule's namespace.
func (r *Rule) Namespace() string {
	return C.GoString(C.rule_namespace(r.cptr))
}

// Tags returns the rule's tags.
func (r *Rule) Tags() (tags []string) {
	var size C.int
	C.rule_tags(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	tagptrs := make([]*C.char, int(size))
	C.rule_tags(r.cptr, &tagptrs[0], &size)
	for _, t := range tagptrs {
		tags = append(tags, C.GoString(t))
	}
	return
}

// Metas returns a map containing the rule's meta variables. Values
// can be of type string, int, bool, or nil.
func (r *Rule) Metas() (metas map[string]interface{}) {
	metas = make(map[string]interface{})
	var size C.int
	C.rule_metas(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	mptrs := make([]*C.YR_META, int(size))
	C.rule_metas(r.cptr, &mptrs[0], &size)
	for _, m := range mptrs {
		var id, str *C.char
		C.meta_get(m, &id, &str)
		switch m._type {
		case C.META_TYPE_NULL:
			metas[C.GoString(id)] = nil
		case C.META_TYPE_STRING:
			metas[C.GoString(id)] = C.GoString(str)
		case C.META_TYPE_INTEGER:
			metas[C.GoString(id)] = int(m.integer)
		case C.META_TYPE_BOOLEAN:
			metas[C.GoString(id)] = m.integer != 0
		}
	}
	return
}

// String represents a string as part of a rule
type String struct{ cptr *C.YR_STRING }

// Strings returns the rule's strings
func (r *Rule) Strings() (strs []String) {
	var size C.int
	C.rule_strings(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	ptrs := make([]*C.YR_STRING, int(size))
	C.rule_strings(r.cptr, &ptrs[0], &size)
	for _, ptr := range ptrs {
		strs = append(strs, String{ptr})
	}
	return
}

// Identifier returns the string's name
func (s *String) Identifier() string {
	return C.GoString(C.string_identifier(s.cptr))
}

// Match represents a string match
type Match struct{ cptr *C.YR_MATCH }

// Matches returns all matches that have been recorded for the string.
func (s *String) Matches() (matches []Match) {
	var size C.int
	C.string_matches(s.cptr, nil, &size)
	ptrs := make([]*C.YR_MATCH, int(size))
	if size == 0 {
		return
	}
	C.string_matches(s.cptr, &ptrs[0], &size)
	for _, ptr := range ptrs {
		matches = append(matches, Match{ptr})
	}
	return
}

// Offset returns the offset at which the string match occurred
func (m *Match) Offset() int64 {
	return int64(m.cptr.offset)
}

func (r *Rule) getMatchStrings() (matchstrings []MatchString) {
	for _, s := range r.Strings() {
		for _, m := range s.Matches() {
			matchstrings = append(matchstrings, MatchString{
				Name:   s.Identifier(),
				Offset: uint64(m.Offset()),
				Data:   m.Data(),
			})
		}
	}
	return
}
<commit_msg>(*Rule).Metas(): Document interface limitation<commit_after>// Copyright © 2015-2017 Hilko Bengen <bengen@hilluzination.de>
// All rights reserved.
//
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

package yara

/*
#include <yara.h>

// rule_identifier is a union accessor function.
static const char* rule_identifier(YR_RULE* r) {
	return r->identifier;
}

// rule_namespace is a union accessor function.
static const char* rule_namespace(YR_RULE* r) {
	return r->ns->name;
}

// rule_tags returns pointers to the tag names associated with a rule,
// using YARA's own implementation
static void rule_tags(YR_RULE* r, const char *tags[], int *n) {
	const char *tag;
	int i = 0;
	yr_rule_tags_foreach(r, tag) {
		if (i < *n)
			tags[i] = tag;
		i++;
	};
	*n = i;
	return;
}

// rule_tags returns pointers to the meta variables associated with a
// rule, using YARA's own implementation
static void rule_metas(YR_RULE* r, const YR_META *metas[], int *n) {
	const YR_META *meta;
	int i = 0;
	yr_rule_metas_foreach(r, meta) {
		if (i < *n)
			metas[i] = meta;
		i++;
	};
	*n = i;
	return;
}

// meta_get is an accessor function for unions that are not directly
// accessible from Go because CGO does not understand them.
static void meta_get(YR_META *m, const char** identifier, char** string) {
	*identifier = m->identifier;
	*string = m->string;
	return;
}

// rule_strings returns pointers to the matching strings associated
// with a rule, using YARA's own implementation.
static void rule_strings(YR_RULE* r, const YR_STRING *strings[], int *n) {
	const YR_STRING *string;
	int i = 0;
	yr_rule_strings_foreach(r, string) {
		if (i < *n)
			strings[i] = string;
		i++;
	}
	*n = i;
	return;
}

// string_identifier is a union accessor function.
static const char* string_identifier(YR_STRING* s) {
	return s->identifier;
}

// string_matches
static void string_matches(YR_STRING* s, const YR_MATCH *matches[], int *n) {
	const YR_MATCH *match;
	int i = 0;
	yr_string_matches_foreach(s, match) {
		if (i < *n)
			matches[i] = match;
		i++;
	};
	*n = i;
	return;
}

*/
import "C"

// Rule represents a single rule as part of a ruleset
type Rule struct{ cptr *C.YR_RULE }

// Identifier returns the rule's name.
func (r *Rule) Identifier() string {
	return C.GoString(C.rule_identifier(r.cptr))
}

// Namespace returns the rule's namespace.
func (r *Rule) Namespace() string {
	return C.GoString(C.rule_namespace(r.cptr))
}

// Tags returns the rule's tags.
func (r *Rule) Tags() (tags []string) {
	var size C.int
	C.rule_tags(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	tagptrs := make([]*C.char, int(size))
	C.rule_tags(r.cptr, &tagptrs[0], &size)
	for _, t := range tagptrs {
		tags = append(tags, C.GoString(t))
	}
	return
}

// Metas returns a map containing the rule's meta variables. Values
// can be of type string, int, bool, or nil.
//
// If a rule contains multiple meta variables with the same name, only
// the last meta variable is returned as part of the map.
func (r *Rule) Metas() (metas map[string]interface{}) {
	metas = make(map[string]interface{})
	var size C.int
	C.rule_metas(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	mptrs := make([]*C.YR_META, int(size))
	C.rule_metas(r.cptr, &mptrs[0], &size)
	for _, m := range mptrs {
		var id, str *C.char
		C.meta_get(m, &id, &str)
		switch m._type {
		case C.META_TYPE_NULL:
			metas[C.GoString(id)] = nil
		case C.META_TYPE_STRING:
			metas[C.GoString(id)] = C.GoString(str)
		case C.META_TYPE_INTEGER:
			metas[C.GoString(id)] = int(m.integer)
		case C.META_TYPE_BOOLEAN:
			metas[C.GoString(id)] = m.integer != 0
		}
	}
	return
}

// String represents a string as part of a rule
type String struct{ cptr *C.YR_STRING }

// Strings returns the rule's strings
func (r *Rule) Strings() (strs []String) {
	var size C.int
	C.rule_strings(r.cptr, nil, &size)
	if size == 0 {
		return
	}
	ptrs := make([]*C.YR_STRING, int(size))
	C.rule_strings(r.cptr, &ptrs[0], &size)
	for _, ptr := range ptrs {
		strs = append(strs, String{ptr})
	}
	return
}

// Identifier returns the string's name
func (s *String) Identifier() string {
	return C.GoString(C.string_identifier(s.cptr))
}

// Match represents a string match
type Match struct{ cptr *C.YR_MATCH }

// Matches returns all matches that have been recorded for the string.
func (s *String) Matches() (matches []Match) {
	var size C.int
	C.string_matches(s.cptr, nil, &size)
	ptrs := make([]*C.YR_MATCH, int(size))
	if size == 0 {
		return
	}
	C.string_matches(s.cptr, &ptrs[0], &size)
	for _, ptr := range ptrs {
		matches = append(matches, Match{ptr})
	}
	return
}

// Offset returns the offset at which the string match occurred
func (m *Match) Offset() int64 {
	return int64(m.cptr.offset)
}

func (r *Rule) getMatchStrings() (matchstrings []MatchString) {
	for _, s := range r.Strings() {
		for _, m := range s.Matches() {
			matchstrings = append(matchstrings, MatchString{
				Name:   s.Identifier(),
				Offset: uint64(m.Offset()),
				Data:   m.Data(),
			})
		}
	}
	return
}
<|endoftext|>


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

package config

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/syncthing/syncthing/internal/events"
	"github.com/syncthing/syncthing/internal/osutil"
	"github.com/syncthing/syncthing/internal/protocol"
)

// An interface to handle configuration changes, and a wrapper type á la
// http.Handler

type Handler interface {
	Changed(Configuration) error
}

type HandlerFunc func(Configuration) error

func (fn HandlerFunc) Changed(cfg Configuration) error {
	return fn(cfg)
}

// A wrapper around a Configuration that manages loads, saves and published
// notifications of changes to registered Handlers

type ConfigWrapper struct {
	cfg  Configuration
	path string

	deviceMap map[protocol.DeviceID]DeviceConfiguration
	folderMap map[string]FolderConfiguration
	replaces  chan Configuration
	subs      []Handler
	mut       sync.Mutex
}

// Wrap wraps an existing Configuration structure and ties it to a file on
// disk.
func Wrap(path string, cfg Configuration) *ConfigWrapper {
	w := &ConfigWrapper{cfg: cfg, path: path}
	w.replaces = make(chan Configuration)
	go w.Serve()
	return w
}

// Load loads an existing file on disk and returns a new configuration
// wrapper.
func Load(path string, myID protocol.DeviceID) (*ConfigWrapper, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	cfg, err := ReadXML(fd, myID)
	if err != nil {
		return nil, err
	}

	return Wrap(path, cfg), nil
}

// Serve handles configuration replace events and calls any interested
// handlers. It is started automatically by Wrap() and Load() and should not
// be run manually.
func (w *ConfigWrapper) Serve() {
	for cfg := range w.replaces {
		w.mut.Lock()
		subs := w.subs
		w.mut.Unlock()
		for _, h := range subs {
			h.Changed(cfg)
		}
	}
}

// Stop stops the Serve() loop.
func (w *ConfigWrapper) Stop() {
	close(w.replaces)
}

// Subscriber registers the given handler to be called on any future
// configuration changes.
func (w *ConfigWrapper) Subscribe(h Handler) {
	w.mut.Lock()
	w.subs = append(w.subs, h)
	w.mut.Unlock()
}

// Raw returns the currently wrapped Configuration object.
func (w *ConfigWrapper) Raw() Configuration {
	return w.cfg
}

// Replace swaps the current configuration object for the given one.
func (w *ConfigWrapper) Replace(cfg Configuration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.cfg = cfg
	w.deviceMap = nil
	w.folderMap = nil
	w.replaces <- cfg
}

// Devices returns a map of devices. Device structures should not be changed,
// other than for the purpose of updating via SetDevice().
func (w *ConfigWrapper) Devices() map[protocol.DeviceID]DeviceConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	if w.deviceMap == nil {
		w.deviceMap = make(map[protocol.DeviceID]DeviceConfiguration, len(w.cfg.Devices))
		for _, dev := range w.cfg.Devices {
			w.deviceMap[dev.DeviceID] = dev
		}
	}
	return w.deviceMap
}

// SetDevice adds a new device to the configuration, or overwrites an existing
// device with the same ID.
func (w *ConfigWrapper) SetDevice(dev DeviceConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.deviceMap = nil

	for i := range w.cfg.Devices {
		if w.cfg.Devices[i].DeviceID == dev.DeviceID {
			w.cfg.Devices[i] = dev
			w.replaces <- w.cfg
			return
		}
	}

	w.cfg.Devices = append(w.cfg.Devices, dev)
	w.replaces <- w.cfg
}

// Devices returns a map of folders. Folder structures should not be changed,
// other than for the purpose of updating via SetFolder().
func (w *ConfigWrapper) Folders() map[string]FolderConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	if w.folderMap == nil {
		w.folderMap = make(map[string]FolderConfiguration, len(w.cfg.Folders))
		for _, fld := range w.cfg.Folders {
			w.folderMap[fld.ID] = fld
		}
	}
	return w.folderMap
}

// SetFolder adds a new folder to the configuration, or overwrites an existing
// folder with the same ID.
func (w *ConfigWrapper) SetFolder(fld FolderConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.folderMap = nil

	for i := range w.cfg.Folders {
		if w.cfg.Folders[i].ID == fld.ID {
			w.cfg.Folders[i] = fld
			w.replaces <- w.cfg
			return
		}
	}

	w.cfg.Folders = append(w.cfg.Folders, fld)
	w.replaces <- w.cfg
}

// Options returns the current options configuration object.
func (w *ConfigWrapper) Options() OptionsConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	return w.cfg.Options
}

// SetOptions replaces the current options configuration object.
func (w *ConfigWrapper) SetOptions(opts OptionsConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()
	w.cfg.Options = opts
	w.replaces <- w.cfg
}

// GUI returns the current GUI configuration object.
func (w *ConfigWrapper) GUI() GUIConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	return w.cfg.GUI
}

// SetGUI replaces the current GUI configuration object.
func (w *ConfigWrapper) SetGUI(gui GUIConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()
	w.cfg.GUI = gui
	w.replaces <- w.cfg
}

// InvalidateFolder sets the invalid marker on the given folder.
func (w *ConfigWrapper) InvalidateFolder(id string, err string) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.folderMap = nil

	for i := range w.cfg.Folders {
		if w.cfg.Folders[i].ID == id {
			w.cfg.Folders[i].Invalid = err
			w.replaces <- w.cfg
			return
		}
	}
}

// Save writes the configuration to disk, and generates a ConfigSaved event.
func (w *ConfigWrapper) Save() error {
	fd, err := ioutil.TempFile(filepath.Dir(w.path), "cfg")
	if err != nil {
		return err
	}

	err = w.cfg.WriteXML(fd)
	if err != nil {
		fd.Close()
		return err
	}

	err = fd.Close()
	if err != nil {
		return err
	}

	events.Default.Log(events.ConfigSaved, w.cfg)

	return osutil.Rename(fd.Name(), w.path)
}
<commit_msg>Use a separate lock for the subscriber stuff<commit_after>// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.

package config

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/syncthing/syncthing/internal/events"
	"github.com/syncthing/syncthing/internal/osutil"
	"github.com/syncthing/syncthing/internal/protocol"
)

// An interface to handle configuration changes, and a wrapper type á la
// http.Handler

type Handler interface {
	Changed(Configuration) error
}

type HandlerFunc func(Configuration) error

func (fn HandlerFunc) Changed(cfg Configuration) error {
	return fn(cfg)
}

// A wrapper around a Configuration that manages loads, saves and published
// notifications of changes to registered Handlers

type ConfigWrapper struct {
	cfg  Configuration
	path string

	deviceMap map[protocol.DeviceID]DeviceConfiguration
	folderMap map[string]FolderConfiguration
	replaces  chan Configuration
	mut       sync.Mutex

	subs []Handler
	sMut sync.Mutex
}

// Wrap wraps an existing Configuration structure and ties it to a file on
// disk.
func Wrap(path string, cfg Configuration) *ConfigWrapper {
	w := &ConfigWrapper{cfg: cfg, path: path}
	w.replaces = make(chan Configuration)
	go w.Serve()
	return w
}

// Load loads an existing file on disk and returns a new configuration
// wrapper.
func Load(path string, myID protocol.DeviceID) (*ConfigWrapper, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	cfg, err := ReadXML(fd, myID)
	if err != nil {
		return nil, err
	}

	return Wrap(path, cfg), nil
}

// Serve handles configuration replace events and calls any interested
// handlers. It is started automatically by Wrap() and Load() and should not
// be run manually.
func (w *ConfigWrapper) Serve() {
	for cfg := range w.replaces {
		w.sMut.Lock()
		subs := w.subs
		w.sMut.Unlock()
		for _, h := range subs {
			h.Changed(cfg)
		}
	}
}

// Stop stops the Serve() loop. Set and Replace operations will panic after a
// Stop.
func (w *ConfigWrapper) Stop() {
	close(w.replaces)
}

// Subscribe registers the given handler to be called on any future
// configuration changes.
func (w *ConfigWrapper) Subscribe(h Handler) {
	w.sMut.Lock()
	w.subs = append(w.subs, h)
	w.sMut.Unlock()
}

// Raw returns the currently wrapped Configuration object.
func (w *ConfigWrapper) Raw() Configuration {
	return w.cfg
}

// Replace swaps the current configuration object for the given one.
func (w *ConfigWrapper) Replace(cfg Configuration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.cfg = cfg
	w.deviceMap = nil
	w.folderMap = nil
	w.replaces <- cfg
}

// Devices returns a map of devices. Device structures should not be changed,
// other than for the purpose of updating via SetDevice().
func (w *ConfigWrapper) Devices() map[protocol.DeviceID]DeviceConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	if w.deviceMap == nil {
		w.deviceMap = make(map[protocol.DeviceID]DeviceConfiguration, len(w.cfg.Devices))
		for _, dev := range w.cfg.Devices {
			w.deviceMap[dev.DeviceID] = dev
		}
	}
	return w.deviceMap
}

// SetDevice adds a new device to the configuration, or overwrites an existing
// device with the same ID.
func (w *ConfigWrapper) SetDevice(dev DeviceConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.deviceMap = nil

	for i := range w.cfg.Devices {
		if w.cfg.Devices[i].DeviceID == dev.DeviceID {
			w.cfg.Devices[i] = dev
			w.replaces <- w.cfg
			return
		}
	}

	w.cfg.Devices = append(w.cfg.Devices, dev)
	w.replaces <- w.cfg
}

// Devices returns a map of folders. Folder structures should not be changed,
// other than for the purpose of updating via SetFolder().
func (w *ConfigWrapper) Folders() map[string]FolderConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	if w.folderMap == nil {
		w.folderMap = make(map[string]FolderConfiguration, len(w.cfg.Folders))
		for _, fld := range w.cfg.Folders {
			w.folderMap[fld.ID] = fld
		}
	}
	return w.folderMap
}

// SetFolder adds a new folder to the configuration, or overwrites an existing
// folder with the same ID.
func (w *ConfigWrapper) SetFolder(fld FolderConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.folderMap = nil

	for i := range w.cfg.Folders {
		if w.cfg.Folders[i].ID == fld.ID {
			w.cfg.Folders[i] = fld
			w.replaces <- w.cfg
			return
		}
	}

	w.cfg.Folders = append(w.cfg.Folders, fld)
	w.replaces <- w.cfg
}

// Options returns the current options configuration object.
func (w *ConfigWrapper) Options() OptionsConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	return w.cfg.Options
}

// SetOptions replaces the current options configuration object.
func (w *ConfigWrapper) SetOptions(opts OptionsConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()
	w.cfg.Options = opts
	w.replaces <- w.cfg
}

// GUI returns the current GUI configuration object.
func (w *ConfigWrapper) GUI() GUIConfiguration {
	w.mut.Lock()
	defer w.mut.Unlock()
	return w.cfg.GUI
}

// SetGUI replaces the current GUI configuration object.
func (w *ConfigWrapper) SetGUI(gui GUIConfiguration) {
	w.mut.Lock()
	defer w.mut.Unlock()
	w.cfg.GUI = gui
	w.replaces <- w.cfg
}

// InvalidateFolder sets the invalid marker on the given folder.
func (w *ConfigWrapper) InvalidateFolder(id string, err string) {
	w.mut.Lock()
	defer w.mut.Unlock()

	w.folderMap = nil

	for i := range w.cfg.Folders {
		if w.cfg.Folders[i].ID == id {
			w.cfg.Folders[i].Invalid = err
			w.replaces <- w.cfg
			return
		}
	}
}

// Save writes the configuration to disk, and generates a ConfigSaved event.
func (w *ConfigWrapper) Save() error {
	fd, err := ioutil.TempFile(filepath.Dir(w.path), "cfg")
	if err != nil {
		return err
	}

	err = w.cfg.WriteXML(fd)
	if err != nil {
		fd.Close()
		return err
	}

	err = fd.Close()
	if err != nil {
		return err
	}

	events.Default.Log(events.ConfigSaved, w.cfg)

	return osutil.Rename(fd.Name(), w.path)
}
<|endoftext|>


<commit_before>// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package json_test

import (
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/internal/json"
	"github.com/gogf/gf/test/gtest"
	"testing"
)

type User struct {
	Id   int64  `json:"id"`
	Name string `json:"name"`
}

var (
	user = &User{
		Id:   1265476890672672808,
		Name: "john",
	}
)

func TestMarshal(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		b, err := json.Marshal(user)
		t.AssertNil(err)
		t.Assert(b, `{"id":1265476890672672808,"name":"john"}`)
	})
}

func TestMarshalIndent(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		b, err := json.MarshalIndent(user, "#", "@")
		t.AssertNil(err)
		t.Assert(b, `{
#@"id": 1265476890672672808,
#@"name": "john"
#}`)
	})
}

func TestUnmarshal(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		var m map[string]interface{}
		b, _ := json.Marshal(g.Map{
			"user": user,
		})
		err := json.Unmarshal(b, &m)
		t.AssertNil(err)
		// precision lost for big int.
		t.Assert(m["user"], g.Map{
			"id":   1265476890672672800,
			"name": user.Name,
		})
	})
}

func TestUnmarshalUseNumber(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		var m map[string]interface{}
		b, _ := json.Marshal(g.Map{
			"user": user,
		})
		err := json.UnmarshalUseNumber(b, &m)
		t.AssertNil(err)
		t.Assert(m["user"], g.Map{
			"id":   user.Id,
			"name": user.Name,
		})
	})
}

func TestValid(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		m := g.Map{
			`{}`:                     true,
			`{"id":1,"name":"john"}`: true,
			`1`:                      true,
			`"john"`:                 true,
			`"`:                      false,
			`<xml></xml>`:            false,
		}
		for k, v := range m {
			t.Assert(json.Valid([]byte(k)), v)
		}
	})
}
<commit_msg>remove unit testing file for package internal/json<commit_after><|endoftext|>


<commit_before>package template

var (
	ProtoFNC = `syntax = "proto3";

package {{.FQDN}};

service Example {
	rpc Call(Request) returns (Response) {}
}

message Message {
	string say = 1;
}

message Request {
	string name = 1;
}

message Response {
	string msg = 1;
}
`

	ProtoSRV = `syntax = "proto3";

package {{.FQDN}};

service Example {
	rpc Call(Request) returns (Response) {}
	rpc Stream(StreamingRequest) returns (stream StreamingResponse) {}
	rpc PingPong(stream Ping) returns (stream Pong) {}
}

message Message {
	string say = 1;
}

message Request {
	string name = 1;
}

message Response {
	string msg = 1;
}

message StreamingRequest {
	int64 count = 1;
}

message StreamingResponse {
	int64 count = 1;
}

message Ping {
	int64 stroke = 1;
}

message Pong {
	int64 stroke = 1;
}
`

	ProtoAPI = `syntax = "proto3";

package {{.FQDN}};

import "github.com/micro/go-api/proto/api.proto";

service Example {
	rpc Call(api.Request) returns (api.Response) {}
}
`
)
<commit_msg>fix compile error for api proto<commit_after>package template

var (
	ProtoFNC = `syntax = "proto3";

package {{.FQDN}};

service Example {
	rpc Call(Request) returns (Response) {}
}

message Message {
	string say = 1;
}

message Request {
	string name = 1;
}

message Response {
	string msg = 1;
}
`

	ProtoSRV = `syntax = "proto3";

package {{.FQDN}};

service Example {
	rpc Call(Request) returns (Response) {}
	rpc Stream(StreamingRequest) returns (stream StreamingResponse) {}
	rpc PingPong(stream Ping) returns (stream Pong) {}
}

message Message {
	string say = 1;
}

message Request {
	string name = 1;
}

message Response {
	string msg = 1;
}

message StreamingRequest {
	int64 count = 1;
}

message StreamingResponse {
	int64 count = 1;
}

message Ping {
	int64 stroke = 1;
}

message Pong {
	int64 stroke = 1;
}
`

	ProtoAPI = `syntax = "proto3";

package {{.FQDN}};

import "github.com/micro/go-api/proto/api.proto";

service Example {
	rpc Call(go.api.Request) returns (go.api.Response) {}
}
`
)
<|endoftext|>