<commit_before>package organization

import (
	"fmt"

	ldap "gopkg.in/ldap.v2"
)

func (org *Organization) search(sc *SearchCondition) ([]map[string]interface{}, error) {

	sr, err := org.l.Search(sc.sq())
	if err != nil {
		return nil, err
	}

	return sc.Convertor(sr), nil
}

// SearchCondition desgin to constrctor search request
type SearchCondition struct {
	DN         string
	Filter     string
	Attributes []string
	Convertor  func(*ldap.SearchResult) []map[string]interface{}
}

func (sc *SearchCondition) sq() *ldap.SearchRequest {
	return ldap.NewSearchRequest(sc.DN,
		ldap.ScopeWholeSubtree,
		ldap.NeverDerefAliases, 0, 0, false,
		sc.Filter, sc.Attributes, nil)
}

func (org *Organization) typeSC(filter string, isUnit bool) *SearchCondition {
	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=doloresType)(%s))`, filter)
	} else {
		filter = `(objectClass=doloresType)`
	}
	return &SearchCondition{
		DN:         org.parentDN(typeCategory(isUnit)),
		Filter:     filter,
		Attributes: []string{`id`, `cn`, `description`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var types []map[string]interface{}
			for _, e := range sr.Entries {
				types = append(types, map[string]interface{}{
					`id`:          e.GetAttributeValue(`id`),
					`name`:        e.GetAttributeValue(`cn`),
					`description`: e.GetAttributeValue(`description`),
				})
			}
			return types
		},
	}
}

func (org *Organization) roleSC(filter string) *SearchCondition {
	return &SearchCondition{
		DN:         org.parentDN(role),
		Filter:     fmt.Sprintf(`(&(objectClass=role)%s)`, filter),
		Attributes: []string{`id`, `cn`, `description`, `upid`, `ppid`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {

			var roles []map[string]interface{}
			for _, e := range sr.Entries {
				roles = append(roles, map[string]interface{}{
					`id`:                  e.GetAttributeValue(`id`),
					`name`:                e.GetAttributeValue(`cn`),
					`description`:         e.GetAttributeValue(`description`),
					`unitPermissionIDs`:   e.GetAttributeValues(`unitpermissionIdentifier`),
					`memberPermissionIDs`: e.GetAttributeValues(`personpermissionIdentifier`),
				})
			}

			return roles
		},
	}
}

func (org *Organization) permissionSC(filter string, isUnit bool) *SearchCondition {
	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=permission)%s)`, filter)
	} else {
		filter = `(objectClass=permission)`
	}

	return &SearchCondition{
		DN:         org.parentDN(permissionCategory(isUnit)),
		Filter:     filter,
		Attributes: []string{`id`, `cn`, `description`, `rbacType`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var types []map[string]interface{}
			for _, e := range sr.Entries {
				types = append(types, map[string]interface{}{
					`id`:          e.GetAttributeValue(`id`),
					`name`:        e.GetAttributeValue(`cn`),
					`description`: e.GetAttributeValue(`description`),
					`rbacType`:    e.GetAttributeValues(`rbacType`),
				})
			}
			return types
		},
	}
}

func (org *Organization) unitSC(filter string, containACL bool) *SearchCondition {

	attributes := []string{`id`, `ou`, `description`}
	if containACL {
		attributes = append(attributes, `rbacType`)
	}

	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=organizationalUnit)%s)`, filter)
	} else {
		filter = `(objectClass=organizationalUnit)`
	}

	return &SearchCondition{
		DN:         org.parentDN(unit),
		Filter:     filter,
		Attributes: attributes,
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var units []map[string]interface{}
			for _, e := range sr.Entries {
				unit := make(map[string]interface{}, 0)
				dn, _ := ldap.ParseDN(e.DN)
				if len(dn.RDNs) > 5 {
					unit[`pid`] = dn.RDNs[1].Attributes[0].Value
				}
				unit[`id`] = e.GetAttributeValue(`id`)
				unit[`name`] = e.GetAttributeValue(`ou`)
				unit[`description`] = e.GetAttributeValue(`description`)
				if containACL {
					unit[`types`] = e.GetAttributeValue(`rbacType`)
				}
				units = append(units, unit)
			}
			return units
		},
	}
}

func (org *Organization) memberSC(filter string, containACL bool) *SearchCondition {

	attributes := []string{`id`, `name`, `unitID`, `email`, `sn`, `thirdAccount`, `thirdPassword`, `title`}
	if containACL {
		attributes = append(attributes, `rbacType`, `rbacRole`)
	}

	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=member)%s)`, filter)
	} else {
		filter = `(objectClass=member)`
	}

	return &SearchCondition{
		DN:         org.parentDN(member),
		Filter:     filter,
		Attributes: attributes,
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {

			var members []map[string]interface{}
			for _, e := range sr.Entries {

				member := make(map[string]interface{}, 0)

				member[`id`] = e.GetAttributeValue(`id`)
				member[`name`] = e.GetAttributeValue(`cn`)
				member[`realName`] = e.GetAttributeValue(`sn`)
				member[`departmentIDs`] = e.GetAttributeValues(`unitID`)
				member[`title`] = e.GetAttributeValues(`title`)
				member[`email`] = e.GetAttributeValues(`email`)
				member[`easemobAccount`] = e.GetAttributeValue(`thirdAccount`)
				member[`easemobPassword`] = e.GetAttributeValue(`thirdPassword`)
				if containACL {
					member[`rbacType`] = e.GetAttributeValue(`rbacType`)
					member[`rbacRole`] = e.GetAttributeValues(`rbacRole`)
				}
				members = append(members, member)
			}

			return members
		},
	}
}

func scConvertIDsToFilter(ids []string) (string, error) {
	return scConvertArraysToFilter(`id`, ids)
}

func scConvertArraysToFilter(label string, datas []string) (string, error) {
	if len(datas) == 0 {
		return ``, fmt.Errorf(`At least one %s`, label)
	}

	filter := `(|`
	for _, id := range datas {
		filter += fmt.Sprintf(`(%s=%s)`, label, id)
	}
	filter += `)`

	return filter, nil
}
<commit_msg>Refine member struct.<commit_after>package organization

import (
	"fmt"

	ldap "gopkg.in/ldap.v2"
)

func (org *Organization) search(sc *SearchCondition) ([]map[string]interface{}, error) {

	sr, err := org.l.Search(sc.sq())
	if err != nil {
		return nil, err
	}

	return sc.Convertor(sr), nil
}

// SearchCondition desgin to constrctor search request
type SearchCondition struct {
	DN         string
	Filter     string
	Attributes []string
	Convertor  func(*ldap.SearchResult) []map[string]interface{}
}

func (sc *SearchCondition) sq() *ldap.SearchRequest {
	return ldap.NewSearchRequest(sc.DN,
		ldap.ScopeWholeSubtree,
		ldap.NeverDerefAliases, 0, 0, false,
		sc.Filter, sc.Attributes, nil)
}

func (org *Organization) typeSC(filter string, isUnit bool) *SearchCondition {
	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=doloresType)(%s))`, filter)
	} else {
		filter = `(objectClass=doloresType)`
	}
	return &SearchCondition{
		DN:         org.parentDN(typeCategory(isUnit)),
		Filter:     filter,
		Attributes: []string{`id`, `cn`, `description`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var types []map[string]interface{}
			for _, e := range sr.Entries {
				types = append(types, map[string]interface{}{
					`id`:          e.GetAttributeValue(`id`),
					`name`:        e.GetAttributeValue(`cn`),
					`description`: e.GetAttributeValue(`description`),
				})
			}
			return types
		},
	}
}

func (org *Organization) roleSC(filter string) *SearchCondition {
	return &SearchCondition{
		DN:         org.parentDN(role),
		Filter:     fmt.Sprintf(`(&(objectClass=role)%s)`, filter),
		Attributes: []string{`id`, `cn`, `description`, `upid`, `ppid`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {

			var roles []map[string]interface{}
			for _, e := range sr.Entries {
				roles = append(roles, map[string]interface{}{
					`id`:                  e.GetAttributeValue(`id`),
					`name`:                e.GetAttributeValue(`cn`),
					`description`:         e.GetAttributeValue(`description`),
					`unitPermissionIDs`:   e.GetAttributeValues(`unitpermissionIdentifier`),
					`memberPermissionIDs`: e.GetAttributeValues(`personpermissionIdentifier`),
				})
			}

			return roles
		},
	}
}

func (org *Organization) permissionSC(filter string, isUnit bool) *SearchCondition {
	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=permission)%s)`, filter)
	} else {
		filter = `(objectClass=permission)`
	}

	return &SearchCondition{
		DN:         org.parentDN(permissionCategory(isUnit)),
		Filter:     filter,
		Attributes: []string{`id`, `cn`, `description`, `rbacType`},
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var types []map[string]interface{}
			for _, e := range sr.Entries {
				types = append(types, map[string]interface{}{
					`id`:          e.GetAttributeValue(`id`),
					`name`:        e.GetAttributeValue(`cn`),
					`description`: e.GetAttributeValue(`description`),
					`rbacType`:    e.GetAttributeValues(`rbacType`),
				})
			}
			return types
		},
	}
}

func (org *Organization) unitSC(filter string, containACL bool) *SearchCondition {

	attributes := []string{`id`, `ou`, `description`}
	if containACL {
		attributes = append(attributes, `rbacType`)
	}

	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=organizationalUnit)%s)`, filter)
	} else {
		filter = `(objectClass=organizationalUnit)`
	}

	return &SearchCondition{
		DN:         org.parentDN(unit),
		Filter:     filter,
		Attributes: attributes,
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {
			var units []map[string]interface{}
			for _, e := range sr.Entries {
				unit := make(map[string]interface{}, 0)
				dn, _ := ldap.ParseDN(e.DN)
				if len(dn.RDNs) > 5 {
					unit[`pid`] = dn.RDNs[1].Attributes[0].Value
				}
				unit[`id`] = e.GetAttributeValue(`id`)
				unit[`name`] = e.GetAttributeValue(`ou`)
				unit[`description`] = e.GetAttributeValue(`description`)
				if containACL {
					unit[`types`] = e.GetAttributeValue(`rbacType`)
				}
				units = append(units, unit)
			}
			return units
		},
	}
}

func (org *Organization) memberSC(filter string, containACL bool) *SearchCondition {

	attributes := []string{`id`, `name`, `unitID`, `email`,
		`cn`, `title`, `telephoneNumber`,
		`labeledURI`, `gender`}
	if containACL {
		attributes = append(attributes, `rbacType`, `rbacRole`, `thirdAccount`, `thirdPassword`)
	}

	if len(filter) > 0 {
		filter = fmt.Sprintf(`(&(objectClass=member)%s)`, filter)
	} else {
		filter = `(objectClass=member)`
	}

	return &SearchCondition{
		DN:         org.parentDN(member),
		Filter:     filter,
		Attributes: attributes,
		Convertor: func(sr *ldap.SearchResult) []map[string]interface{} {

			var members []map[string]interface{}
			for _, e := range sr.Entries {

				member := make(map[string]interface{}, 0)

				member[`id`] = e.GetAttributeValue(`id`)
				member[`name`] = e.GetAttributeValue(`name`)
				member[`realName`] = e.GetAttributeValue(`cn`)
				member[`departmentIDs`] = e.GetAttributeValues(`unitID`)
				member[`title`] = e.GetAttributeValues(`title`)
				member[`email`] = e.GetAttributeValues(`email`)
				member[`avatarURL`] = e.GetAttributeValue(`labeledURI`)
				member[`gender`] = e.GetAttributeValue(`gender`)
				member[`telephoneNumber`] = e.GetAttributeValue(`telephoneNumber`)

				if containACL {
					member[`rbacType`] = e.GetAttributeValue(`rbacType`)
					member[`rbacRole`] = e.GetAttributeValues(`rbacRole`)
					member[`easemobAccount`] = e.GetAttributeValue(`thirdAccount`)
					member[`easemobPassword`] = e.GetAttributeValue(`thirdPassword`)
				}
				members = append(members, member)
			}

			return members
		},
	}
}

func scConvertIDsToFilter(ids []string) (string, error) {
	return scConvertArraysToFilter(`id`, ids)
}

func scConvertArraysToFilter(label string, datas []string) (string, error) {
	if len(datas) == 0 {
		return ``, fmt.Errorf(`At least one %s`, label)
	}

	filter := `(|`
	for _, id := range datas {
		filter += fmt.Sprintf(`(%s=%s)`, label, id)
	}
	filter += `)`

	return filter, nil
}
<|endoftext|>


<commit_before>package pgx

import (
	"bytes"
	"context"
	"fmt"
	"strconv"

	"github.com/jackc/pgconn"
	errors "golang.org/x/xerrors"
)

type TxIsoLevel string

// Transaction isolation levels
const (
	Serializable    = TxIsoLevel("serializable")
	RepeatableRead  = TxIsoLevel("repeatable read")
	ReadCommitted   = TxIsoLevel("read committed")
	ReadUncommitted = TxIsoLevel("read uncommitted")
)

type TxAccessMode string

// Transaction access modes
const (
	ReadWrite = TxAccessMode("read write")
	ReadOnly  = TxAccessMode("read only")
)

type TxDeferrableMode string

// Transaction deferrable modes
const (
	Deferrable    = TxDeferrableMode("deferrable")
	NotDeferrable = TxDeferrableMode("not deferrable")
)

type TxOptions struct {
	IsoLevel       TxIsoLevel
	AccessMode     TxAccessMode
	DeferrableMode TxDeferrableMode
}

func (txOptions TxOptions) beginSQL() string {
	buf := &bytes.Buffer{}
	buf.WriteString("begin")
	if txOptions.IsoLevel != "" {
		fmt.Fprintf(buf, " isolation level %s", txOptions.IsoLevel)
	}
	if txOptions.AccessMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.AccessMode)
	}
	if txOptions.DeferrableMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.DeferrableMode)
	}

	return buf.String()
}

var ErrTxClosed = errors.New("tx is closed")

// ErrTxCommitRollback occurs when an error has occurred in a transaction and
// Commit() is called. PostgreSQL accepts COMMIT on aborted transactions, but
// it is treated as ROLLBACK.
var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback")

// Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no
// auto-rollback on context cancellation.
func (c *Conn) Begin(ctx context.Context) (*dbTx, error) {
	return c.BeginTx(ctx, TxOptions{})
}

// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike database/sql, the context only
// affects the begin command. i.e. there is no auto-rollback on context cancellation.
func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (*dbTx, error) {
	_, err := c.Exec(ctx, txOptions.beginSQL())
	if err != nil {
		// begin should never fail unless there is an underlying connection issue or
		// a context timeout. In either case, the connection is possibly broken.
		c.die(errors.New("failed to begin transaction"))
		return nil, err
	}

	return &dbTx{conn: c}, nil
}

type Tx interface {
	// Begin starts a pseudo nested transaction
	Begin(ctx context.Context) (Tx, error)
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error

	CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error)
	SendBatch(ctx context.Context, b *Batch) BatchResults
	LargeObjects() LargeObjects

	Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error)

	Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) Row
}

// dbTx represents a database transaction.
//
// All dbTx methods return ErrTxClosed if Commit or Rollback has already been
// called on the dbTx.
type dbTx struct {
	conn         *Conn
	err          error
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (tx *dbTx) Begin(ctx context.Context) (Tx, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	tx.savepointNum += 1
	_, err := tx.conn.Exec(ctx, "savepoint sp_"+strconv.FormatInt(tx.savepointNum, 10))
	if err != nil {
		return nil, err
	}

	return &dbSavepoint{tx: tx, savepointNum: tx.savepointNum}, nil
}

// Commit commits the transaction.
func (tx *dbTx) Commit(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	commandTag, err := tx.conn.Exec(ctx, "commit")
	tx.closed = true
	if err != nil {
		// A commit failure leaves the connection in an undefined state so kill the connection (though any error that could
		// cause this to fail should have already killed the connection)
		tx.conn.die(errors.Errorf("commit failed: %w", err))
		return err
	}
	if string(commandTag) == "ROLLBACK" {
		return ErrTxCommitRollback
	}

	return nil
}

// Rollback rolls back the transaction. Rollback will return ErrTxClosed if the
// Tx is already closed, but is otherwise safe to call multiple times. Hence, a
// defer tx.Rollback() is safe even if tx.Commit() will be called first in a
// non-error condition.
func (tx *dbTx) Rollback(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	_, err := tx.conn.Exec(ctx, "rollback")
	tx.closed = true
	if err != nil {
		// A rollback failure leaves the connection in an undefined state
		tx.conn.die(errors.Errorf("rollback failed: %w", err))
		return err
	}

	return nil
}

// Exec delegates to the underlying *Conn
func (tx *dbTx) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	return tx.conn.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying *Conn
func (tx *dbTx) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	return tx.conn.Prepare(ctx, name, sql)
}

// Query delegates to the underlying *Conn
func (tx *dbTx) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if tx.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return tx.conn.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying *Conn
func (tx *dbTx) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := tx.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (tx *dbTx) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if tx.closed {
		return 0, ErrTxClosed
	}

	return tx.conn.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (tx *dbTx) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if tx.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return tx.conn.SendBatch(ctx, b)
}

// LargeObjects returns a LargeObjects instance for the transaction.
func (tx *dbTx) LargeObjects() LargeObjects {
	return LargeObjects{tx: tx}
}

// dbSavepoint represents a nested transaction implemented by a savepoint.
type dbSavepoint struct {
	tx           Tx
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (sp *dbSavepoint) Begin(ctx context.Context) (Tx, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.Begin(ctx)
}

// Commit releases the savepoint essentially committing the pseudo nested transaction.
func (sp *dbSavepoint) Commit(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "release savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Rollback rolls back to the savepoint essentially rolling back the pseudo nested transaction. Rollback will return
// ErrTxClosed if the dbSavepoint is already closed, but is otherwise safe to call multiple times. Hence, a defer sp.Rollback()
// is safe even if sp.Commit() will be called first in a non-error condition.
func (sp *dbSavepoint) Rollback(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "rollback to savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Exec delegates to the underlying Tx
func (sp *dbSavepoint) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying Tx
func (sp *dbSavepoint) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Prepare(ctx, name, sql)
}

// Query delegates to the underlying Tx
func (sp *dbSavepoint) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if sp.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return sp.tx.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying Tx
func (sp *dbSavepoint) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := sp.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (sp *dbSavepoint) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if sp.closed {
		return 0, ErrTxClosed
	}

	return sp.tx.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (sp *dbSavepoint) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if sp.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return sp.tx.SendBatch(ctx, b)
}

func (sp *dbSavepoint) LargeObjects() LargeObjects {
	return LargeObjects{tx: sp}
}
<commit_msg>Add more transaction docs<commit_after>package pgx

import (
	"bytes"
	"context"
	"fmt"
	"strconv"

	"github.com/jackc/pgconn"
	errors "golang.org/x/xerrors"
)

type TxIsoLevel string

// Transaction isolation levels
const (
	Serializable    = TxIsoLevel("serializable")
	RepeatableRead  = TxIsoLevel("repeatable read")
	ReadCommitted   = TxIsoLevel("read committed")
	ReadUncommitted = TxIsoLevel("read uncommitted")
)

type TxAccessMode string

// Transaction access modes
const (
	ReadWrite = TxAccessMode("read write")
	ReadOnly  = TxAccessMode("read only")
)

type TxDeferrableMode string

// Transaction deferrable modes
const (
	Deferrable    = TxDeferrableMode("deferrable")
	NotDeferrable = TxDeferrableMode("not deferrable")
)

type TxOptions struct {
	IsoLevel       TxIsoLevel
	AccessMode     TxAccessMode
	DeferrableMode TxDeferrableMode
}

func (txOptions TxOptions) beginSQL() string {
	buf := &bytes.Buffer{}
	buf.WriteString("begin")
	if txOptions.IsoLevel != "" {
		fmt.Fprintf(buf, " isolation level %s", txOptions.IsoLevel)
	}
	if txOptions.AccessMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.AccessMode)
	}
	if txOptions.DeferrableMode != "" {
		fmt.Fprintf(buf, " %s", txOptions.DeferrableMode)
	}

	return buf.String()
}

var ErrTxClosed = errors.New("tx is closed")

// ErrTxCommitRollback occurs when an error has occurred in a transaction and
// Commit() is called. PostgreSQL accepts COMMIT on aborted transactions, but
// it is treated as ROLLBACK.
var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback")

// Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no
// auto-rollback on context cancellation.
func (c *Conn) Begin(ctx context.Context) (*dbTx, error) {
	return c.BeginTx(ctx, TxOptions{})
}

// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike database/sql, the context only
// affects the begin command. i.e. there is no auto-rollback on context cancellation.
func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (*dbTx, error) {
	_, err := c.Exec(ctx, txOptions.beginSQL())
	if err != nil {
		// begin should never fail unless there is an underlying connection issue or
		// a context timeout. In either case, the connection is possibly broken.
		c.die(errors.New("failed to begin transaction"))
		return nil, err
	}

	return &dbTx{conn: c}, nil
}

type Tx interface {
	// Begin starts a pseudo nested transaction.
	Begin(ctx context.Context) (Tx, error)

	// Commit commits the transaction if this is a real transaction or releases the savepoint if this is a pseudo nested
	// transaction. Commit will return ErrTxClosed if the Tx is already closed, but is otherwise safe to call multiple
	// times. If the commit fails with a rollback status (e.g. a deferred constraint was violated) then
	// ErrTxCommitRollback will be returned. Any other failure of a real transaction will result in the connection being
	// closed.
	Commit(ctx context.Context) error

	// Rollback rolls back the transaction if this is a real transaction or rolls back to the savepoint if this is a
	// pseudo nested transaction. Rollback will return ErrTxClosed if the Tx is already closed, but is otherwise safe to
	// call multiple times. Hence, a defer tx.Rollback() is safe even if tx.Commit() will be called first in a non-error
	// condition. Any other failure of a real transaction will result in the connection being closed.
	Rollback(ctx context.Context) error

	CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error)
	SendBatch(ctx context.Context, b *Batch) BatchResults
	LargeObjects() LargeObjects

	Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error)

	Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) Row
}

// dbTx represents a database transaction.
//
// All dbTx methods return ErrTxClosed if Commit or Rollback has already been
// called on the dbTx.
type dbTx struct {
	conn         *Conn
	err          error
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (tx *dbTx) Begin(ctx context.Context) (Tx, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	tx.savepointNum += 1
	_, err := tx.conn.Exec(ctx, "savepoint sp_"+strconv.FormatInt(tx.savepointNum, 10))
	if err != nil {
		return nil, err
	}

	return &dbSavepoint{tx: tx, savepointNum: tx.savepointNum}, nil
}

// Commit commits the transaction.
func (tx *dbTx) Commit(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	commandTag, err := tx.conn.Exec(ctx, "commit")
	tx.closed = true
	if err != nil {
		// A commit failure leaves the connection in an undefined state so kill the connection (though any error that could
		// cause this to fail should have already killed the connection)
		tx.conn.die(errors.Errorf("commit failed: %w", err))
		return err
	}
	if string(commandTag) == "ROLLBACK" {
		return ErrTxCommitRollback
	}

	return nil
}

// Rollback rolls back the transaction. Rollback will return ErrTxClosed if the
// Tx is already closed, but is otherwise safe to call multiple times. Hence, a
// defer tx.Rollback() is safe even if tx.Commit() will be called first in a
// non-error condition.
func (tx *dbTx) Rollback(ctx context.Context) error {
	if tx.closed {
		return ErrTxClosed
	}

	_, err := tx.conn.Exec(ctx, "rollback")
	tx.closed = true
	if err != nil {
		// A rollback failure leaves the connection in an undefined state
		tx.conn.die(errors.Errorf("rollback failed: %w", err))
		return err
	}

	return nil
}

// Exec delegates to the underlying *Conn
func (tx *dbTx) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	return tx.conn.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying *Conn
func (tx *dbTx) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if tx.closed {
		return nil, ErrTxClosed
	}

	return tx.conn.Prepare(ctx, name, sql)
}

// Query delegates to the underlying *Conn
func (tx *dbTx) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if tx.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return tx.conn.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying *Conn
func (tx *dbTx) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := tx.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (tx *dbTx) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if tx.closed {
		return 0, ErrTxClosed
	}

	return tx.conn.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (tx *dbTx) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if tx.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return tx.conn.SendBatch(ctx, b)
}

// LargeObjects returns a LargeObjects instance for the transaction.
func (tx *dbTx) LargeObjects() LargeObjects {
	return LargeObjects{tx: tx}
}

// dbSavepoint represents a nested transaction implemented by a savepoint.
type dbSavepoint struct {
	tx           Tx
	savepointNum int64
	closed       bool
}

// Begin starts a pseudo nested transaction implemented with a savepoint.
func (sp *dbSavepoint) Begin(ctx context.Context) (Tx, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.Begin(ctx)
}

// Commit releases the savepoint essentially committing the pseudo nested transaction.
func (sp *dbSavepoint) Commit(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "release savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Rollback rolls back to the savepoint essentially rolling back the pseudo nested transaction. Rollback will return
// ErrTxClosed if the dbSavepoint is already closed, but is otherwise safe to call multiple times. Hence, a defer sp.Rollback()
// is safe even if sp.Commit() will be called first in a non-error condition.
func (sp *dbSavepoint) Rollback(ctx context.Context) error {
	if sp.closed {
		return ErrTxClosed
	}

	_, err := sp.Exec(ctx, "rollback to savepoint sp_"+strconv.FormatInt(sp.savepointNum, 10))
	sp.closed = true
	return err
}

// Exec delegates to the underlying Tx
func (sp *dbSavepoint) Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Exec(ctx, sql, arguments...)
}

// Prepare delegates to the underlying Tx
func (sp *dbSavepoint) Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error) {
	if sp.closed {
		return nil, ErrTxClosed
	}

	return sp.tx.Prepare(ctx, name, sql)
}

// Query delegates to the underlying Tx
func (sp *dbSavepoint) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) {
	if sp.closed {
		// Because checking for errors can be deferred to the *Rows, build one with the error
		err := ErrTxClosed
		return &connRows{closed: true, err: err}, err
	}

	return sp.tx.Query(ctx, sql, args...)
}

// QueryRow delegates to the underlying Tx
func (sp *dbSavepoint) QueryRow(ctx context.Context, sql string, args ...interface{}) Row {
	rows, _ := sp.Query(ctx, sql, args...)
	return (*connRow)(rows.(*connRows))
}

// CopyFrom delegates to the underlying *Conn
func (sp *dbSavepoint) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) {
	if sp.closed {
		return 0, ErrTxClosed
	}

	return sp.tx.CopyFrom(ctx, tableName, columnNames, rowSrc)
}

// SendBatch delegates to the underlying *Conn
func (sp *dbSavepoint) SendBatch(ctx context.Context, b *Batch) BatchResults {
	if sp.closed {
		return &batchResults{err: ErrTxClosed}
	}

	return sp.tx.SendBatch(ctx, b)
}

func (sp *dbSavepoint) LargeObjects() LargeObjects {
	return LargeObjects{tx: sp}
}
<|endoftext|>


<commit_before>package utee

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/http"
	"net/smtp"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

var (
	PlainMd5  = Md5Str("")
	PlainSha1 = Sha1Str("")
)

func init() {
	rand.Seed(time.Now().UTC().UnixNano())
}

func Md5Str(salt string) func(string) string {
	return func(s string) string {
		h := md5.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func Sha1Str(salt string) func(string) string {
	return func(s string) string {
		h := sha1.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func Sha256Str(salt string) func(string) string {
	return func(s string) string {
		h := sha256.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func HmacSha256(s string, key string) string {
	h := hmac.New(sha256.New, []byte(key))
	io.WriteString(h, s)
	return hex.EncodeToString(h.Sum(nil))
}

func Chk(err error) {
	if err != nil {
		panic(err)
	}
}

func Log(err error, prefix ...string) {
	if err == nil {
		return
	}

	s := ""
	if len(prefix) > 0 {
		s = prefix[0]
	}
	log.Println(s, err)
}

//truncate string
func Truncate(s string, n int) string {
	if n <= 0 {
		return ""
	}

	length := utf8.RuneCountInString(s)
	if length <= n {
		return s
	}

	l := []rune{}
	for _, r := range s {
		l = append(l, r)
	}

	l = l[:(length - n)]
	return string(l)
}

func Tick(t ...time.Time) int64 {
	if len(t) == 0 {
		return time.Now().UnixNano() / 1e6
	} else {
		return t[0].UnixNano() / 1e6
	}
}

func TickSec() int64 {
	return time.Now().Unix()
}

func TickHour() int64 {
	return time.Now().Unix() / 3600 * 3600
}

func Contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ContainsInf(s []interface{}, e interface{}) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ContainsInt(s []int, e int) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func IndexOf(s []string, e string) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func IndexOfInf(s []interface{}, e interface{}) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func IndexOfInt(s []int, e int) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func Millis(fmt string, timeStr string) (int64, error) {
	data, err := time.Parse(fmt, timeStr)
	if err != nil {
		return 0, err
	}
	return data.UnixNano() / 1e6, nil
}

func Md5(b []byte) []byte {
	h := md5.New()
	h.Write(b)
	return h.Sum(nil)
}

// parse form into J
func F2j(r *http.Request) J {
	r.ParseForm()
	j := J{}
	for k, v := range r.Form {
		if len(v) == 1 {
			if len(v[0]) > 0 {
				j[k] = v[0]
			}
		} else {
			j[k] = v
		}
	}
	return j
}

func Fint64(s interface{}, dft ...int64) int64 {
	var i int64
	var err error
	if s == nil {
		if len(dft) > 0 {
			return dft[0]
		} else {
			s = "0"
		}
	}
	i, err = strconv.ParseInt(s.(string), 10, 64)
	if err != nil && len(dft) > 0 {
		i = dft[0]
	}
	return i
}

func Fint(s interface{}, dft ...int64) int {
	if len(dft) > 0 {
		return int(Fint64(s, dft[0]))
	} else {
		return int(Fint64(s))
	}
}

func DeleteMap(m map[string]interface{}, ks ...string) {
	for _, v := range ks {
		delete(m, v)
	}
}

func IsPemExpire(b []byte) (bool, error) {
	block, _ := pem.Decode(b)
	if block == nil {
		return false, errors.New("failed to parse certificate PEM")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return false, err
	}
	return cert.NotAfter.Before(time.Now()), nil
}

func Shuffle(src []string) []string {
	dest := make([]string, len(src))
	perm := rand.Perm(len(src))
	for i, v := range perm {
		dest[v] = src[i]
	}
	return dest
}

func SendMail(user, password, host, to, subject, body, mailtype string) error {
	hp := strings.Split(host, ":")
	auth := smtp.PlainAuth("", user, password, hp[0])
	var content_type string
	if mailtype == "html" {
		content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
	} else {
		content_type = "Content-Type: text/plain" + "; charset=UTF-8"
	}

	msg := []byte("To: " + to + "\r\nFrom: " + user + "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
	send_to := strings.Split(to, ";")
	err := smtp.SendMail(host, auth, user, send_to, msg)
	return err
}

func ParseAddr(s string) (string, int, error) {
	a := strings.Split(s, ":")
	if len(a) != 2 {
		return "", 0, fmt.Errorf("bad url %s", s)
	}
	port, err := strconv.Atoi(a[1])
	return a[0], port, err
}

func Unique(data []interface{}) []interface{} {
	m := map[interface{}]interface{}{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []interface{}{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

func UniqueInt(data []int) []int {
	m := map[int]string{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []int{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

func UniqueStr(data []string) []string {
	m := map[string]string{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []string{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

//split a into several parts, no more than n
func SplitSlice(a []string, n int) [][]string {
	if len(a) < n || n == 1 {
		return [][]string{a}
	}

	result := make([][]string, n)
	for i, s := range a {
		idx := i % n
		result[idx] = append(result[idx], s)
	}
	return result
}

func IntToInf(src []int) []interface{} {
	result := []interface{}{}
	for _, v := range src {
		result = append(result, v)
	}
	return result
}

func StrToInf(src []string) []interface{} {
	result := []interface{}{}
	for _, v := range src {
		result = append(result, v)
	}
	return result
}
<commit_msg>minor<commit_after>package utee

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/http"
	"net/smtp"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

var (
	PlainMd5  = Md5Str("")
	PlainSha1 = Sha1Str("")
)

func init() {
	rand.Seed(time.Now().UTC().UnixNano())
}

func Md5Str(salt string) func(string) string {
	return func(s string) string {
		h := md5.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func Sha1Str(salt string) func(string) string {
	return func(s string) string {
		h := sha1.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func Sha256Str(salt string) func(string) string {
	return func(s string) string {
		h := sha256.New()
		io.WriteString(h, s)
		io.WriteString(h, salt)
		return hex.EncodeToString(h.Sum(nil))
	}
}

func HmacSha256(s string, key string) string {
	h := hmac.New(sha256.New, []byte(key))
	io.WriteString(h, s)
	return hex.EncodeToString(h.Sum(nil))
}

func Chk(err error) {
	if err != nil {
		panic(err)
	}
}

func Log(err error, prefix ...string) {
	if err == nil {
		return
	}

	s := ""
	if len(prefix) > 0 {
		s = prefix[0]
	}
	log.Println(s, err)
}

//truncate string
func Truncate(s string, n int) string {
	if n <= 0 {
		return ""
	}

	length := utf8.RuneCountInString(s)
	if length <= n {
		return s
	}

	l := []rune{}
	for _, r := range s {
		l = append(l, r)
	}

	l = l[:(length - n)]
	return string(l)
}

func Tick(t ...time.Time) int64 {
	if len(t) == 0 {
		return time.Now().UnixNano() / 1e6
	} else {
		return t[0].UnixNano() / 1e6
	}
}

func TickSec() int64 {
	return time.Now().Unix()
}

func TickHour() int64 {
	return time.Now().Unix() / 3600 * 3600
}

func Contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ContainsInf(s []interface{}, e interface{}) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ContainsInt(s []int, e int) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func IndexOf(s []string, e string) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func IndexOfInf(s []interface{}, e interface{}) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func IndexOfInt(s []int, e int) int {
	for i, a := range s {
		if a == e {
			return i
		}
	}
	return -1
}

func Millis(fmt string, timeStr string) (int64, error) {
	data, err := time.Parse(fmt, timeStr)
	if err != nil {
		return 0, err
	}
	return data.UnixNano() / 1e6, nil
}

func Md5(b []byte) []byte {
	h := md5.New()
	h.Write(b)
	return h.Sum(nil)
}

// parse form into J
func F2j(r *http.Request) J {
	r.ParseForm()
	j := J{}
	for k, v := range r.Form {
		if len(v) == 1 {
			if len(v[0]) > 0 {
				j[k] = v[0]
			}
		} else {
			j[k] = v
		}
	}
	return j
}

func Fint64(s interface{}, dft ...int64) int64 {
	var i int64
	var err error
	if s == nil {
		if len(dft) > 0 {
			return dft[0]
		} else {
			s = "0"
		}
	}
	i, err = strconv.ParseInt(s.(string), 10, 64)
	if err != nil && len(dft) > 0 {
		i = dft[0]
	}
	return i
}

func Fint(s interface{}, dft ...int64) int {
	if len(dft) > 0 {
		return int(Fint64(s, dft[0]))
	} else {
		return int(Fint64(s))
	}
}

func DeleteMap(m map[string]interface{}, ks ...string) {
	for _, v := range ks {
		delete(m, v)
	}
}

func IsPemExpire(b []byte) (bool, error) {
	block, _ := pem.Decode(b)
	if block == nil {
		return false, errors.New("failed to parse certificate PEM")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return false, err
	}
	return cert.NotAfter.Before(time.Now()), nil
}

func Shuffle(src []string) []string {
	dest := make([]string, len(src))
	perm := rand.Perm(len(src))
	for i, v := range perm {
		dest[v] = src[i]
	}
	return dest
}

func SendMail(user, password, host, to, subject, body, mailtype string) error {
	hp := strings.Split(host, ":")
	auth := smtp.PlainAuth("", user, password, hp[0])
	var content_type string
	if mailtype == "html" {
		content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
	} else {
		content_type = "Content-Type: text/plain" + "; charset=UTF-8"
	}

	msg := []byte("To: " + to + "\r\nFrom: " + user + "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
	send_to := strings.Split(to, ";")
	err := smtp.SendMail(host, auth, user, send_to, msg)
	return err
}

func ParseAddr(s string) (string, int, error) {
	a := strings.Split(s, ":")
	if len(a) != 2 {
		return "", 0, fmt.Errorf("bad url %s", s)
	}
	port, err := strconv.Atoi(a[1])
	return a[0], port, err
}

func Unique(data []interface{}) []interface{} {
	m := map[interface{}]interface{}{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []interface{}{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

func UniqueInt(data []int) []int {
	m := map[int]string{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []int{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

func UniqueStr(data []string) []string {
	m := map[string]string{}

	for _, d := range data {
		m[d] = "0"
	}

	l := []string{}
	for key := range m {
		l = append(l, key)
	}
	return l
}

//split a into several parts, no more than n
func SplitSlice(a []string, n int) [][]string {
	if len(a) < n || n == 1 {
		return [][]string{a}
	}

	result := make([][]string, n)
	for i, s := range a {
		idx := i % n
		result[idx] = append(result[idx], s)
	}
	return result
}

func IntToInf(src []int) []interface{} {
	result := []interface{}{}
	for _, v := range src {
		result = append(result, v)
	}
	return result
}

func StrToInf(src []string) []interface{} {
	result := []interface{}{}
	for _, v := range src {
		result = append(result, v)
	}
	return result
}

func PrintJson(any ...interface{}) {
	for _, obj := range any {
		b, err := json.Marshal(obj)
		fmt.Println(err, string(b))
	}
}
<|endoftext|>


<commit_before>// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Aki is a modern LambdaMOO clone.
package main

import (
    "time"
    "log"
)

const (
    NOP byte = iota
    IMM
    ADD
    FORK
    SUSPEND
    RET
    EXT
)

const (
    OptinumStart = int(EXT) + 1
    MaxOpcode = 255
    OptinumLo = -10
    OptinumHi = MaxOpcode - OptinumStart + OptinumLo
)

type Program struct {
    Main []byte
    Forks [][]byte
    Literals []Var
    VarNames []string
}

type Activation struct {
    Vector int
    Prog *Program
    Env []Var
    Stack []Var
    PC int
}

const MainVector = -1

type VM struct {
    Stack []*Activation
}

// Determines whether the specified opcode represents an optinum
func IsOptinumOpcode(o byte) bool {
    return int(o) >= OptinumStart
}

func OpcodeToOptinum(o byte) int {
    return int(o) - OptinumStart + OptinumLo
}

func InOptinumRange(i int) bool {
    return i >= OptinumLo && i <= OptinumHi
}

func OptinumToOpcode(i int) byte {
    return byte(OptinumStart + i - OptinumLo)
}

func (a *Activation) Pop() (v Var, ok bool) {
    s := a.Stack
    if len(s) == 0 {
        return
    }
    v, a.Stack, ok = s[len(s) - 1], s[:len(s) - 1], true
    return
}

func (a *Activation) Push(v Var) {
    a.Stack = append(a.Stack, v)
}

func (vm *VM) Pop() (a *Activation, ok bool) {
    s := vm.Stack
    if len(s) == 0 {
        return
    }
    a, vm.Stack, ok = s[len(s) - 1], s[:len(s) - 1], true
    return
}

func NewVM(prog *Program, vector int) *VM {
    vm := new(VM)
    vm.Push(&Activation{Prog: prog, Vector: vector})
    return vm
}

func (vm *VM) Push(a *Activation) {
    vm.Stack = append(vm.Stack, a)
}

func toInt(bs []byte) int {
    i := int(bs[0]) << 24 | int(bs[1] << 16) | int(bs[2]) << 8 | int(bs[3])
    return i
}

// This is the runtime channel. Multiple go-routines
// will feed VM's into this channel using various ways.
//
// NOTE: VM pointers are NOT thread safe. Don't feed
// them into this channel willy-nilly. Although small
// in declaration, careful management of any pointers
// going into this channel is very important.
//
// NOTE: __The public API is (or should be) safe__.
var rt = make(chan *VM)

// This is a hack to enable some kind of insight into
// what the VM is doing (we can't output yet).
//
// Set it to 1 to have all the (intermediate) results
// logged with the standard log package.
var LOG = 0

func init() {
    go func() {
        for {
            vm := <-rt
            r := run(vm)
            if LOG > 0 {
                log.Printf("=> %v", r)
            }
        }
    }()
}

func Execute(prog *Program) {
    rt <- NewVM(prog, -1)
}

// Most executions will be started by delaying them
// for a few seconds.
func Delay(prog *Program, seconds int) {
    exec(prog, seconds, -1)
}

func exec(prog *Program, delay int, vector int) {
    vm := NewVM(prog, vector)
    suspend(vm, delay)
}

func suspend(vm *VM, seconds int) {
    go func() {
        if seconds > 0 {
            time.Sleep(time.Duration(seconds) * time.Second)
        }
        rt <- vm
    }()
}

// This is the interpreter. It will go untill it
// finds a RET. It will then try to output some kind
// of sensible Var.
func run(vm *VM) Var {
    a, ok := vm.Pop()
    if !ok {
        panic("VM needs at least one activation frame!")
    }
    var v []byte
    if a.Vector == MainVector {
        v = a.Prog.Main
    } else {
        v = a.Prog.Forks[a.Vector]
    }
    for {
        op := v[a.PC]
        a.PC++
        switch op {
        case NOP:
            continue
        case IMM:
            i := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            a.Push(a.Prog.Literals[i])
            continue
        case ADD:
            v1, _ := a.Pop()
            v2, _ := a.Pop()
            a.Push(v1.Add(v2))
            continue
        case RET:
            r, _ := a.Pop()
            a, ok := vm.Pop()
            if ok {
                a.Push(r)
                continue
            }
            return r
        case SUSPEND:
            d := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            vm.Push(a)
            suspend(vm, d)
            return NewInt(0)
        case FORK:
            i := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            d := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            exec(a.Prog, d, i)
            continue
        default:
            if IsOptinumOpcode(op) {
                r := NewInt(OpcodeToOptinum(op))
                a.Push(r)
            } else {
                panic("Unknown opcode!")
            }
        }
    }
}<commit_msg>Removed some comments<commit_after>// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Aki is a modern LambdaMOO clone.
package main

import (
    "time"
    "log"
)

const (
    NOP byte = iota
    IMM
    ADD
    FORK
    SUSPEND
    RET
    EXT
)

const (
    OptinumStart = int(EXT) + 1
    MaxOpcode = 255
    OptinumLo = -10
    OptinumHi = MaxOpcode - OptinumStart + OptinumLo
)

type Program struct {
    Main []byte
    Forks [][]byte
    Literals []Var
    VarNames []string
}

type Activation struct {
    Vector int
    Prog *Program
    Env []Var
    Stack []Var
    PC int
}

const MainVector = -1

type VM struct {
    Stack []*Activation
}

// Determines whether the specified opcode represents an optinum
func IsOptinumOpcode(o byte) bool {
    return int(o) >= OptinumStart
}

func OpcodeToOptinum(o byte) int {
    return int(o) - OptinumStart + OptinumLo
}

func InOptinumRange(i int) bool {
    return i >= OptinumLo && i <= OptinumHi
}

func OptinumToOpcode(i int) byte {
    return byte(OptinumStart + i - OptinumLo)
}

func (a *Activation) Pop() (v Var, ok bool) {
    s := a.Stack
    if len(s) == 0 {
        return
    }
    v, a.Stack, ok = s[len(s) - 1], s[:len(s) - 1], true
    return
}

func (a *Activation) Push(v Var) {
    a.Stack = append(a.Stack, v)
}

func (vm *VM) Pop() (a *Activation, ok bool) {
    s := vm.Stack
    if len(s) == 0 {
        return
    }
    a, vm.Stack, ok = s[len(s) - 1], s[:len(s) - 1], true
    return
}

func NewVM(prog *Program, vector int) *VM {
    vm := new(VM)
    vm.Push(&Activation{Prog: prog, Vector: vector})
    return vm
}

func (vm *VM) Push(a *Activation) {
    vm.Stack = append(vm.Stack, a)
}

func toInt(bs []byte) int {
    i := int(bs[0]) << 24 | int(bs[1] << 16) | int(bs[2]) << 8 | int(bs[3])
    return i
}

var rt = make(chan *VM)

var LOG = 0

func init() {
    go func() {
        for {
            vm := <-rt
            r := run(vm)
            if LOG > 0 {
                log.Printf("=> %v", r)
            }
        }
    }()
}

func Execute(prog *Program) {
    rt <- NewVM(prog, -1)
}

func Delay(prog *Program, seconds int) {
    exec(prog, seconds, -1)
}

func exec(prog *Program, delay int, vector int) {
    vm := NewVM(prog, vector)
    suspend(vm, delay)
}

func suspend(vm *VM, seconds int) {
    go func() {
        if seconds > 0 {
            time.Sleep(time.Duration(seconds) * time.Second)
        }
        rt <- vm
    }()
}

func run(vm *VM) Var {
    a, ok := vm.Pop()
    if !ok {
        panic("VM needs at least one activation frame!")
    }
    var v []byte
    if a.Vector == MainVector {
        v = a.Prog.Main
    } else {
        v = a.Prog.Forks[a.Vector]
    }
    for {
        op := v[a.PC]
        a.PC++
        switch op {
        case NOP:
            continue
        case IMM:
            i := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            a.Push(a.Prog.Literals[i])
            continue
        case ADD:
            v1, _ := a.Pop()
            v2, _ := a.Pop()
            a.Push(v1.Add(v2))
            continue
        case RET:
            r, _ := a.Pop()
            a, ok := vm.Pop()
            if ok {
                a.Push(r)
                continue
            }
            return r
        case SUSPEND:
            d := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            vm.Push(a)
            suspend(vm, d)
            return NewInt(0)
        case FORK:
            i := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            d := toInt(v[a.PC:a.PC + 4])
            a.PC += 4
            exec(a.Prog, d, i)
            continue
        default:
            if IsOptinumOpcode(op) {
                r := NewInt(OpcodeToOptinum(op))
                a.Push(r)
            } else {
                panic("Unknown opcode!")
            }
        }
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rand_test

import (
	"fmt"
	"math/rand"
	"os"
	"text/tabwriter"
)

// These tests serve as an example but also make sure we don't change
// the output of the random number generator when given a fixed seed.

func Example() {
	rand.Seed(42) // Try changing this number!
	answers := []string{
		"It is certain",
		"It is decidedly so",
		"Without a doubt",
		"Yes definitely",
		"You may rely on it",
		"As I see it yes",
		"Most likely",
		"Outlook good",
		"Yes",
		"Signs point to yes",
		"Reply hazy try again",
		"Ask again later",
		"Better not tell you now",
		"Cannot predict now",
		"Concentrate and ask again",
		"Don't count on it",
		"My reply is no",
		"My sources say no",
		"Outlook not so good",
		"Very doubtful",
	}
	fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))])
	// Output: Magic 8-Ball says: As I see it yes
}

// This example shows the use of each of the methods on a *Rand.
// The use of the global functions is the same, without the receiver.
func Example_rand() {
	// Create and seed the generator.
	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
	// Using a fixed seed will produce the same output on every run.
	r := rand.New(rand.NewSource(99))

	// The tabwriter here helps us generate aligned output.
	w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
	defer w.Flush()
	show := func(name string, v1, v2, v3 interface{}) {
		fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
	}

	// Float32 and Float64 values are in [0, 1).
	show("Float32", r.Float32(), r.Float32(), r.Float32())
	show("Float64", r.Float64(), r.Float64(), r.Float64())

	// ExpFloat64 values have an average of 1 but decay exponentially.
	show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())

	// NormFloat64 values have an average of 0 and a standard deviation of 1.
	show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())

	// Int31, Int63, and Uint32 generate values of the given width.
	// The Int method (not shown) is like either Int31 or Int63
	// depending on the size of 'int'.
	show("Int31", r.Int31(), r.Int31(), r.Int31())
	show("Int63", r.Int63(), r.Int63(), r.Int63())
	show("Uint32", r.Int63(), r.Int63(), r.Int63())

	// Intn, Int31n, and Int63n limit their output to be < n.
	// They do so more carefully than using r.Int()%n.
	show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
	show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
	show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))

	// Perm generates a random permutation of the numbers [0, n).
	show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
	// Output:
	// Float32     0.2635776           0.6358173           0.6718283
	// Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
	// ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
	// NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
	// Int31       1501292890          1486668269          182840835
	// Int63       3546343826724305832 5724354148158589552 5239846799706671610
	// Uint32      5927547564735367388 637072299495207830  4128311955958246186
	// Intn(10)    1                   2                   5
	// Int31n(10)  4                   7                   8
	// Int63n(10)  7                   6                   3
	// Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
}
<commit_msg>math/rand: fix example_test to show with the correct method<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rand_test

import (
	"fmt"
	"math/rand"
	"os"
	"text/tabwriter"
)

// These tests serve as an example but also make sure we don't change
// the output of the random number generator when given a fixed seed.

func Example() {
	rand.Seed(42) // Try changing this number!
	answers := []string{
		"It is certain",
		"It is decidedly so",
		"Without a doubt",
		"Yes definitely",
		"You may rely on it",
		"As I see it yes",
		"Most likely",
		"Outlook good",
		"Yes",
		"Signs point to yes",
		"Reply hazy try again",
		"Ask again later",
		"Better not tell you now",
		"Cannot predict now",
		"Concentrate and ask again",
		"Don't count on it",
		"My reply is no",
		"My sources say no",
		"Outlook not so good",
		"Very doubtful",
	}
	fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))])
	// Output: Magic 8-Ball says: As I see it yes
}

// This example shows the use of each of the methods on a *Rand.
// The use of the global functions is the same, without the receiver.
func Example_rand() {
	// Create and seed the generator.
	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
	// Using a fixed seed will produce the same output on every run.
	r := rand.New(rand.NewSource(99))

	// The tabwriter here helps us generate aligned output.
	w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
	defer w.Flush()
	show := func(name string, v1, v2, v3 interface{}) {
		fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
	}

	// Float32 and Float64 values are in [0, 1).
	show("Float32", r.Float32(), r.Float32(), r.Float32())
	show("Float64", r.Float64(), r.Float64(), r.Float64())

	// ExpFloat64 values have an average of 1 but decay exponentially.
	show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())

	// NormFloat64 values have an average of 0 and a standard deviation of 1.
	show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())

	// Int31, Int63, and Uint32 generate values of the given width.
	// The Int method (not shown) is like either Int31 or Int63
	// depending on the size of 'int'.
	show("Int31", r.Int31(), r.Int31(), r.Int31())
	show("Int63", r.Int63(), r.Int63(), r.Int63())
	show("Uint32", r.Uint32(), r.Uint32(), r.Uint32())

	// Intn, Int31n, and Int63n limit their output to be < n.
	// They do so more carefully than using r.Int()%n.
	show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
	show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
	show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))

	// Perm generates a random permutation of the numbers [0, n).
	show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
	// Output:
	// Float32     0.2635776           0.6358173           0.6718283
	// Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
	// ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
	// NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
	// Int31       1501292890          1486668269          182840835
	// Int63       3546343826724305832 5724354148158589552 5239846799706671610
	// Uint32      2760229429          296659907           1922395059
	// Intn(10)    1                   2                   5
	// Int31n(10)  4                   7                   8
	// Int63n(10)  7                   6                   3
	// Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
}
<|endoftext|>


<commit_before>//Package subcommand is an option parsing utility a la git/mercurial/go loosely
//inspired by Ruby's OptionParser
package subcommand

import (
	"fmt"
	"strings"
)

//FlagType defines the different flag types. Options have values associated to the flag, Switches have no value associated.
type FlagType int

const (
	Option FlagType = iota
	Switch
)

//Command aggregates different flags under a common name. Every time a command is found during the parsing process the associated function is executed.
type Command struct {
	//Name
	Name            string
	Description     string //Command help line
	Params          string //Description of the parameters
	innerFlagsLong  map[string]*Flag
	innerFlagsShort map[string]*Flag
	fn              func(command string, leftOvers ...string) error
	parent          *Command
}

//Access to flags
type Flagged interface {
	Flags() []Flag
}

//getFlags returns a slice containing the c's flags
func (c *Command) Flags() []Flag {
	//return c.Name
	flags := make([]Flag, 0)
	for _, val := range c.innerFlagsLong {
		flags = append(flags, *val)
	}

	return flags
}

//Returns the command parent
func (c Command) Parent() *Command {
	return c.parent
}

//Parser contains other commands. It's the data structure and its name should be the program's name.
type Parser struct {
	Command
	Commands map[string]*Command
	help     Command
}

func newCommand(parent *Command, name string, description string, fn func(string, ...string) error) *Command {
	return &Command{
		Name:            name,
		innerFlagsShort: make(map[string]*Flag),
		innerFlagsLong:  make(map[string]*Flag),
		fn:              fn,
		Description:     description,
		parent:          parent,
	}
}

//Sets the help command. There is one default implementation automatically added when the parser is created.
func (p *Parser) SetHelp(name string, description string, fn func(string, ...string) error) *Command {
	command := newCommand(&p.Command, name, description, fn)
	p.help = *command
	return command

}
func (p *Parser) OnCommand(fn func() error) {
	p.Command.fn = func(string, ...string) error {
		return fn()
	}
}

//Returns the help command
func (p Parser) Help() Command {
	return p.help
}

type CommandFunction func(string, ...string) error

//NewParser constructs a parser for program name given
func NewParser(program string) *Parser {
	parser := &Parser{
		Command:  *newCommand(nil, program, "", func(string, ...string) error { return nil }),
		Commands: make(map[string]*Command),
	}
	parser.SetHelp("help", fmt.Sprintf("Type %v help [command] for detailed information about a command", program), defaultHelp(parser))
	return parser
}

func defaultHelp(p *Parser) func(string, ...string) error {
	return func(help string, args ...string) error {
		if len(args) > 0 {
			if cmd, ok := p.Commands[args[0]]; ok {
				visitCommand(*cmd)
				return nil
			} else {
				fmt.Printf("help: command not found %v\n", args[0])
			}
		}
		visitParser(*p)
		return nil
	}
}

//AddCommand inserts a new subcommand to the parser. The callback fn receives as first argument
//the command name followed by the left overs of the parsing process
//Example:
// command "hello" prints the non flags (options and switches) arguments.
// The associated callback should be something like
// func processCommand(commandName string,args ...string){
//      fmt.Printf("The command %v says:\n",commandName)
//      for _,arg:= rage args{
//              fmt.Printf("%v \n",arg)
//      }
//}
func (p *Parser) AddCommand(name string, description string, fn func(string, ...string) error) *Command {
	if _, exists := p.Commands[name]; exists {
		panic(fmt.Sprintf("Command '%s' already exists ", name))
	}
	//create the command
	command := newCommand(&p.Command, name, description, fn)
	//add it to the parser
	p.Commands[name] = command
	return command
}

//Adds a new option to the command to be used as "--option OPTION" (expects a value after the flag) in the command line
//The short definition has no length restriction but it should be significantly shorter that its long counterpart
//The function fn receives the name of the option and its value
//Example:
//command.AddOption("path","p",setPath)//option
//[...]
// func setPath(option,value string){
//      printf("According the option %v the path is set to %v",option,value);
//}
func (c *Command) AddOption(long string, short string, description string, fn func(string, string) error) *Flag {
	flag := buildFlag(long, short, description, fn, Option)
	c.addFlag(flag)
	return flag
}

//Adds a new switch to the command to be used as "--switch" (expects no value after the flag) in the command line
//The short definition has no length restriction but it should be significantly shorter that its long counterpart
//The function fn receives two string, the first is the switch name and the second is just an empty string
//Example:
//command.AddSwitch("verbose","v",setVerbose)//option
//[...]
// func setVerbose(switch string){
//      printf("I'm get to get quite talkative! I'm set to be %v ",switch);
//}
func (c *Command) AddSwitch(long string, short string, description string, fn func(string, string) error) *Flag {
	flag := buildFlag(long, short, description, fn, Switch)
	c.addFlag(flag)
	return flag
}

//Adds a flag to the command
func (c *Command) addFlag(flag *Flag) {

	if _, exists := c.innerFlagsLong[flag.Long]; exists {
		panic(fmt.Errorf("Flag '%s' already exists ", flag.Long))
	}
	if _, exists := c.innerFlagsShort[flag.Short]; exists {
		panic(fmt.Errorf("Flag '%s' already exists ", flag.Short))
	}
	c.innerFlagsLong[flag.Long] = flag
	if flag.Short != "" {
		c.innerFlagsShort[flag.Short] = flag
	}

}

func (c *Command) String() string {
	return fmt.Sprintf("%v\t %v", c.Name, c.Description)
}

//Parse parses the arguments executing the associated functions for each command and flag.
//It returns the left overs if some non-option strings or commands  were not processed.
//Errors are returned in case an unknown flag is found or a mandatory flag was not supplied.
// The set of function calls to be performed are carried in order and once the parsing process is done
func (p *Parser) Parse(args []string) (leftOvers []string, err error) {
	//get the delayed functions to call
	//for every flag//command
	fns, leftOvers, err := p.parse(args)
	if err != nil {
		return
	}
	for _, fn := range fns {
		if err := fn(); err != nil {
			return leftOvers, err
		}

	}
	return
}

//The actual parsing process
func (p *Parser) parse(args []string) (functions []func() error, leftOvers []string, err error) {
	//visited flags
	var visited []Flag
	//functions to call once the parsing process is over
	var currentCommand Command = p.Command
	var currentFunc func() error = commandCaller(p.Name, &leftOvers, p.Command.fn)
	//go comsuming options commands and sub-options
	for i := 0; i < len(args); i++ {
		arg := args[i]
		if strings.HasPrefix(arg, "-") { //flag
			var opt *Flag
			var ok bool
			if strings.HasPrefix(arg, "--") {
				opt, ok = currentCommand.innerFlagsLong[arg[2:]]
			} else {
				opt, ok = currentCommand.innerFlagsShort[arg[1:]]
			}
			//not present
			if !ok {
				err = fmt.Errorf("%v is not a valid flag for %v", arg, currentCommand.Name)
				return
			}

			if opt.Type == Option { //option
				if i+1 >= len(args) {
					err = fmt.Errorf("No value for option %v", arg)
					return
				}
				functions = append(functions, flagCaller(opt.Long, args[i+1], opt.fn))
				i++
			} else { //switch
				functions = append(functions, flagCaller(opt.Long, "", opt.fn))
			}
			//add to visited options
			visited = append(visited, *opt)
		} else {
			//_,isParser:=currentCommand.(Parser)
			if err = checkVisited(visited, currentCommand); err != nil {
				return
			}
			cmd, ok := p.Commands[arg]
			//if its a command
			if isHelp := (arg == p.help.Name); ok || isHelp {
				visited = []Flag{}
				if currentFunc != nil {
					functions = append(functions, currentFunc)
				}
				if !isHelp {
					currentCommand = *cmd
					currentFunc = commandCaller(arg, &leftOvers, cmd.fn)
				} else {
					currentCommand = p.help
					currentFunc = commandCaller(arg, &leftOvers, p.help.fn)
				}
			} else {
				leftOvers = append(leftOvers, arg)
			}

		}

	}
	if currentFunc != nil {
		functions = append(functions, currentFunc)
	}
	//last check for visited
	err = checkVisited(visited, currentCommand)

	return
}

func flagCaller(name, value string, fn func(string, string) error) func() error {
	return func() error { return fn(name, value) }
}
func commandCaller(command string, leftOvers *[]string, fn func(string, ...string) error) func() error {
	return func() error { return fn(command, *leftOvers...) }
}

//checks if the mandatory flags were visited
func checkVisited(visited []Flag, command Command) error {
	for _, flag := range command.Flags() {
		if flag.Mandatory {
			ok := false
			for _, vFlag := range visited {
				if vFlag.Long == flag.Long {
					ok = true
					break
				}
			}
			if !ok {
				return fmt.Errorf("%v was not found and is mandatory for %v", flag, command)
			}
		}
	}
	return nil
}

//Flag structure
type Flag struct {
	//long definition (--option OPTION)
	Long string
	//Short definition (-o )
	Short string
	//Description
	Description string
	//FlagType, option or switch
	Type FlagType
	//Function to call when the flag is found during the parsing process
	fn func(string, string) error
	//Says if the flag is optional or mandatory
	Mandatory bool
}

//Must sets the flag as mandatory. The parser will raise an error in case it isn't present in the arguments
//TODO make sure that switches are not allowed to get mandatory
func (f *Flag) Must(isIt bool) {
	f.Mandatory = isIt
}

//Gets a help friendly flag representation:
//-o,--option  OPTION           This option does this and that
//-s,--switch                   This is a switch
//-i,--ignoreme [IGNOREME]      Optional option
func (f Flag) String() string {
	var format string
	var help string
	shortFormat := "%v"
	if f.Short != "" {
		shortFormat = "--%v,"
	}
	if f.Type == Option {
		if f.Mandatory {
			format = "--%v %v\t%v"
		} else {
			format = "--%v [%v]\t%v"
		}
		help = fmt.Sprintf(shortFormat+format, f.Short, f.Long, strings.ToUpper(f.Long), f.Description)
	} else {
		format = "--%v \t%v"
		help = fmt.Sprintf(shortFormat+format, f.Short, f.Long, f.Description)
	}
	return help
}

//Checks that the definition is just one word
func checkDefinition(flag string) bool {
	parts := strings.Split(flag, " ")
	return len(parts) == 1
}

//builds the flag struct panicking if errors are encountered
func buildFlag(long string, short string, desc string, fn func(string, string) error, kind FlagType) *Flag {
	long = strings.Trim(long, " ")
	short = strings.Trim(short, " ")
	if len(long) == 0 {
		panic("Long definition is empty")
	}

	if !checkDefinition(long) {
		panic(fmt.Sprintf("Long definition %v has two words. Only one is accepted", long))
	}

	if !checkDefinition(short) {
		panic(fmt.Sprintf("Short definition %v has two words. Only one is accepted", long))
	}
	return &Flag{
		Type:        kind,
		Long:        long,
		Short:       short,
		fn:          fn,
		Description: desc,
		Mandatory:   false,
	}
}

//Help printing functions
func visitParser(p Parser) {
	fmt.Printf("Usage: %v [global_options] command [arguments]\n", p.Name)
	fmt.Printf("\n")
	fmt.Printf("Global Options\n")
	fmt.Printf("--------------\n")
	fmt.Printf("\n")
	for _, flag := range p.Flags() {
		fmt.Printf("\t%v\n", flag)
	}
	fmt.Printf("Commands\n")
	fmt.Printf("--------\n")
	fmt.Printf("\n")
	for _, cmd := range p.Commands {
		fmt.Printf("\t%v\t\t%v\n", cmd.Name, cmd.Description)
	}

	fmt.Printf("\n")
	fmt.Printf("\t%v\t\t%v\n", p.help.Name, p.help.Description)
}

func visitCommand(c Command) {
	fmt.Printf("%v\t\t%v\n", c.Name, c.Description)
	fmt.Printf("\n")
	for _, flag := range c.Flags() {
		fmt.Printf("\t%v\n", flag)
	}
}
<commit_msg>Modify OnCommand call so it's done while parsing<commit_after>//Package subcommand is an option parsing utility a la git/mercurial/go loosely
//inspired by Ruby's OptionParser
package subcommand

import (
	"fmt"
	"strings"
)

//FlagType defines the different flag types. Options have values associated to the flag, Switches have no value associated.
type FlagType int

const (
	Option FlagType = iota
	Switch
)

//Command aggregates different flags under a common name. Every time a command is found during the parsing process the associated function is executed.
type Command struct {
	//Name
	Name            string
	Description     string //Command help line
	Params          string //Description of the parameters
	innerFlagsLong  map[string]*Flag
	innerFlagsShort map[string]*Flag
	fn              func(command string, leftOvers ...string) error
	parent          *Command
}

//Access to flags
type Flagged interface {
	Flags() []Flag
}

//getFlags returns a slice containing the c's flags
func (c *Command) Flags() []Flag {
	//return c.Name
	flags := make([]Flag, 0)
	for _, val := range c.innerFlagsLong {
		flags = append(flags, *val)
	}

	return flags
}

//Returns the command parent
func (c Command) Parent() *Command {
	return c.parent
}

//Parser contains other commands. It's the data structure and its name should be the program's name.
type Parser struct {
	Command
	Commands map[string]*Command
	help     Command
}

func newCommand(parent *Command, name string, description string, fn func(string, ...string) error) *Command {
	return &Command{
		Name:            name,
		innerFlagsShort: make(map[string]*Flag),
		innerFlagsLong:  make(map[string]*Flag),
		fn:              fn,
		Description:     description,
		parent:          parent,
	}
}

//Sets the help command. There is one default implementation automatically added when the parser is created.
func (p *Parser) SetHelp(name string, description string, fn func(string, ...string) error) *Command {
	command := newCommand(&p.Command, name, description, fn)
	p.help = *command
	return command

}
func (p *Parser) OnCommand(fn func() error) {
	p.Command.fn = func(string, ...string) error {
		return fn()
	}
}

//Returns the help command
func (p Parser) Help() Command {
	return p.help
}

type CommandFunction func(string, ...string) error

//NewParser constructs a parser for program name given
func NewParser(program string) *Parser {
	parser := &Parser{
		Command:  *newCommand(nil, program, "", func(string, ...string) error { return nil }),
		Commands: make(map[string]*Command),
	}
	parser.SetHelp("help", fmt.Sprintf("Type %v help [command] for detailed information about a command", program), defaultHelp(parser))
	return parser
}

func defaultHelp(p *Parser) func(string, ...string) error {
	return func(help string, args ...string) error {
		if len(args) > 0 {
			if cmd, ok := p.Commands[args[0]]; ok {
				visitCommand(*cmd)
				return nil
			} else {
				fmt.Printf("help: command not found %v\n", args[0])
			}
		}
		visitParser(*p)
		return nil
	}
}

//AddCommand inserts a new subcommand to the parser. The callback fn receives as first argument
//the command name followed by the left overs of the parsing process
//Example:
// command "hello" prints the non flags (options and switches) arguments.
// The associated callback should be something like
// func processCommand(commandName string,args ...string){
//      fmt.Printf("The command %v says:\n",commandName)
//      for _,arg:= rage args{
//              fmt.Printf("%v \n",arg)
//      }
//}
func (p *Parser) AddCommand(name string, description string, fn func(string, ...string) error) *Command {
	if _, exists := p.Commands[name]; exists {
		panic(fmt.Sprintf("Command '%s' already exists ", name))
	}
	//create the command
	command := newCommand(&p.Command, name, description, fn)
	//add it to the parser
	p.Commands[name] = command
	return command
}

//Adds a new option to the command to be used as "--option OPTION" (expects a value after the flag) in the command line
//The short definition has no length restriction but it should be significantly shorter that its long counterpart
//The function fn receives the name of the option and its value
//Example:
//command.AddOption("path","p",setPath)//option
//[...]
// func setPath(option,value string){
//      printf("According the option %v the path is set to %v",option,value);
//}
func (c *Command) AddOption(long string, short string, description string, fn func(string, string) error) *Flag {
	flag := buildFlag(long, short, description, fn, Option)
	c.addFlag(flag)
	return flag
}

//Adds a new switch to the command to be used as "--switch" (expects no value after the flag) in the command line
//The short definition has no length restriction but it should be significantly shorter that its long counterpart
//The function fn receives two string, the first is the switch name and the second is just an empty string
//Example:
//command.AddSwitch("verbose","v",setVerbose)//option
//[...]
// func setVerbose(switch string){
//      printf("I'm get to get quite talkative! I'm set to be %v ",switch);
//}
func (c *Command) AddSwitch(long string, short string, description string, fn func(string, string) error) *Flag {
	flag := buildFlag(long, short, description, fn, Switch)
	c.addFlag(flag)
	return flag
}

//Adds a flag to the command
func (c *Command) addFlag(flag *Flag) {

	if _, exists := c.innerFlagsLong[flag.Long]; exists {
		panic(fmt.Errorf("Flag '%s' already exists ", flag.Long))
	}
	if _, exists := c.innerFlagsShort[flag.Short]; exists {
		panic(fmt.Errorf("Flag '%s' already exists ", flag.Short))
	}
	c.innerFlagsLong[flag.Long] = flag
	if flag.Short != "" {
		c.innerFlagsShort[flag.Short] = flag
	}

}

func (c *Command) String() string {
	return fmt.Sprintf("%v\t %v", c.Name, c.Description)
}

//Parse parses the arguments executing the associated functions for each command and flag.
//It returns the left overs if some non-option strings or commands  were not processed.
//Errors are returned in case an unknown flag is found or a mandatory flag was not supplied.
// The set of function calls to be performed are carried in order and once the parsing process is done
func (p *Parser) Parse(args []string) (leftOvers []string, err error) {
	//get the delayed functions to call
	//for every flag//command
	fns, leftOvers, err := p.parse(args)
	if err != nil {
		return
	}
	for _, fn := range fns {
		if err := fn(); err != nil {
			return leftOvers, err
		}

	}
	return
}

//The actual parsing process
func (p *Parser) parse(args []string) (functions []func() error, leftOvers []string, err error) {
	//visited flags
	var visited []Flag
	//functions to call once the parsing process is over
	var currentCommand Command = p.Command
	var currentFunc func() error = commandCaller(p.Name, &leftOvers, p.Command.fn)
	//go comsuming options commands and sub-options
	for i := 0; i < len(args); i++ {
		arg := args[i]
		if strings.HasPrefix(arg, "-") { //flag
			var opt *Flag
			var ok bool
			if strings.HasPrefix(arg, "--") {
				opt, ok = currentCommand.innerFlagsLong[arg[2:]]
			} else {
				opt, ok = currentCommand.innerFlagsShort[arg[1:]]
			}
			//not present
			if !ok {
				err = fmt.Errorf("%v is not a valid flag for %v", arg, currentCommand.Name)
				return
			}

			if opt.Type == Option { //option
				if i+1 >= len(args) {
					err = fmt.Errorf("No value for option %v", arg)
					return
				}
				functions = append(functions, flagCaller(opt.Long, args[i+1], opt.fn))
				i++
			} else { //switch
				functions = append(functions, flagCaller(opt.Long, "", opt.fn))
			}
			//add to visited options
			visited = append(visited, *opt)
		} else {
			//_,isParser:=currentCommand.(Parser)
			if err = checkVisited(visited, currentCommand); err != nil {
				return
			}
			cmd, ok := p.Commands[arg]
			//if its a command
			if isHelp := (arg == p.help.Name); ok || isHelp {
				visited = []Flag{}
				if currentFunc != nil {
					if err := currentFunc(); err != nil {
						return functions, leftOvers, err
					}
					//functions = append(functions, currentFunc)
				}
				if !isHelp {
					currentCommand = *cmd
					currentFunc = commandCaller(arg, &leftOvers, cmd.fn)
				} else {
					currentCommand = p.help
					currentFunc = commandCaller(arg, &leftOvers, p.help.fn)
				}
			} else {
				leftOvers = append(leftOvers, arg)
			}

		}

	}
	if currentFunc != nil {
		functions = append(functions, currentFunc)
	}
	//last check for visited
	err = checkVisited(visited, currentCommand)

	return
}

func flagCaller(name, value string, fn func(string, string) error) func() error {
	return func() error { return fn(name, value) }
}
func commandCaller(command string, leftOvers *[]string, fn func(string, ...string) error) func() error {
	return func() error { return fn(command, *leftOvers...) }
}

//checks if the mandatory flags were visited
func checkVisited(visited []Flag, command Command) error {
	for _, flag := range command.Flags() {
		if flag.Mandatory {
			ok := false
			for _, vFlag := range visited {
				if vFlag.Long == flag.Long {
					ok = true
					break
				}
			}
			if !ok {
				return fmt.Errorf("%v was not found and is mandatory for %v", flag, command)
			}
		}
	}
	return nil
}

//Flag structure
type Flag struct {
	//long definition (--option OPTION)
	Long string
	//Short definition (-o )
	Short string
	//Description
	Description string
	//FlagType, option or switch
	Type FlagType
	//Function to call when the flag is found during the parsing process
	fn func(string, string) error
	//Says if the flag is optional or mandatory
	Mandatory bool
}

//Must sets the flag as mandatory. The parser will raise an error in case it isn't present in the arguments
//TODO make sure that switches are not allowed to get mandatory
func (f *Flag) Must(isIt bool) {
	f.Mandatory = isIt
}

//Gets a help friendly flag representation:
//-o,--option  OPTION           This option does this and that
//-s,--switch                   This is a switch
//-i,--ignoreme [IGNOREME]      Optional option
func (f Flag) String() string {
	var format string
	var help string
	shortFormat := "%v"
	if f.Short != "" {
		shortFormat = "--%v,"
	}
	if f.Type == Option {
		if f.Mandatory {
			format = "--%v %v\t%v"
		} else {
			format = "--%v [%v]\t%v"
		}
		help = fmt.Sprintf(shortFormat+format, f.Short, f.Long, strings.ToUpper(f.Long), f.Description)
	} else {
		format = "--%v \t%v"
		help = fmt.Sprintf(shortFormat+format, f.Short, f.Long, f.Description)
	}
	return help
}

//Checks that the definition is just one word
func checkDefinition(flag string) bool {
	parts := strings.Split(flag, " ")
	return len(parts) == 1
}

//builds the flag struct panicking if errors are encountered
func buildFlag(long string, short string, desc string, fn func(string, string) error, kind FlagType) *Flag {
	long = strings.Trim(long, " ")
	short = strings.Trim(short, " ")
	if len(long) == 0 {
		panic("Long definition is empty")
	}

	if !checkDefinition(long) {
		panic(fmt.Sprintf("Long definition %v has two words. Only one is accepted", long))
	}

	if !checkDefinition(short) {
		panic(fmt.Sprintf("Short definition %v has two words. Only one is accepted", long))
	}
	return &Flag{
		Type:        kind,
		Long:        long,
		Short:       short,
		fn:          fn,
		Description: desc,
		Mandatory:   false,
	}
}

//Help printing functions
func visitParser(p Parser) {
	fmt.Printf("Usage: %v [global_options] command [arguments]\n", p.Name)
	fmt.Printf("\n")
	fmt.Printf("Global Options\n")
	fmt.Printf("--------------\n")
	fmt.Printf("\n")
	for _, flag := range p.Flags() {
		fmt.Printf("\t%v\n", flag)
	}
	fmt.Printf("Commands\n")
	fmt.Printf("--------\n")
	fmt.Printf("\n")
	for _, cmd := range p.Commands {
		fmt.Printf("\t%v\t\t%v\n", cmd.Name, cmd.Description)
	}

	fmt.Printf("\n")
	fmt.Printf("\t%v\t\t%v\n", p.help.Name, p.help.Description)
}

func visitCommand(c Command) {
	fmt.Printf("%v\t\t%v\n", c.Name, c.Description)
	fmt.Printf("\n")
	for _, flag := range c.Flags() {
		fmt.Printf("\t%v\n", flag)
	}
}
<|endoftext|>


<commit_before>// Package xsrf provides simple routines for creating and retrieving XSRF
// tokens with the Angular framework.
package xsrf

import (
	"errors"
	"net/http"

	"github.com/sermodigital/crypto"
	"github.com/sermodigital/crypto/tokens"
)

// CookieName is the name of the cookie angular checks to determine whether
// it should send an "X-XSRF-TOKEN" header.
const CookieName = "XSRF-TOKEN"

// Hash returns the SHAKE-256 hash of the token. Hash should be used when
// storing the XSRF token on the backend and comparisons should be done in
// constant-time function, using a function like those found in crypto/subtle.
func Hash(t tokens.AuthToken) []byte {
	return crypto.Shake256(t[:])
}

// Cookie returns an http.Cookie with the Name and Value fields set.
func Cookie(t tokens.AuthToken) *http.Cookie {
	return &http.Cookie{Name: CookieName, Value: string(t[:])}
}

// Retrieve fetches the Token from the X-XSRF-TOKEN header, if it exists.
func Retrieve(r *http.Request) (t tokens.AuthToken, err error) {
	val := r.Header.Get("X-" + CookieName)
	if len(val) != len(t) {
		return t, errors.New("X-" + CookieName + " header is an incorrect length")
	}
	copy(t[:], val)
	return t, nil
}
<commit_msg>Rename Retrieve -> FromRequest<commit_after>// Package xsrf provides simple routines for creating and retrieving XSRF
// tokens with the Angular framework.
package xsrf

import (
	"errors"
	"net/http"

	"github.com/sermodigital/crypto"
	"github.com/sermodigital/crypto/tokens"
)

// CookieName is the name of the cookie angular checks to determine whether
// it should send an "X-XSRF-TOKEN" header.
const CookieName = "XSRF-TOKEN"

// Hash returns the SHAKE-256 hash of the token. Hash should be used when
// storing the XSRF token on the backend and comparisons should be done in
// constant-time function, using a function like those found in crypto/subtle.
func Hash(t tokens.AuthToken) []byte {
	return crypto.Shake256(t[:])
}

// Cookie returns an http.Cookie with the Name and Value fields set.
func Cookie(t tokens.AuthToken) *http.Cookie {
	return &http.Cookie{Name: CookieName, Value: string(t[:])}
}

// FromRequest fetches the Token from the X-XSRF-TOKEN header, if it exists.
func FromRequest(r *http.Request) (t tokens.AuthToken, err error) {
	return FromHeader(r.Header)
}

// FromHeader fetches the Token from the X-XSRF-TOKEN header, if it exists.
func FromHeader(h http.Header) (t tokens.AuthToken, err error) {
	val := h.Get("X-" + CookieName)
	if len(val) != len(t) {
		return t, errors.New("X-" + CookieName + " header is an incorrect length")
	}
	copy(t[:], val)
	return t, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"lentil"
	"testing"
)

func TestPriority(t *testing.T) {
	q := connect(t)
	put(t, "job1", "tube1", 2, q)
	put(t, "job2", "tube2", 0, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job2")
}

func TestMoarPriorities(t *testing.T) {
	q := connect(t)
	put(t, "job11", "tube1", 3, q)
	put(t, "job21", "tube2", 1, q)
	put(t, "job31", "tube3", 2, q)
	put(t, "job22", "tube2", 1, q)
	put(t, "job32", "tube3", 2, q)
	put(t, "job12", "tube1", 3, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job21")
	assertNextJob(t, jobs, "job22")
	assertNextJob(t, jobs, "job31")
	assertNextJob(t, jobs, "job32")
	assertNextJob(t, jobs, "job11")
	assertNextJob(t, jobs, "job12")
}

func TestSamePriorityDifferentJobCount(t *testing.T) {
	q := connect(t)
	put(t, "job11", "tube1", 0, q)
	put(t, "job12", "tube1", 0, q)
	put(t, "job13", "tube1", 0, q)
	put(t, "job21", "tube2", 0, q)
	put(t, "job22", "tube2", 0, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job11")
	assertNextJob(t, jobs, "job21")
	assertNextJob(t, jobs, "job12")
	assertNextJob(t, jobs, "job22")
	assertNextJob(t, jobs, "job13")
}

func assertNextJob(t *testing.T, jobqueue *JobQueue, expected string) {
	jobinfo := make(map[string]string)
	job, e := jobqueue.Next()
	if e != nil {
		t.Error(e)
		return
	}
	json.Unmarshal(job.Body, &jobinfo)
	if jobinfo["name"] != expected {
		t.Errorf("%s != %s\n", expected, jobinfo["name"])
	}
	jobqueue.Delete(job.Id)
}

func put(t *testing.T, jobName, tube string, pri int, q *lentil.Beanstalkd) {
	job := make(map[string]string)
	job["tube"] = tube
	job["name"] = jobName
	jobjson, _ := json.Marshal(job)
	e := q.Use(tube)
	if e != nil {
		t.Fatal(e)
	}
	_, e = q.Put(pri, 0, 60, jobjson)
	if e != nil {
		t.Error(e)
	}
}

func connect(t *testing.T) *lentil.Beanstalkd {
	q, e := lentil.Dial("0.0.0.0:11300")
	if e != nil {
		t.Fatal(e)
	}
	// Clear beanstalkd
	tubes, e := q.ListTubes()
	if e != nil {
		t.Fatal(e)
	}
	for _, tube := range tubes {
		if tube == "default" {
			continue
		}
		_, e = q.Watch(tube)
		if e != nil {
			t.Fatal(e)
		}
		for {
			job, e := q.ReserveWithTimeout(0)
			if e != nil {
				break
			}
			q.Delete(job.Id)
		}
		_, e := q.Ignore(tube)
		if e != nil {
			t.Fatal(e)
		}
	}
	return q
}
<commit_msg>imoprt lentil using github address<commit_after>package main

import (
	"encoding/json"
	"github.com/nutrun/lentil"
	"testing"
)

func TestPriority(t *testing.T) {
	q := connect(t)
	put(t, "job1", "tube1", 2, q)
	put(t, "job2", "tube2", 0, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job2")
}

func TestMoarPriorities(t *testing.T) {
	q := connect(t)
	put(t, "job11", "tube1", 3, q)
	put(t, "job21", "tube2", 1, q)
	put(t, "job31", "tube3", 2, q)
	put(t, "job22", "tube2", 1, q)
	put(t, "job32", "tube3", 2, q)
	put(t, "job12", "tube1", 3, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job21")
	assertNextJob(t, jobs, "job22")
	assertNextJob(t, jobs, "job31")
	assertNextJob(t, jobs, "job32")
	assertNextJob(t, jobs, "job11")
	assertNextJob(t, jobs, "job12")
}

func TestSamePriorityDifferentJobCount(t *testing.T) {
	q := connect(t)
	put(t, "job11", "tube1", 0, q)
	put(t, "job12", "tube1", 0, q)
	put(t, "job13", "tube1", 0, q)
	put(t, "job21", "tube2", 0, q)
	put(t, "job22", "tube2", 0, q)
	jobs := NewJobQueue(q)
	assertNextJob(t, jobs, "job11")
	assertNextJob(t, jobs, "job21")
	assertNextJob(t, jobs, "job12")
	assertNextJob(t, jobs, "job22")
	assertNextJob(t, jobs, "job13")
}

func assertNextJob(t *testing.T, jobqueue *JobQueue, expected string) {
	jobinfo := make(map[string]string)
	job, e := jobqueue.Next()
	if e != nil {
		t.Error(e)
		return
	}
	json.Unmarshal(job.Body, &jobinfo)
	if jobinfo["name"] != expected {
		t.Errorf("%s != %s\n", expected, jobinfo["name"])
	}
	jobqueue.Delete(job.Id)
}

func put(t *testing.T, jobName, tube string, pri int, q *lentil.Beanstalkd) {
	job := make(map[string]string)
	job["tube"] = tube
	job["name"] = jobName
	jobjson, _ := json.Marshal(job)
	e := q.Use(tube)
	if e != nil {
		t.Fatal(e)
	}
	_, e = q.Put(pri, 0, 60, jobjson)
	if e != nil {
		t.Error(e)
	}
}

func connect(t *testing.T) *lentil.Beanstalkd {
	q, e := lentil.Dial("0.0.0.0:11300")
	if e != nil {
		t.Fatal(e)
	}
	// Clear beanstalkd
	tubes, e := q.ListTubes()
	if e != nil {
		t.Fatal(e)
	}
	for _, tube := range tubes {
		if tube == "default" {
			continue
		}
		_, e = q.Watch(tube)
		if e != nil {
			t.Fatal(e)
		}
		for {
			job, e := q.ReserveWithTimeout(0)
			if e != nil {
				break
			}
			q.Delete(job.Id)
		}
		_, e := q.Ignore(tube)
		if e != nil {
			t.Fatal(e)
		}
	}
	return q
}
<|endoftext|>


<commit_before>package cons

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	Start = "\033["
	Reset = "\033[0m"
)

var (
	plain  = false
	colors = map[string][2]string{
		"k": {"30", "40"}, // black
		"r": {"31", "41"}, // red
		"g": {"32", "42"}, // green
		"y": {"33", "43"}, // yellow
		"b": {"34", "44"}, // blue
		"m": {"35", "45"}, // magenta
		"c": {"36", "46"}, // cyan
		"w": {"37", "47"}, // white
	}
	styles = map[string]string{
		"b": "1",  // bold
		"k": "5",  // blink
		"u": "4",  // underline
		"i": "3",  // italic
		"v": "7",  // inverted
		"f": "51", // framed
	}
	// Three diagnostics set after each call to Color()
	// Tracers[0] is three indexes used in parsing the arg to Color():
	//     the first +, the :, and the second +
	// Tracers[1] gives the parsed colors and styles as foreground color, style, background color, style
	// Tracers[2] gives the final ansi control string
	Tracers [3]string
)

func append_code(base string, code string) string {
	if len(code) == 0 {
		return base
	}
	appended := base
	if len(appended) > 0 {
		appended += ";"
	}
	appended += code
	return appended
}

type style_spec struct {
	fg_color string
	fg_style string
	bg_color string
	bg_style string
}

func (spec style_spec) String() string {
	var result string
	result = append_code(result, spec.fg_color)
	result = append_code(result, spec.fg_style)
	result = append_code(result, spec.bg_color)
	result = append_code(result, spec.bg_style)
	return result
}

func IsValid(s string) bool {
	rx := []string{"(?:^[krgbymcw]$)", "(?:^[bkuivf]$)"}
	halves := strings.Split(s, ":")
	for _, h := range halves {
		if len(h) == 0 {
			continue
		}
		quarters := strings.Split(h, "+")
		rxIx := 0
		for _, q := range quarters {
			if len(q) == 0 {
				rxIx++
				continue
			}
			//fmt.Printf("pattern = %s\n", q)
			match, err := regexp.MatchString(rx[rxIx], q)
			if err != nil || !match {
				return false
			}
			rxIx++
		}
	}
	return true
}

// ColorCode returns the ansi control chars for coloring and styling console text
// code should be in UTF-8
func ColorCode(code string) string {
	code = strings.ToLower(code)
	if plain || code == "" || code == "reset" {
		return Reset
	}

	var spec style_spec
	var ptrs = []*string{&spec.fg_color, &spec.fg_style, &spec.bg_color, &spec.bg_style}
	ptrIx := 0
	for _, roon := range code {
		switch string(roon) {
		case ":":
			ptrIx = 2
		case "+":
			ptrIx++
		default:
			*ptrs[ptrIx] = string(roon)
		}
	}
	Tracers[1] = fmt.Sprintf("%s %s %s %s",
		spec.fg_color, spec.fg_style, spec.bg_color, spec.bg_style)
	// now map to the real styles
	spec.fg_color = colors[spec.fg_color][0]
	spec.fg_style = styles[spec.fg_style]
	spec.bg_color = colors[spec.bg_color][1]
	spec.bg_style = styles[spec.bg_style]
	// get the ansi codes without the start and end escapes
	// (useful for printing the codes without sending escapes)
	Tracers[2] = fmt.Sprintf("%s", spec)

	if len(spec.String()) == 0 {
		return ""
	}
	return fmt.Sprintf("%s%sm", Start, spec)

}

func resetIfNeeded(code string) string {
	if len(code) > 0 {
		return Reset
	}
	return ""
}

// Color(s, style) Surrounds `s` with ANSI color and reset code.
func Color(s, style string) string {
	code := ColorCode(style)
	return code + s + resetIfNeeded(code)
}

// ColorFunc Creates a fast closure.
//
// Prefer ColorFunc over Color as it does not recompute ANSI codes.
func ColorFunc(style string) func(string) string {
	if style == "" {
		return func(s string) string {
			return s
		}
	} else {
		code := ColorCode(style)
		return func(s string) string {
			return code + s + resetIfNeeded(code)
		}
	}
}

var ShowRed = ColorFunc("r")
var ShowMagenta = ColorFunc("m")
var ShowGreen = ColorFunc("g")

// DisableColors disables ANSI color codes. On by default.
func DisableColors(disable bool) {
	plain = disable
}

func Printf(code, format string, args ...interface{}) {

}
<commit_msg>added Printf(), Sprintf(). Deprecated Color() in favor of Style()<commit_after>package cons

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	Start = "\033["
	Reset = "\033[0m"
)

var (
	plain  = false
	colors = map[string][2]string{
		"k": {"30", "40"}, // black
		"r": {"31", "41"}, // red
		"g": {"32", "42"}, // green
		"y": {"33", "43"}, // yellow
		"b": {"34", "44"}, // blue
		"m": {"35", "45"}, // magenta
		"c": {"36", "46"}, // cyan
		"w": {"37", "47"}, // white
	}
	styles = map[string]string{
		"b": "1",  // bold
		"k": "5",  // blink
		"u": "4",  // underline
		"i": "3",  // italic
		"v": "7",  // inverted
		"f": "51", // framed
	}
	// Three diagnostics set after each call to Color()
	// Tracers[0] is three indexes used in parsing the arg to Color():
	//     the first +, the :, and the second +
	// Tracers[1] gives the parsed colors and styles as foreground color, style, background color, style
	// Tracers[2] gives the final ansi control string
	Tracers [3]string
)

func append_code(base string, code string) string {
	if len(code) == 0 {
		return base
	}
	appended := base
	if len(appended) > 0 {
		appended += ";"
	}
	appended += code
	return appended
}

type style_spec struct {
	fg_color string
	fg_style string
	bg_color string
	bg_style string
}

func (spec style_spec) String() string {
	var result string
	result = append_code(result, spec.fg_color)
	result = append_code(result, spec.fg_style)
	result = append_code(result, spec.bg_color)
	result = append_code(result, spec.bg_style)
	return result
}

func IsValid(s string) bool {
	rx := []string{"(?:^[krgbymcw]$)", "(?:^[bkuivf]$)"}
	halves := strings.Split(s, ":")
	for _, h := range halves {
		if len(h) == 0 {
			continue
		}
		quarters := strings.Split(h, "+")
		rxIx := 0
		for _, q := range quarters {
			if len(q) == 0 {
				rxIx++
				continue
			}
			//fmt.Printf("pattern = %s\n", q)
			match, err := regexp.MatchString(rx[rxIx], q)
			if err != nil || !match {
				return false
			}
			rxIx++
		}
	}
	return true
}

// ColorCode returns the ansi control chars for coloring and styling console text
// code should be in UTF-8
func ColorCode(code string) string {
	code = strings.ToLower(code)
	if plain || code == "" || code == "reset" {
		return Reset
	}

	var spec style_spec
	var ptrs = []*string{&spec.fg_color, &spec.fg_style, &spec.bg_color, &spec.bg_style}
	ptrIx := 0
	for _, roon := range code {
		switch string(roon) {
		case ":":
			ptrIx = 2
		case "+":
			ptrIx++
		default:
			*ptrs[ptrIx] = string(roon)
		}
	}
	Tracers[1] = fmt.Sprintf("%s %s %s %s",
		spec.fg_color, spec.fg_style, spec.bg_color, spec.bg_style)
	// now map to the real styles
	spec.fg_color = colors[spec.fg_color][0]
	spec.fg_style = styles[spec.fg_style]
	spec.bg_color = colors[spec.bg_color][1]
	spec.bg_style = styles[spec.bg_style]
	// get the ansi codes without the start and end escapes
	// (useful for printing the codes without sending escapes)
	Tracers[2] = fmt.Sprintf("%s", spec)

	if len(spec.String()) == 0 {
		return ""
	}
	return fmt.Sprintf("%s%sm", Start, spec)

}

func resetIfNeeded(code string) string {
	if len(code) > 0 {
		return Reset
	}
	return ""
}

// Color(s, style) Surrounds `s` with ANSI color and reset code.
// deprecated, use Style instead
func Color(s, style string) string {
	code := ColorCode(style)
	return code + s + resetIfNeeded(code)
}

func Style(style string, s string) string {
	code := ColorCode(style)
	return code + s + resetIfNeeded(code)
}

// ColorFunc Creates a fast closure.
//
// Prefer ColorFunc over Style, Printf etc. if you are concerned about performance
// as it does not recompute ANSI codes.
func ColorFunc(style string) func(string) string {
	if style == "" {
		return func(s string) string {
			return s
		}
	} else {
		code := ColorCode(style)
		return func(s string) string {
			return code + s + resetIfNeeded(code)
		}
	}
}

var ShowRed = ColorFunc("r")
var ShowMagenta = ColorFunc("m")
var ShowGreen = ColorFunc("g")

// DisableColors disables ANSI color codes. On by default.
func DisableColors(disable bool) {
	plain = disable
}

// convenience function
func Printf(style, format string, args ...interface{}) {
	s := fmt.Sprintf(format, args)
	fmt.Printf("%s", Color(s, style))
}

// convenience function
func Sprintf(style, format string, args ...interface{}) string {
	s := fmt.Sprintf(format, args)
	return Color(s, style)
}
<|endoftext|>