<commit_before>package cellnet

import (
	"fmt"
	"path"
	"reflect"
	"regexp"
	"strings"
)

// 消息元信息
type MessageMeta struct {
	Codec Codec        // 消息用到的编码
	Type  reflect.Type // 消息类型

	ID int // 消息ID (二进制协议中使用)
}

func (self *MessageMeta) TypeName() string {

	if self == nil {
		return ""
	}

	if self.Type.Kind() == reflect.Ptr {
		return self.Type.Elem().Name()
	}

	return self.Type.Name()
}

func (self *MessageMeta) FullName() string {

	if self == nil {
		return ""
	}

	rtype := self.Type
	if rtype.Kind() == reflect.Ptr {
		rtype = rtype.Elem()
	}

	var sb strings.Builder
	sb.WriteString(path.Base(rtype.PkgPath()))
	sb.WriteString(".")
	sb.WriteString(rtype.Name())

	return sb.String()
}

func (self *MessageMeta) NewType() interface{} {
	return reflect.New(self.Type).Interface()
}

var (
	// 消息元信息与消息名称，消息ID和消息类型的关联关系
	metaByFullName = map[string]*MessageMeta{}
	metaByID       = map[int]*MessageMeta{}
	metaByType     = map[reflect.Type]*MessageMeta{}
)

/*
http消息
Method URL -> Meta
Type -> Meta

非http消息
ID -> Meta
Type -> Meta

*/

// 注册消息元信息
func RegisterMessageMeta(meta *MessageMeta) {

	// 非http类,才需要包装Type必须唯一

	if _, ok := metaByType[meta.Type]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by type: %d", meta.ID))
	} else {
		metaByType[meta.Type] = meta
	}

	if _, ok := metaByFullName[meta.FullName()]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by fullname: %s", meta.FullName()))
	} else {
		metaByFullName[meta.FullName()] = meta
	}

	if meta.ID == 0 {
		panic("message meta require 'ID' field: " + meta.TypeName())
	}

	if _, ok := metaByID[meta.ID]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by id: %d", meta.ID))
	} else {
		metaByID[meta.ID] = meta
	}

}

// 根据名字查找消息元信息
func MessageMetaByFullName(name string) *MessageMeta {
	if v, ok := metaByFullName[name]; ok {
		return v
	}

	return nil
}

func MessageMetaVisit(nameRule string, callback func(meta *MessageMeta) bool) error {
	exp, err := regexp.Compile(nameRule)
	if err != nil {
		return err
	}

	for name, meta := range metaByFullName {
		if exp.MatchString(name) {

			if !callback(meta) {
				return nil
			}

		}
	}

	return nil
}

// 根据类型查找消息元信息
func MessageMetaByType(t reflect.Type) *MessageMeta {

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if v, ok := metaByType[t]; ok {
		return v
	}

	return nil
}

// 根据消息对象获得消息元信息
func MessageMetaByMsg(msg interface{}) *MessageMeta {

	if msg == nil {
		return nil
	}

	return MessageMetaByType(reflect.TypeOf(msg))
}

// 根据id查找消息元信息
func MessageMetaByID(id int) *MessageMeta {
	if v, ok := metaByID[id]; ok {
		return v
	}

	return nil
}

func MessageToName(msg interface{}) string {

	if msg == nil {
		return ""
	}

	meta := MessageMetaByMsg(msg)
	if meta == nil {
		return ""
	}

	return meta.TypeName()
}

func MessageToID(msg interface{}) int {

	if msg == nil {
		return 0
	}

	meta := MessageMetaByMsg(msg)
	if meta == nil {
		return 0
	}

	return int(meta.ID)
}

func MessageSize(msg interface{}) int {

	if msg == nil {
		return 0
	}

	// 获取消息元信息
	meta := MessageMetaByType(reflect.TypeOf(msg))
	if meta == nil {
		return 0
	}

	// 将消息编码为字节数组
	raw, err := meta.Codec.Encode(msg, nil)

	if err != nil {
		return 0
	}

	return len(raw.([]byte))
}

func MessageToString(msg interface{}) string {

	if msg == nil {
		return ""
	}

	if stringer, ok := msg.(interface {
		String() string
	}); ok {
		return stringer.String()
	}

	return ""
}
<commit_msg>修复: 防止取meta崩溃<commit_after>package cellnet

import (
	"fmt"
	"path"
	"reflect"
	"regexp"
	"strings"
)

// 消息元信息
type MessageMeta struct {
	Codec Codec        // 消息用到的编码
	Type  reflect.Type // 消息类型

	ID int // 消息ID (二进制协议中使用)
}

func (self *MessageMeta) TypeName() string {

	if self == nil {
		return ""
	}

	if self.Type.Kind() == reflect.Ptr {
		return self.Type.Elem().Name()
	}

	return self.Type.Name()
}

func (self *MessageMeta) FullName() string {

	if self == nil {
		return ""
	}

	rtype := self.Type
	if rtype.Kind() == reflect.Ptr {
		rtype = rtype.Elem()
	}

	var sb strings.Builder
	sb.WriteString(path.Base(rtype.PkgPath()))
	sb.WriteString(".")
	sb.WriteString(rtype.Name())

	return sb.String()
}

func (self *MessageMeta) NewType() interface{} {
	return reflect.New(self.Type).Interface()
}

var (
	// 消息元信息与消息名称，消息ID和消息类型的关联关系
	metaByFullName = map[string]*MessageMeta{}
	metaByID       = map[int]*MessageMeta{}
	metaByType     = map[reflect.Type]*MessageMeta{}
)

/*
http消息
Method URL -> Meta
Type -> Meta

非http消息
ID -> Meta
Type -> Meta

*/

// 注册消息元信息
func RegisterMessageMeta(meta *MessageMeta) {

	// 非http类,才需要包装Type必须唯一

	if _, ok := metaByType[meta.Type]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by type: %d", meta.ID))
	} else {
		metaByType[meta.Type] = meta
	}

	if _, ok := metaByFullName[meta.FullName()]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by fullname: %s", meta.FullName()))
	} else {
		metaByFullName[meta.FullName()] = meta
	}

	if meta.ID == 0 {
		panic("message meta require 'ID' field: " + meta.TypeName())
	}

	if _, ok := metaByID[meta.ID]; ok {
		panic(fmt.Sprintf("Duplicate message meta register by id: %d", meta.ID))
	} else {
		metaByID[meta.ID] = meta
	}

}

// 根据名字查找消息元信息
func MessageMetaByFullName(name string) *MessageMeta {
	if v, ok := metaByFullName[name]; ok {
		return v
	}

	return nil
}

func MessageMetaVisit(nameRule string, callback func(meta *MessageMeta) bool) error {
	exp, err := regexp.Compile(nameRule)
	if err != nil {
		return err
	}

	for name, meta := range metaByFullName {
		if exp.MatchString(name) {

			if !callback(meta) {
				return nil
			}

		}
	}

	return nil
}

// 根据类型查找消息元信息
func MessageMetaByType(t reflect.Type) *MessageMeta {

	if t == nil {
		return nil
	}

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if v, ok := metaByType[t]; ok {
		return v
	}

	return nil
}

// 根据消息对象获得消息元信息
func MessageMetaByMsg(msg interface{}) *MessageMeta {

	if msg == nil {
		return nil
	}

	return MessageMetaByType(reflect.TypeOf(msg))
}

// 根据id查找消息元信息
func MessageMetaByID(id int) *MessageMeta {
	if v, ok := metaByID[id]; ok {
		return v
	}

	return nil
}

func MessageToName(msg interface{}) string {

	if msg == nil {
		return ""
	}

	meta := MessageMetaByMsg(msg)
	if meta == nil {
		return ""
	}

	return meta.TypeName()
}

func MessageToID(msg interface{}) int {

	if msg == nil {
		return 0
	}

	meta := MessageMetaByMsg(msg)
	if meta == nil {
		return 0
	}

	return int(meta.ID)
}

func MessageSize(msg interface{}) int {

	if msg == nil {
		return 0
	}

	// 获取消息元信息
	meta := MessageMetaByType(reflect.TypeOf(msg))
	if meta == nil {
		return 0
	}

	// 将消息编码为字节数组
	raw, err := meta.Codec.Encode(msg, nil)

	if err != nil {
		return 0
	}

	return len(raw.([]byte))
}

func MessageToString(msg interface{}) string {

	if msg == nil {
		return ""
	}

	if stringer, ok := msg.(interface {
		String() string
	}); ok {
		return stringer.String()
	}

	return ""
}
<|endoftext|>


<commit_before>package mint

import "testing"
import "fmt"
import "os"

type Testee struct {
	t        *testing.T
	actual   interface{}
	expected interface{}
	dry      bool
	not      bool
	Result   Result
}
type Result struct {
	OK      bool
	Message string
}

var (
	FailBase = 0
	FailType = 1
	Scolds   = map[int]string{
		FailBase: "Expected %sto be `%+v`, but actual `%+v`\n",
		FailType: "Expected %stype `%+v`, but actual `%T`\n",
	}
)

func Expect(t *testing.T, actual interface{}) *Testee {
	return &Testee{t: t, actual: actual, Result: Result{OK: true}}
}
func (testee *Testee) Dry() *Testee {
	testee.dry = true
	return testee
}
func (testee *Testee) Not() *Testee {
	testee.not = true
	return testee
}
func (testee *Testee) failed(failure int) *Testee {
	message := testee.toText(failure)
	if !testee.dry {
		fmt.Println(message)
		testee.t.Fail()
		os.Exit(1)
	}
	testee.Result.OK = false
	testee.Result.Message = message
	return testee
}
func (testee *Testee) toText(fail int) string {
	not := ""
	if testee.not {
		not = "NOT "
	}
	return fmt.Sprintf(
		Scolds[fail],
		not,
		testee.expected,
		testee.actual,
	)
}
func judge(a, b interface{}, not bool) bool {
	if not {
		return a != b
	}
	return a == b
}
<commit_msg>Use `t.Errorf()` instead of `fmt.Printf()`<commit_after>package mint

import "testing"
import "fmt"
import "os"

type Testee struct {
	t        *testing.T
	actual   interface{}
	expected interface{}
	dry      bool
	not      bool
	Result   Result
}
type Result struct {
	OK      bool
	Message string
}

var (
	FailBase = 0
	FailType = 1
	Scolds   = map[int]string{
		FailBase: "Expected %sto be `%+v`, but actual `%+v`\n",
		FailType: "Expected %stype `%+v`, but actual `%T`\n",
	}
)

func Expect(t *testing.T, actual interface{}) *Testee {
	return &Testee{t: t, actual: actual, Result: Result{OK: true}}
}
func (testee *Testee) Dry() *Testee {
	testee.dry = true
	return testee
}
func (testee *Testee) Not() *Testee {
	testee.not = true
	return testee
}
func (testee *Testee) failed(failure int) *Testee {
	message := testee.toText(failure)
	if !testee.dry {
		testee.t.Errorf(message)
		testee.t.Fail()
		os.Exit(1)
	}
	testee.Result.OK = false
	testee.Result.Message = message
	return testee
}
func (testee *Testee) toText(fail int) string {
	not := ""
	if testee.not {
		not = "NOT "
	}
	return fmt.Sprintf(
		Scolds[fail],
		not,
		testee.expected,
		testee.actual,
	)
}
func judge(a, b interface{}, not bool) bool {
	if not {
		return a != b
	}
	return a == b
}
<|endoftext|>


<commit_before>package torrent

import (
	"errors"
	"net"

	"github.com/anacrolix/torrent/metainfo"
	pp "github.com/anacrolix/torrent/peer_protocol"
)

type chunkSpec struct {
	Begin, Length pp.Integer
}

type request struct {
	Index pp.Integer
	chunkSpec
}

func newRequest(index, begin, length pp.Integer) request {
	return request{index, chunkSpec{begin, length}}
}

func newRequestFromMessage(msg *pp.Message) request {
	switch msg.Type {
	case pp.Request:
		return newRequest(msg.Index, msg.Begin, msg.Length)
	case pp.Piece:
		return newRequest(msg.Index, msg.Begin, pp.Integer(len(msg.Piece)))
	default:
		panic(msg.Type)
	}
}

// The size in bytes of a metadata extension piece.
func metadataPieceSize(totalSize int, piece int) int {
	ret := totalSize - piece*(1<<14)
	if ret > 1<<14 {
		ret = 1 << 14
	}
	return ret
}

// Return the request that would include the given offset into the torrent data.
func torrentOffsetRequest(torrentLength, pieceSize, chunkSize, offset int64) (
	r request, ok bool) {
	if offset < 0 || offset >= torrentLength {
		return
	}
	r.Index = pp.Integer(offset / pieceSize)
	r.Begin = pp.Integer(offset % pieceSize / chunkSize * chunkSize)
	r.Length = pp.Integer(chunkSize)
	pieceLeft := pp.Integer(pieceSize - int64(r.Begin))
	if r.Length > pieceLeft {
		r.Length = pieceLeft
	}
	torrentLeft := torrentLength - int64(r.Index)*pieceSize - int64(r.Begin)
	if int64(r.Length) > torrentLeft {
		r.Length = pp.Integer(torrentLeft)
	}
	ok = true
	return
}

func torrentRequestOffset(torrentLength, pieceSize int64, r request) (off int64) {
	off = int64(r.Index)*pieceSize + int64(r.Begin)
	if off < 0 || off >= torrentLength {
		panic("invalid request")
	}
	return
}

func validateInfo(info *metainfo.Info) error {
	if len(info.Pieces)%20 != 0 {
		return errors.New("pieces has invalid length")
	}
	if info.PieceLength == 0 {
		if info.TotalLength() != 0 {
			return errors.New("zero piece length")
		}
	} else {
		if int((info.TotalLength()+info.PieceLength-1)/info.PieceLength) != info.NumPieces() {
			return errors.New("piece count and file lengths are at odds")
		}
	}
	return nil
}

func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
	ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
	if ret.Begin+ret.Length > pieceLength {
		ret.Length = pieceLength - ret.Begin
	}
	return ret
}

func connLessTrusted(l, r *connection) bool {
	return l.netGoodPiecesDirtied() < r.netGoodPiecesDirtied()
}

// Convert a net.Addr to its compact IP representation. Either 4 or 16 bytes
// per "yourip" field of http://www.bittorrent.org/beps/bep_0010.html.
func addrCompactIP(addr net.Addr) (string, error) {
	host, _, err := net.SplitHostPort(addr.String())
	if err != nil {
		return "", err
	}
	ip := net.ParseIP(host)
	if v4 := ip.To4(); v4 != nil {
		if len(v4) != 4 {
			panic(v4)
		}
		return string(v4), nil
	}
	return string(ip.To16()), nil
}
<commit_msg>request can be made from Reject and Cancel messages too<commit_after>package torrent

import (
	"errors"
	"net"

	"github.com/anacrolix/torrent/metainfo"
	pp "github.com/anacrolix/torrent/peer_protocol"
)

type chunkSpec struct {
	Begin, Length pp.Integer
}

type request struct {
	Index pp.Integer
	chunkSpec
}

func newRequest(index, begin, length pp.Integer) request {
	return request{index, chunkSpec{begin, length}}
}

func newRequestFromMessage(msg *pp.Message) request {
	switch msg.Type {
	case pp.Request, pp.Cancel, pp.Reject:
		return newRequest(msg.Index, msg.Begin, msg.Length)
	case pp.Piece:
		return newRequest(msg.Index, msg.Begin, pp.Integer(len(msg.Piece)))
	default:
		panic(msg.Type)
	}
}

// The size in bytes of a metadata extension piece.
func metadataPieceSize(totalSize int, piece int) int {
	ret := totalSize - piece*(1<<14)
	if ret > 1<<14 {
		ret = 1 << 14
	}
	return ret
}

// Return the request that would include the given offset into the torrent data.
func torrentOffsetRequest(torrentLength, pieceSize, chunkSize, offset int64) (
	r request, ok bool) {
	if offset < 0 || offset >= torrentLength {
		return
	}
	r.Index = pp.Integer(offset / pieceSize)
	r.Begin = pp.Integer(offset % pieceSize / chunkSize * chunkSize)
	r.Length = pp.Integer(chunkSize)
	pieceLeft := pp.Integer(pieceSize - int64(r.Begin))
	if r.Length > pieceLeft {
		r.Length = pieceLeft
	}
	torrentLeft := torrentLength - int64(r.Index)*pieceSize - int64(r.Begin)
	if int64(r.Length) > torrentLeft {
		r.Length = pp.Integer(torrentLeft)
	}
	ok = true
	return
}

func torrentRequestOffset(torrentLength, pieceSize int64, r request) (off int64) {
	off = int64(r.Index)*pieceSize + int64(r.Begin)
	if off < 0 || off >= torrentLength {
		panic("invalid request")
	}
	return
}

func validateInfo(info *metainfo.Info) error {
	if len(info.Pieces)%20 != 0 {
		return errors.New("pieces has invalid length")
	}
	if info.PieceLength == 0 {
		if info.TotalLength() != 0 {
			return errors.New("zero piece length")
		}
	} else {
		if int((info.TotalLength()+info.PieceLength-1)/info.PieceLength) != info.NumPieces() {
			return errors.New("piece count and file lengths are at odds")
		}
	}
	return nil
}

func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec {
	ret := chunkSpec{pp.Integer(index) * chunkSize, chunkSize}
	if ret.Begin+ret.Length > pieceLength {
		ret.Length = pieceLength - ret.Begin
	}
	return ret
}

func connLessTrusted(l, r *connection) bool {
	return l.netGoodPiecesDirtied() < r.netGoodPiecesDirtied()
}

// Convert a net.Addr to its compact IP representation. Either 4 or 16 bytes
// per "yourip" field of http://www.bittorrent.org/beps/bep_0010.html.
func addrCompactIP(addr net.Addr) (string, error) {
	host, _, err := net.SplitHostPort(addr.String())
	if err != nil {
		return "", err
	}
	ip := net.ParseIP(host)
	if v4 := ip.To4(); v4 != nil {
		if len(v4) != 4 {
			panic(v4)
		}
		return string(v4), nil
	}
	return string(ip.To16()), nil
}
<|endoftext|>


<commit_before>package GoJob

import (
	"sync"
	"testing"
	"time"
)

type TestJobData struct {
	Value int;
}
var mutex sync.Mutex;
var counter = 0;

func (testData * TestJobData)  Job(){
	mutex.Lock();
	defer mutex.Unlock();
	counter += testData.Value;
}
func NewTestJobData(value int) *TestJobData  {
	return &TestJobData{Value:value};
}

func TestJobStart(t *testing.T)  {

	totalValueCount:= 0;
	job := NewJob("newtest",3);

	if job.WorkerQueue.count != 3 {
		t.Error("Error Occured on worker queue");
	}
	for i := 0; i < 10; i++ {
		totalValueCount += i;
		job.NewTask(NewTestJobData(i));
	}
	job.Start();
	time.Sleep(time.Second * 1)
	mutex.Lock();
	if counter != totalValueCount {
		t.Error("Workers are not working properly");
	}
	mutex.Unlock();
	tmp := job.WorkerQueue.head;
	job.WorkerQueue.mutex.RLock();
	doneTaskCount := 0;
	for tmp != nil {
		worker,ok := tmp.value.(*Worker);
		if ok {
			doneTaskCount += worker.doneTaskCount;
		}else {
			t.Error("Node value is not a worker!");
		}
		tmp = tmp.next;
	}
	job.WorkerQueue.mutex.RUnlock();
	if doneTaskCount != 10 {
		t.Error("All task Are not done!");
	}
	job.Stop();
	if !job.shouldStop.getBoolValue() {
		t.Error("Should be false");
	}
	time.Sleep(time.Second * 1)
}<commit_msg>1.6 race problem fixed<commit_after>package GoJob

import (
	"sync"
	"testing"
	"time"
)

type TestJobData struct {
	Value int;
}
var mutex sync.Mutex;
var counter = 0;

func (testData * TestJobData)  Job(){
	mutex.Lock();
	defer mutex.Unlock();
	counter += testData.Value;
}
func NewTestJobData(value int) *TestJobData  {
	return &TestJobData{Value:value};
}

func TestJobStart(t *testing.T)  {

	totalValueCount:= 0;
	job := NewJob("newtest",3);

	if job.WorkerQueue.count != 3 {
		t.Error("Error Occured on worker queue");
	}
	for i := 0; i < 10; i++ {
		totalValueCount += i;
		job.NewTask(NewTestJobData(i));
	}
	job.Start();
	time.Sleep(time.Second * 1)
	mutex.Lock();
	if counter != totalValueCount {
		t.Error("Workers are not working properly");
	}
	mutex.Unlock();
	job.WorkerQueue.mutex.RLock();
	tmp := job.WorkerQueue.head;
	doneTaskCount := 0;
	for tmp != nil {
		worker,ok := tmp.value.(*Worker);
		if ok {
			doneTaskCount += worker.doneTaskCount;
		}else {
			t.Error("Node value is not a worker!");
		}
		tmp = tmp.next;
	}
	job.WorkerQueue.mutex.RUnlock();
	if doneTaskCount != 10 {
		t.Error("All task Are not done!");
	}
	job.Stop();
	if !job.shouldStop.getBoolValue() {
		t.Error("Should be false");
	}
	time.Sleep(time.Second * 1)
}<|endoftext|>


<commit_before>// Package mqtt implements the Message Queuing Telemetry Transport (MQTT)
// protocol.
//
// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
package mqtt

import (
	"errors"
	"fmt"
	"net"
)

// Fixed Packets
var (
	pingPacket    = []byte{ping << 4, 0}
	pongPacket    = []byte{pong << 4, 0}
	disconnPacket = []byte{disconn << 4, 0}
)

const (
	packetMax = 268_435_455 // 4-byte varint
	stringMax = 65535       // 16-bit size prefixes
)

var (
	errPacketMax = errors.New("mqtt: packet limit of 256 MiB exceeded")
	errStringMax = errors.New("mqtt: string exceeds 65535 bytes")

	errUTF8 = errors.New("mqtt: invalid UTF-8 byte sequence")
	errNull = errors.New("mqtt: string contains null characer")
)

func stringCheck(s string) error {
	if len(s) > stringMax {
		return errStringMax
	}
	for _, r := range s {
		// “The character data in a UTF-8 encoded string MUST be
		// well-formed UTF-8 as defined by the Unicode specification …”
		// — MQTT Version 3.1.1, conformance statement MQTT-1.5.3-1
		if r == '\uFFFD' {
			return errUTF8
		}

		// “A UTF-8 encoded string MUST NOT include an encoding of the
		// null character U+0000.”
		// — MQTT Version 3.1.1, conformance statement MQTT-1.5.3-2
		if r == 0 {
			return errNull
		}
	}
	return nil
}

// ErrRequestLimit signals too many client requests.
var ErrRequestLimit = errors.New("mqtt: maximum number of pending requests reached")

// Protocol Constraints
var (
	ErrTopicName   = errors.New("mqtt: malformed topic name: null [U+0000] character, illegal UTF-8 sequence or size exceeds 64 kiB")
	ErrMessageSize = errors.New("mqtt: message size exceeds 268,435,451 B minus UTF-8 length of topic name")
)

// Quality of Service (QoS) are defines as numeric levels.
const (
	atMostOnce   = iota // fire and forget
	atLeastOnce         // network round trip + Persistence
	exactlyOnce         // two network round trips + Persistence
	reservedQoS3        // must not be used
)

// Control Packet Types
const (
	connReq = iota + 1
	connAck
	pubMsg
	pubAck      // QoS 1 confirm
	pubReceived // QoS 2 confirm, part Ⅰ
	pubRelease  // QoS 2 confirm, part Ⅱ
	pubComplete // QoS 2 confirm, part Ⅲ
	subReq
	subAck
	unsubReq
	unsubAck
	ping
	pong
	disconn
)

// Publication Flags
const (
	// Indicates that this might be re-delivery of an earlier attempt.
	dupeFlag = 8
	// Store the application message and its QoS, so that it can be
	// delivered to future subscribers.
	retainFlag = 1
)

// SessionConfig defines protocol settings.
type SessionConfig struct {
	// Required for the server to uniquely identify the session.
	ClientID string

	// Optional identification claim.
	UserName string
	// Optional credentials.
	Password []byte

	// Discard any previous session (on the server) and start a new one.
	CleanSession bool

	// Will is a message publication to be send when the
	// connection terminates without a disconnect package.
	Will struct {
		// Destination for the message.
		Topic string

		// The Will feature is disabled when nil.
		Message []byte

		// Persistence constraints.
		Retain bool

		// Delivery constraints.
		AtLeastOnce bool // raises the QoS to level 1
		ExactlyOnce bool // raises the QoS to level 2
	}

	// Timeout in seconds or disabled when zero.
	KeepAlive uint16
}

// Valid returns a protocol constraint violation, if any.
func (c *SessionConfig) Valid() error {
	if err := stringCheck(c.ClientID); err != nil {
		return fmt.Errorf("mqtt: illegal client identifier: %w", err)
	}
	if err := stringCheck(c.UserName); err != nil {
		return fmt.Errorf("mqtt: illegal user name: %w", err)
	}
	if len(c.Password) > stringMax {
		return fmt.Errorf("mqtt: password exceeds %d bytes", stringMax)
	}
	if c.Will.Message != nil {
		// MQTT Version 3.1.1, conformance statement MQTT-3.1.3-10
		if err := stringCheck(c.Will.Topic); err != nil {
			return fmt.Errorf("mqtt: illegal will topic: %w", err)
		}
		if len(c.Will.Message) > stringMax {
			return fmt.Errorf("mqtt: will message exceeds %d bytes", stringMax)
		}
	}
	return nil
}

func (c *SessionConfig) appendConnReq(dst []byte) []byte {
	size := 6 + 1 + 1 + 2 // protocol name + protocol level + connect flags + keep alive
	size += 2 + len(c.ClientID)
	var flags uint
	if c.UserName != "" {
		size += 2 + len(c.UserName)
		flags |= 1 << 7
	}
	if c.Password != nil {
		size += 2 + len(c.Password)
		flags |= 1 << 6
	}
	if c.Will.Message != nil {
		size += 4 + len(c.Will.Topic) + len(c.Will.Message)
		if c.Will.Retain {
			flags |= 1 << 5
		}
		switch {
		case c.Will.ExactlyOnce:
			flags |= exactlyOnce << 3
		case c.Will.AtLeastOnce:
			flags |= atLeastOnce << 3
		}
		flags |= 1 << 2
	}
	if c.CleanSession {
		flags |= 1 << 1
	}

	// encode packet
	dst = append(dst, connReq<<4)
	for size > 127 {
		dst = append(dst, byte(size|128))
		size >>= 7
	}
	dst = append(dst, byte(size),
		0, 4, 'M', 'Q', 'T', 'T', 4, byte(flags),
		byte(c.KeepAlive>>8), byte(c.KeepAlive),
		byte(len(c.ClientID)>>8), byte(len(c.ClientID)),
	)
	dst = append(dst, c.ClientID...)
	if c.Will.Message != nil {
		dst = append(dst, byte(len(c.Will.Topic)>>8), byte(len(c.Will.Topic)))
		dst = append(dst, c.Will.Topic...)
		dst = append(dst, byte(len(c.Will.Message)>>8), byte(len(c.Will.Message)))
		dst = append(dst, c.Will.Message...)
	}
	if c.UserName != "" {
		dst = append(dst, byte(len(c.UserName)>>8), byte(len(c.UserName)))
		dst = append(dst, c.UserName...)
	}
	if c.Password != nil {
		dst = append(dst, byte(len(c.Password)>>8), byte(len(c.Password)))
		dst = append(dst, c.Password...)
	}
	return dst
}

// LocalPacketIDFlag marks the key in the a local address space.
const localPacketIDFlag = 1 << 16

// Persistence abstracts session storage, for continuation inbetween connects.
// Content is addressed by a 17-bit key (range 0 to 131071).
type Persistence interface {
	// Resolves data under the key. Malfunction may cause submission delay.
	Load(key uint) ([]byte, error)

	// Upserts data under the key. Malfunction may cause resubmission with
	// OnceOrMore or ExactlyOnce deliveries. The Client Publish operation
	// fails entirely on Persist errors.
	Store(key uint, data net.Buffers) error

	// Removes data under the key. Malfunction may threaten the availability
	// of Persist in terms of storage space.
	Delete(key uint) error

	// Enumerates available data. Malfunction may prevent new connection
	// establishment when an existing session is continued!
	List() (keys []uint, err error)
}

// ConnectReturn is a response code for connect requests.
type connectReturn byte

const (
	accepted connectReturn = iota

	// ErrProto means that the server does not support the level of the MQTT
	// protocol requested by the client.
	ErrProto

	// ErrClientID means that the client identifier is correct UTF-8 but not
	// allowed by the Server.
	ErrClientID

	// ErrUnavailable means that the network connection has been made but
	// the MQTT service is unavailable.
	ErrUnavailable

	// ErrAuthBad means that the data in the user name or password is
	// malformed.
	ErrAuthBad

	// ErrAuth means that the client is not authorized to connect.
	ErrAuth
)

// Error honors the standard error interface.
func (code connectReturn) Error() string {
	const refuse = "mqtt: connection refused: "

	switch code {
	case accepted:
		return "OK" // not an error
	case ErrProto:
		return refuse + "unacceptable protocol version"
	case ErrClientID:
		return refuse + "client identifier rejected"
	case ErrUnavailable:
		return refuse + "server unavailable"
	case ErrAuthBad:
		return refuse + "malformed user name or password"
	case ErrAuth:
		return refuse + "not authorized"
	default:
		return fmt.Sprintf(refuse+"reserved return code %d", code)
	}
}
<commit_msg>Prevent use of accept response code and the reserved QoS level.<commit_after>// Package mqtt implements the Message Queuing Telemetry Transport (MQTT)
// protocol.
//
// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
package mqtt

import (
	"errors"
	"fmt"
	"net"
)

// Fixed Packets
var (
	pingPacket    = []byte{ping << 4, 0}
	pongPacket    = []byte{pong << 4, 0}
	disconnPacket = []byte{disconn << 4, 0}
)

const (
	packetMax = 268_435_455 // 4-byte varint
	stringMax = 65535       // 16-bit size prefixes
)

var (
	errPacketMax = errors.New("mqtt: packet limit of 256 MiB exceeded")
	errStringMax = errors.New("mqtt: string exceeds 65535 bytes")

	errUTF8 = errors.New("mqtt: invalid UTF-8 byte sequence")
	errNull = errors.New("mqtt: string contains null characer")
)

func stringCheck(s string) error {
	if len(s) > stringMax {
		return errStringMax
	}
	for _, r := range s {
		// “The character data in a UTF-8 encoded string MUST be
		// well-formed UTF-8 as defined by the Unicode specification …”
		// — MQTT Version 3.1.1, conformance statement MQTT-1.5.3-1
		if r == '\uFFFD' {
			return errUTF8
		}

		// “A UTF-8 encoded string MUST NOT include an encoding of the
		// null character U+0000.”
		// — MQTT Version 3.1.1, conformance statement MQTT-1.5.3-2
		if r == 0 {
			return errNull
		}
	}
	return nil
}

// ErrRequestLimit signals too many client requests.
var ErrRequestLimit = errors.New("mqtt: maximum number of pending requests reached")

// Protocol Constraints
var (
	ErrTopicName   = errors.New("mqtt: malformed topic name: null [U+0000] character, illegal UTF-8 sequence or size exceeds 64 kiB")
	ErrMessageSize = errors.New("mqtt: message size exceeds 268,435,451 B minus UTF-8 length of topic name")
)

// Quality of Service (QoS) are defined as numeric levels.
const (
	atMostOnce  = iota // fire and forget
	atLeastOnce        // network round trip + Persistence
	exactlyOnce        // two network round trips + Persistence
)

// Control Packet Types
const (
	connReq = iota + 1
	connAck
	pubMsg
	pubAck      // QoS 1 confirm
	pubReceived // QoS 2 confirm, part Ⅰ
	pubRelease  // QoS 2 confirm, part Ⅱ
	pubComplete // QoS 2 confirm, part Ⅲ
	subReq
	subAck
	unsubReq
	unsubAck
	ping
	pong
	disconn
)

// Publication Flags
const (
	// Indicates that this might be re-delivery of an earlier attempt.
	dupeFlag = 8
	// Store the application message and its QoS, so that it can be
	// delivered to future subscribers.
	retainFlag = 1
)

// SessionConfig defines protocol settings.
type SessionConfig struct {
	// Required for the server to uniquely identify the session.
	ClientID string

	// Optional identification claim.
	UserName string
	// Optional credentials.
	Password []byte

	// Discard any previous session (on the server) and start a new one.
	CleanSession bool

	// Will is a message publication to be send when the
	// connection terminates without a disconnect package.
	Will struct {
		// Destination for the message.
		Topic string

		// The Will feature is disabled when nil.
		Message []byte

		// Persistence constraints.
		Retain bool

		// Delivery constraints.
		AtLeastOnce bool // raises the QoS to level 1
		ExactlyOnce bool // raises the QoS to level 2
	}

	// Timeout in seconds or disabled when zero.
	KeepAlive uint16
}

// Valid returns a protocol constraint violation, if any.
func (c *SessionConfig) Valid() error {
	if err := stringCheck(c.ClientID); err != nil {
		return fmt.Errorf("mqtt: illegal client identifier: %w", err)
	}
	if err := stringCheck(c.UserName); err != nil {
		return fmt.Errorf("mqtt: illegal user name: %w", err)
	}
	if len(c.Password) > stringMax {
		return fmt.Errorf("mqtt: password exceeds %d bytes", stringMax)
	}
	if c.Will.Message != nil {
		// MQTT Version 3.1.1, conformance statement MQTT-3.1.3-10
		if err := stringCheck(c.Will.Topic); err != nil {
			return fmt.Errorf("mqtt: illegal will topic: %w", err)
		}
		if len(c.Will.Message) > stringMax {
			return fmt.Errorf("mqtt: will message exceeds %d bytes", stringMax)
		}
	}
	return nil
}

func (c *SessionConfig) appendConnReq(dst []byte) []byte {
	size := 6 + 1 + 1 + 2 // protocol name + protocol level + connect flags + keep alive
	size += 2 + len(c.ClientID)
	var flags uint
	if c.UserName != "" {
		size += 2 + len(c.UserName)
		flags |= 1 << 7
	}
	if c.Password != nil {
		size += 2 + len(c.Password)
		flags |= 1 << 6
	}
	if c.Will.Message != nil {
		size += 4 + len(c.Will.Topic) + len(c.Will.Message)
		if c.Will.Retain {
			flags |= 1 << 5
		}
		switch {
		case c.Will.ExactlyOnce:
			flags |= exactlyOnce << 3
		case c.Will.AtLeastOnce:
			flags |= atLeastOnce << 3
		}
		flags |= 1 << 2
	}
	if c.CleanSession {
		flags |= 1 << 1
	}

	// encode packet
	dst = append(dst, connReq<<4)
	for size > 127 {
		dst = append(dst, byte(size|128))
		size >>= 7
	}
	dst = append(dst, byte(size),
		0, 4, 'M', 'Q', 'T', 'T', 4, byte(flags),
		byte(c.KeepAlive>>8), byte(c.KeepAlive),
		byte(len(c.ClientID)>>8), byte(len(c.ClientID)),
	)
	dst = append(dst, c.ClientID...)
	if c.Will.Message != nil {
		dst = append(dst, byte(len(c.Will.Topic)>>8), byte(len(c.Will.Topic)))
		dst = append(dst, c.Will.Topic...)
		dst = append(dst, byte(len(c.Will.Message)>>8), byte(len(c.Will.Message)))
		dst = append(dst, c.Will.Message...)
	}
	if c.UserName != "" {
		dst = append(dst, byte(len(c.UserName)>>8), byte(len(c.UserName)))
		dst = append(dst, c.UserName...)
	}
	if c.Password != nil {
		dst = append(dst, byte(len(c.Password)>>8), byte(len(c.Password)))
		dst = append(dst, c.Password...)
	}
	return dst
}

// LocalPacketIDFlag marks the key in the a local address space.
const localPacketIDFlag = 1 << 16

// Persistence abstracts session storage, for continuation inbetween connects.
// Content is addressed by a 17-bit key (range 0 to 131071).
type Persistence interface {
	// Resolves data under the key. Malfunction may cause submission delay.
	Load(key uint) ([]byte, error)

	// Upserts data under the key. Malfunction may cause resubmission with
	// OnceOrMore or ExactlyOnce deliveries. The Client Publish operation
	// fails entirely on Persist errors.
	Store(key uint, data net.Buffers) error

	// Removes data under the key. Malfunction may threaten the availability
	// of Persist in terms of storage space.
	Delete(key uint) error

	// Enumerates available data. Malfunction may prevent new connection
	// establishment when an existing session is continued!
	List() (keys []uint, err error)
}

// ConnectReturn is a response code for connect requests.
type connectReturn byte

const (
	accepted connectReturn = iota

	// ErrProto means that the server does not support the level of the MQTT
	// protocol requested by the client.
	ErrProto

	// ErrClientID means that the client identifier is correct UTF-8 but not
	// allowed by the Server.
	ErrClientID

	// ErrUnavailable means that the network connection has been made but
	// the MQTT service is unavailable.
	ErrUnavailable

	// ErrAuthBad means that the data in the user name or password is
	// malformed.
	ErrAuthBad

	// ErrAuth means that the client is not authorized to connect.
	ErrAuth
)

// Error implements the standard error interface.
func (code connectReturn) Error() string {
	const refuse = "mqtt: connection refused: "

	switch code {
	case accepted:
		panic("connect return 0 [accepted] used as an error")
	case ErrProto:
		return refuse + "unacceptable protocol version"
	case ErrClientID:
		return refuse + "client identifier rejected"
	case ErrUnavailable:
		return refuse + "server unavailable"
	case ErrAuthBad:
		return refuse + "malformed user name or password"
	case ErrAuth:
		return refuse + "not authorized"
	default:
		return fmt.Sprintf(refuse+"reserved return code %d", code)
	}
}
<|endoftext|>


<commit_before><commit_msg>Fixed a read test, due to the Grammar now being correctly formatted.<commit_after><|endoftext|>


<commit_before><commit_msg>configurable tree date<commit_after><|endoftext|>


<commit_before>package main

import "io/ioutil"
import "path"
import "path/filepath"
import "errors"
import "fmt"
import "strings"
import "strconv"
import "os"

type Assemblable map[string]Instruction

type Instruction struct {
	Data, Path string
	Indent, Indented, Args int

	Indentation int
	Else *Instruction
	Function func(args []string) string
}

func is(s string, ns ...int) Instruction {
	var args, ind, indent int
	if len(ns) > 0 {
		args = ns[0]
	}
	if len(ns) > 1 {
		indent = ns[1]
	}
	if len(ns) > 2 {
		ind = ns[2]
	}
	return Instruction{Data:s, Args:args, Indent:indent, Indentation:ind}
}

func Reserved() Instruction {
	return Instruction{}
}

func (asm Assemblable) Header() []byte {
	b, err := asm.Assemble("HEADER", []string{asm["NAME"].Data})
	if err != nil {
		panic(err.Error())
	}
	return b
}

func (asm Assemblable) Indentation(n ...int) string {
	if _, ok := asm["INDENT"]; !ok {
		return ""
	}
	if len(n) > 0 {
		if int(asm["INDENT"].Indent)+n[0] < 0 {
			return ""
		}
		return strings.Repeat("\t", int(asm["INDENT"].Indent)+n[0])
	} else {
		return strings.Repeat("\t", int(asm["INDENT"].Indent))
	}
}

func (asm Assemblable) SetFileName(name string) {
	if _, err := os.Stat(path.Dir(name)+asm["FILE"].Path); os.IsNotExist(err) {
		ioutil.WriteFile(path.Dir(name)+asm["FILE"].Path, []byte(asm["FILE"].Data), 0600)
	}
	var extension = filepath.Ext(name)
	name = filepath.Base(name[0:len(name)-len(extension)])
	asm["NAME"] = Instruction{Data:path.Base(name)}
}

func (asm Assemblable) Footer() []byte {
	b, _ := asm.Assemble("FOOTER", nil)
	return b
}

func (asm Assemblable) Assemble(command string, args []string) ([]byte, error) {
	instruction, ok := asm[command]
	if !ok || instruction.Data  == "" {
		return nil, errors.New("Unrecognised command! "+command)
	}
	if command == "NUMBER" || command == "SIZE" || command == "STRING" {
		return []byte(fmt.Sprintf(instruction.Data, args[0])), nil
	}
	if command == "ERRORS" {
		return []byte(fmt.Sprintf(instruction.Data)), nil
	}
	for i, arg := range args {
		if len(arg) == 0 {
			break
		}

		var b []byte
		if _, err := strconv.Atoi(arg); err == nil {
			b, err = asm.Assemble("NUMBER", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		}

		if _, err := strconv.Atoi(arg); err == nil {
			b, err = asm.Assemble("NUMBER", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		} else if _, err := strconv.Atoi(string(arg[0])); err == nil || arg[0] == '-' {
			b, err = asm.Assemble("BIG", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		}

		if arg[0] == '#' {
			b, _ = asm.Assemble("SIZE", []string{arg[1:]})
			args[i] = string(b)
			continue
		}
		if arg[0] == '"' {
			b, _ = asm.Assemble("STRING", []string{strings.Join(args[i:], " ")})
			args[i] = string(b)
			args = args[:i+1]
			break
		}
		if arg == "ERROR" {
			b, _ = asm.Assemble("ERRORS", []string{arg[1:]})
			args[i] = string(b)
			continue
		}
		if _, ok := asm[arg]; ok {
			args[i] = "u_"+args[i]
		}
	}

	if indent, ok := asm["INDENT"]; ok {
		if (instruction.Indented == -1 && 0 != indent.Indent) ||
		(instruction.Indented != 0 && instruction.Indented != indent.Indent) {
			instruction = *instruction.Else
		}
	}

	if len(args) != instruction.Args {
		return nil, errors.New(command+" Argument count mismatch! "+fmt.Sprintf("%v != %v args:%v", len(args), instruction.Args,args))
	}

	if instruction.Function != nil {
		result := instruction.Function(args)
		return []byte(result), nil
	}

	varaidic := make([]interface {}, len(args))
	for i, v := range args {
		varaidic[i] = v
	}
	if len(args) > 0 && strings.Count(instruction.Data, "%s") > instruction.Args {
		varaidic = append(varaidic, varaidic[len(varaidic)-1])
	}

	if instruction.Indent != 0 {
		if _, ok := asm["INDENT"]; !ok {
			asm["INDENT"] = Instruction{}
		}
		defer func() {
			asm["INDENT"] = Instruction{Indent: asm["INDENT"].Indent+instruction.Indent}
			if asm["INDENT"].Indent < 0 {
				asm["INDENT"] = Instruction{Indent: 0}
			}
		}()

	}

	if strings.Count(instruction.Data, "%s") >= 1 {

		return []byte(asm.Indentation(instruction.Indentation)+
			fmt.Sprintf(instruction.Data+"\n", varaidic...)), nil
	} else {
		return []byte(asm.Indentation(instruction.Indentation)+
			fmt.Sprint(instruction.Data+"\n")), nil
	}
}
<commit_msg>Add embeddable native code instructions.<commit_after>package main

import "io/ioutil"
import "path"
import "path/filepath"
import "errors"
import "fmt"
import "strings"
import "strconv"
import "os"

type Assemblable map[string]Instruction

type Instruction struct {
	Data, Path string
	Indent, Indented, Args int

	All bool

	Indentation int
	Else *Instruction
	Function func(args []string) string
}

func is(s string, ns ...int) Instruction {
	var args, ind, indent int
	if len(ns) > 0 {
		args = ns[0]
	}
	if len(ns) > 1 {
		indent = ns[1]
	}
	if len(ns) > 2 {
		ind = ns[2]
	}
	return Instruction{Data:s, Args:args, Indent:indent, Indentation:ind}
}

func Reserved() Instruction {
	return Instruction{}
}

func (asm Assemblable) Header() []byte {
	b, err := asm.Assemble("HEADER", []string{asm["NAME"].Data})
	if err != nil {
		panic(err.Error())
	}
	return b
}

func (asm Assemblable) Indentation(n ...int) string {
	if _, ok := asm["INDENT"]; !ok {
		return ""
	}
	if len(n) > 0 {
		if int(asm["INDENT"].Indent)+n[0] < 0 {
			return ""
		}
		return strings.Repeat("\t", int(asm["INDENT"].Indent)+n[0])
	} else {
		return strings.Repeat("\t", int(asm["INDENT"].Indent))
	}
}

func (asm Assemblable) SetFileName(name string) {
	if _, err := os.Stat(path.Dir(name)+asm["FILE"].Path); os.IsNotExist(err) {
		ioutil.WriteFile(path.Dir(name)+asm["FILE"].Path, []byte(asm["FILE"].Data), 0600)
	}
	var extension = filepath.Ext(name)
	name = filepath.Base(name[0:len(name)-len(extension)])
	asm["NAME"] = Instruction{Data:path.Base(name)}
}

func (asm Assemblable) Footer() []byte {
	b, _ := asm.Assemble("FOOTER", nil)
	return b
}

var Languages = map[string]bool {
	"JAVA":true,
	"GO":true,
	"PYTHON":true,
}

func (asm Assemblable) Assemble(command string, args []string) ([]byte, error) {
	instruction, ok := asm[command]
	if !ok {
		if Languages[command] {
			return []byte(""), nil
		}
		return nil, errors.New("Unrecognised command! "+command)
	}
	if instruction.All {
		return []byte(strings.Join(args, " ")+"\n"), nil
	}
	if instruction.Data  == "" {
		return nil, errors.New("Bad command! "+command)
	}
	if command == "NUMBER" || command == "SIZE" || command == "STRING" {
		return []byte(fmt.Sprintf(instruction.Data, args[0])), nil
	}
	if command == "ERRORS" {
		return []byte(fmt.Sprintf(instruction.Data)), nil
	}
	for i, arg := range args {
		if len(arg) == 0 {
			break
		}

		var b []byte
		if _, err := strconv.Atoi(arg); err == nil {
			b, err = asm.Assemble("NUMBER", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		}

		if _, err := strconv.Atoi(arg); err == nil {
			b, err = asm.Assemble("NUMBER", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		} else if _, err := strconv.Atoi(string(arg[0])); err == nil || arg[0] == '-' {
			b, err = asm.Assemble("BIG", []string{arg})
			if err != nil {
				panic(err.Error())
			}
			args[i] = string(b)
			continue
		}

		if arg[0] == '#' {
			b, _ = asm.Assemble("SIZE", []string{arg[1:]})
			args[i] = string(b)
			continue
		}
		if arg[0] == '"' {
			b, _ = asm.Assemble("STRING", []string{strings.Join(args[i:], " ")})
			args[i] = string(b)
			args = args[:i+1]
			break
		}
		if arg == "ERROR" {
			b, _ = asm.Assemble("ERRORS", []string{arg[1:]})
			args[i] = string(b)
			continue
		}
		if _, ok := asm[arg]; ok {
			args[i] = "u_"+args[i]
		}
	}

	if indent, ok := asm["INDENT"]; ok {
		if (instruction.Indented == -1 && 0 != indent.Indent) ||
		(instruction.Indented != 0 && instruction.Indented != indent.Indent) {
			instruction = *instruction.Else
		}
	}

	if len(args) != instruction.Args {
		return nil, errors.New(command+" Argument count mismatch! "+fmt.Sprintf("%v != %v args:%v", len(args), instruction.Args,args))
	}

	if instruction.Function != nil {
		result := instruction.Function(args)
		return []byte(result), nil
	}

	varaidic := make([]interface {}, len(args))
	for i, v := range args {
		varaidic[i] = v
	}
	if len(args) > 0 && strings.Count(instruction.Data, "%s") > instruction.Args {
		varaidic = append(varaidic, varaidic[len(varaidic)-1])
	}

	if instruction.Indent != 0 {
		if _, ok := asm["INDENT"]; !ok {
			asm["INDENT"] = Instruction{}
		}
		defer func() {
			asm["INDENT"] = Instruction{Indent: asm["INDENT"].Indent+instruction.Indent}
			if asm["INDENT"].Indent < 0 {
				asm["INDENT"] = Instruction{Indent: 0}
			}
		}()

	}

	if strings.Count(instruction.Data, "%s") >= 1 {

		return []byte(asm.Indentation(instruction.Indentation)+
			fmt.Sprintf(instruction.Data+"\n", varaidic...)), nil
	} else {
		return []byte(asm.Indentation(instruction.Indentation)+
			fmt.Sprint(instruction.Data+"\n")), nil
	}
}
<|endoftext|>


<commit_before>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"github.com/briandowns/spinner"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/disc"
	"github.com/mehrdadrad/mylg/http/ping"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ns"
	"github.com/mehrdadrad/mylg/packet"
	"github.com/mehrdadrad/mylg/peeringdb"
	"github.com/mehrdadrad/mylg/scan"
	"github.com/mehrdadrad/mylg/services/httpd"
	"github.com/mehrdadrad/mylg/whois"
)

// Provider represents looking glass
type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() []string
	ChangeNode(node string) bool
	Ping() (string, error)
	Trace() chan string
	BGP() chan string
}

const (
	version = "0.2.1"
)

var (
	// register looking glass hosts
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
	req       = make(chan string, 1)
	nxt       = make(chan struct{}, 1)
	spin      = spinner.New(spinner.CharSets[26], 220*time.Millisecond)
	args      string
	prompt    string
	cPName    string
	nsr       *ns.Request
	c         *cli.Readline
)

// providerName
func providerNames() []string {
	pNames := []string{}
	for p := range providers {
		pNames = append(pNames, p)
	}
	return pNames
}

// validateProvider
func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	}
	return "", errors.New("provider not support")

}
func init() {
	// initialize cli
	c = cli.Init("local", version)
	go c.Run(req, nxt)
	// initialize name server
	nsr = ns.NewRequest()
	go nsr.Init()
	// start web server
	go httpd.Run()
	// set default provider
	cPName = "local"
}

func main() {
	var (
		request string
		loop    = true
	)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			if len(request) < 1 {
				c.Next()
				continue
			}
			subReq := cli.CMDReg.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				c.Next()
				continue
			}
			prompt = c.GetPrompt()
			args = strings.TrimSpace(subReq[2])
			cmd := strings.TrimSpace(subReq[1])
			switch {
			case cmd == "hping" && cPName == "local":
				hping()
			case cmd == "ping" && cPName == "local":
				pingLocal()
			case cmd == "ping":
				pingLG()
			case cmd == "trace":
				trace()
			case cmd == "bgp":
				BGP()
			case cmd == "dig":
				nsr.Dig(args)
			case cmd == "node":
				node()
			case cmd == "local":
				nsr.Local()
				cPName = "local"
				c.SetPrompt(cPName)
			case cmd == "connect":
				connect()
			case cmd == "lg":
				c.SetPrompt("lg")
				c.UpdateCompleter("connect", pNames)
			case cmd == "ns":
				c.UpdateCompleter("connect", nsr.CountryList())
				c.UpdateCompleter("node", []string{})
				c.SetPrompt("ns")
			case cmd == "whois":
				whois.Lookup(args)
			case cmd == "peering":
				peeringdb.Search(args)
			case cmd == "scan":
				scanPorts()
			case cmd == "mode":
				mode()
			case cmd == "web":
				web()
			case cmd == "dump":
				dump()
			case cmd == "disc":
				discovery()
			case cmd == "help":
				c.Help()
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
			}
			// next line
			c.Next()
		}
	}
}

// node handles node cmd
func node() {
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if _, ok := providers[cPName]; ok {
			if providers[cPName].ChangeNode(args) {
				c.UpdatePromptN(args, 3)
				return
			}
		}
		println("the specified node doesn't support")
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkNode(args) {
			println("error: argument is not valid")
		} else {
			c.UpdatePromptN(args, 3)
		}
	default:
		if cPName == "local" {
			println("local doesn't support node")
		}

	}
}

// web tries to open web interface at default web browser
func web() {
	var openCmd = "open"
	println("opening default web broswer ...")
	if runtime.GOOS != "darwin" {
		openCmd = "xdg-open"
	}
	cmd := exec.Command(openCmd, "http://localhost:8080")
	err := cmd.Start()
	if err != nil {
		println("error opening default browser")
	}

}

// dump provides decoding packets
func dump() {
	p, err := packet.NewPacket(args)
	if p == nil || err != nil {
		return
	}
	for l := range p.Open() {
		l.PrintPretty()
	}
}

// connect handles connect cmd
func connect() {
	var (
		pName string
		err   error
	)
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if pName, err = validateProvider(args); err != nil {
			println("provider not available")
			c.Next()
			return
		}
		cPName = pName
		if _, ok := providers[cPName]; ok {
			c.UpdatePromptN(cPName+"/"+providers[cPName].GetDefaultNode(), 2)
			go func() {
				c.UpdateCompleter("node", providers[cPName].GetNodes())
			}()
		} else {
			println("it doesn't support")
		}
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkCountry(args) {
			println("error: argument is not valid")
		} else {
			c.SetPrompt("ns/" + args)
			c.UpdateCompleter("node", nsr.NodeList())
		}
	}
}

// mode set editor mode
func mode() {
	if args == "vim" {
		c.SetVim()
	} else if args == "emacs" {
		c.SetEmacs()
	} else {
		println("the request mode doesn't support")
	}
}

// trace tries to trace from local and lg
func trace() {
	switch {
	case strings.HasPrefix(prompt, "local"):
		trace := icmp.Trace{}
		trace.Run(args)
	case strings.HasPrefix(prompt, "lg"):
		providers[cPName].Set(args, "ipv4")
		for l := range providers[cPName].Trace() {
			println(l)
		}
	}
}

// hping tries to ping a web server by http
func hping() {
	p, err := ping.NewPing(args)
	if err != nil {
		println(err.Error())
	} else {
		p.Run()
	}
}

// pingLG tries to ping through a looking glass
func pingLG() {
	spin.Prefix = "please wait "
	spin.Start()
	providers[cPName].Set(args, "ipv4")
	m, err := providers[cPName].Ping()
	spin.Stop()
	if err != nil {
		println(err.Error())
	} else {
		println(m)
	}
}

// pingLocal tries to ping from local source ip
func pingLocal() {
	p, err := icmp.NewPing(args)
	if err != nil {
		return
	}
	p.PrintPretty()
}

// scanPorts tries to scan tcp/ip ports
func scanPorts() {
	scan, err := scan.NewScan(args)
	if err != nil {
		println(err.Error())
	} else {
		scan.Run()
	}
}

// BGP tries to get BGP lookup from a LG
func BGP() {
	if cPName == "local" {
		println("no provider selected")
		return
	}
	providers[cPName].Set(args, "ipv4")
	for l := range providers[cPName].BGP() {
		println(l)
	}
}

// discovery handles disc command
func discovery() {
	var (
		wg sync.WaitGroup
		//ts = time.Now()
	)

	d := disc.New(args)
	// help requested
	if d == nil {
		return
	}

	spin.Prefix = "please wait "
	spin.Start()

	// load OUI async
	go func() {
		wg.Add(1)
		d.LoadOUI()
		wg.Done()
	}()
	d.PingLan()
	//s := 10 - int(time.Since(ts).Seconds())
	time.Sleep(5 * time.Second)
	if err := d.GetARPTable(); err != nil {
		println(err.Error())
		return
	}
	wg.Wait()
	spin.Stop()

	println("Network LAN Discovery")
	d.PrintPretty()
}
<commit_msg>print out error out of icmp package<commit_after>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"github.com/briandowns/spinner"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/disc"
	"github.com/mehrdadrad/mylg/http/ping"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ns"
	"github.com/mehrdadrad/mylg/packet"
	"github.com/mehrdadrad/mylg/peeringdb"
	"github.com/mehrdadrad/mylg/scan"
	"github.com/mehrdadrad/mylg/services/httpd"
	"github.com/mehrdadrad/mylg/whois"
)

// Provider represents looking glass
type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() []string
	ChangeNode(node string) bool
	Ping() (string, error)
	Trace() chan string
	BGP() chan string
}

const (
	version = "0.2.1"
)

var (
	// register looking glass hosts
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
	req       = make(chan string, 1)
	nxt       = make(chan struct{}, 1)
	spin      = spinner.New(spinner.CharSets[26], 220*time.Millisecond)
	args      string
	prompt    string
	cPName    string
	nsr       *ns.Request
	c         *cli.Readline
)

// providerName
func providerNames() []string {
	pNames := []string{}
	for p := range providers {
		pNames = append(pNames, p)
	}
	return pNames
}

// validateProvider
func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	}
	return "", errors.New("provider not support")

}
func init() {
	// initialize cli
	c = cli.Init("local", version)
	go c.Run(req, nxt)
	// initialize name server
	nsr = ns.NewRequest()
	go nsr.Init()
	// start web server
	go httpd.Run()
	// set default provider
	cPName = "local"
}

func main() {
	var (
		request string
		loop    = true
	)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			if len(request) < 1 {
				c.Next()
				continue
			}
			subReq := cli.CMDReg.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				c.Next()
				continue
			}
			prompt = c.GetPrompt()
			args = strings.TrimSpace(subReq[2])
			cmd := strings.TrimSpace(subReq[1])
			switch {
			case cmd == "hping" && cPName == "local":
				hping()
			case cmd == "ping" && cPName == "local":
				pingLocal()
			case cmd == "ping":
				pingLG()
			case cmd == "trace":
				trace()
			case cmd == "bgp":
				BGP()
			case cmd == "dig":
				nsr.Dig(args)
			case cmd == "node":
				node()
			case cmd == "local":
				nsr.Local()
				cPName = "local"
				c.SetPrompt(cPName)
			case cmd == "connect":
				connect()
			case cmd == "lg":
				c.SetPrompt("lg")
				c.UpdateCompleter("connect", pNames)
			case cmd == "ns":
				c.UpdateCompleter("connect", nsr.CountryList())
				c.UpdateCompleter("node", []string{})
				c.SetPrompt("ns")
			case cmd == "whois":
				whois.Lookup(args)
			case cmd == "peering":
				peeringdb.Search(args)
			case cmd == "scan":
				scanPorts()
			case cmd == "mode":
				mode()
			case cmd == "web":
				web()
			case cmd == "dump":
				dump()
			case cmd == "disc":
				discovery()
			case cmd == "help":
				c.Help()
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
			}
			// next line
			c.Next()
		}
	}
}

// node handles node cmd
func node() {
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if _, ok := providers[cPName]; ok {
			if providers[cPName].ChangeNode(args) {
				c.UpdatePromptN(args, 3)
				return
			}
		}
		println("the specified node doesn't support")
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkNode(args) {
			println("error: argument is not valid")
		} else {
			c.UpdatePromptN(args, 3)
		}
	default:
		if cPName == "local" {
			println("local doesn't support node")
		}

	}
}

// web tries to open web interface at default web browser
func web() {
	var openCmd = "open"
	println("opening default web broswer ...")
	if runtime.GOOS != "darwin" {
		openCmd = "xdg-open"
	}
	cmd := exec.Command(openCmd, "http://localhost:8080")
	err := cmd.Start()
	if err != nil {
		println("error opening default browser")
	}

}

// dump provides decoding packets
func dump() {
	p, err := packet.NewPacket(args)
	if p == nil || err != nil {
		return
	}
	for l := range p.Open() {
		l.PrintPretty()
	}
}

// connect handles connect cmd
func connect() {
	var (
		pName string
		err   error
	)
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if pName, err = validateProvider(args); err != nil {
			println("provider not available")
			c.Next()
			return
		}
		cPName = pName
		if _, ok := providers[cPName]; ok {
			c.UpdatePromptN(cPName+"/"+providers[cPName].GetDefaultNode(), 2)
			go func() {
				c.UpdateCompleter("node", providers[cPName].GetNodes())
			}()
		} else {
			println("it doesn't support")
		}
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkCountry(args) {
			println("error: argument is not valid")
		} else {
			c.SetPrompt("ns/" + args)
			c.UpdateCompleter("node", nsr.NodeList())
		}
	}
}

// mode set editor mode
func mode() {
	if args == "vim" {
		c.SetVim()
	} else if args == "emacs" {
		c.SetEmacs()
	} else {
		println("the request mode doesn't support")
	}
}

// trace tries to trace from local and lg
func trace() {
	switch {
	case strings.HasPrefix(prompt, "local"):
		trace := icmp.Trace{}
		trace.Run(args)
	case strings.HasPrefix(prompt, "lg"):
		providers[cPName].Set(args, "ipv4")
		for l := range providers[cPName].Trace() {
			println(l)
		}
	}
}

// hping tries to ping a web server by http
func hping() {
	p, err := ping.NewPing(args)
	if err != nil {
		println(err.Error())
	} else {
		p.Run()
	}
}

// pingLG tries to ping through a looking glass
func pingLG() {
	spin.Prefix = "please wait "
	spin.Start()
	providers[cPName].Set(args, "ipv4")
	m, err := providers[cPName].Ping()
	spin.Stop()
	if err != nil {
		println(err.Error())
	} else {
		println(m)
	}
}

// pingLocal tries to ping from local source ip
func pingLocal() {
	p, err := icmp.NewPing(args)
	if err != nil {
		println(err.Error())
	}
	if p == nil {
		return
	}
	p.PrintPretty()
}

// scanPorts tries to scan tcp/ip ports
func scanPorts() {
	scan, err := scan.NewScan(args)
	if err != nil {
		println(err.Error())
	} else {
		scan.Run()
	}
}

// BGP tries to get BGP lookup from a LG
func BGP() {
	if cPName == "local" {
		println("no provider selected")
		return
	}
	providers[cPName].Set(args, "ipv4")
	for l := range providers[cPName].BGP() {
		println(l)
	}
}

// discovery handles disc command
func discovery() {
	var (
		wg sync.WaitGroup
		//ts = time.Now()
	)

	d := disc.New(args)
	// help requested
	if d == nil {
		return
	}

	spin.Prefix = "please wait "
	spin.Start()

	// load OUI async
	go func() {
		wg.Add(1)
		d.LoadOUI()
		wg.Done()
	}()
	d.PingLan()
	//s := 10 - int(time.Since(ts).Seconds())
	time.Sleep(5 * time.Second)
	if err := d.GetARPTable(); err != nil {
		println(err.Error())
		return
	}
	wg.Wait()
	spin.Stop()

	println("Network LAN Discovery")
	d.PrintPretty()
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "log"
    /*"os"*/
    "io/ioutil"
    "flag"
    "time"
    /*"math/big"
    crand "crypto/rand"*/
    "math/rand"
    "strings"
    /*"encoding/json"*/
)

// Declare command line arguments
var input_files = flag.String("i", "language.dict", "the dictionary input file(s)") // TODO enable support for more than one input file
var separator = flag.String("l", "\n", "the separator used to split the input file")
var fill = flag.String("f", "0,1,2,3,4,5,6,7,8,9,_,!,?", "comma separated list of random fill characters")
var fill_length_min = flag.Int("fill-length-min", 1, "minimum length of the random fill insert")
var fill_length_max = flag.Int("fill-length-max", 3, "maximum length of the random fill insert")
var fill_before = flag.Bool("fill-before", false, "whether to insert a fill character before or after a word")
/*var output_file = flag.String("o", "passphrases.csv", "the output file (csv passphrase list)") // TODO or simply pass the result to the bash so it can be re-directed to a file
var output_file_type = flag.String("o-type", "csv", "the output file type")*/
var min_pass_length = flag.Int("min", 30, "minimum passphrase length")
var number_gen_passp = flag.Int("n", 10, "number of passphrases to generate")
var replace_chars = flag.String("r", "u\",ue,a\",ae,o\",oe,A\",Ae,O\",Oe,U\",Ue", "comma separated list of old new characters to replace in every dictionary word that is used for an actual passphrase")
// TODO add argument to enable/disable hashing of passwords (to only get distinct results)
var distinct = flag.Bool("d", true, "whether the generated passphrases have to be distinct from each other")

func main() {
    // Read the command line arguments.
    flag.Parse()

    /*flags := flag.Args()
    //fmt.Println(flags)
    for key, _ := range flags {
        fmt.Println(flags[key])
    }*/

    // Seed the RNG
    rand.Seed(time.Now().UnixNano()) // only pseudo random, better use crypto/rand

    // Read the dictionary files.
    dict, err := readDictionary(*input_files, *separator)
    if err != nil {
        panic(err)
    }
    if len(dict) == 0 {
        log.Fatal("Input dictionary is empty. Exiting.")
    }

    output := []string{}
    // repeat until enough passphrases are generated
    for i := 0; i < *number_gen_passp; i++ {
        new_passphrase := generatePassphrase(dict, strings.Split(*fill, ","))
        if checkUniqueness(output, new_passphrase) {
            output = append(output, new_passphrase)
        } else {
            i--
        }
    }

    // write the passphrases to the console
    for key, _ := range output {
        fmt.Println(output[key])
    }
}

// Open and read the dictionary file and push it's contents into a string array
func readDictionary(dict_file string, sep string) (dict[]string, err error) {
    // TODO maybe better check the filesize first ...
    b, err := ioutil.ReadFile(dict_file)
    if err != nil {
        return nil, err
    }
    dict = strings.Split(string(b), sep)
    return
}

// Check if a given passphrase is already present in the output array
func checkUniqueness(output []string, new_passphrase string) bool {
    if _, is_unique := output[new_passphrase], is_unique {
        return true
    } else {
        return false
    }
}

// Generate the actual passphrase
func generatePassphrase(words []string, fills []string) (gen_passphrase string) {
    if len(words) == 0 {
        log.Fatal("Dictionary import is empty. Exiting.")
    }
    // Create the passphrase string:
    gen_passphrase = ""
    for len(gen_passphrase) < *min_pass_length { // Check if the passphrase's length is equal or greater than the minimum length.
        // If fill_before = true insert y random characters (before the word)
        if *fill_before {
            for i := 0; i < getRandomInt(*fill_length_min, *fill_length_max); i++ {
                gen_passphrase += getRandomWord(fills)
            }
        }

        // Add the next word to the passphrase string.
        gen_passphrase += getRandomWord(words)

        // If fill_before = false insert y random characters (after the word)
        if !*fill_before {
            for i := 0; i < getRandomInt(*fill_length_min, *fill_length_max); i++ {
                gen_passphrase += getRandomWord(fills)
            }
        }
    }
    return
}

// Replace all chars in raw with replace_with (oldnew ...string)
func replaceSpecialChars(raw string, replace_with string) (fixed string) {
    r := strings.NewReplacer(strings.Split(replace_with, ",")...)
    fixed = r.Replace(raw)
    return
}

// Return a random word from dict
func getRandomWord(words []string) string {
    if len(words) == 0 {
        return ""
    }
    // math.rand implementation
    //cr, _ := crand.Int(crand.Reader, big.NewInt(int64(len(i))))
        // TODO: how to convert *big.Int to int64 / int ?
//    rand.Seed(time.Now().UnixNano())
    r := rand.Intn(len(words))

    if len(*replace_chars) != 0 {
        words[r] = replaceSpecialChars(words[r], *replace_chars)
    }

    // crypto.rand implementation (sadly this returns an int64 which I can't use to access my array index :(
    /*r, _ := rand.Int(rand.Reader, big.NewInt(int64(len(words))))
    r = r
    fmt.Println(r)*/

    return words[r]
}

// Return a random integer value r with min <= r <= max
func getRandomInt(min int, max int) (r int) {
    r = 0
    if (min == 0 && max == 0) || min >= max {
        return
    }
    r = rand.Intn(max-min)
    r += min
    return
}
<commit_msg>Implemented distinct check.<commit_after>package main

import (
    "fmt"
    "log"
    /*"os"*/
    "io/ioutil"
    "flag"
    "time"
    /*"math/big"
    crand "crypto/rand"*/
    "math/rand"
    "strings"
    /*"encoding/json"*/
)

// Declare command line arguments
var input_files = flag.String("i", "language.dict", "the dictionary input file(s)") // TODO enable support for more than one input file
var separator = flag.String("l", "\n", "the separator used to split the input file")
var fill = flag.String("f", "0,1,2,3,4,5,6,7,8,9,_,!,?", "comma separated list of random fill characters")
var fill_length_min = flag.Int("fill-length-min", 1, "minimum length of the random fill insert")
var fill_length_max = flag.Int("fill-length-max", 3, "maximum length of the random fill insert")
var fill_before = flag.Bool("fill-before", false, "whether to insert a fill character before or after a word")
/*var output_file = flag.String("o", "passphrases.csv", "the output file (csv passphrase list)") // TODO or simply pass the result to the bash so it can be re-directed to a file
var output_file_type = flag.String("o-type", "csv", "the output file type")*/
var min_pass_length = flag.Int("min", 30, "minimum passphrase length")
var number_gen_passp = flag.Int("n", 10, "number of passphrases to generate")
var replace_chars = flag.String("r", "u\",ue,a\",ae,o\",oe,A\",Ae,O\",Oe,U\",Ue", "comma separated list of old new characters to replace in every dictionary word that is used for an actual passphrase")
// TODO add argument to enable/disable hashing of passwords (to only get distinct results)
var distinct = flag.Bool("d", true, "whether the generated passphrases have to be distinct from each other.")

func main() {
    // Read the command line arguments.
    flag.Parse()

    fmt.Println(*distinct)

    /*flags := flag.Args()
    fmt.Println(flags)
    for key, _ := range flags {
        fmt.Println(flags[key])
    }*/

    // Seed the RNG
    rand.Seed(time.Now().UnixNano()) // only pseudo random, better use crypto/rand

    // Read the dictionary files.
    dict, err := readDictionary(*input_files, *separator)
    if err != nil {
        panic(err)
    }
    if len(dict) == 0 {
        log.Fatal("Input dictionary is empty. Exiting.")
    }

    output := []string{}
    // repeat until enough passphrases are generated
    for i := 0; i < *number_gen_passp; i++ {
        new_passphrase := generatePassphrase(dict, strings.Split(*fill, ","))
        if checkUniqueness(output, new_passphrase) {
            output = append(output, new_passphrase)
        } else {
            i--
        }
    }

    // write the passphrases to the console
    for key, _ := range output {
        fmt.Println(output[key])
    }
}

// Open and read the dictionary file and push it's contents into a string array
func readDictionary(dict_file string, sep string) (dict[]string, err error) {
    // TODO maybe better check the filesize first ...
    b, err := ioutil.ReadFile(dict_file)
    if err != nil {
        return nil, err
    }
    dict = strings.Split(string(b), sep)
    return
}

// Check if a given passphrase is already present in the output array
func checkUniqueness(output []string, new_passphrase string) (is_unique bool) {
    // TODO properly check for uniqueness
    if !*distinct {
        is_unique = true
        return
    }
    is_unique = true
    for _, value := range output {
        if new_passphrase == value {
            is_unique = false
        }
    }
    return
}

// Generate the actual passphrase
func generatePassphrase(words []string, fills []string) (gen_passphrase string) {
    if len(words) == 0 {
        log.Fatal("Dictionary import is empty. Exiting.")
    }
    // Create the passphrase string:
    gen_passphrase = ""
    for len(gen_passphrase) < *min_pass_length { // Check if the passphrase's length is equal or greater than the minimum length.
        // If fill_before = true insert y random characters (before the word)
        if *fill_before {
            for i := 0; i < getRandomInt(*fill_length_min, *fill_length_max); i++ {
                gen_passphrase += getRandomWord(fills)
            }
        }

        // Add the next word to the passphrase string.
        gen_passphrase += getRandomWord(words)

        // If fill_before = false insert y random characters (after the word)
        if !*fill_before {
            for i := 0; i < getRandomInt(*fill_length_min, *fill_length_max); i++ {
                gen_passphrase += getRandomWord(fills)
            }
        }
    }
    return
}

// Replace all chars in raw with replace_with (oldnew ...string)
func replaceSpecialChars(raw string, replace_with string) (fixed string) {
    r := strings.NewReplacer(strings.Split(replace_with, ",")...)
    fixed = r.Replace(raw)
    return
}

// Return a random word from dict
func getRandomWord(words []string) string {
    if len(words) == 0 {
        return ""
    }
    // math.rand implementation
    //cr, _ := crand.Int(crand.Reader, big.NewInt(int64(len(i))))
        // TODO: how to convert *big.Int to int64 / int ?
//    rand.Seed(time.Now().UnixNano())
    r := rand.Intn(len(words))

    if len(*replace_chars) != 0 {
        words[r] = replaceSpecialChars(words[r], *replace_chars)
    }

    // crypto.rand implementation (sadly this returns an int64 which I can't use to access my array index :(
    /*r, _ := rand.Int(rand.Reader, big.NewInt(int64(len(words))))
    r = r
    fmt.Println(r)*/

    return words[r]
}

// Return a random integer value r with min <= r <= max
func getRandomInt(min int, max int) (r int) {
    r = 0
    if (min == 0 && max == 0) || min >= max {
        return
    }
    r = rand.Intn(max-min)
    r += min
    return
}
<|endoftext|>


<commit_before>package musictheory

import (
	"time"
)

// Dotted makes a dotted duration
func Dotted(d Duration, dots int) Duration {
	return Duration{d.Value, dots, false}
}

// Triplet makes a triplet duration
func Triplet(d Duration) Duration {
	return Duration{d.Value, 0, true}
}

const ns = 1000000000

// Durations
var (
	D1   = Duration{1, 0, false}   // Whole
	D2   = Duration{2, 0, false}   // Half
	D4   = Duration{4, 0, false}   // Quarter
	D8   = Duration{8, 0, false}   // Eighth
	D16  = Duration{16, 0, false}  // Sixteenth
	D32  = Duration{32, 0, false}  // Thirty Second
	D64  = Duration{64, 0, false}  // Sixty Fourth
	D128 = Duration{128, 0, false} // Hundred Twenty Eighth
)

// Duration represents a note's duration
type Duration struct {
	Value   int
	Dots    int
	Triplet bool
}

// Time returns the time in nanoseconds the note's duration lasts.
// Calculated based on what unit gets the beat and what the BPM is.
func (d Duration) Time(unit Duration, bpm int) time.Duration {
	val := (60.0 / float64(bpm)) / (float64(d.Value) / 4.0) / (float64(unit.Value) / 4.0)

	for i := 0; i < d.Dots; i++ {
		val += val / 2.0
	}

	if d.Triplet {
		val = val / 3.0
	}

	return time.Duration(val * ns)
}

func (d Duration) String() string {
	switch d.Value {
	case 1:
		return "whole"
	case 2:
		return "half"
	case 4:
		return "quarter"
	case 8:
		return "eighth"
	case 16:
		return "sixteenth"
	case 32:
		return "thirty-second"
	case 64:
		return "sixty-fourth"
	case 128:
		return "hundred-twenty-eighth"
	default:
		return "unknown"
	}
}

// Note is a pitch with a duration
type Note struct {
	Pitch
	Duration
}

// NewNote creates a new note
func NewNote(pitch Pitch, duration Duration) Note {
	return Note{pitch, duration}
}

// Transpose transposes a note by a given interval
func (n Note) Transpose(i Interval) Transposer {
	return Note{n.Pitch.Transpose(i).(Pitch), n.Duration}
}
<commit_msg>More helpful stringer output for notes.<commit_after>package musictheory

import (
	"fmt"
	"time"
)

// Dotted makes a dotted duration
func Dotted(d Duration, dots int) Duration {
	return Duration{d.Value, dots, false}
}

// Triplet makes a triplet duration
func Triplet(d Duration) Duration {
	return Duration{d.Value, 0, true}
}

const ns = 1000000000

// Durations
var (
	D1   = Duration{1, 0, false}   // Whole
	D2   = Duration{2, 0, false}   // Half
	D4   = Duration{4, 0, false}   // Quarter
	D8   = Duration{8, 0, false}   // Eighth
	D16  = Duration{16, 0, false}  // Sixteenth
	D32  = Duration{32, 0, false}  // Thirty Second
	D64  = Duration{64, 0, false}  // Sixty Fourth
	D128 = Duration{128, 0, false} // Hundred Twenty Eighth
)

// Duration represents a note's duration
type Duration struct {
	Value   int
	Dots    int
	Triplet bool
}

// Time returns the time in nanoseconds the note's duration lasts.
// Calculated based on what unit gets the beat and what the BPM is.
func (d Duration) Time(unit Duration, bpm int) time.Duration {
	val := (60.0 / float64(bpm)) / (float64(d.Value) / 4.0) / (float64(unit.Value) / 4.0)

	for i := 0; i < d.Dots; i++ {
		val += val / 2.0
	}

	if d.Triplet {
		val = val / 3.0
	}

	return time.Duration(val * ns)
}

func (d Duration) String() string {
	var value string
	switch d.Value {
	case 1:
		value = "whole"
	case 2:
		value = "half"
	case 4:
		value = "quarter"
	case 8:
		value = "eighth"
	case 16:
		value = "sixteenth"
	case 32:
		value = "thirty-second"
	case 64:
		value = "sixty-fourth"
	case 128:
		value = "hundred-twenty-eighth"
	default:
		value = "unknown"
	}

	var dots string
	if d.Dots > 0 {
		dots = fmt.Sprintf("dotted(%d) ", d.Dots)
	}

	var triplet string
	if d.Triplet {
		triplet = "triplet "
	}

	return fmt.Sprintf("%s%s%s", dots, triplet, value)
}

// Note is a pitch with a duration
type Note struct {
	Pitch
	Duration
}

// NewNote creates a new note
func NewNote(pitch Pitch, duration Duration) Note {
	return Note{pitch, duration}
}

// Transpose transposes a note by a given interval
func (n Note) Transpose(i Interval) Transposer {
	return Note{n.Pitch.Transpose(i).(Pitch), n.Duration}
}

func (n Note) String() string {
	return fmt.Sprintf("%s %s", n.Pitch.String(), n.Duration.String())
}
<|endoftext|>


<commit_before>package adsi

// Open opens an ADSI object with the given path. It creates an ephemeral
// local client and uses it to open the requested object. The connection is made
// using the security context of the application and the default client flags
// specifying that it be encrypted and read-only.
//
// Open returns the ADSI object as an Object type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADs interface.
//
// If the requested ADSI object does not implement the IADs interface an error
// is returned.
//
// The returned object consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned object when it is no
// longer needed.
func Open(path string) (obj *Object, err error) {
	var c *Client

	c, err = NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	obj, err = c.Open(path)
	return
}

// OpenSC opens an ADSI object with the given path. Most users will use Open
// instead. It creates an ephemeral local client and uses it to open the
// requested object.
//
// When provided, the username and password are used to establish a security
// context for the connection. When credentials are not provided the existing
// security context of the application is used instead. The provided flags will
// be used to make the connection.
//
// OpenSC returns the ADSI object as an Object type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADs interface.
//
// If the requested ADSI object does not implement the IADs interface an error
// is returned.
//
// The returned object consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned object when it is no
// longer needed.
func OpenSC(path, user, password string, flags uint32) (obj *Object, err error) {
	var c *Client

	c, err = NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	obj, err = c.OpenSC(path, user, password, flags)
	return
}
<commit_msg>Added more package-level open functions<commit_after>package adsi

// Open opens an ADSI object with the given path. It creates an ephemeral
// local client and uses it to open the requested object. The connection is made
// using the security context of the application and the default client flags
// specifying that it be encrypted and read-only.
//
// Open returns the ADSI object as an Object type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADs interface.
//
// If the requested ADSI object does not implement the IADs interface an error
// is returned.
//
// The returned object consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned object when it is no
// longer needed.
func Open(path string) (obj *Object, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	return c.Open(path)
}

// OpenSC opens an ADSI object with the given path. Most users will use Open
// instead. It creates an ephemeral local client and uses it to open the
// requested object.
//
// When provided, the username and password are used to establish a security
// context for the connection. When they are not provided the existing
// security context of the application is used instead. The provided flags will
// be used to make the connection.
//
// OpenSC returns the ADSI object as an Object type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADs interface.
//
// If the requested ADSI object does not implement the IADs interface an error
// is returned.
//
// The returned object consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned object when it is no
// longer needed.
func OpenSC(path, user, password string, flags uint32) (obj *Object, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()
	return c.OpenSC(path, user, password, flags)
}

// OpenContainer opens an ADSI container with the given path. It creates an
// ephemeral local client and uses it to open the requested container. The
// connection is made using the security context of the application and the
// default client flags specifying that it be encrypted and read-only.
//
// OpenContainer returns the ADSI container as a Container type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADsContainer interface.
//
// If the returned directory object does not implement the IADsContainer
// interface an error is returned.
//
// The returned container consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned container when it is no
// longer needed.
func OpenContainer(path string) (container *Container, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()
	return c.OpenContainer(path)
}

// OpenContainerSC opens an ADSI container with the given path. Most users will
// use OpenContainer instead. It creates an ephemeral local client and uses it
// to open the requested container.
//
// When provided, the username and password are used to establish a security
// context for the connection. When they are not provided the existing
// security context of the application is used instead. The provided flags will
// be used to make the connection.
//
// OpenContainerSC returns the ADSI container as a Container type, which
// provides an idiomatic go wrapper around the underlying component object model
// IADsContainer interface.
//
// If the returned directory object does not implement the IADsContainer
// interface an error is returned.
//
// The returned container consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned container when it is no
// longer needed.
func OpenContainerSC(path, user, password string, flags uint32) (container *Container, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()
	return c.OpenContainerSC(path, user, password, flags)
}

// OpenComputer opens an ADSI computer with the given path. The existing
// security context of the application and any flags specified via SetFlags will
// be used when making the connection. The default flags specify an encrypted
// read-only connection.
//
// OpenComputer returns the ADSI computer as a Computer type, which provides
// an idiomatic go wrapper around the underlying component object model
// IADsComputer interface.
//
// If the returned directory object does not implement the IADsComputer
// interface an error is returned.
//
// The returned computer consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned computer when it is no
// longer needed.
func OpenComputer(path string) (computer *Computer, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()
	return c.OpenComputer(path)
}

// OpenComputerSC opens an ADSI computer with the given path. Most users will
// use OpenComputer instead. It creates an ephemeral local client and uses it
// to open the requested computer.
//
// When provided, the username and password are used to establish a security
// context for the connection. When they are not provided the existing
// security context of the application is used instead. The provided flags will
// be used to make the connection.
//
// OpenComputerSC returns the ADSI computer as a Computer type, which
// provides an idiomatic go wrapper around the underlying component object model
// IADsComputer interface.
//
// If the returned directory object does not implement the IADsComputer
// interface an error is returned.
//
// The returned computer consumes resources until it is closed. It is the
// caller's responsibilty to call Close on the returned computer when it is no
// longer needed.
func OpenComputerSC(path, user, password string, flags uint32) (computer *Computer, err error) {
	c, err := NewClient()
	if err != nil {
		return nil, err
	}
	defer c.Close()
	return c.OpenComputerSC(path, user, password, flags)
}
<|endoftext|>


<commit_before>package goat

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

func LogMng(doneChan chan bool, logChan chan string) {
	// create log file and pull current time to add to logfile name
	currentTime := time.Now().String()
	logFile, err := os.Create("GoatLog" + currentTime + ".log")
	if err != nil {
		fmt.Println(err)
	}
	writer := bufio.NewWriter(logFile)
	// create a logger that will use the writer created above
	logger := log.New(writer, "", log.Lmicroseconds|log.Lshortfile)
	amIDone := false
	msg := ""
	// wait for errer to be passed on the logChan channel or the done chan
	for !amIDone {
		select {
		case amIDone = <-doneChan:
			logFile.Close()
		case msg = <-logChan:
			logger.Println(msg)
		}
	}
}
<commit_msg>Make logs directory, simplify log to goat-yyyy-mm-dd.log<commit_after>package goat

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

func LogMng(doneChan chan bool, logChan chan string) {
	// Create log directory and file, and pull current date to add to logfile name
	now := time.Now()
	os.Mkdir("logs", os.ModeDir|os.ModePerm)
	logFile, err := os.Create(fmt.Sprintf("logs/goat-%d-%d-%d.log", now.Year(), now.Month(), now.Day()))
	if err != nil {
		fmt.Println(err)
	}

	// create a logger that will use the writer created above
	logger := log.New(bufio.NewWriter(logFile), "", log.Lmicroseconds|log.Lshortfile)
	amIDone := false
	msg := ""

	// wait for errer to be passed on the logChan channel or the done chan
	for !amIDone {
		select {
		case amIDone = <-doneChan:
			logFile.Close()
		case msg = <-logChan:
			logger.Println(msg)
		}
	}
}
<|endoftext|>


<commit_before>package gocheck

import (
    "testing"
    "reflect"
    "fmt"
)

type T struct {
    *call
}

// -----------------------------------------------------------------------
// Basic succeeding/failing logic.

func (t *T) Failed() bool {
    return t.call.status == failedSt
}

func (t *T) Fail() {
    t.call.status = failedSt
}

func (t *T) FailNow() {
    t.Fail()
    t.stopNow()
}

func (t *T) Succeed() {
    t.call.status = succeededSt
}

func (t *T) SucceedNow() {
    t.Succeed()
    t.stopNow()
}

func (t *T) ExpectFailure(reason string) {
    t.expectedFailure = &reason
}

// -----------------------------------------------------------------------
// Basic logging.

func (t *T) GetLog() string {
    return t.call.logv
}

func (t *T) Log(args ...interface{}) {
    t.log(args...)
}

func (t *T) Logf(format string, args ...interface{}) {
    t.logf(format, args...)
}

func (t *T) Error(args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprint(args...)))
    t.Fail()
}

func (t *T) Errorf(format string, args ...interface{}) {
    t.logCaller(1, fmt.Sprintf("Error: " + format, args...))
    t.Fail()
}

func(t *T) Fatal(args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprint(args...)))
    t.FailNow()
}

func(t *T) Fatalf(format string, args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
    t.FailNow()
}

// -----------------------------------------------------------------------
// Equality testing.

func (t *T) CheckEqual(obtained interface{}, expected interface{},
                       issue ...interface{}) bool {
    summary := "CheckEqual(obtained, expected):"
    return t.internalCheckEqual(obtained, expected, true, summary, issue...)
}

func (t *T) CheckNotEqual(obtained interface{}, expected interface{},
                          issue ...interface{}) bool {
    summary := "CheckNotEqual(obtained, unexpected):"
    return t.internalCheckEqual(obtained, expected, false, summary, issue...)
}

func (t *T) AssertEqual(obtained interface{}, expected interface{},
                        issue ...interface{}) {
    summary := "AssertEqual(obtained, expected):"
    if !t.internalCheckEqual(obtained, expected, true, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) AssertNotEqual(obtained interface{}, expected interface{},
                           issue ...interface{}) {
    summary := "AssertNotEqual(obtained, unexpected):"
    if !t.internalCheckEqual(obtained, expected, false, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) internalCheckEqual(a interface{}, b interface{}, equal bool,
                               summary string, issue ...interface{}) bool {
    typeA := reflect.Typeof(a)
    typeB := reflect.Typeof(b)
    if (typeA == typeB && checkEqual(a, b)) != equal {
        t.logCaller(2, summary)
        if equal {
            t.logValue("Obtained", a)
            t.logValue("Expected", b)
        } else {
            t.logValue("Both", a)
        }
        if len(issue) != 0 {
            t.logString(fmt.Sprint(issue...))
        }
        t.logNewLine()
        t.Fail()
        return false
    }
    return true
}

// This will use a fast path to check for equality of normal types,
// and then fallback to reflect.DeepEqual if things go wrong.
func checkEqual(a interface{}, b interface{}) (result bool) {
    defer func() {
        if recover() != nil {
            result = reflect.DeepEqual(a, b)
        }
    }()
    return (a == b)
}

// -----------------------------------------------------------------------
// Error testing.

func (t *T) AssertErr(obtained interface{}, expected interface{},
                      issue ...interface{}) {
    var summary string
    if expected == nil {
        summary = "AssertErr(error, nil):"
    } else {
        summary = "AssertErr(error, expected):"
    }
    if !t.internalCheckErr(obtained, expected, true, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) CheckErr(obtained interface{}, expected interface{},
                     issue ...interface{}) bool {
    var summary string
    if expected == nil {
        summary = "CheckErr(error, nil):"
    } else {
        summary = "CheckErr(error, expected):"
    }
    return t.internalCheckErr(obtained, expected, true, summary, issue...)
}

func (t *T) internalCheckErr(a interface{}, b interface{},
                             equal bool, summary string,
                             issue ...interface{}) bool {
    typeA := reflect.Typeof(a)
    typeB := reflect.Typeof(b)
    _, aHasStr := a.(hasString)
    _, aIsStr := a.(string)
    _, bIsStr := b.(string)
    if bIsStr && (aIsStr || aHasStr) {
        var strA string
        if aIsStr {
            strA = a.(string)
        } else {
            strA = a.(hasString).String()
        }
        matches, err := testing.MatchString("^" + b.(string) + "$", strA)
        if err != "" || !matches {
            t.logCaller(2, summary)
            var msg string
            if !matches {
                t.logValue("Error", a)
                msg = fmt.Sprintf("Expected to match expression: %#v", b)
            } else {
                msg = fmt.Sprintf("Can't compile match expression: %#v", b)
            }
            t.logString(msg)
            t.logNewLine()
            t.Fail()
            return false
        }
    } else if (typeA == typeB && checkEqual(a, b)) != equal {
        t.logCaller(2, summary)
        if b == nil {
            t.logValue("Error", a)
        } else {
            t.logValue("Error", a)
            t.logValue("Expected", b)
        }
        if len(issue) != 0 {
            t.logString(fmt.Sprint(issue...))
        }
        t.logNewLine()
        t.Fail()
        return false
    }
    return true
}

<commit_msg>Minor tweaks to improve the error message on error testing.<commit_after>package gocheck

import (
    "testing"
    "reflect"
    "fmt"
)

type T struct {
    *call
}

// -----------------------------------------------------------------------
// Basic succeeding/failing logic.

func (t *T) Failed() bool {
    return t.call.status == failedSt
}

func (t *T) Fail() {
    t.call.status = failedSt
}

func (t *T) FailNow() {
    t.Fail()
    t.stopNow()
}

func (t *T) Succeed() {
    t.call.status = succeededSt
}

func (t *T) SucceedNow() {
    t.Succeed()
    t.stopNow()
}

func (t *T) ExpectFailure(reason string) {
    t.expectedFailure = &reason
}

// -----------------------------------------------------------------------
// Basic logging.

func (t *T) GetLog() string {
    return t.call.logv
}

func (t *T) Log(args ...interface{}) {
    t.log(args...)
}

func (t *T) Logf(format string, args ...interface{}) {
    t.logf(format, args...)
}

func (t *T) Error(args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprint(args...)))
    t.Fail()
}

func (t *T) Errorf(format string, args ...interface{}) {
    t.logCaller(1, fmt.Sprintf("Error: " + format, args...))
    t.Fail()
}

func(t *T) Fatal(args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprint(args...)))
    t.FailNow()
}

func(t *T) Fatalf(format string, args ...interface{}) {
    t.logCaller(1, fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
    t.FailNow()
}

// -----------------------------------------------------------------------
// Equality testing.

func (t *T) CheckEqual(obtained interface{}, expected interface{},
                       issue ...interface{}) bool {
    summary := "CheckEqual(obtained, expected):"
    return t.internalCheckEqual(obtained, expected, true, summary, issue...)
}

func (t *T) CheckNotEqual(obtained interface{}, expected interface{},
                          issue ...interface{}) bool {
    summary := "CheckNotEqual(obtained, unexpected):"
    return t.internalCheckEqual(obtained, expected, false, summary, issue...)
}

func (t *T) AssertEqual(obtained interface{}, expected interface{},
                        issue ...interface{}) {
    summary := "AssertEqual(obtained, expected):"
    if !t.internalCheckEqual(obtained, expected, true, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) AssertNotEqual(obtained interface{}, expected interface{},
                           issue ...interface{}) {
    summary := "AssertNotEqual(obtained, unexpected):"
    if !t.internalCheckEqual(obtained, expected, false, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) internalCheckEqual(a interface{}, b interface{}, equal bool,
                               summary string, issue ...interface{}) bool {
    typeA := reflect.Typeof(a)
    typeB := reflect.Typeof(b)
    if (typeA == typeB && checkEqual(a, b)) != equal {
        t.logCaller(2, summary)
        if equal {
            t.logValue("Obtained", a)
            t.logValue("Expected", b)
        } else {
            t.logValue("Both", a)
        }
        if len(issue) != 0 {
            t.logString(fmt.Sprint(issue...))
        }
        t.logNewLine()
        t.Fail()
        return false
    }
    return true
}

// This will use a fast path to check for equality of normal types,
// and then fallback to reflect.DeepEqual if things go wrong.
func checkEqual(a interface{}, b interface{}) (result bool) {
    defer func() {
        if recover() != nil {
            result = reflect.DeepEqual(a, b)
        }
    }()
    return (a == b)
}

// -----------------------------------------------------------------------
// Error testing.

func (t *T) AssertErr(obtained interface{}, expected interface{},
                      issue ...interface{}) {
    var summary string
    if expected == nil {
        summary = "AssertErr(error, nil):"
    } else {
        summary = "AssertErr(error, expected):"
    }
    if !t.internalCheckErr(obtained, expected, true, summary, issue...) {
        t.stopNow()
    }
}

func (t *T) CheckErr(obtained interface{}, expected interface{},
                     issue ...interface{}) bool {
    var summary string
    if expected == nil {
        summary = "CheckErr(error, nil):"
    } else {
        summary = "CheckErr(error, expected):"
    }
    return t.internalCheckErr(obtained, expected, true, summary, issue...)
}

func (t *T) internalCheckErr(a interface{}, b interface{},
                             equal bool, summary string,
                             issue ...interface{}) bool {
    typeA := reflect.Typeof(a)
    typeB := reflect.Typeof(b)
    // If b is string, handle it as a match expression.
    if bStr, ok := b.(string); ok {
        var err string
        var matches bool
        aStr, aIsStr := a.(string)
        if !aIsStr {
            if aWithStr, aHasStr := a.(hasString); aHasStr {
                aStr, aIsStr = aWithStr.String(), true
            }
        }
        if aIsStr {
            matches, err = testing.MatchString("^" + bStr + "$", aStr)
        }
        if !matches || err != "" {
            t.logCaller(2, summary)
            var msg string
            if !matches {
                t.logValue("Error", a)
                msg = fmt.Sprintf("Expected to match expression: %#v", b)
            } else {
                msg = fmt.Sprintf("Can't compile match expression: %#v", b)
            }
            t.logString(msg)
            t.logNewLine()
            t.Fail()
            return false
        }
    } else if (typeA == typeB && checkEqual(a, b)) != equal {
        t.logCaller(2, summary)
        if b == nil {
            t.logValue("Error", a)
        } else {
            t.logValue("Error", a)
            t.logValue("Expected", b)
        }
        if len(issue) != 0 {
            t.logString(fmt.Sprint(issue...))
        }
        t.logNewLine()
        t.Fail()
        return false
    }
    return true
}

<|endoftext|>