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

// Package yara provides bindings to the YARA library.
package yara

/*
#include <yara.h>

int scanCallbackFunc(int, void*, void*);
*/
import "C"
import (
	"errors"
	"runtime"
	"time"
	"unsafe"
)

// Rules contains a compiled YARA ruleset.
type Rules struct {
	*rules
}

type rules struct {
	cptr *C.YR_RULES
}

var dummy *[]MatchRule

// A MatchRule represents a rule successfully matched against a block
// of data.
type MatchRule struct {
	Rule      string
	Namespace string
	Tags      []string
	Meta      map[string]interface{}
	Strings   []MatchString
}

// A MatchString represents a string declared and matched in a rule.
type MatchString struct {
	Name   string
	Offset uint64
	Data   []byte
}

// ScanFlags are used to tweak the behavior of Scan* functions.
type ScanFlags int

const (
	// ScanFlagsFastMode avoids multiple matches of the same string
	// when not necessary.
	ScanFlagsFastMode = C.SCAN_FLAGS_FAST_MODE
	// ScanFlagsProcessMemory causes the scanned data to be
	// interpreted like live, in-prcess memory rather than an on-disk
	// file.
	ScanFlagsProcessMemory = C.SCAN_FLAGS_PROCESS_MEMORY
)

// ScanMem scans an in-memory buffer using the ruleset, returning
// matches via a list of MatchRule objects.
func (r *Rules) ScanMem(buf []byte, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanMemWithCallback(buf, flags, timeout, &cb)
	matches = cb
	return
}

// ScanMemWithCallback scans an in-memory buffer using the ruleset.
// For every event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanMemWithCallback(buf []byte, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	var ptr *C.uint8_t
	if len(buf) > 0 {
		ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0])))
	}
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_mem(
		r.cptr,
		ptr,
		C.size_t(len(buf)),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// ScanFile scans a file using the ruleset, returning matches via a
// list of MatchRule objects.
func (r *Rules) ScanFile(filename string, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanFileWithCallback(filename, flags, timeout, &cb)
	matches = cb
	return
}

// ScanFileWithCallback scans a file using the ruleset. For every
// event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanFileWithCallback(filename string, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_file(
		r.cptr,
		cfilename,
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// ScanProc scans a live process using the ruleset, returning matches
// via a list of MatchRule objects.
func (r *Rules) ScanProc(pid int, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanProcWithCallback(pid, flags, timeout, &cb)
	matches = cb
	return
}

// ScanProcWithCallback scans a live process using the ruleset.  For
// every event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanProcWithCallback(pid int, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_proc(
		r.cptr,
		C.int(pid),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// Save writes a compiled ruleset to filename.
func (r *Rules) Save(filename string) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_save(r.cptr, cfilename))
	keepAlive(r)
	return
}

// LoadRules retrieves a compiled ruleset from filename.
func LoadRules(filename string) (*Rules, error) {
	r := &Rules{rules: &rules{}}
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	if err := newError(C.yr_rules_load(cfilename,
		&(r.rules.cptr))); err != nil {
		return nil, err
	}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

func (r *rules) finalize() {
	C.yr_rules_destroy(r.cptr)
	runtime.SetFinalizer(r, nil)
}

// Destroy destroys the YARA data structure representing a ruleset.
// Since a Finalizer for the underlying YR_RULES structure is
// automatically set up on creation, it should not be necessary to
// explicitly call this method.
func (r *Rules) Destroy() {
	if r.rules != nil {
		r.rules.finalize()
		r.rules = nil
	}
}

// DefineVariable defines a named variable for use by the compiler.
// Boolean, int64, float64, and string types are supported.
func (r *Rules) DefineVariable(identifier string, value interface{}) (err error) {
	cid := C.CString(identifier)
	defer C.free(unsafe.Pointer(cid))
	switch value.(type) {
	case bool:
		var v int
		if value.(bool) {
			v = 1
		}
		err = newError(C.yr_rules_define_boolean_variable(
			r.cptr, cid, C.int(v)))
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		value := toint64(value)
		err = newError(C.yr_rules_define_integer_variable(
			r.cptr, cid, C.int64_t(value)))
	case float64:
		err = newError(C.yr_rules_define_float_variable(
			r.cptr, cid, C.double(value.(float64))))
	case string:
		cvalue := C.CString(value.(string))
		defer C.free(unsafe.Pointer(cvalue))
		err = newError(C.yr_rules_define_string_variable(
			r.cptr, cid, cvalue))
	default:
		err = errors.New("wrong value type passed to DefineVariable; bool, int64, float64, string are accepted")
	}
	keepAlive(r)
	return
}

// GetRules returns a slice of rule objects that are part of the
// ruleset
func (r *Rules) GetRules() (rv []Rule) {
	for p := unsafe.Pointer(r.cptr.rules_list_head); (*C.YR_RULE)(p).g_flags&C.RULE_GFLAGS_NULL == 0; p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(*r.cptr.rules_list_head)) {
		rv = append(rv, Rule{(*C.YR_RULE)(p)})
	}
	return
}
<commit_msg>Document (*Rules)GetRules() implementation, simplify by shifting typecasts.<commit_after>// Copyright © 2015-2019 Hilko Bengen <bengen@hilluzination.de>
// All rights reserved.
//
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

// Package yara provides bindings to the YARA library.
package yara

/*
#include <yara.h>

int scanCallbackFunc(int, void*, void*);
*/
import "C"
import (
	"errors"
	"runtime"
	"time"
	"unsafe"
)

// Rules contains a compiled YARA ruleset.
type Rules struct {
	*rules
}

type rules struct {
	cptr *C.YR_RULES
}

var dummy *[]MatchRule

// A MatchRule represents a rule successfully matched against a block
// of data.
type MatchRule struct {
	Rule      string
	Namespace string
	Tags      []string
	Meta      map[string]interface{}
	Strings   []MatchString
}

// A MatchString represents a string declared and matched in a rule.
type MatchString struct {
	Name   string
	Offset uint64
	Data   []byte
}

// ScanFlags are used to tweak the behavior of Scan* functions.
type ScanFlags int

const (
	// ScanFlagsFastMode avoids multiple matches of the same string
	// when not necessary.
	ScanFlagsFastMode = C.SCAN_FLAGS_FAST_MODE
	// ScanFlagsProcessMemory causes the scanned data to be
	// interpreted like live, in-prcess memory rather than an on-disk
	// file.
	ScanFlagsProcessMemory = C.SCAN_FLAGS_PROCESS_MEMORY
)

// ScanMem scans an in-memory buffer using the ruleset, returning
// matches via a list of MatchRule objects.
func (r *Rules) ScanMem(buf []byte, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanMemWithCallback(buf, flags, timeout, &cb)
	matches = cb
	return
}

// ScanMemWithCallback scans an in-memory buffer using the ruleset.
// For every event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanMemWithCallback(buf []byte, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	var ptr *C.uint8_t
	if len(buf) > 0 {
		ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0])))
	}
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_mem(
		r.cptr,
		ptr,
		C.size_t(len(buf)),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// ScanFile scans a file using the ruleset, returning matches via a
// list of MatchRule objects.
func (r *Rules) ScanFile(filename string, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanFileWithCallback(filename, flags, timeout, &cb)
	matches = cb
	return
}

// ScanFileWithCallback scans a file using the ruleset. For every
// event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanFileWithCallback(filename string, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_file(
		r.cptr,
		cfilename,
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// ScanProc scans a live process using the ruleset, returning matches
// via a list of MatchRule objects.
func (r *Rules) ScanProc(pid int, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cb := MatchRules{}
	err = r.ScanProcWithCallback(pid, flags, timeout, &cb)
	matches = cb
	return
}

// ScanProcWithCallback scans a live process using the ruleset.  For
// every event emitted by libyara, the appropriate method on the
// ScanCallback object is called.
func (r *Rules) ScanProcWithCallback(pid int, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) {
	cbc := &scanCallbackContainer{ScanCallback: cb}
	defer cbc.destroy()
	id := callbackData.Put(cbc)
	defer callbackData.Delete(id)
	err = newError(C.yr_rules_scan_proc(
		r.cptr,
		C.int(pid),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.scanCallbackFunc),
		id,
		C.int(timeout/time.Second)))
	keepAlive(r)
	return
}

// Save writes a compiled ruleset to filename.
func (r *Rules) Save(filename string) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_save(r.cptr, cfilename))
	keepAlive(r)
	return
}

// LoadRules retrieves a compiled ruleset from filename.
func LoadRules(filename string) (*Rules, error) {
	r := &Rules{rules: &rules{}}
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	if err := newError(C.yr_rules_load(cfilename,
		&(r.rules.cptr))); err != nil {
		return nil, err
	}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

func (r *rules) finalize() {
	C.yr_rules_destroy(r.cptr)
	runtime.SetFinalizer(r, nil)
}

// Destroy destroys the YARA data structure representing a ruleset.
// Since a Finalizer for the underlying YR_RULES structure is
// automatically set up on creation, it should not be necessary to
// explicitly call this method.
func (r *Rules) Destroy() {
	if r.rules != nil {
		r.rules.finalize()
		r.rules = nil
	}
}

// DefineVariable defines a named variable for use by the compiler.
// Boolean, int64, float64, and string types are supported.
func (r *Rules) DefineVariable(identifier string, value interface{}) (err error) {
	cid := C.CString(identifier)
	defer C.free(unsafe.Pointer(cid))
	switch value.(type) {
	case bool:
		var v int
		if value.(bool) {
			v = 1
		}
		err = newError(C.yr_rules_define_boolean_variable(
			r.cptr, cid, C.int(v)))
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		value := toint64(value)
		err = newError(C.yr_rules_define_integer_variable(
			r.cptr, cid, C.int64_t(value)))
	case float64:
		err = newError(C.yr_rules_define_float_variable(
			r.cptr, cid, C.double(value.(float64))))
	case string:
		cvalue := C.CString(value.(string))
		defer C.free(unsafe.Pointer(cvalue))
		err = newError(C.yr_rules_define_string_variable(
			r.cptr, cid, cvalue))
	default:
		err = errors.New("wrong value type passed to DefineVariable; bool, int64, float64, string are accepted")
	}
	keepAlive(r)
	return
}

// GetRules returns a slice of rule objects that are part of the
// ruleset
func (r *Rules) GetRules() (rv []Rule) {
	// Equivalent to:
	// #define yr_rules_foreach(rules, rule) \
	//     for (rule = rules->rules_list_head; !RULE_IS_NULL(rule); rule++)
	// #define RULE_IS_NULL(x) \
	//     (((x)->g_flags) & RULE_GFLAGS_NULL)
	for p := r.cptr.rules_list_head; p.g_flags&C.RULE_GFLAGS_NULL == 0; p = (*C.YR_RULE)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(*p))) {
		rv = append(rv, Rule{p})
	}
	return
}
<|endoftext|>


<commit_before>package gorm

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
	"time"

	"reflect"
)

type Scope struct {
	Search          *search
	Value           interface{}
	Sql             string
	SqlVars         []interface{}
	db              *DB
	indirectValue   *reflect.Value
	instanceId      string
	primaryKeyField *Field
	skipLeft        bool
	fields          map[string]*Field
	selectAttrs     *[]string
}

func (scope *Scope) IndirectValue() reflect.Value {
	if scope.indirectValue == nil {
		value := reflect.Indirect(reflect.ValueOf(scope.Value))
		if value.Kind() == reflect.Ptr {
			value = value.Elem()
		}
		scope.indirectValue = &value
	}
	return *scope.indirectValue
}

func (scope *Scope) NeedPtr() *Scope {
	reflectKind := reflect.ValueOf(scope.Value).Kind()
	if !((reflectKind == reflect.Invalid) || (reflectKind == reflect.Ptr)) {
		err := fmt.Errorf("%v %v\n", fileWithLineNum(), "using unaddressable value")
		scope.Err(err)
		fmt.Printf(err.Error())
	}
	return scope
}

// New create a new Scope without search information
func (scope *Scope) New(value interface{}) *Scope {
	return &Scope{db: scope.NewDB(), Search: &search{}, Value: value}
}

// NewDB create a new DB without search information
func (scope *Scope) NewDB() *DB {
	if scope.db != nil {
		db := scope.db.clone()
		db.search = nil
		db.Value = nil
		return db
	}
	return nil
}

func (scope *Scope) DB() *DB {
	return scope.db
}

// SqlDB return *sql.DB
func (scope *Scope) SqlDB() sqlCommon {
	return scope.db.db
}

// SkipLeft skip remaining callbacks
func (scope *Scope) SkipLeft() {
	scope.skipLeft = true
}

// Quote used to quote database column name according to database dialect
func (scope *Scope) Quote(str string) string {
	if strings.Index(str, ".") != -1 {
		newStrs := []string{}
		for _, str := range strings.Split(str, ".") {
			newStrs = append(newStrs, scope.Dialect().Quote(str))
		}
		return strings.Join(newStrs, ".")
	} else {
		return scope.Dialect().Quote(str)
	}
}

func (scope *Scope) QuoteIfPossible(str string) string {
	if regexp.MustCompile("^[a-zA-Z]+(.[a-zA-Z]+)*$").MatchString(str) {
		return scope.Quote(str)
	}
	return str
}

// Dialect get dialect
func (scope *Scope) Dialect() Dialect {
	return scope.db.parent.dialect
}

// Err write error
func (scope *Scope) Err(err error) error {
	if err != nil {
		scope.db.err(err)
	}
	return err
}

// Log print log message
func (scope *Scope) Log(v ...interface{}) {
	scope.db.log(v...)
}

// HasError check if there are any error
func (scope *Scope) HasError() bool {
	return scope.db.Error != nil
}

func (scope *Scope) PrimaryFields() []*Field {
	var fields = []*Field{}
	for _, field := range scope.GetModelStruct().PrimaryFields {
		fields = append(fields, scope.Fields()[field.DBName])
	}
	return fields
}

func (scope *Scope) PrimaryField() *Field {
	if primaryFields := scope.GetModelStruct().PrimaryFields; len(primaryFields) > 0 {
		if len(primaryFields) > 1 {
			if field, ok := scope.Fields()["id"]; ok {
				return field
			}
		}
		return scope.Fields()[primaryFields[0].DBName]
	}
	return nil
}

// PrimaryKey get the primary key's column name
func (scope *Scope) PrimaryKey() string {
	if field := scope.PrimaryField(); field != nil {
		return field.DBName
	}
	return ""
}

// PrimaryKeyZero check the primary key is blank or not
func (scope *Scope) PrimaryKeyZero() bool {
	field := scope.PrimaryField()
	return field == nil || field.IsBlank
}

// PrimaryKeyValue get the primary key's value
func (scope *Scope) PrimaryKeyValue() interface{} {
	if field := scope.PrimaryField(); field != nil && field.Field.IsValid() {
		return field.Field.Interface()
	}
	return 0
}

// HasColumn to check if has column
func (scope *Scope) HasColumn(column string) bool {
	for _, field := range scope.GetStructFields() {
		if field.IsNormal && (field.Name == column || field.DBName == column) {
			return true
		}
	}
	return false
}

// SetColumn to set the column's value
func (scope *Scope) SetColumn(column interface{}, value interface{}) error {
	if field, ok := column.(*Field); ok {
		return field.Set(value)
	} else if name, ok := column.(string); ok {

		if field, ok := scope.Fields()[name]; ok {
			return field.Set(value)
		}

		dbName := ToDBName(name)
		if field, ok := scope.Fields()[dbName]; ok {
			return field.Set(value)
		}

		if field, ok := scope.FieldByName(name); ok {
			return field.Set(value)
		}
	}
	return errors.New("could not convert column to field")
}

func (scope *Scope) CallMethod(name string, checkError bool) {
	if scope.Value == nil || (checkError && scope.HasError()) {
		return
	}

	call := func(value interface{}) {
		if fm := reflect.ValueOf(value).MethodByName(name); fm.IsValid() {
			switch f := fm.Interface().(type) {
			case func():
				f()
			case func(s *Scope):
				f(scope)
			case func(s *DB):
				f(scope.NewDB())
			case func() error:
				scope.Err(f())
			case func(s *Scope) error:
				scope.Err(f(scope))
			case func(s *DB) error:
				scope.Err(f(scope.NewDB()))
			default:
				scope.Err(fmt.Errorf("unsupported function %v", name))
			}
		}
	}

	if values := scope.IndirectValue(); values.Kind() == reflect.Slice {
		for i := 0; i < values.Len(); i++ {
			call(values.Index(i).Addr().Interface())
		}
	} else {
		call(scope.Value)
	}
}

func (scope *Scope) CallMethodWithErrorCheck(name string) {
	scope.CallMethod(name, true)
}

// AddToVars add value as sql's vars, gorm will escape them
func (scope *Scope) AddToVars(value interface{}) string {
	if expr, ok := value.(*expr); ok {
		exp := expr.expr
		for _, arg := range expr.args {
			exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1)
		}
		return exp
	} else {
		scope.SqlVars = append(scope.SqlVars, value)
		return scope.Dialect().BinVar(len(scope.SqlVars))
	}
}

type tabler interface {
	TableName() string
}

type dbTabler interface {
	TableName(*DB) string
}

// TableName get table name
func (scope *Scope) TableName() string {
	if scope.Search != nil && len(scope.Search.tableName) > 0 {
		return scope.Search.tableName
	}

	if tabler, ok := scope.Value.(tabler); ok {
		return tabler.TableName()
	}

	if tabler, ok := scope.Value.(dbTabler); ok {
		return tabler.TableName(scope.db)
	}

	return scope.GetModelStruct().TableName(scope.db.Model(scope.Value))
}

func (scope *Scope) QuotedTableName() (name string) {
	if scope.Search != nil && len(scope.Search.tableName) > 0 {
		if strings.Index(scope.Search.tableName, " ") != -1 {
			return scope.Search.tableName
		}
		return scope.Quote(scope.Search.tableName)
	} else {
		return scope.Quote(scope.TableName())
	}
}

// CombinedConditionSql get combined condition sql
func (scope *Scope) CombinedConditionSql() string {
	return scope.joinsSql() + scope.whereSql() + scope.groupSql() +
		scope.havingSql() + scope.orderSql() + scope.limitSql() + scope.offsetSql()
}

func (scope *Scope) FieldByName(name string) (field *Field, ok bool) {
	for _, field := range scope.Fields() {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

// Raw set sql
func (scope *Scope) Raw(sql string) *Scope {
	scope.Sql = strings.Replace(sql, "$$", "?", -1)
	return scope
}

// Exec invoke sql
func (scope *Scope) Exec() *Scope {
	defer scope.Trace(NowFunc())

	if !scope.HasError() {
		if result, err := scope.SqlDB().Exec(scope.Sql, scope.SqlVars...); scope.Err(err) == nil {
			if count, err := result.RowsAffected(); scope.Err(err) == nil {
				scope.db.RowsAffected = count
			}
		}
	}
	return scope
}

// Set set value by name
func (scope *Scope) Set(name string, value interface{}) *Scope {
	scope.db.InstantSet(name, value)
	return scope
}

// Get get value by name
func (scope *Scope) Get(name string) (interface{}, bool) {
	return scope.db.Get(name)
}

// InstanceId get InstanceId for scope
func (scope *Scope) InstanceId() string {
	if scope.instanceId == "" {
		scope.instanceId = fmt.Sprintf("%v%v", &scope, &scope.db)
	}
	return scope.instanceId
}

func (scope *Scope) InstanceSet(name string, value interface{}) *Scope {
	return scope.Set(name+scope.InstanceId(), value)
}

func (scope *Scope) InstanceGet(name string) (interface{}, bool) {
	return scope.Get(name + scope.InstanceId())
}

// Trace print sql log
func (scope *Scope) Trace(t time.Time) {
	if len(scope.Sql) > 0 {
		scope.db.slog(scope.Sql, t, scope.SqlVars...)
	}
}

// Begin start a transaction
func (scope *Scope) Begin() *Scope {
	if db, ok := scope.SqlDB().(sqlDb); ok {
		if tx, err := db.Begin(); err == nil {
			scope.db.db = interface{}(tx).(sqlCommon)
			scope.InstanceSet("gorm:started_transaction", true)
		}
	}
	return scope
}

// CommitOrRollback commit current transaction if there is no error, otherwise rollback it
func (scope *Scope) CommitOrRollback() *Scope {
	if _, ok := scope.InstanceGet("gorm:started_transaction"); ok {
		if db, ok := scope.db.db.(sqlTx); ok {
			if scope.HasError() {
				db.Rollback()
			} else {
				db.Commit()
			}
			scope.db.db = scope.db.parent.db
		}
	}
	return scope
}

func (scope *Scope) SelectAttrs() []string {
	if scope.selectAttrs == nil {
		attrs := []string{}
		for _, value := range scope.Search.selects {
			if str, ok := value.(string); ok {
				attrs = append(attrs, str)
			} else if strs, ok := value.([]string); ok {
				attrs = append(attrs, strs...)
			} else if strs, ok := value.([]interface{}); ok {
				for _, str := range strs {
					attrs = append(attrs, fmt.Sprintf("%v", str))
				}
			}
		}
		scope.selectAttrs = &attrs
	}
	return *scope.selectAttrs
}

func (scope *Scope) OmitAttrs() []string {
	return scope.Search.omits
}

func (scope *Scope) changeableDBColumn(column string) bool {
	selectAttrs := scope.SelectAttrs()
	omitAttrs := scope.OmitAttrs()

	if len(selectAttrs) > 0 {
		for _, attr := range selectAttrs {
			if column == ToDBName(attr) {
				return true
			}
		}
		return false
	}

	for _, attr := range omitAttrs {
		if column == ToDBName(attr) {
			return false
		}
	}
	return true
}

func (scope *Scope) changeableField(field *Field) bool {
	selectAttrs := scope.SelectAttrs()
	omitAttrs := scope.OmitAttrs()

	if len(selectAttrs) > 0 {
		for _, attr := range selectAttrs {
			if field.Name == attr || field.DBName == attr {
				return true
			}
		}
		return false
	}

	for _, attr := range omitAttrs {
		if field.Name == attr || field.DBName == attr {
			return false
		}
	}

	return !field.IsIgnored
}

func (scope *Scope) shouldSaveAssociations() bool {
	saveAssociations, ok := scope.Get("gorm:save_associations")
	if ok && !saveAssociations.(bool) {
		return false
	}
	return true
}
<commit_msg>Handle children db's Error in callbacks<commit_after>package gorm

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
	"time"

	"reflect"
)

type Scope struct {
	Search          *search
	Value           interface{}
	Sql             string
	SqlVars         []interface{}
	db              *DB
	indirectValue   *reflect.Value
	instanceId      string
	primaryKeyField *Field
	skipLeft        bool
	fields          map[string]*Field
	selectAttrs     *[]string
}

func (scope *Scope) IndirectValue() reflect.Value {
	if scope.indirectValue == nil {
		value := reflect.Indirect(reflect.ValueOf(scope.Value))
		if value.Kind() == reflect.Ptr {
			value = value.Elem()
		}
		scope.indirectValue = &value
	}
	return *scope.indirectValue
}

func (scope *Scope) NeedPtr() *Scope {
	reflectKind := reflect.ValueOf(scope.Value).Kind()
	if !((reflectKind == reflect.Invalid) || (reflectKind == reflect.Ptr)) {
		err := fmt.Errorf("%v %v\n", fileWithLineNum(), "using unaddressable value")
		scope.Err(err)
		fmt.Printf(err.Error())
	}
	return scope
}

// New create a new Scope without search information
func (scope *Scope) New(value interface{}) *Scope {
	return &Scope{db: scope.NewDB(), Search: &search{}, Value: value}
}

// NewDB create a new DB without search information
func (scope *Scope) NewDB() *DB {
	if scope.db != nil {
		db := scope.db.clone()
		db.search = nil
		db.Value = nil
		return db
	}
	return nil
}

func (scope *Scope) DB() *DB {
	return scope.db
}

// SqlDB return *sql.DB
func (scope *Scope) SqlDB() sqlCommon {
	return scope.db.db
}

// SkipLeft skip remaining callbacks
func (scope *Scope) SkipLeft() {
	scope.skipLeft = true
}

// Quote used to quote database column name according to database dialect
func (scope *Scope) Quote(str string) string {
	if strings.Index(str, ".") != -1 {
		newStrs := []string{}
		for _, str := range strings.Split(str, ".") {
			newStrs = append(newStrs, scope.Dialect().Quote(str))
		}
		return strings.Join(newStrs, ".")
	} else {
		return scope.Dialect().Quote(str)
	}
}

func (scope *Scope) QuoteIfPossible(str string) string {
	if regexp.MustCompile("^[a-zA-Z]+(.[a-zA-Z]+)*$").MatchString(str) {
		return scope.Quote(str)
	}
	return str
}

// Dialect get dialect
func (scope *Scope) Dialect() Dialect {
	return scope.db.parent.dialect
}

// Err write error
func (scope *Scope) Err(err error) error {
	if err != nil {
		scope.db.err(err)
	}
	return err
}

// Log print log message
func (scope *Scope) Log(v ...interface{}) {
	scope.db.log(v...)
}

// HasError check if there are any error
func (scope *Scope) HasError() bool {
	return scope.db.Error != nil
}

func (scope *Scope) PrimaryFields() []*Field {
	var fields = []*Field{}
	for _, field := range scope.GetModelStruct().PrimaryFields {
		fields = append(fields, scope.Fields()[field.DBName])
	}
	return fields
}

func (scope *Scope) PrimaryField() *Field {
	if primaryFields := scope.GetModelStruct().PrimaryFields; len(primaryFields) > 0 {
		if len(primaryFields) > 1 {
			if field, ok := scope.Fields()["id"]; ok {
				return field
			}
		}
		return scope.Fields()[primaryFields[0].DBName]
	}
	return nil
}

// PrimaryKey get the primary key's column name
func (scope *Scope) PrimaryKey() string {
	if field := scope.PrimaryField(); field != nil {
		return field.DBName
	}
	return ""
}

// PrimaryKeyZero check the primary key is blank or not
func (scope *Scope) PrimaryKeyZero() bool {
	field := scope.PrimaryField()
	return field == nil || field.IsBlank
}

// PrimaryKeyValue get the primary key's value
func (scope *Scope) PrimaryKeyValue() interface{} {
	if field := scope.PrimaryField(); field != nil && field.Field.IsValid() {
		return field.Field.Interface()
	}
	return 0
}

// HasColumn to check if has column
func (scope *Scope) HasColumn(column string) bool {
	for _, field := range scope.GetStructFields() {
		if field.IsNormal && (field.Name == column || field.DBName == column) {
			return true
		}
	}
	return false
}

// SetColumn to set the column's value
func (scope *Scope) SetColumn(column interface{}, value interface{}) error {
	if field, ok := column.(*Field); ok {
		return field.Set(value)
	} else if name, ok := column.(string); ok {

		if field, ok := scope.Fields()[name]; ok {
			return field.Set(value)
		}

		dbName := ToDBName(name)
		if field, ok := scope.Fields()[dbName]; ok {
			return field.Set(value)
		}

		if field, ok := scope.FieldByName(name); ok {
			return field.Set(value)
		}
	}
	return errors.New("could not convert column to field")
}

func (scope *Scope) CallMethod(name string, checkError bool) {
	if scope.Value == nil || (checkError && scope.HasError()) {
		return
	}

	call := func(value interface{}) {
		if fm := reflect.ValueOf(value).MethodByName(name); fm.IsValid() {
			switch f := fm.Interface().(type) {
			case func():
				f()
			case func(s *Scope):
				f(scope)
			case func(s *DB):
				newDB := scope.NewDB()
				f(newDB)
				scope.Err(newDB.Error)
			case func() error:
				scope.Err(f())
			case func(s *Scope) error:
				scope.Err(f(scope))
			case func(s *DB) error:
				scope.Err(f(scope.NewDB()))
			default:
				scope.Err(fmt.Errorf("unsupported function %v", name))
			}
		}
	}

	if values := scope.IndirectValue(); values.Kind() == reflect.Slice {
		for i := 0; i < values.Len(); i++ {
			call(values.Index(i).Addr().Interface())
		}
	} else {
		call(scope.Value)
	}
}

func (scope *Scope) CallMethodWithErrorCheck(name string) {
	scope.CallMethod(name, true)
}

// AddToVars add value as sql's vars, gorm will escape them
func (scope *Scope) AddToVars(value interface{}) string {
	if expr, ok := value.(*expr); ok {
		exp := expr.expr
		for _, arg := range expr.args {
			exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1)
		}
		return exp
	} else {
		scope.SqlVars = append(scope.SqlVars, value)
		return scope.Dialect().BinVar(len(scope.SqlVars))
	}
}

type tabler interface {
	TableName() string
}

type dbTabler interface {
	TableName(*DB) string
}

// TableName get table name
func (scope *Scope) TableName() string {
	if scope.Search != nil && len(scope.Search.tableName) > 0 {
		return scope.Search.tableName
	}

	if tabler, ok := scope.Value.(tabler); ok {
		return tabler.TableName()
	}

	if tabler, ok := scope.Value.(dbTabler); ok {
		return tabler.TableName(scope.db)
	}

	return scope.GetModelStruct().TableName(scope.db.Model(scope.Value))
}

func (scope *Scope) QuotedTableName() (name string) {
	if scope.Search != nil && len(scope.Search.tableName) > 0 {
		if strings.Index(scope.Search.tableName, " ") != -1 {
			return scope.Search.tableName
		}
		return scope.Quote(scope.Search.tableName)
	} else {
		return scope.Quote(scope.TableName())
	}
}

// CombinedConditionSql get combined condition sql
func (scope *Scope) CombinedConditionSql() string {
	return scope.joinsSql() + scope.whereSql() + scope.groupSql() +
		scope.havingSql() + scope.orderSql() + scope.limitSql() + scope.offsetSql()
}

func (scope *Scope) FieldByName(name string) (field *Field, ok bool) {
	for _, field := range scope.Fields() {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

// Raw set sql
func (scope *Scope) Raw(sql string) *Scope {
	scope.Sql = strings.Replace(sql, "$$", "?", -1)
	return scope
}

// Exec invoke sql
func (scope *Scope) Exec() *Scope {
	defer scope.Trace(NowFunc())

	if !scope.HasError() {
		if result, err := scope.SqlDB().Exec(scope.Sql, scope.SqlVars...); scope.Err(err) == nil {
			if count, err := result.RowsAffected(); scope.Err(err) == nil {
				scope.db.RowsAffected = count
			}
		}
	}
	return scope
}

// Set set value by name
func (scope *Scope) Set(name string, value interface{}) *Scope {
	scope.db.InstantSet(name, value)
	return scope
}

// Get get value by name
func (scope *Scope) Get(name string) (interface{}, bool) {
	return scope.db.Get(name)
}

// InstanceId get InstanceId for scope
func (scope *Scope) InstanceId() string {
	if scope.instanceId == "" {
		scope.instanceId = fmt.Sprintf("%v%v", &scope, &scope.db)
	}
	return scope.instanceId
}

func (scope *Scope) InstanceSet(name string, value interface{}) *Scope {
	return scope.Set(name+scope.InstanceId(), value)
}

func (scope *Scope) InstanceGet(name string) (interface{}, bool) {
	return scope.Get(name + scope.InstanceId())
}

// Trace print sql log
func (scope *Scope) Trace(t time.Time) {
	if len(scope.Sql) > 0 {
		scope.db.slog(scope.Sql, t, scope.SqlVars...)
	}
}

// Begin start a transaction
func (scope *Scope) Begin() *Scope {
	if db, ok := scope.SqlDB().(sqlDb); ok {
		if tx, err := db.Begin(); err == nil {
			scope.db.db = interface{}(tx).(sqlCommon)
			scope.InstanceSet("gorm:started_transaction", true)
		}
	}
	return scope
}

// CommitOrRollback commit current transaction if there is no error, otherwise rollback it
func (scope *Scope) CommitOrRollback() *Scope {
	if _, ok := scope.InstanceGet("gorm:started_transaction"); ok {
		if db, ok := scope.db.db.(sqlTx); ok {
			if scope.HasError() {
				db.Rollback()
			} else {
				db.Commit()
			}
			scope.db.db = scope.db.parent.db
		}
	}
	return scope
}

func (scope *Scope) SelectAttrs() []string {
	if scope.selectAttrs == nil {
		attrs := []string{}
		for _, value := range scope.Search.selects {
			if str, ok := value.(string); ok {
				attrs = append(attrs, str)
			} else if strs, ok := value.([]string); ok {
				attrs = append(attrs, strs...)
			} else if strs, ok := value.([]interface{}); ok {
				for _, str := range strs {
					attrs = append(attrs, fmt.Sprintf("%v", str))
				}
			}
		}
		scope.selectAttrs = &attrs
	}
	return *scope.selectAttrs
}

func (scope *Scope) OmitAttrs() []string {
	return scope.Search.omits
}

func (scope *Scope) changeableDBColumn(column string) bool {
	selectAttrs := scope.SelectAttrs()
	omitAttrs := scope.OmitAttrs()

	if len(selectAttrs) > 0 {
		for _, attr := range selectAttrs {
			if column == ToDBName(attr) {
				return true
			}
		}
		return false
	}

	for _, attr := range omitAttrs {
		if column == ToDBName(attr) {
			return false
		}
	}
	return true
}

func (scope *Scope) changeableField(field *Field) bool {
	selectAttrs := scope.SelectAttrs()
	omitAttrs := scope.OmitAttrs()

	if len(selectAttrs) > 0 {
		for _, attr := range selectAttrs {
			if field.Name == attr || field.DBName == attr {
				return true
			}
		}
		return false
	}

	for _, attr := range omitAttrs {
		if field.Name == attr || field.DBName == attr {
			return false
		}
	}

	return !field.IsIgnored
}

func (scope *Scope) shouldSaveAssociations() bool {
	saveAssociations, ok := scope.Get("gorm:save_associations")
	if ok && !saveAssociations.(bool) {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"sort"
	"strings"
	"unicode/utf8"
)

func indexRuneStarting(str string, r rune, start int) int {
	idx := strings.IndexRune(str[start:], r)
	if idx == -1 {
		return -1
	}
	return idx + start
}

func indexesRune(str string, r rune) []int {
	var indexes []int
	for i, c := range str {
		if c == r {
			indexes = append(indexes, i)
		}
	}
	return indexes
}

func findMatch(candidate string, query string) (Match, error) {
	var runePositions Match
	start := 0
	for _, r := range query {
		start = indexRuneStarting(candidate, r, start)
		if start == -1 {
			return nil, errors.New("No Match Found")
		}
		runePositions = append(runePositions, start)
		start += utf8.RuneLen(r)
	}
	return runePositions, nil
}

type Match []int

func (m Match) Length() int {
	return m[len(m)-1] - m[0] + 1
}

type matchSlice []Match

func (ms matchSlice) Len() int           { return len(ms) }
func (ms matchSlice) Swap(i, j int)      { ms[i], ms[j] = ms[j], ms[i] }
func (ms matchSlice) Less(i, j int) bool { return ms[i].Length() < ms[j].Length() }

func bestMatch(ms []Match) Match {
	sort.Sort(matchSlice(ms))
	return ms[0]
}

func Score(candidate, query string) float64 {
	if len(query) == 0 {
		return 1.0
	}
	if len(candidate) < len(query) {
		return 0.0
	}

	candidate = strings.ToLower(candidate)
	query = strings.ToLower(query)

	first, _ := utf8.DecodeRuneInString(query)
	firstQueryRunePositions := indexesRune(candidate, first)

	var matches []Match
	for _, start := range firstQueryRunePositions {
		match, err := findMatch(candidate[start:], query)
		if err != nil {
			continue
		}
		matches = append(matches, match)
	}

	if len(matches) == 0 {
		return 0.0
	}

	var score float64
	score = float64(bestMatch(matches).Length())
	score = float64(len(query)) / score
	score = score / float64(len(candidate))

	return score
}
<commit_msg>Don't sort all matches just for taking the best<commit_after>package main

import (
	"errors"
	"strings"
	"unicode/utf8"
)

func indexRuneStarting(str string, r rune, start int) int {
	idx := strings.IndexRune(str[start:], r)
	if idx == -1 {
		return -1
	}
	return idx + start
}

func indexesRune(str string, r rune) []int {
	var indexes []int
	for i, c := range str {
		if c == r {
			indexes = append(indexes, i)
		}
	}
	return indexes
}

func findMatch(candidate string, query string) (Match, error) {
	var runePositions Match
	start := 0
	for _, r := range query {
		start = indexRuneStarting(candidate, r, start)
		if start == -1 {
			return nil, errors.New("No Match Found")
		}
		runePositions = append(runePositions, start)
		start += utf8.RuneLen(r)
	}
	return runePositions, nil
}

type Match []int

func (m Match) Length() int {
	return m[len(m)-1] - m[0] + 1
}

func bestMatch(ms []Match) Match {
	if len(ms) == 0 {
		return nil
	}
	best := ms[0]
	for _, m := range ms {
		if m.Length() < best.Length() {
			best = m
		}
	}
	return best
}

func Score(candidate, query string) float64 {
	if len(query) == 0 {
		return 1.0
	}
	if len(candidate) < len(query) {
		return 0.0
	}

	candidate = strings.ToLower(candidate)
	query = strings.ToLower(query)

	first, _ := utf8.DecodeRuneInString(query)
	firstQueryRunePositions := indexesRune(candidate, first)

	var matches []Match
	for _, start := range firstQueryRunePositions {
		match, err := findMatch(candidate[start:], query)
		if err != nil {
			continue
		}
		matches = append(matches, match)
	}

	if len(matches) == 0 {
		return 0.0
	}

	var score float64
	score = float64(bestMatch(matches).Length())
	score = float64(len(query)) / score
	score = score / float64(len(candidate))

	return score
}
<|endoftext|>


<commit_before>package medianame

import (
	"errors"
	"fmt"
	"path/filepath"

	"strconv"
	"strings"

	regexp "github.com/glenn-brown/golang-pkg-pcre/src/pkg/pcre"
	"github.com/labstack/gommon/log"
)

var (
	separators = "[/ -]"

	unwantedRegexps = []regexp.Regexp{
		regexp.MustCompile("(\\d{1,3})\\s?x\\s?(0+)[^1-9]", regexp.CASELESS), //5x0
		regexp.MustCompile("S(\\d{1,3})D(\\d{1,3})", regexp.CASELESS),        //S3D1
		regexp.MustCompile("(?:s|series|\\b)\\s?\\d\\s?(?:&\\s?\\d)?[\\s-]*(?:complete|full)", regexp.CASELESS),
		regexp.MustCompile("disc\\s\\d", regexp.CASELESS),
	}

	//Make sure none of these are found embedded within a word or other numbers
	dateRegexps = []regexp.Regexp{
		notInWord(fmt.Sprintf("(\\d{2,4})%s(\\d{1,2})%s(\\d{1,2})", separators, separators)),
		notInWord(fmt.Sprintf("(\\d{1,2})%s(\\d{1,2})%s(\\d{2,4})", separators, separators)),
		notInWord(fmt.Sprintf("(\\d{4})x(\\d{1,2})%s(\\d{1,2})", separators)),
		notInWord(fmt.Sprintf("(\\d{1,2})(?:st|nd|rd|th)?%s([a-z]{3,10})%s(\\d{4})", separators, separators)),
	}

	romanNumeralRe = "X{0,3}(?:IX|XI{0,4}|VI{0,4}|IV|V|I{1,4})"

	seasonPackRegexps = []regexp.Regexp{
		//S01 or Season 1 but not Season 1 Episode|Part 2
		regexp.MustCompile(fmt.Sprintf("(?:season\\s?|s)(\\d{1,})(?:\\s|$)(?!(?:(?:.*?\\s)?(?:episode|e|ep|part|pt)\\s?(?:\\d{1,3}|%s)|(?:\\d{1,3})\\s?of\\s?(?:\\d{1,3})))", romanNumeralRe), regexp.CASELESS),
		regexp.MustCompile("(\\d{1,3})\\s?x\\s?all'", regexp.CASELESS), // 1xAll
	}

	englishNumbers = []string{"one", "two", "three", "four", "five", "six", "seven",
		"eight", "nine", "ten"}

	epRegexps = []regexp.Regexp{
		notInWord(fmt.Sprintf("(?:series|season|s)\\s?(\\d{1,4})(?:\\s(?:.*\\s)?)?(?:episode|ep|e|part|pt)\\s?(\\d{1,3}|%s)(?:\\s?e(\\d{1,2}))*", romanNumeralRe)),
		notInWord(fmt.Sprintf("(?:series|season)\\s?(\\d{1,4})\\s(\\d{1,3})\\s?of\\s?(?:\\d{1,3})")),
		notInWord(fmt.Sprintf("(\\d{1,2})\\s?x\\s?(\\d+)(?:\\s(\\d{1,2}))?")),
		notInWord(fmt.Sprintf("(\\d{1,3})\\s?of\\s?(?:\\d{1,3})")),
		notInWord(fmt.Sprintf("(?:episode|e|ep|part|pt)\\s?(\\d{1,3}|%s)", romanNumeralRe)),
		notInWord(fmt.Sprintf("part\\s(%s)", strings.Join(englishNumbers, "|"))),
	}

	ignorePrefixes = []string{
		"(?:\\[[^\\[\\]]*\\])",
		"(?:HD.720p?:)",
		"(?:HD.1080p?:)",
		"(?:HD.2160p?:)",
	}
)

func notInWord(re string) regexp.Regexp {
	return regexp.MustCompile( /*"(?<![^\\W_])"+*/ re /*+"(?![^\\W_])"*/, regexp.CASELESS)
}

//Serie Represent serie object
type Serie struct {
	Name       string
	Episode    int
	Season     int
	Quality    string
	EndEpisode int
}

//SerieParser parser object
type SerieParser struct {
	logger *log.Logger
}

//NewSerieParser create Parser
func NewSerieParser(logger *log.Logger) *SerieParser {
	return &SerieParser{
		logger: logger,
	}
}

func (s *SerieParser) guessName(name string) (result Serie, err error) {

	for _, c := range "_.,[]():" {
		name = strings.Replace(name, string(c), " ", -1)
	}
	matched, matchResult := s.parseIt(name, unwantedRegexps, dummyMatch)
	if matched {
		s.logger.Debugf("Matched %s", matchResult.Matches[0].Value)
		err = errors.New("Matched unwanted names")
		return
	}
	identifiedBy := ""
	matched, matchResult = s.parseIt(name, dateRegexps, dummyMatch)
	if matched {
		identifiedBy = "date"
	} else {
		matched, matchResult = s.parseIt(name, seasonPackRegexps, s.seasonCB)
		if !matched {
			matched, matchResult = s.parseIt(name, epRegexps, s.episodeCB)
		}
		identifiedBy = "ep"
	}
	if !matched {
		err = errors.New("No match found")
		return
	}

	extra := ""

	s.logger.Debugf("Found a match %s", matchResult.Matches)
	if matchResult.Matches[0].Index > 1 {
		start := 0
		ignoreReg := regexp.MustCompile(strings.Join(ignorePrefixes, "|"), regexp.CASELESS)
		match := ignoreReg.MatcherString(name, regexp.NOTEMPTY)
		if match.Groups() != 0 {
			start = strings.Index(name, match.GroupString(0))
		}
		extra = name[matchResult.Matches[0].Index:]
		name = name[start : matchResult.Matches[0].Index-1]
		name = strings.Split(name, " - ")[0]
		specialReg := regexp.MustCompile("[\\._\\(\\) ]+", regexp.CASELESS)
		name = string(specialReg.ReplaceAll([]byte(name), []byte(" "), 0))
		name = strings.Trim(name, " -")
		name = strings.ToTitle(name)
	}
	s.logger.Debugf("Identified by %s", identifiedBy)

	result.Quality = ParseQuality(extra, s.logger)
	switch matchResult.context.(type) {
	case *episodeMatch:
		s.logger.Debugf("Matched the episode!!\n")
		em := matchResult.context.(*episodeMatch)
		result.EndEpisode = em.EndEpisode
		result.Episode = em.Episode
		result.Season = em.Season
	}
	result.Name = name

	return
}

type matchCB func(matches matchResult) (bool, interface{})

func dummyMatch(matches matchResult) (bool, interface{}) {
	return true, nil
}

type match struct {
	Value string
	Index int
}
type matchResult struct {
	Matches []match
	context interface{}
}

func (s *SerieParser) parseIt(name string, regexps []regexp.Regexp, cb matchCB) (bool, matchResult) {
	name = strings.ToLower(name)
	for _, re := range regexps {

		matches := re.MatcherString(name, regexp.NOTEMPTY)
		if matches.Matches() {
			s.logger.Debugf("Found matches %s, %v, %v", string(fmt.Sprintf("%s", re)), name, matches)
			nbMatch := 1
			for i := 1; i <= matches.Groups(); i++ {
				if matches.Present(i) {
					nbMatch++
				} else {
					break
				}
			}
			s.logger.Debugf("nbMatch %s", nbMatch)

			res := matchResult{
				Matches: make([]match, nbMatch-1),
			}
			offset := 0
			for i := 1; i < nbMatch; i++ {
				m := matches.GroupString(i)
				mbyte := matches.Group(i)
				s.logger.Debugf("====>%s", mbyte)
				offset += strings.Index(name[offset:], m)
				res.Matches[i-1] = match{
					Value: m,
					Index: offset,
				}
			}
			if matched, context := cb(res); matched {
				res.context = context
				return true, res
			}
		} else {
			s.logger.Debugf("No match for %s %s", re, name)
		}
	}
	return false, matchResult{}
}

func (s *SerieParser) seasonCB(matches matchResult) (bool, interface{}) {
	if len(matches.Matches) == 1 {
		return true, nil
	}
	return false, nil
}

type episodeMatch struct {
	Episode    int
	Season     int
	EndEpisode int
}

func (s *SerieParser) episodeCB(matches matchResult) (bool, interface{}) {
	season := 0
	episode := 0
	endEpisode := 0
	s.logger.Debugf("Found %d matches", len(matches.Matches))
	nbMatches := len(matches.Matches)
	if nbMatches != 0 {
		var epError error
		strEp := ""
		if nbMatches >= 2 {
			strEp = matches.Matches[1].Value
			season, _ = strconv.Atoi(matches.Matches[0].Value)
			episode, epError = strconv.Atoi(strEp)
			if nbMatches == 3 {
				endEpisode, _ = strconv.Atoi(matches.Matches[2].Value)
			}
		} else if nbMatches == 1 {
			season = 1
			strEp = matches.Matches[0].Value
			episode, epError = strconv.Atoi(strEp)
		} else {
			s.logger.Errorf("Unknown matches length %d", nbMatches)
			return false, nil
		}
		if epError != nil {
			//Let's convert it into int
			for i, num := range englishNumbers {
				if strEp == num {
					episode = i + 1
					epError = nil
					break
				}
			}
			if epError != nil {
				episode, epError = s.romanToInt(strEp)
			}
		}
		if epError != nil {
			s.logger.Errorf("Error retrieving information %v", epError)
			return false, nil
		}
		return true, &episodeMatch{
			Episode:    episode,
			Season:     season,
			EndEpisode: endEpisode,
		}
	}
	return false, nil
}

func (s *SerieParser) romanToInt(strEp string) (int, error) {
	//TODO
	return 0, errors.New("Couldn't find Value")
}

//Parse file name and return matching serie
func (s *SerieParser) Parse(name string) (Serie, error) {
	//Remove extension
	ext := filepath.Ext(name)
	name = name[:len(name)-len(ext)]
	return s.guessName(name)
}
<commit_msg>[serie] Remove leading [] texts<commit_after>package medianame

import (
	"errors"
	"fmt"
	"path/filepath"

	"strconv"
	"strings"

	regexp "github.com/glenn-brown/golang-pkg-pcre/src/pkg/pcre"
	"github.com/labstack/gommon/log"
)

var (
	separators = "[/ -]"

	unwantedRegexps = []regexp.Regexp{
		regexp.MustCompile("(\\d{1,3})\\s?x\\s?(0+)[^1-9]", regexp.CASELESS), //5x0
		regexp.MustCompile("S(\\d{1,3})D(\\d{1,3})", regexp.CASELESS),        //S3D1
		regexp.MustCompile("(?:s|series|\\b)\\s?\\d\\s?(?:&\\s?\\d)?[\\s-]*(?:complete|full)", regexp.CASELESS),
		regexp.MustCompile("disc\\s\\d", regexp.CASELESS),
	}

	//Make sure none of these are found embedded within a word or other numbers
	dateRegexps = []regexp.Regexp{
		notInWord(fmt.Sprintf("(\\d{2,4})%s(\\d{1,2})%s(\\d{1,2})", separators, separators)),
		notInWord(fmt.Sprintf("(\\d{1,2})%s(\\d{1,2})%s(\\d{2,4})", separators, separators)),
		notInWord(fmt.Sprintf("(\\d{4})x(\\d{1,2})%s(\\d{1,2})", separators)),
		notInWord(fmt.Sprintf("(\\d{1,2})(?:st|nd|rd|th)?%s([a-z]{3,10})%s(\\d{4})", separators, separators)),
	}

	romanNumeralRe = "X{0,3}(?:IX|XI{0,4}|VI{0,4}|IV|V|I{1,4})"

	seasonPackRegexps = []regexp.Regexp{
		//S01 or Season 1 but not Season 1 Episode|Part 2
		regexp.MustCompile(fmt.Sprintf("(?:season\\s?|s)(\\d{1,})(?:\\s|$)(?!(?:(?:.*?\\s)?(?:episode|e|ep|part|pt)\\s?(?:\\d{1,3}|%s)|(?:\\d{1,3})\\s?of\\s?(?:\\d{1,3})))", romanNumeralRe), regexp.CASELESS),
		regexp.MustCompile("(\\d{1,3})\\s?x\\s?all'", regexp.CASELESS), // 1xAll
	}

	englishNumbers = []string{"one", "two", "three", "four", "five", "six", "seven",
		"eight", "nine", "ten"}

	epRegexps = []regexp.Regexp{
		notInWord(fmt.Sprintf("(?:series|season|s)\\s?(\\d{1,4})(?:\\s(?:.*\\s)?)?(?:episode|ep|e|part|pt)\\s?(\\d{1,3}|%s)(?:\\s?e(\\d{1,2}))*", romanNumeralRe)),
		notInWord(fmt.Sprintf("(?:series|season)\\s?(\\d{1,4})\\s(\\d{1,3})\\s?of\\s?(?:\\d{1,3})")),
		notInWord(fmt.Sprintf("(\\d{1,2})\\s?x\\s?(\\d+)(?:\\s(\\d{1,2}))?")),
		notInWord(fmt.Sprintf("(\\d{1,3})\\s?of\\s?(?:\\d{1,3})")),
		notInWord(fmt.Sprintf("(?:episode|e|ep|part|pt)\\s?(\\d{1,3}|%s)", romanNumeralRe)),
		notInWord(fmt.Sprintf("part\\s(%s)", strings.Join(englishNumbers, "|"))),
	}

	ignorePrefixes = []string{
		"(?:\\[[^\\[.*\\]]*\\])",
		"(?:HD.720p?:)",
		"(?:HD.1080p?:)",
		"(?:HD.2160p?:)",
	}
)

func notInWord(re string) regexp.Regexp {
	return regexp.MustCompile( /*"(?<![^\\W_])"+*/ re /*+"(?![^\\W_])"*/, regexp.CASELESS)
}

//Serie Represent serie object
type Serie struct {
	Name       string
	Episode    int
	Season     int
	Quality    string
	EndEpisode int
}

//SerieParser parser object
type SerieParser struct {
	logger *log.Logger
}

//NewSerieParser create Parser
func NewSerieParser(logger *log.Logger) *SerieParser {
	return &SerieParser{
		logger: logger,
	}
}

func (s *SerieParser) guessName(name string) (result Serie, err error) {

	for _, c := range "_.," {
		name = strings.Replace(name, string(c), " ", -1)
	}

	type excludePrefix struct {
		Start string
		Stop  string
	}

	excludePrefixList := []excludePrefix{{Start: "[", Stop: "]"}, {Start: "HD", Stop: "720p"}, {Start: "HD", Stop: "1080p"},}
	for _, e := range excludePrefixList {
		log.Infof("################## %s\n", name)
		if name[:len(e.Start)] == e.Start {
			name = strings.TrimSpace(name[strings.Index(name, e.Stop)+len(e.Stop):])
		}

	}

	for _, c := range "[]():" {
		name = strings.Replace(name, string(c), " ", -1)
	}
	matched, matchResult := s.parseIt(name, unwantedRegexps, dummyMatch)
	if matched {
		s.logger.Debugf("Matched %s", matchResult.Matches[0].Value)
		err = errors.New("Matched unwanted names")
		return
	}
	identifiedBy := ""
	matched, matchResult = s.parseIt(name, dateRegexps, dummyMatch)
	if matched {
		identifiedBy = "date"
	} else {
		matched, matchResult = s.parseIt(name, seasonPackRegexps, s.seasonCB)
		if !matched {
			matched, matchResult = s.parseIt(name, epRegexps, s.episodeCB)
		}
		identifiedBy = "ep"
	}
	if !matched {
		err = errors.New("No match found")
		return
	}

	extra := ""

	s.logger.Debugf("Found a match %s", matchResult.Matches)
	if matchResult.Matches[0].Index > 1 {
		start := 0
		ignoreReg := regexp.MustCompile(strings.Join(ignorePrefixes, "|"), regexp.CASELESS)
		match := ignoreReg.MatcherString(name, regexp.NOTEMPTY)
		if match.Groups() != 0 {
			start = strings.Index(name, match.GroupString(0))
		}
		extra = name[matchResult.Matches[0].Index:]
		name = name[start : matchResult.Matches[0].Index-1]
		name = strings.Split(name, " - ")[0]
		specialReg := regexp.MustCompile("[\\._\\(\\) ]+", regexp.CASELESS)
		name = string(specialReg.ReplaceAll([]byte(name), []byte(" "), 0))
		name = strings.Trim(name, " -")
		name = strings.ToTitle(name)
	}
	s.logger.Debugf("Identified by %s", identifiedBy)

	result.Quality = ParseQuality(extra, s.logger)
	switch matchResult.context.(type) {
	case *episodeMatch:
		s.logger.Debugf("Matched the episode!!\n")
		em := matchResult.context.(*episodeMatch)
		result.EndEpisode = em.EndEpisode
		result.Episode = em.Episode
		result.Season = em.Season
	}
	result.Name = name

	return
}

type matchCB func(matches matchResult) (bool, interface{})

func dummyMatch(matches matchResult) (bool, interface{}) {
	return true, nil
}

type match struct {
	Value string
	Index int
}
type matchResult struct {
	Matches []match
	context interface{}
}

func (s *SerieParser) parseIt(name string, regexps []regexp.Regexp, cb matchCB) (bool, matchResult) {
	name = strings.ToLower(name)
	for _, re := range regexps {

		matches := re.MatcherString(name, regexp.NOTEMPTY)
		if matches.Matches() {
			s.logger.Debugf("Found matches %s, %v, %v", string(fmt.Sprintf("%s", re)), name, matches)
			nbMatch := 1
			for i := 1; i <= matches.Groups(); i++ {
				if matches.Present(i) {
					nbMatch++
				} else {
					break
				}
			}
			s.logger.Debugf("nbMatch %s", nbMatch)

			res := matchResult{
				Matches: make([]match, nbMatch-1),
			}
			offset := 0
			for i := 1; i < nbMatch; i++ {
				m := matches.GroupString(i)
				mbyte := matches.Group(i)
				s.logger.Debugf("====>%s", mbyte)
				offset += strings.Index(name[offset:], m)
				res.Matches[i-1] = match{
					Value: m,
					Index: offset,
				}
			}
			if matched, context := cb(res); matched {
				res.context = context
				return true, res
			}
		} else {
			s.logger.Debugf("No match for %s %s", re, name)
		}
	}
	return false, matchResult{}
}

func (s *SerieParser) seasonCB(matches matchResult) (bool, interface{}) {
	if len(matches.Matches) == 1 {
		return true, nil
	}
	return false, nil
}

type episodeMatch struct {
	Episode    int
	Season     int
	EndEpisode int
}

func (s *SerieParser) episodeCB(matches matchResult) (bool, interface{}) {
	season := 0
	episode := 0
	endEpisode := 0
	s.logger.Debugf("Found %d matches", len(matches.Matches))
	nbMatches := len(matches.Matches)
	if nbMatches != 0 {
		var epError error
		strEp := ""
		if nbMatches >= 2 {
			strEp = matches.Matches[1].Value
			season, _ = strconv.Atoi(matches.Matches[0].Value)
			episode, epError = strconv.Atoi(strEp)
			if nbMatches == 3 {
				endEpisode, _ = strconv.Atoi(matches.Matches[2].Value)
			}
		} else if nbMatches == 1 {
			season = 1
			strEp = matches.Matches[0].Value
			episode, epError = strconv.Atoi(strEp)
		} else {
			s.logger.Errorf("Unknown matches length %d", nbMatches)
			return false, nil
		}
		if epError != nil {
			//Let's convert it into int
			for i, num := range englishNumbers {
				if strEp == num {
					episode = i + 1
					epError = nil
					break
				}
			}
			if epError != nil {
				episode, epError = s.romanToInt(strEp)
			}
		}
		if epError != nil {
			s.logger.Errorf("Error retrieving information %v", epError)
			return false, nil
		}
		return true, &episodeMatch{
			Episode:    episode,
			Season:     season,
			EndEpisode: endEpisode,
		}
	}
	return false, nil
}

func (s *SerieParser) romanToInt(strEp string) (int, error) {
	//TODO
	return 0, errors.New("Couldn't find Value")
}

//Parse file name and return matching serie
func (s *SerieParser) Parse(name string) (Serie, error) {
	//Remove extension
	ext := filepath.Ext(name)
	name = name[:len(name)-len(ext)]
	return s.guessName(name)
}
<|endoftext|>


<commit_before>// +build !appengine

package kami

import (
	"crypto/tls"
	"flag"
	"log"
	"net"
	"net/http"
	"time"

	"github.com/zenazn/goji/bind"
	"github.com/zenazn/goji/graceful"
)

func init() {
	bind.WithFlag()
	graceful.DoubleKickWindow(2 * time.Second)
}

// Serve starts kami with reasonable defaults.
// It works (exactly) like Goji, looking for Einhorn, the bind flag, GOJI_BIND...
func Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	ServeListener(bind.Default())
}

// ServeTLS is like Serve, but enables TLS using the given config.
func ServeTLS(config *tls.Config) {
	if !flag.Parsed() {
		flag.Parse()
	}

	ServeListener(tls.NewListener(bind.Default(), config))
}

// ServeListener is like Serve, but runs kami on top of an arbitrary net.Listener.
func ServeListener(listener net.Listener) {
	// Install our handler at the root of the standard net/http default mux.
	// This allows packages like expvar to continue working as expected.
	http.Handle("/", Handler())

	log.Println("Starting kami on", listener.Addr())

	graceful.HandleSignals()
	bind.Ready()
	graceful.PreHook(func() { log.Printf("kami received signal, gracefully stopping") })
	graceful.PostHook(func() { log.Printf("kami stopped") })

	err := graceful.Serve(listener, http.DefaultServeMux)

	if err != nil {
		log.Fatal(err)
	}

	graceful.Wait()
}
<commit_msg>add Serve* methods to Mux<commit_after>// +build !appengine

package kami

import (
	"crypto/tls"
	"flag"
	"log"
	"net"
	"net/http"
	"time"

	"github.com/zenazn/goji/bind"
	"github.com/zenazn/goji/graceful"
)

func init() {
	bind.WithFlag()
	graceful.DoubleKickWindow(2 * time.Second)
}

// Serve starts kami with reasonable defaults.
// The bind address can be changed by setting the GOJI_BIND environment variable, or
// by setting the "bind" command line flag.
// Serve detects einhorn and systemd for you.
// It works exactly like zenazn/goji.
func Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	serveListener(Handler(), bind.Default())
}

// ServeTLS is like Serve, but enables TLS using the given config.
func ServeTLS(config *tls.Config) {
	if !flag.Parsed() {
		flag.Parse()
	}

	serveListener(Handler(), tls.NewListener(bind.Default(), config))
}

// ServeListener is like Serve, but runs kami on top of an arbitrary net.Listener.
func ServeListener(listener net.Listener) {
	serveListener(Handler(), listener)
}

// Serve starts serving this mux with reasonable defaults.
// The bind address can be changed by setting the GOJI_BIND environment variable, or
// by setting the "--bind" command line flag.
// Serve detects einhorn and systemd for you.
// It works exactly like zenazn/goji. Only one mux may be served at a time.
func (m *Mux) Serve() {
	if !flag.Parsed() {
		flag.Parse()
	}

	serveListener(m, bind.Default())
}

// ServeTLS is like Serve, but enables TLS using the given config.
func (m *Mux) ServeTLS(config *tls.Config) {
	if !flag.Parsed() {
		flag.Parse()
	}

	serveListener(m, tls.NewListener(bind.Default(), config))
}

// ServeListener is like Serve, but runs kami on top of an arbitrary net.Listener.
func (m *Mux) ServeListener(listener net.Listener) {
	serveListener(m, listener)
}

// ServeListener is like Serve, but runs kami on top of an arbitrary net.Listener.
func serveListener(h http.Handler, listener net.Listener) {
	// Install our handler at the root of the standard net/http default mux.
	// This allows packages like expvar to continue working as expected.
	http.Handle("/", h)

	log.Println("Starting kami on", listener.Addr())

	graceful.HandleSignals()
	bind.Ready()
	graceful.PreHook(func() { log.Printf("kami received signal, gracefully stopping") })
	graceful.PostHook(func() { log.Printf("kami stopped") })

	err := graceful.Serve(listener, http.DefaultServeMux)

	if err != nil {
		log.Fatal(err)
	}

	graceful.Wait()
}
<|endoftext|>


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

package ezcx

import (
	"context"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var (
	ServerDefaultSignals []os.Signal = []os.Signal{
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGHUP,
	}
)

//Handler interface: Defines the contract.
type Handler interface {
	http.Handler
	Handle(res *WebhookResponse, req *WebhookRequest) error
}

// Functional Adapter: HandlerFunc is an adapter.
// HandlerFunc satisfies the Handler interface
type HandlerFunc func(*WebhookResponse, *WebhookRequest) error

// Seems  redundant; may serve a purpose, though, for structural handlers.
// (ie Need to implement for functional handler to satisfy Handle which would
// require implementation for structural handlers.)
func (h HandlerFunc) Handle(res *WebhookResponse, req *WebhookRequest) error {
	return h(res, req)
}

// yaquino@2022-10-07: http.Request's context is flowd down to the WebhookRequest
// via WebhookRequestFromRequest (requests.go)
func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	req, err := WebhookRequestFromRequest(r)
	if err != nil {
		log.Println("Error during WebhookRequestFromRequest")
		log.Println(err)
		return
	}
	req.ctx = r.Context // flowing down the requests's Context added.
	res := req.InitializeResponse()
	err = h(res, req)
	if err != nil {
		log.Println("Error during HandlerFunc execution")
		log.Println(err)
		return
	}
	err = res.WriteResponse(w)
	if err != nil {
		log.Println("Error during WebhookResponse.WriteResponse")
		return
	}
}

type Server struct {
	signals []os.Signal
	signal  chan os.Signal
	errs    chan error
	server  *http.Server
	mux     *http.ServeMux
	lg      *log.Logger
}

func NewServer(ctx context.Context, addr string, lg *log.Logger, signals ...os.Signal) *Server {
	return new(Server).Init(ctx, addr, lg, signals...)
}

func (s *Server) Init(ctx context.Context, addr string, lg *log.Logger, signals ...os.Signal) *Server {
	if len(signals) == 0 {
		s.signals = ServerDefaultSignals
	} else {
		// rethink this later on.  We need to make sure there at least
		// the right group of signals!
		s.signals = signals
	}
	s.signal = make(chan os.Signal, 1)
	signal.Notify(s.signal, s.signals...)

	if lg == nil {
		lg = log.Default()
	}
	s.lg = lg

	s.errs = make(chan error)
	s.mux = http.NewServeMux()
	s.server = &http.Server{
		Addr:        addr,
		Handler:     s.mux,
		BaseContext: func(l net.Listener) context.Context { return ctx },
	}
	return s
}

func (s *Server) SetHandler(h http.Handler) {
	s.server.Handler = h
	if s.isMux(h) {
		s.mux = h.(*http.ServeMux)
	} else {
		s.mux = nil
	}
}

func (s *Server) ServeMux() *http.ServeMux {
	return s.mux
}

func (s *Server) isMux(h http.Handler) bool {
	_, ok := h.(*http.ServeMux)
	return ok
}

func (s *Server) HandleCx(pattern string, handler HandlerFunc) {
	s.mux.Handle(pattern, handler)
}

// yaquino@2022-09-21: I have concerns that checking the parent context will not work as desired.
func (s *Server) ListenAndServe(ctx context.Context) {
	defer func() {
		close(s.errs)
		close(s.signal)
	}()
	// Run ListenAndServe on a separate goroutine.
	s.lg.Printf("EZCX server listening and serving on %s\n", s.server.Addr)
	go func() {
		err := s.server.ListenAndServe()
		if err != nil {
			s.lg.Println(err)
			s.errs <- err
			close(s.errs)
		}
	}()

	for {
		select {
		// If the context is done, we need to return.
		case <-ctx.Done():
			s.lg.Println("EZCX server context is done")
			err := ctx.Err()
			if err != nil {
				s.lg.Print("EZCX server context error...")
				s.lg.Println(err)
			}
			return
		// If there's a non-nil error, we need to return
		case err := <-s.errs:
			if err != nil {
				s.lg.Print("EZCX server non-nil error...")
				s.lg.Println(err)
				return
			}
		case sig := <-s.signal:
			s.lg.Printf("EZCX server signal %s received...", sig)
			switch sig {
			case syscall.SIGHUP:
				s.lg.Println("EZCX reconfigure", sig)
				err := s.Reconfigure()
				if err != nil {
					s.errs <- err
				}
			default:
				s.lg.Printf("EZCX graceful shutdown initiated...")
				err := s.Shutdown(ctx)
				if err != nil {
					s.lg.Println(err)
				}
				s.lg.Println("EZCX shutdown SUCCESS")
				return
			}
		}
	}
}

// Omitted for now.
func (s *Server) Reconfigure() error {
	return nil
}

func (s *Server) Shutdown(ctx context.Context) error {
	timeout, cancel := context.WithTimeout(ctx, time.Second*5)
	defer cancel()
	err := s.server.Shutdown(timeout)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>better error handling<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ezcx

import (
	"context"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var (
	ServerDefaultSignals []os.Signal = []os.Signal{
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGHUP,
	}
)

//Handler interface: Defines the contract.
type Handler interface {
	http.Handler
	Handle(res *WebhookResponse, req *WebhookRequest) error
}

// Functional Adapter: HandlerFunc is an adapter.
// HandlerFunc satisfies the Handler interface
type HandlerFunc func(*WebhookResponse, *WebhookRequest) error

// Seems  redundant; may serve a purpose, though, for structural handlers.
// (ie Need to implement for functional handler to satisfy Handle which would
// require implementation for structural handlers.)
func (h HandlerFunc) Handle(res *WebhookResponse, req *WebhookRequest) error {
	return h(res, req)
}

// yaquino@2022-10-07: http.Request's context is flowd down to the WebhookRequest
// via WebhookRequestFromRequest (requests.go)
func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	req, err := WebhookRequestFromRequest(r)
	if err != nil {
		log.Println("Error during WebhookRequestFromRequest")
		log.Println(err)
		return
	}
	req.ctx = r.Context // flowing down the requests's Context added..
	res := req.InitializeResponse()
	err = h(res, req)
	if err != nil {
		log.Println("Error during HandlerFunc execution")
		log.Println(err)
		return
	}
	err = res.WriteResponse(w)
	if err != nil {
		log.Println("Error during WebhookResponse.WriteResponse")
		return
	}
}

type Server struct {
	signals []os.Signal
	signal  chan os.Signal
	errs    chan error
	server  *http.Server
	mux     *http.ServeMux
	lg      *log.Logger
}

func NewServer(ctx context.Context, addr string, lg *log.Logger, signals ...os.Signal) *Server {
	return new(Server).Init(ctx, addr, lg, signals...)
}

func (s *Server) Init(ctx context.Context, addr string, lg *log.Logger, signals ...os.Signal) *Server {
	if len(signals) == 0 {
		s.signals = ServerDefaultSignals
	} else {
		// rethink this later on.  We need to make sure there at least
		// the right group of signals!
		s.signals = signals
	}
	s.signal = make(chan os.Signal, 1)
	signal.Notify(s.signal, s.signals...)

	if lg == nil {
		lg = log.Default()
	}
	s.lg = lg

	s.errs = make(chan error)
	s.mux = http.NewServeMux()
	s.server = &http.Server{
		Addr:        addr,
		Handler:     s.mux,
		BaseContext: func(l net.Listener) context.Context { return ctx },
	}
	return s
}

func (s *Server) SetHandler(h http.Handler) {
	s.server.Handler = h
	if s.isMux(h) {
		s.mux = h.(*http.ServeMux)
	} else {
		s.mux = nil
	}
}

func (s *Server) ServeMux() *http.ServeMux {
	return s.mux
}

func (s *Server) isMux(h http.Handler) bool {
	_, ok := h.(*http.ServeMux)
	return ok
}

func (s *Server) HandleCx(pattern string, handler HandlerFunc) {
	s.mux.Handle(pattern, handler)
}

// yaquino@2022-09-21: I have concerns that checking the parent context will not work as desired.
func (s *Server) ListenAndServe(ctx context.Context) {
	defer func() {
		close(s.errs)
		close(s.signal)
	}()
	// Run ListenAndServe on a separate goroutine.
	s.lg.Printf("EZCX server listening and serving on %s\n", s.server.Addr)
	go func() {
		err := s.server.ListenAndServe()
		if err != nil {
			s.lg.Println(err)
			s.errs <- err
			close(s.errs)
		}
	}()

	for {
		select {
		// If the context is done, we need to return.
		case <-ctx.Done():
			s.lg.Println("EZCX server context is done")
			err := ctx.Err()
			if err != nil {
				s.lg.Print("EZCX server context error...")
				s.lg.Println(err)
			}
			return
		// If there's a non-nil error, we need to return
		case err := <-s.errs:
			if err != nil {
				s.lg.Print("EZCX server non-nil error...")
				s.lg.Println(err)
				return
			}
		case sig := <-s.signal:
			s.lg.Printf("EZCX server signal %s received...", sig)
			switch sig {
			case syscall.SIGHUP:
				s.lg.Println("EZCX reconfigure", sig)
				err := s.Reconfigure()
				if err != nil {
					s.errs <- err
				}
			default:
				s.lg.Printf("EZCX graceful shutdown initiated...")
				err := s.Shutdown(ctx)
				if err != nil {
					s.lg.Println(err)
				}
				s.lg.Println("EZCX shutdown SUCCESS")
				return
			}
		}
	}
}

// Omitted for now.
func (s *Server) Reconfigure() error {
	return nil
}

func (s *Server) Shutdown(ctx context.Context) error {
	timeout, cancel := context.WithTimeout(ctx, time.Second*5)
	defer cancel()
	err := s.server.Shutdown(timeout)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package uploads

type tracker interface {
	setBlock(id string, block int)
	done(id string) bool
	load(id string, numBlocks int)
	clear(id string)
	clearBlock(id string, block int)
}

var (
	requestBlockCountTracker tracker = newBlockCountTracker()
	requestBlockTracker      tracker = newBlockTracker()
)
<commit_msg>Add hash and addToHash to tracker interface.<commit_after>package uploads

type tracker interface {
	setBlock(id string, block int)
	done(id string) bool
	load(id string, numBlocks int)
	clear(id string)
	clearBlock(id string, block int)
	hash(id string) string
	addToHash(id string, what []byte)
}

var (
	requestBlockCountTracker tracker = newBlockCountTracker()
	requestBlockTracker      tracker = newBlockTracker()
)
<|endoftext|>


<commit_before>package opennebula

import (
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"endpoint": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The URL to your public or private OpenNebula",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_ENDPOINT", nil),
			},
			"username": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The ID of the user to identify as",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_USERNAME", nil),
			},
			"password": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The password for the user",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_PASSWORD", nil),
			},
		},

		ResourcesMap: map[string]*schema.Resource{
			"opennebula_template": resourceTemplate(),
		},

		ConfigureFunc: providerConfigure,
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	return NewClient(
		d.Get("endpoint").(string),
		d.Get("username").(string),
		d.Get("password").(string),
	)
}
<commit_msg>included vnets in the provider<commit_after>package opennebula

import (
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

func Provider() terraform.ResourceProvider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"endpoint": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The URL to your public or private OpenNebula",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_ENDPOINT", nil),
			},
			"username": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The ID of the user to identify as",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_USERNAME", nil),
			},
			"password": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The password for the user",
				DefaultFunc: schema.EnvDefaultFunc("OPENNEBULA_PASSWORD", nil),
			},
		},

		ResourcesMap: map[string]*schema.Resource{
			"opennebula_template": resourceTemplate(),
			"opennebula_vnet":     resourceVnet(),
		},

		ConfigureFunc: providerConfigure,
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	return NewClient(
		d.Get("endpoint").(string),
		d.Get("username").(string),
		d.Get("password").(string),
	)
}
<|endoftext|>


<commit_before>// +build linux darwin dragonfly freebsd netbsd openbsd rumprun

// Package tcplisten provides customizable TCP net.Listener with various
// performance-related options:
//
//   - SO_REUSEPORT. This option allows linear scaling server performance
//     on multi-CPU servers.
//     See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
//
//   - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
//     connection before writing to them.
//
//   - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
//
// The package is derived from https://github.com/kavu/go_reuseport .
package tcplisten

import (
	"errors"
	"fmt"
	"net"
	"os"
	"syscall"
)

// Config provides options to enable on the returned listener.
type Config struct {
	// ReusePort enables SO_REUSEPORT.
	ReusePort bool

	// DeferAccept enables TCP_DEFER_ACCEPT.
	DeferAccept bool

	// FastOpen enables TCP_FASTOPEN.
	FastOpen bool
}

// NewListener returns TCP listener with options set in the Config.
//
// Only tcp4 and tcp6 networks are supported.
func (cfg *Config) NewListener(network, addr string) (net.Listener, error) {
	sa, soType, err := getSockaddr(network, addr)
	if err != nil {
		return nil, err
	}

	syscall.ForkLock.RLock()
	fd, err := syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
	if err == nil {
		syscall.CloseOnExec(fd)
	}
	syscall.ForkLock.RUnlock()
	if err != nil {
		return nil, err
	}

	if err = cfg.fdSetup(fd, sa, addr); err != nil {
		syscall.Close(fd)
		return nil, err
	}

	name := fmt.Sprintf("reuseport.%d.%s.%s", os.Getpid(), network, addr)
	file := os.NewFile(uintptr(fd), name)
	ln, err := net.FileListener(file)
	if err != nil {
		file.Close()
		return nil, err
	}

	if err = file.Close(); err != nil {
		ln.Close()
		return nil, err
	}

	return ln, nil
}

func (cfg *Config) fdSetup(fd int, sa syscall.Sockaddr, addr string) error {
	var err error

	if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
		return fmt.Errorf("cannot enable SO_REUSEADDR: %s", err)
	}

	if cfg.ReusePort {
		if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, soReusePort, 1); err != nil {
			return fmt.Errorf("cannot enable SO_REUSEPORT: %s", err)
		}
	}

	if cfg.DeferAccept {
		if err = enableDeferAccept(fd); err != nil {
			return err
		}
	}

	if cfg.FastOpen {
		if err = enableFastOpen(fd); err != nil {
			return err
		}
	}

	if err = syscall.Bind(fd, sa); err != nil {
		return fmt.Errorf("cannot bind to %q: %s", addr, err)
	}

	if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
		return fmt.Errorf("cannot listen on %q: %s", addr, err)
	}

	return nil
}

func getSockaddr(network, addr string) (sa syscall.Sockaddr, soType int, err error) {
	if network != "tcp4" && network != "tcp6" {
		return nil, -1, errors.New("only tcp4 and tcp6 network is supported")
	}

	tcpAddr, err := net.ResolveTCPAddr(network, addr)
	if err != nil {
		return nil, -1, err
	}

	switch network {
	case "tcp4":
		var sa4 syscall.SockaddrInet4
		sa4.Port = tcpAddr.Port
		copy(sa4.Addr[:], tcpAddr.IP.To4())
		return &sa4, syscall.AF_INET, nil
	case "tcp6":
		var sa6 syscall.SockaddrInet6
		sa6.Port = tcpAddr.Port
		copy(sa6.Addr[:], tcpAddr.IP.To16())
		if tcpAddr.Zone != "" {
			ifi, err := net.InterfaceByName(tcpAddr.Zone)
			if err != nil {
				return nil, -1, err
			}
			sa6.ZoneId = uint32(ifi.Index)
		}
		return &sa6, syscall.AF_INET6, nil
	default:
		return nil, -1, errors.New("Unknown network type " + network)
	}
}
<commit_msg>mention that Config.NewListener may be called multiple times<commit_after>// +build linux darwin dragonfly freebsd netbsd openbsd rumprun

// Package tcplisten provides customizable TCP net.Listener with various
// performance-related options:
//
//   - SO_REUSEPORT. This option allows linear scaling server performance
//     on multi-CPU servers.
//     See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
//
//   - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
//     connection before writing to them.
//
//   - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
//
// The package is derived from https://github.com/kavu/go_reuseport .
package tcplisten

import (
	"errors"
	"fmt"
	"net"
	"os"
	"syscall"
)

// Config provides options to enable on the returned listener.
type Config struct {
	// ReusePort enables SO_REUSEPORT.
	ReusePort bool

	// DeferAccept enables TCP_DEFER_ACCEPT.
	DeferAccept bool

	// FastOpen enables TCP_FASTOPEN.
	FastOpen bool
}

// NewListener returns TCP listener with options set in the Config.
//
// The function may be called many times for creating distinct listeners
// with the given config.
//
// Only tcp4 and tcp6 networks are supported.
func (cfg *Config) NewListener(network, addr string) (net.Listener, error) {
	sa, soType, err := getSockaddr(network, addr)
	if err != nil {
		return nil, err
	}

	syscall.ForkLock.RLock()
	fd, err := syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
	if err == nil {
		syscall.CloseOnExec(fd)
	}
	syscall.ForkLock.RUnlock()
	if err != nil {
		return nil, err
	}

	if err = cfg.fdSetup(fd, sa, addr); err != nil {
		syscall.Close(fd)
		return nil, err
	}

	name := fmt.Sprintf("reuseport.%d.%s.%s", os.Getpid(), network, addr)
	file := os.NewFile(uintptr(fd), name)
	ln, err := net.FileListener(file)
	if err != nil {
		file.Close()
		return nil, err
	}

	if err = file.Close(); err != nil {
		ln.Close()
		return nil, err
	}

	return ln, nil
}

func (cfg *Config) fdSetup(fd int, sa syscall.Sockaddr, addr string) error {
	var err error

	if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
		return fmt.Errorf("cannot enable SO_REUSEADDR: %s", err)
	}

	if cfg.ReusePort {
		if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, soReusePort, 1); err != nil {
			return fmt.Errorf("cannot enable SO_REUSEPORT: %s", err)
		}
	}

	if cfg.DeferAccept {
		if err = enableDeferAccept(fd); err != nil {
			return err
		}
	}

	if cfg.FastOpen {
		if err = enableFastOpen(fd); err != nil {
			return err
		}
	}

	if err = syscall.Bind(fd, sa); err != nil {
		return fmt.Errorf("cannot bind to %q: %s", addr, err)
	}

	if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
		return fmt.Errorf("cannot listen on %q: %s", addr, err)
	}

	return nil
}

func getSockaddr(network, addr string) (sa syscall.Sockaddr, soType int, err error) {
	if network != "tcp4" && network != "tcp6" {
		return nil, -1, errors.New("only tcp4 and tcp6 network is supported")
	}

	tcpAddr, err := net.ResolveTCPAddr(network, addr)
	if err != nil {
		return nil, -1, err
	}

	switch network {
	case "tcp4":
		var sa4 syscall.SockaddrInet4
		sa4.Port = tcpAddr.Port
		copy(sa4.Addr[:], tcpAddr.IP.To4())
		return &sa4, syscall.AF_INET, nil
	case "tcp6":
		var sa6 syscall.SockaddrInet6
		sa6.Port = tcpAddr.Port
		copy(sa6.Addr[:], tcpAddr.IP.To16())
		if tcpAddr.Zone != "" {
			ifi, err := net.InterfaceByName(tcpAddr.Zone)
			if err != nil {
				return nil, -1, err
			}
			sa6.ZoneId = uint32(ifi.Index)
		}
		return &sa6, syscall.AF_INET6, nil
	default:
		return nil, -1, errors.New("Unknown network type " + network)
	}
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package common

import (
	"errors"
	"testing"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow"
)

// EngineTest is a test engine
type EngineTest struct {
	T *testing.T

	CantIsBootstrapped,
	CantStartup,
	CantGossip,
	CantShutdown,

	CantContext,

	CantNotify,

	CantGetAcceptedFrontier,
	CantGetAcceptedFrontierFailed,
	CantAcceptedFrontier,

	CantGetAccepted,
	CantGetAcceptedFailed,
	CantAccepted,

	CantGet,
	CantGetAncestors,
	CantGetFailed,
	CantGetAncestorsFailed,
	CantPut,
	CantMultiPut,

	CantPushQuery,
	CantPullQuery,
	CantQueryFailed,
	CantChits bool

	IsBootstrappedF                                    func() bool
	ContextF                                           func() *snow.Context
	StartupF, GossipF, ShutdownF                       func() error
	NotifyF                                            func(Message) error
	GetF, GetAncestorsF, PullQueryF                    func(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error
	PutF, PushQueryF                                   func(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error
	MultiPutF                                          func(validatorID ids.ShortID, requestID uint32, containers [][]byte) error
	AcceptedFrontierF, GetAcceptedF, AcceptedF, ChitsF func(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error
	GetAcceptedFrontierF, GetFailedF, GetAncestorsFailedF,
	QueryFailedF, GetAcceptedFrontierFailedF, GetAcceptedFailedF func(validatorID ids.ShortID, requestID uint32) error
}

var _ Engine = &EngineTest{}

// Default ...
func (e *EngineTest) Default(cant bool) {
	e.CantIsBootstrapped = cant

	e.CantStartup = cant
	e.CantGossip = cant
	e.CantShutdown = cant

	e.CantContext = cant

	e.CantNotify = cant

	e.CantGetAcceptedFrontier = cant
	e.CantGetAcceptedFrontierFailed = cant
	e.CantAcceptedFrontier = cant

	e.CantGetAccepted = cant
	e.CantGetAcceptedFailed = cant
	e.CantAccepted = cant

	e.CantGet = cant
	e.CantGetAncestors = cant
	e.CantGetAncestorsFailed = cant
	e.CantGetFailed = cant
	e.CantPut = cant
	e.CantMultiPut = cant

	e.CantPushQuery = cant
	e.CantPullQuery = cant
	e.CantQueryFailed = cant
	e.CantChits = cant
}

// Context ...
func (e *EngineTest) Context() *snow.Context {
	if e.ContextF != nil {
		return e.ContextF()
	}
	if e.CantContext && e.T != nil {
		e.T.Fatalf("Unexpectedly called Context")
	}
	return nil
}

// Startup ...
func (e *EngineTest) Startup() error {
	if e.StartupF != nil {
		return e.StartupF()
	} else if e.CantStartup {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Startup")
		}
		return errors.New("Unexpectedly called Startup")
	}
	return nil
}

// Gossip ...
func (e *EngineTest) Gossip() error {
	if e.GossipF != nil {
		return e.GossipF()
	} else if e.CantGossip {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Gossip")
		}
		return errors.New("Unexpectedly called Gossip")
	}
	return nil
}

// Shutdown ...
func (e *EngineTest) Shutdown() error {
	if e.ShutdownF != nil {
		return e.ShutdownF()
	} else if e.CantShutdown {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Shutdown")
		}
		return errors.New("Unexpectedly called Shutdown")
	}
	return nil
}

// Notify ...
func (e *EngineTest) Notify(msg Message) error {
	if e.NotifyF != nil {
		return e.NotifyF(msg)
	} else if e.CantNotify {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Notify")
		}
		return errors.New("Unexpectedly called Notify")
	}
	return nil
}

// GetAcceptedFrontier ...
func (e *EngineTest) GetAcceptedFrontier(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFrontierF != nil {
		return e.GetAcceptedFrontierF(validatorID, requestID)
	} else if e.CantGetAcceptedFrontier {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFrontier")
		}
		return errors.New("Unexpectedly called GetAcceptedFrontier")
	}
	return nil
}

// GetAcceptedFrontierFailed ...
func (e *EngineTest) GetAcceptedFrontierFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFrontierFailedF != nil {
		return e.GetAcceptedFrontierFailedF(validatorID, requestID)
	} else if e.CantGetAcceptedFrontierFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFrontierFailed")
		}
		return errors.New("Unexpectedly called GetAcceptedFrontierFailed")
	}
	return nil
}

// AcceptedFrontier ...
func (e *EngineTest) AcceptedFrontier(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.AcceptedFrontierF != nil {
		return e.AcceptedFrontierF(validatorID, requestID, containerIDs)
	} else if e.CantAcceptedFrontier {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called AcceptedFrontierF")
		}
		return errors.New("Unexpectedly called AcceptedFrontierF")
	}
	return nil
}

// GetAccepted ...
func (e *EngineTest) GetAccepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.GetAcceptedF != nil {
		return e.GetAcceptedF(validatorID, requestID, containerIDs)
	} else if e.CantGetAccepted {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAccepted")
		}
		return errors.New("Unexpectedly called GetAccepted")
	}
	return nil
}

// GetAcceptedFailed ...
func (e *EngineTest) GetAcceptedFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFailedF != nil {
		return e.GetAcceptedFailedF(validatorID, requestID)
	} else if e.CantGetAcceptedFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFailed")
		}
		return errors.New("Unexpectedly called GetAcceptedFailed")
	}
	return nil
}

// Accepted ...
func (e *EngineTest) Accepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.AcceptedF != nil {
		return e.AcceptedF(validatorID, requestID, containerIDs)
	} else if e.CantAccepted {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Accepted")
		}
		return errors.New("Unexpectedly called Accepted")
	}
	return nil
}

// Get ...
func (e *EngineTest) Get(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.GetF != nil {
		return e.GetF(validatorID, requestID, containerID)
	} else if e.CantGet {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Get")
		}
		return errors.New("Unexpectedly called Get")
	}
	return nil
}

// GetAncestors ...
func (e *EngineTest) GetAncestors(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.GetAncestorsF != nil {
		e.GetAncestorsF(validatorID, requestID, containerID)
	} else if e.CantGetAncestors && e.T != nil {
		e.T.Fatalf("Unexpectedly called GetAncestors")
	}
	return nil
}

// GetFailed ...
func (e *EngineTest) GetFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetFailedF != nil {
		return e.GetFailedF(validatorID, requestID)
	} else if e.CantGetFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetFailed")
		}
		return errors.New("Unexpectedly called GetFailed")
	}
	return nil
}

// GetAncestorsFailed ...
func (e *EngineTest) GetAncestorsFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAncestorsFailedF != nil {
		return e.GetAncestorsFailedF(validatorID, requestID)
	} else if e.CantGetAncestorsFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAncestorsFailed")
		}
		return errors.New("Unexpectedly called GetAncestorsFailed")
	}
	return nil
}

// Put ...
func (e *EngineTest) Put(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error {
	if e.PutF != nil {
		return e.PutF(validatorID, requestID, containerID, container)
	} else if e.CantPut {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Put")
		}
		return errors.New("Unexpectedly called Put")
	}
	return nil
}

// MultiPut ...
func (e *EngineTest) MultiPut(validatorID ids.ShortID, requestID uint32, containers [][]byte) error {
	if e.MultiPutF != nil {
		return e.MultiPutF(validatorID, requestID, containers)
	} else if e.CantMultiPut {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called MultiPut")
		}
		return errors.New("Unexpectedly called MultiPut")
	}
	return nil
}

// PushQuery ...
func (e *EngineTest) PushQuery(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error {
	if e.PushQueryF != nil {
		return e.PushQueryF(validatorID, requestID, containerID, container)
	} else if e.CantPushQuery {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called PushQuery")
		}
		return errors.New("Unexpectedly called PushQuery")
	}
	return nil
}

// PullQuery ...
func (e *EngineTest) PullQuery(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.PullQueryF != nil {
		return e.PullQueryF(validatorID, requestID, containerID)
	} else if e.CantPullQuery {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called PullQuery")
		}
		return errors.New("Unexpectedly called PullQuery")
	}
	return nil
}

// QueryFailed ...
func (e *EngineTest) QueryFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.QueryFailedF != nil {
		return e.QueryFailedF(validatorID, requestID)
	} else if e.CantQueryFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called QueryFailed")
		}
		return errors.New("Unexpectedly called QueryFailed")
	}
	return nil
}

// Chits ...
func (e *EngineTest) Chits(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.ChitsF != nil {
		return e.ChitsF(validatorID, requestID, containerIDs)
	} else if e.CantChits {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Chits")
		}
		return errors.New("Unexpectedly called Chits")
	}
	return nil
}

// IsBootstrapped ...
func (e *EngineTest) IsBootstrapped() bool {
	if e.IsBootstrappedF != nil {
		return e.IsBootstrappedF()
	} else if e.CantIsBootstrapped {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called IsBootstrapped")
		}
		return false
	}
	return false
}
<commit_msg>nit cleanup<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package common

import (
	"errors"
	"testing"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow"
)

// EngineTest is a test engine
type EngineTest struct {
	T *testing.T

	CantIsBootstrapped,
	CantStartup,
	CantGossip,
	CantShutdown,

	CantContext,

	CantNotify,

	CantGetAcceptedFrontier,
	CantGetAcceptedFrontierFailed,
	CantAcceptedFrontier,

	CantGetAccepted,
	CantGetAcceptedFailed,
	CantAccepted,

	CantGet,
	CantGetAncestors,
	CantGetFailed,
	CantGetAncestorsFailed,
	CantPut,
	CantMultiPut,

	CantPushQuery,
	CantPullQuery,
	CantQueryFailed,
	CantChits bool

	IsBootstrappedF                                    func() bool
	ContextF                                           func() *snow.Context
	StartupF, GossipF, ShutdownF                       func() error
	NotifyF                                            func(Message) error
	GetF, GetAncestorsF, PullQueryF                    func(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error
	PutF, PushQueryF                                   func(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error
	MultiPutF                                          func(validatorID ids.ShortID, requestID uint32, containers [][]byte) error
	AcceptedFrontierF, GetAcceptedF, AcceptedF, ChitsF func(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error
	GetAcceptedFrontierF, GetFailedF, GetAncestorsFailedF,
	QueryFailedF, GetAcceptedFrontierFailedF, GetAcceptedFailedF func(validatorID ids.ShortID, requestID uint32) error
}

var _ Engine = &EngineTest{}

// Default ...
func (e *EngineTest) Default(cant bool) {
	e.CantIsBootstrapped = cant

	e.CantStartup = cant
	e.CantGossip = cant
	e.CantShutdown = cant

	e.CantContext = cant

	e.CantNotify = cant

	e.CantGetAcceptedFrontier = cant
	e.CantGetAcceptedFrontierFailed = cant
	e.CantAcceptedFrontier = cant

	e.CantGetAccepted = cant
	e.CantGetAcceptedFailed = cant
	e.CantAccepted = cant

	e.CantGet = cant
	e.CantGetAncestors = cant
	e.CantGetAncestorsFailed = cant
	e.CantGetFailed = cant
	e.CantPut = cant
	e.CantMultiPut = cant

	e.CantPushQuery = cant
	e.CantPullQuery = cant
	e.CantQueryFailed = cant
	e.CantChits = cant
}

// Context ...
func (e *EngineTest) Context() *snow.Context {
	if e.ContextF != nil {
		return e.ContextF()
	}
	if e.CantContext && e.T != nil {
		e.T.Fatalf("Unexpectedly called Context")
	}
	return nil
}

// Startup ...
func (e *EngineTest) Startup() error {
	if e.StartupF != nil {
		return e.StartupF()
	} else if e.CantStartup {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Startup")
		}
		return errors.New("Unexpectedly called Startup")
	}
	return nil
}

// Gossip ...
func (e *EngineTest) Gossip() error {
	if e.GossipF != nil {
		return e.GossipF()
	} else if e.CantGossip {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Gossip")
		}
		return errors.New("Unexpectedly called Gossip")
	}
	return nil
}

// Shutdown ...
func (e *EngineTest) Shutdown() error {
	if e.ShutdownF != nil {
		return e.ShutdownF()
	} else if e.CantShutdown {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Shutdown")
		}
		return errors.New("Unexpectedly called Shutdown")
	}
	return nil
}

// Notify ...
func (e *EngineTest) Notify(msg Message) error {
	if e.NotifyF != nil {
		return e.NotifyF(msg)
	} else if e.CantNotify {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Notify")
		}
		return errors.New("Unexpectedly called Notify")
	}
	return nil
}

// GetAcceptedFrontier ...
func (e *EngineTest) GetAcceptedFrontier(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFrontierF != nil {
		return e.GetAcceptedFrontierF(validatorID, requestID)
	} else if e.CantGetAcceptedFrontier {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFrontier")
		}
		return errors.New("Unexpectedly called GetAcceptedFrontier")
	}
	return nil
}

// GetAcceptedFrontierFailed ...
func (e *EngineTest) GetAcceptedFrontierFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFrontierFailedF != nil {
		return e.GetAcceptedFrontierFailedF(validatorID, requestID)
	} else if e.CantGetAcceptedFrontierFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFrontierFailed")
		}
		return errors.New("Unexpectedly called GetAcceptedFrontierFailed")
	}
	return nil
}

// AcceptedFrontier ...
func (e *EngineTest) AcceptedFrontier(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.AcceptedFrontierF != nil {
		return e.AcceptedFrontierF(validatorID, requestID, containerIDs)
	} else if e.CantAcceptedFrontier {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called AcceptedFrontierF")
		}
		return errors.New("Unexpectedly called AcceptedFrontierF")
	}
	return nil
}

// GetAccepted ...
func (e *EngineTest) GetAccepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.GetAcceptedF != nil {
		return e.GetAcceptedF(validatorID, requestID, containerIDs)
	} else if e.CantGetAccepted {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAccepted")
		}
		return errors.New("Unexpectedly called GetAccepted")
	}
	return nil
}

// GetAcceptedFailed ...
func (e *EngineTest) GetAcceptedFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAcceptedFailedF != nil {
		return e.GetAcceptedFailedF(validatorID, requestID)
	} else if e.CantGetAcceptedFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAcceptedFailed")
		}
		return errors.New("Unexpectedly called GetAcceptedFailed")
	}
	return nil
}

// Accepted ...
func (e *EngineTest) Accepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.AcceptedF != nil {
		return e.AcceptedF(validatorID, requestID, containerIDs)
	} else if e.CantAccepted {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Accepted")
		}
		return errors.New("Unexpectedly called Accepted")
	}
	return nil
}

// Get ...
func (e *EngineTest) Get(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.GetF != nil {
		return e.GetF(validatorID, requestID, containerID)
	} else if e.CantGet {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Get")
		}
		return errors.New("Unexpectedly called Get")
	}
	return nil
}

// GetAncestors ...
func (e *EngineTest) GetAncestors(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.GetAncestorsF != nil {
		e.GetAncestorsF(validatorID, requestID, containerID)
	} else if e.CantGetAncestors && e.T != nil {
		e.T.Fatalf("Unexpectedly called GetAncestors")
	}
	return nil
}

// GetFailed ...
func (e *EngineTest) GetFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetFailedF != nil {
		return e.GetFailedF(validatorID, requestID)
	} else if e.CantGetFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetFailed")
		}
		return errors.New("Unexpectedly called GetFailed")
	}
	return nil
}

// GetAncestorsFailed ...
func (e *EngineTest) GetAncestorsFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.GetAncestorsFailedF != nil {
		return e.GetAncestorsFailedF(validatorID, requestID)
	} else if e.CantGetAncestorsFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called GetAncestorsFailed")
		}
		return errors.New("Unexpectedly called GetAncestorsFailed")
	}
	return nil
}

// Put ...
func (e *EngineTest) Put(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error {
	if e.PutF != nil {
		return e.PutF(validatorID, requestID, containerID, container)
	} else if e.CantPut {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Put")
		}
		return errors.New("Unexpectedly called Put")
	}
	return nil
}

// MultiPut ...
func (e *EngineTest) MultiPut(validatorID ids.ShortID, requestID uint32, containers [][]byte) error {
	if e.MultiPutF != nil {
		return e.MultiPutF(validatorID, requestID, containers)
	} else if e.CantMultiPut {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called MultiPut")
		}
		return errors.New("Unexpectedly called MultiPut")
	}
	return nil
}

// PushQuery ...
func (e *EngineTest) PushQuery(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) error {
	if e.PushQueryF != nil {
		return e.PushQueryF(validatorID, requestID, containerID, container)
	} else if e.CantPushQuery {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called PushQuery")
		}
		return errors.New("Unexpectedly called PushQuery")
	}
	return nil
}

// PullQuery ...
func (e *EngineTest) PullQuery(validatorID ids.ShortID, requestID uint32, containerID ids.ID) error {
	if e.PullQueryF != nil {
		return e.PullQueryF(validatorID, requestID, containerID)
	} else if e.CantPullQuery {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called PullQuery")
		}
		return errors.New("Unexpectedly called PullQuery")
	}
	return nil
}

// QueryFailed ...
func (e *EngineTest) QueryFailed(validatorID ids.ShortID, requestID uint32) error {
	if e.QueryFailedF != nil {
		return e.QueryFailedF(validatorID, requestID)
	} else if e.CantQueryFailed {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called QueryFailed")
		}
		return errors.New("Unexpectedly called QueryFailed")
	}
	return nil
}

// Chits ...
func (e *EngineTest) Chits(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) error {
	if e.ChitsF != nil {
		return e.ChitsF(validatorID, requestID, containerIDs)
	} else if e.CantChits {
		if e.T != nil {
			e.T.Fatalf("Unexpectedly called Chits")
		}
		return errors.New("Unexpectedly called Chits")
	}
	return nil
}

// IsBootstrapped ...
func (e *EngineTest) IsBootstrapped() bool {
	if e.IsBootstrappedF != nil {
		return e.IsBootstrappedF()
	}
	if e.CantIsBootstrapped && e.T != nil {
		e.T.Fatalf("Unexpectedly called IsBootstrapped")
	}
	return false
}
<|endoftext|>