func (w *SnowballWord) FitsInR2(x int) bool {
	return w.R2start <= len(w.RS)-x
}

func ( w * SnowballWord ) FitsInR2 ( x int ) bool { return w . R2start <= len ( w . RS ) - x }

// Returns true if `x` runes would fit into R2.
//

Returns true if x runes would fit into R2 .


func (w *SnowballWord) FitsInRV(x int) bool {
	return w.RVstart <= len(w.RS)-x
}

func ( w * SnowballWord ) FitsInRV ( x int ) bool { return w . RVstart <= len ( w . RS ) - x }

// Returns true if `x` runes would fit into RV.
//

Returns true if x runes would fit into RV .


func (w *SnowballWord) FirstPrefix(prefixes ...string) (foundPrefix string, foundPrefixRunes []rune) {
	found := false
	rsLen := len(w.RS)

	for _, prefix := range prefixes {
		prefixRunes := []rune(prefix)
		if len(prefixRunes) > rsLen {
			continue
		}

		found = true
		for i, r := range prefixRunes {
			if i > rsLen-1 || (w.RS)[i] != r {
				found = false
				break
			}
		}
		if found {
			foundPrefix = prefix
			foundPrefixRunes = prefixRunes
			break
		}
	}
	return
}

func ( w * SnowballWord ) FirstPrefix ( prefixes ... string ) ( foundPrefix string , foundPrefixRunes [ ] rune ) { found := false rsLen := len ( w . RS ) for _ , prefix := range prefixes { prefixRunes := [ ] rune ( prefix ) if len ( prefixRunes ) > rsLen { continue } found = true for i , r := range prefixRunes { if i > rsLen - 1 || ( w . RS ) [ i ] != r { found = false break } } if found { foundPrefix = prefix foundPrefixRunes = prefixRunes break } } return }

// Return the first prefix found or the empty string.

Return the first prefix found or the empty string .


func (w *SnowballWord) HasSuffixRunes(suffixRunes []rune) bool {
	return w.HasSuffixRunesIn(0, len(w.RS), suffixRunes)
}

func ( w * SnowballWord ) HasSuffixRunes ( suffixRunes [ ] rune ) bool { return w . HasSuffixRunesIn ( 0 , len ( w . RS ) , suffixRunes ) }

// Return true if `w` ends with `suffixRunes`
//


func (w *SnowballWord) FirstSuffixIfIn(startPos, endPos int, suffixes ...string) (suffix string, suffixRunes []rune) {
	for _, suffix := range suffixes {
		suffixRunes := []rune(suffix)
		if w.HasSuffixRunesIn(0, endPos, suffixRunes) {
			if endPos-len(suffixRunes) >= startPos {
				return suffix, suffixRunes
			} else {
				// Empty out suffixRunes
				suffixRunes = suffixRunes[:0]
				return "", suffixRunes
			}
		}
	}

	// Empty out suffixRunes
	suffixRunes = suffixRunes[:0]
	return "", suffixRunes
}

func
(
w
*
SnowballWord
)
FirstSuffixIfIn
(
startPos
,
endPos
int
,
suffixes
...
string
)
(
suffix
string
,
suffixRunes
[
]
rune
)
{
for
_
,
suffix
:=
range
suffixes
{
suffixRunes
:=
[
]
rune
(
suffix
)
if
w
.
HasSuffixRunesIn
(
0
,
endPos
,
suffixRunes
)
{
if
endPos
len
(
suffixRunes
)
>=
startPos
{
return
suffix
,
suffixRunes
}
else
{
// Empty out suffixRunes
suffixRunes
=
suffixRunes
[
:
0
]
return
"
"
,
suffixRunes
}
}
}
// Empty out suffixRunes
suffixRunes
=
suffixRunes
[
:
0
]
return
"
"
,
suffixRunes
}

// Find the first suffix that ends at `endPos` in the word among
// those provided; then,
// check to see if it begins after startPos.  If it does, return
// it, else return the empty string and empty rune slice.  This
// may seem a counterintuitive manner to do this.  However, it
// matches what is required most of the time by the Snowball
// stemmer steps.
//

Find the first suffix that ends at endPos in the word among those provided ; then check to see if it begins after startPos . If it does return it else return the empty string and empty rune slice . This may seem a counterintuitive manner to do this . However it matches what is required most of the time by the Snowball stemmer steps .


func (w *SnowballWord) RemoveFirstSuffixIfIn(startPos int, suffixes ...string) (suffix string, suffixRunes []rune) {
	suffix, suffixRunes = w.FirstSuffixIfIn(startPos, len(w.RS), suffixes...)
	if suffix != "" {
		w.RemoveLastNRunes(len(suffixRunes))
	}
	return
}

func ( w * SnowballWord ) RemoveFirstSuffixIfIn ( startPos int , suffixes ... string ) ( suffix string , suffixRunes [ ] rune ) { suffix , suffixRunes = w . FirstSuffixIfIn ( startPos , len ( w . RS ) , suffixes ... ) if suffix != " " { w . RemoveLastNRunes ( len ( suffixRunes ) ) } return }

// Find the first suffix in the word among those provided; then,
// check to see if it begins after startPos.  If it does,
// remove it.
//

Find the first suffix in the word among those provided ; then check to see if it begins after startPos . If it does remove it .


func (w *SnowballWord) RemoveFirstSuffix(suffixes ...string) (suffix string, suffixRunes []rune) {
	return w.RemoveFirstSuffixIn(0, suffixes...)
}

func ( w * SnowballWord ) RemoveFirstSuffix ( suffixes ... string ) ( suffix string , suffixRunes [ ] rune ) { return w . RemoveFirstSuffixIn ( 0 , suffixes ... ) }


func (w *SnowballWord) FirstSuffix(suffixes ...string) (suffix string, suffixRunes []rune) {
	return w.FirstSuffixIfIn(0, len(w.RS), suffixes...)
}

func ( w * SnowballWord ) FirstSuffix ( suffixes ... string ) ( suffix string , suffixRunes [ ] rune ) { return w . FirstSuffixIfIn ( 0 , len ( w . RS ) , suffixes ... ) }

// Return the first suffix found or the empty string.

Return the first suffix found or the empty string .


func preprocess(word *snowballword.SnowballWord) {

	// Clean up apostrophes
	normalizeApostrophes(word)
	trimLeftApostrophes(word)

	// Capitalize Y's that are not behaving
	// as vowels.
	capitalizeYs(word)

	// Find the two regions, R1 & R2
	r1start, r2start := r1r2(word)
	word.R1start = r1start
	word.R2start = r2start
}

func
preprocess
(
word
*
snowballword
.
SnowballWord
)
{
// Clean up apostrophes
normalizeApostrophes
(
word
)
trimLeftApostrophes
(
word
)
// Capitalize Y's that are not behaving
// as vowels.
capitalizeYs
(
word
)
// Find the two regions, R1 & R2
r1start
,
r2start
:=
r1r2
(
word
)
word
.
R1start
=
r1start
word
.
R2start
=
r2start
}

// Applies various transformations necessary for the
// other, subsequent stemming steps.  Most important
// of which is defining the two regions R1 & R2.
//

Applies various transformations necessary for the other subsequent stemming steps . Most important of which is defining the two regions R1 & R2 .


func step0(word *snowballword.SnowballWord) bool {

	// Search for the longest among the following suffixes
	suffix1, suffix1Runes := word.FirstSuffixIn(word.RVstart, len(word.RS),
		"selas", "selos", "sela", "selo", "las", "les",
		"los", "nos", "me", "se", "la", "le", "lo",
	)

	// If the suffix empty or not in RV, we have nothing to do.
	if suffix1 == "" {
		return false
	}

	// We'll remove suffix1, if comes after one of the following
	suffix2, suffix2Runes := word.FirstSuffixIn(word.RVstart, len(word.RS)-len(suffix1),
		"iéndo", "iendo", "yendo", "ando", "ándo",
		"ár", "ér", "ír", "ar", "er", "ir",
	)
	switch suffix2 {
	case "":

		// Nothing to do
		return false

	case "iéndo", "ándo", "ár", "ér", "ír":

		// In these cases, deletion is followed by removing
		// the acute accent (e.g., haciéndola -> haciendo).

		var suffix2repl string
		switch suffix2 {
		case "":
			return false
		case "iéndo":
			suffix2repl = "iendo"
		case "ándo":
			suffix2repl = "ando"
		case "ár":
			suffix2repl = "ar"
		case "ír":
			suffix2repl = "ir"
		}
		word.RemoveLastNRunes(len(suffix1Runes))
		word.ReplaceSuffixRunes(suffix2Runes, []rune(suffix2repl), true)
		return true

	case "ando", "iendo", "ar", "er", "ir":
		word.RemoveLastNRunes(len(suffix1Runes))
		return true

	case "yendo":

		// In the case of "yendo", the "yendo" must lie in RV,
		// and be preceded by a "u" somewhere in the word.

		for i := 0; i < len(word.RS)-(len(suffix1)+len(suffix2)); i++ {

			// Note, the unicode code point for "u" is 117.
			if word.RS[i] == 117 {
				word.RemoveLastNRunes(len(suffix1Runes))
				return true
			}
		}
	}
	return false
}

// Step 0 is the removal of attached pronouns
//


func step1b(w *snowballword.SnowballWord) bool {

	suffix, suffixRunes := w.FirstSuffix("eedly", "ingly", "edly", "ing", "eed", "ed")

	switch suffix {

	case "":
		// No suffix found
		return false

	case "eed", "eedly":

		// Replace by ee if in R1
		if len(suffixRunes) <= len(w.RS)-w.R1start {
			w.ReplaceSuffixRunes(suffixRunes, []rune("ee"), true)
		}
		return true

	case "ed", "edly", "ing", "ingly":
		hasLowerVowel := false
		for i := 0; i < len(w.RS)-len(suffixRunes); i++ {
			if isLowerVowel(w.RS[i]) {
				hasLowerVowel = true
				break
			}
		}
		if hasLowerVowel {

			// This case requires a two-step transformation and, due
			// to the way we've implemented the `ReplaceSuffix` method
			// here, information about R1 and R2 would be lost between
			// the two.  Therefore, we need to keep track of the
			// original R1 & R2, so that we may set them below, at the
			// end of this case.
			//
			originalR1start := w.R1start
			originalR2start := w.R2start

			// Delete if the preceding word part contains a vowel
			w.RemoveLastNRunes(len(suffixRunes))

			// ...and after the deletion...

			newSuffix, newSuffixRunes := w.FirstSuffix("at", "bl", "iz", "bb", "dd", "ff", "gg", "mm", "nn", "pp", "rr", "tt")
			switch newSuffix {

			case "":

				// If the word is short, add "e"
				if isShortWord(w) {

					// By definition, r1 and r2 are the empty string for
					// short words.
					w.RS = append(w.RS, []rune("e")...)
					w.R1start = len(w.RS)
					w.R2start = len(w.RS)
					return true
				}

			case "at", "bl", "iz":

				// If the word ends "at", "bl" or "iz" add "e"
				w.ReplaceSuffixRunes(newSuffixRunes, []rune(newSuffix+"e"), true)

			case "bb", "dd", "ff", "gg", "mm", "nn", "pp", "rr", "tt":

				// If the word ends with a double remove the last letter.
				// Note that, "double" does not include all possible doubles,
				// just those shown above.
				//
				w.RemoveLastNRunes(1)
			}

			// Because we did a double replacement, we need to fix
			// R1 and R2 manually. This is just becase of how we've
			// implemented the `ReplaceSuffix` method.
			//
			rsLen := len(w.RS)
			if originalR1start < rsLen {
				w.R1start = originalR1start
			} else {
				w.R1start = rsLen
			}
			if originalR2start < rsLen {
				w.R2start = originalR2start
			} else {
				w.R2start = rsLen
			}

			return true
		}

	}

	return false
}

// Step 1b is the normalization of various "ly" and "ed" sufficies.
//

Step 1b is the normalization of various ly and ed sufficies .


func step2b(word *snowballword.SnowballWord) bool {

	// Search for the longest among the following suffixes in RV.
	//
	suffix, suffixRunes := word.FirstSuffixIn(word.RVstart, len(word.RS),
		"eraIent", "assions", "erions", "assiez", "assent",
		"èrent", "eront", "erons", "eriez", "erait", "erais",
		"asses", "antes", "aIent", "âtes", "âmes", "ions",
		"erez", "eras", "erai", "asse", "ants", "ante", "ées",
		"iez", "era", "ant", "ait", "ais", "és", "ée", "ât",
		"ez", "er", "as", "ai", "é", "a",
	)

	switch suffix {
	case "ions":

		// Delete if in R2
		suffixLen := len(suffixRunes)
		if word.FitsInR2(suffixLen) {
			word.RemoveLastNRunes(suffixLen)
			return true
		}
		return false

	case "é", "ée", "ées", "és", "èrent", "er", "era",
		"erai", "eraIent", "erais", "erait", "eras", "erez",
		"eriez", "erions", "erons", "eront", "ez", "iez":

		// Delete
		word.RemoveLastNRunes(len(suffixRunes))
		return true

	case "âmes", "ât", "âtes", "a", "ai", "aIent",
		"ais", "ait", "ant", "ante", "antes", "ants", "as",
		"asse", "assent", "asses", "assiez", "assions":

		// Delete
		word.RemoveLastNRunes(len(suffixRunes))

		// If preceded by e (unicode code point 101), delete
		//
		idx := len(word.RS) - 1
		if idx >= 0 && word.RS[idx] == 101 && word.FitsInRV(1) {
			word.RemoveLastNRunes(1)
		}
		return true

	}
	return false
}

// Step 2b is the removal of Verb suffixes in RV
// that do not begin with "i".
//

Step 2b is the removal of Verb suffixes in RV that do not begin with i .


func capitalizeYs(word *snowballword.SnowballWord) (numCapitalizations int) {
	for i, r := range word.RS {

		// (Note: Y & y unicode code points = 89 & 121)

		if r == 121 && (i == 0 || isLowerVowel(word.RS[i-1])) {
			word.RS[i] = 89
			numCapitalizations += 1
		}
	}
	return
}

// Capitalize all 'Y's preceded by vowels or starting a word
//

Capitalize all Y s preceded by vowels or starting a word


func uncapitalizeYs(word *snowballword.SnowballWord) {
	for i, r := range word.RS {

		// (Note: Y & y unicode code points = 89 & 121)

		if r == 89 {
			word.RS[i] = 121
		}
	}
	return
}


func stemSpecialWord(word string) (stemmed string) {
	switch word {
	case "skis":
		stemmed = "ski"
	case "skies":
		stemmed = "sky"
	case "dying":
		stemmed = "die"
	case "lying":
		stemmed = "lie"
	case "tying":
		stemmed = "tie"
	case "idly":
		stemmed = "idl"
	case "gently":
		stemmed = "gentl"
	case "ugly":
		stemmed = "ugli"
	case "early":
		stemmed = "earli"
	case "only":
		stemmed = "onli"
	case "singly":
		stemmed = "singl"
	case "sky":
		stemmed = "sky"
	case "news":
		stemmed = "news"
	case "howe":
		stemmed = "howe"
	case "atlas":
		stemmed = "atlas"
	case "cosmos":
		stemmed = "cosmos"
	case "bias":
		stemmed = "bias"
	case "andes":
		stemmed = "andes"
	case "inning":
		stemmed = "inning"
	case "innings":
		stemmed = "inning"
	case "outing":
		stemmed = "outing"
	case "outings":
		stemmed = "outing"
	case "canning":
		stemmed = "canning"
	case "cannings":
		stemmed = "canning"
	case "herring":
		stemmed = "herring"
	case "herrings":
		stemmed = "herring"
	case "earring":
		stemmed = "earring"
	case "earrings":
		stemmed = "earring"
	case "proceed":
		stemmed = "proceed"
	case "proceeds":
		stemmed = "proceed"
	case "proceeded":
		stemmed = "proceed"
	case "proceeding":
		stemmed = "proceed"
	case "exceed":
		stemmed = "exceed"
	case "exceeds":
		stemmed = "exceed"
	case "exceeded":
		stemmed = "exceed"
	case "exceeding":
		stemmed = "exceed"
	case "succeed":
		stemmed = "succeed"
	case "succeeds":
		stemmed = "succeed"
	case "succeeded":
		stemmed = "succeed"
	case "succeeding":
		stemmed = "succeed"
	}
	return
}

func stemSpecialWord ( word string ) ( stemmed string ) { switch word { case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " case " " : stemmed = " " } return }

// Returns the stemmed version of a word if it is a special
// case, otherwise returns the empty string.
//

Returns the stemmed version of a word if it is a special case otherwise returns the empty string .


func isShortWord(w *snowballword.SnowballWord) (isShort bool) {

	// If r1 is not empty, the word is not short
	if w.R1start < len(w.RS) {
		return
	}

	// Otherwise it must end in a short syllable
	return endsShortSyllable(w, len(w.RS))
}

// A word is called short if it ends in a short syllable, and if R1 is null.
//

A word is called short if it ends in a short syllable and if R1 is null .


func step1a(w *snowballword.SnowballWord) bool {

	suffix, suffixRunes := w.FirstSuffix("sses", "ied", "ies", "us", "ss", "s")
	switch suffix {

	case "sses":

		// Replace by ss
		w.ReplaceSuffixRunes(suffixRunes, []rune("ss"), true)
		return true

	case "ies", "ied":

		// Replace by i if preceded by more than one letter,
		// otherwise by ie (so ties -> tie, cries -> cri).

		var repl string
		if len(w.RS) > 4 {
			repl = "i"
		} else {
			repl = "ie"
		}
		w.ReplaceSuffixRunes(suffixRunes, []rune(repl), true)
		return true

	case "us", "ss":

		// Do nothing
		return false

	case "s":

		// Delete if the preceding word part contains a vowel
		// not immediately before the s (so gas and this retain
		// the s, gaps and kiwis lose it)
		//
		for i := 0; i < len(w.RS)-2; i++ {
			if isLowerVowel(w.RS[i]) {
				w.RemoveLastNRunes(len(suffixRunes))
				return true
			}
		}
	}
	return false
}

// Step 1a is normalization of various special "s"-endings.
//

Step 1a is normalization of various special s - endings .


func Set(key string, value interface{}) {
	gid := curGoroutineID()
	dataLock.Lock()
	if data[gid] == nil {
		data[gid] = Values{}
	}
	data[gid][key] = value
	dataLock.Unlock()
}

func Set ( key string , value interface { } ) { gid := curGoroutineID ( ) dataLock . Lock ( ) if data [ gid ] == nil { data [ gid ] = Values { } } data [ gid ] [ key ] = value dataLock . Unlock ( ) }

// Set sets the value by key and associates it with the current goroutine.

Set sets the value by key and associates it with the current goroutine .


func Get(key string) interface{} {
	gid := curGoroutineID()
	dataLock.RLock()
	if data[gid] == nil {
		dataLock.RUnlock()
		return nil
	}
	value := data[gid][key]
	dataLock.RUnlock()
	return value
}

func Get ( key string ) interface { } { gid := curGoroutineID ( ) dataLock . RLock ( ) if data [ gid ] == nil { dataLock . RUnlock ( ) return nil } value := data [ gid ] [ key ] dataLock . RUnlock ( ) return value }

// Get gets the value by key as it exists for the current goroutine.

Get gets the value by key as it exists for the current goroutine .


func Cleanup() {
	gid := curGoroutineID()
	dataLock.Lock()
	delete(data, gid)
	dataLock.Unlock()
}

func Cleanup ( ) { gid := curGoroutineID ( ) dataLock . Lock ( ) delete ( data , gid ) dataLock . Unlock ( ) }

// Cleanup removes all data associated with this goroutine. If this is not
// called, the data may persist for the lifetime of your application. This
// must be called from the very first goroutine to invoke Set

Cleanup removes all data associated with this goroutine . If this is not called the data may persist for the lifetime of your application . This must be called from the very first goroutine to invoke Set


func getValues() Values {
	gid := curGoroutineID()
	dataLock.Lock()
	values := data[gid]
	dataLock.Unlock()
	return values
}

func getValues ( ) Values { gid := curGoroutineID ( ) dataLock . Lock ( ) values := data [ gid ] dataLock . Unlock ( ) return values }


func linkGRs(parentData Values) {
	childID := curGoroutineID()
	dataLock.Lock()
	data[childID] = parentData
	dataLock.Unlock()
}

func linkGRs ( parentData Values ) { childID := curGoroutineID ( ) dataLock . Lock ( ) data [ childID ] = parentData dataLock . Unlock ( ) }

// linkGRs links two goroutines together, allowing the child to access the
// data present in the parent.

linkGRs links two goroutines together allowing the child to access the data present in the parent .


func unlinkGRs() {
	childID := curGoroutineID()
	dataLock.Lock()
	delete(data, childID)
	dataLock.Unlock()
}

func unlinkGRs ( ) { childID := curGoroutineID ( ) dataLock . Lock ( ) delete ( data , childID ) dataLock . Unlock ( ) }


func AppUri(appName, path string, config helpersinternal.CurlConfig) string {
	uriCreator := &helpersinternal.AppUriCreator{CurlConfig: config}

	return uriCreator.AppUri(appName, path)
}

func AppUri ( appName , path string , config helpersinternal . CurlConfig ) string { uriCreator := & helpersinternal . AppUriCreator { CurlConfig : config } return uriCreator . AppUri ( appName , path ) }

// Gets an app's endpoint with the specified path

Gets an app s endpoint with the specified path


func CurlAppWithTimeout(cfg helpersinternal.CurlConfig, appName, path string, timeout time.Duration, args ...string) string {
	appCurler := helpersinternal.NewAppCurler(Curl, cfg)
	return appCurler.CurlAndWait(cfg, appName, path, timeout, args...)
}

func CurlAppWithTimeout ( cfg helpersinternal . CurlConfig , appName , path string , timeout time . Duration , args ... string ) string { appCurler := helpersinternal . NewAppCurler ( Curl , cfg ) return appCurler . CurlAndWait ( cfg , appName , path , timeout , args ... ) }

// Curls an app's endpoint and exit successfully before the specified timeout

Curls an app s endpoint and exit successfully before the specified timeout


func CurlApp(cfg helpersinternal.CurlConfig, appName, path string, args ...string) string {
	appCurler := helpersinternal.NewAppCurler(Curl, cfg)
	return appCurler.CurlAndWait(cfg, appName, path, CURL_TIMEOUT, args...)
}

func CurlApp ( cfg helpersinternal . CurlConfig , appName , path string , args ... string ) string { appCurler := helpersinternal . NewAppCurler ( Curl , cfg ) return appCurler . CurlAndWait ( cfg , appName , path , CURL_TIMEOUT , args ... ) }

// Curls an app's endpoint and exit successfully before the default timeout

Curls an app s endpoint and exit successfully before the default timeout


func CurlAppRoot(cfg helpersinternal.CurlConfig, appName string) string {
	appCurler := helpersinternal.NewAppCurler(Curl, cfg)
	return appCurler.CurlAndWait(cfg, appName, "/", CURL_TIMEOUT)
}

func CurlAppRoot ( cfg helpersinternal . CurlConfig , appName string ) string { appCurler := helpersinternal . NewAppCurler ( Curl , cfg ) return appCurler . CurlAndWait ( cfg , appName , " " , CURL_TIMEOUT ) }

// Curls an app's root endpoint and exit successfully before the default timeout

Curls an app s root endpoint and exit successfully before the default timeout


func GetTags(prefix rune, str string, terminator ...rune) (tags []Tag) {
	// If we have no terminators given, default to only whitespace
	if len(terminator) == 0 {
		terminator = []rune(" ")
	}
	// get list of indexes in our str that is a terminator
	// Always include the beginning of our str a terminator. This is so we can
	// detect the first character as a prefix
	termIndexes := []int{-1}
	for i, char := range str {
		if isTerminator(char, terminator...) {
			termIndexes = append(termIndexes, i)
		}
	}
	// Always include last character as a terminator
	termIndexes = append(termIndexes, len(str))

	// check if the character AFTER our term index is our prefix
	for i, t := range termIndexes {
		// ensure term index is not the last character in str
		if t >= (len(str) - 1) {
			break
		}
		if str[t+1] == byte(prefix) {
			tagText := strings.TrimLeft(str[t+2:termIndexes[i+1]], string(prefix))
			if tagText == "" {
				continue
			}
			index := t + 1
			tags = append(tags, Tag{prefix, tagText, index})
		}
	}

	return
}

// GetTags returns a slice of Tags, that is all characters after rune char up
// to occurrence of space or another occurrence of rune char. Additionally you
// can provide a coma separated unicode characters to be used as terminating
// sequence.

GetTags returns a slice of Tags that is all characters after rune char up to occurrence of space or another occurrence of rune char . Additionally you can provide a coma separated unicode characters to be used as terminating sequence .


func GetTagsAsUniqueStrings(prefix rune, str string, terminator ...rune) (strs []string) {
	tags := GetTags(prefix, str, terminator...)
	for _, tag := range tags {
		strs = append(strs, tag.Tag)
	}
	return uniquify(strs)
}

func GetTagsAsUniqueStrings ( prefix rune , str string , terminator ... rune ) ( strs [ ] string ) { tags := GetTags ( prefix , str , terminator ... ) for _ , tag := range tags { strs = append ( strs , tag . Tag ) } return uniquify ( strs ) }

// GetTagsAsUniqueStrings gets all tags as a slice of unique strings. This is
// here to have a means of being somewhat backwards compatible with previous
// versions of mention

GetTagsAsUniqueStrings gets all tags as a slice of unique strings . This is here to have a means of being somewhat backwards compatible with previous versions of mention


func isTerminator(r rune, terminator ...rune) bool {
	for _, t := range terminator {
		if r == t {
			return true
		}
	}
	return unicode.IsSpace(r) || !unicode.IsPrint(r)
}

func isTerminator ( r rune , terminator ... rune ) bool { for _ , t := range terminator { if r == t { return true } } return unicode . IsSpace ( r ) || ! unicode . IsPrint ( r ) }


func uniquify(in []string) (out []string) {
	for _, i := range in {
		if i == "" {
			continue
		}
		for _, o := range out {
			if i == o {
				continue
			}
		}
		out = append(out, i)
	}
	return
}

func uniquify ( in [ ] string ) ( out [ ] string ) { for _ , i := range in { if i == " " { continue } for _ , o := range out { if i == o { continue } } out = append ( out , i ) } return }

// Ensures the given slice of strings are unique and that none are empty
// strings

Ensures the given slice of strings are unique and that none are empty strings


func New(config Config) gin.HandlerFunc {
	location := newLocation(config)

	return func(c *gin.Context) {
		location.applyToContext(c)
	}
}

func New ( config Config ) gin . HandlerFunc { location := newLocation ( config ) return func ( c * gin . Context ) { location . applyToContext ( c ) } }

// New returns the location middleware with user-defined custom configuration.

New returns the location middleware with user - defined custom configuration .


func Get(c *gin.Context) *url.URL {
	v, ok := c.Get(key)

	if !ok {
		return nil
	}

	vv, ok := v.(*url.URL)

	if !ok {
		return nil
	}

	return vv
}

func Get ( c * gin . Context ) * url . URL { v , ok := c . Get ( key ) if ! ok { return nil } vv , ok := v . ( * url . URL ) if ! ok { return nil } return vv }

// Get returns the Location information for the incoming http.Request from the
// context. If the location is not set a nil value is returned.

Get returns the Location information for the incoming http . Request from the context . If the location is not set a nil value is returned .


func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) {
	if bits < 512 {
		return nil, nil, ErrRsaKeyTooSmall
	}
	priv, err := rsa.GenerateKey(src, bits)
	if err != nil {
		return nil, nil, err
	}
	pk := &priv.PublicKey
	return &RsaPrivateKey{sk: priv}, &RsaPublicKey{pk}, nil
}

func GenerateRSAKeyPair ( bits int , src io . Reader ) ( PrivKey , PubKey , error ) { if bits < 512 { return nil , nil , ErrRsaKeyTooSmall } priv , err := rsa . GenerateKey ( src , bits ) if err != nil { return nil , nil , err } pk := & priv . PublicKey return & RsaPrivateKey { sk : priv } , & RsaPublicKey { pk } , nil }

// GenerateRSAKeyPair generates a new rsa private and public key


func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) {
	hashed := sha256.Sum256(data)
	err := rsa.VerifyPKCS1v15(pk.k, crypto.SHA256, hashed[:], sig)
	if err != nil {
		return false, err
	}
	return true, nil
}

func ( pk * RsaPublicKey ) Verify ( data , sig [ ] byte ) ( bool , error ) { hashed := sha256 . Sum256 ( data ) err := rsa . VerifyPKCS1v15 ( pk . k , crypto . SHA256 , hashed [ : ] , sig ) if err != nil { return false , err } return true , nil }

// Verify compares a signature against input data


func (pk *RsaPublicKey) Encrypt(b []byte) ([]byte, error) {
	return rsa.EncryptPKCS1v15(rand.Reader, pk.k, b)
}

func ( pk * RsaPublicKey ) Encrypt ( b [ ] byte ) ( [ ] byte , error ) { return rsa . EncryptPKCS1v15 ( rand . Reader , pk . k , b ) }

// Encrypt returns encrypted bytes from the inpu data


func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) {
	hashed := sha256.Sum256(message)
	return rsa.SignPKCS1v15(rand.Reader, sk.sk, crypto.SHA256, hashed[:])
}

func ( sk * RsaPrivateKey ) Sign ( message [ ] byte ) ( [ ] byte , error ) { hashed := sha256 . Sum256 ( message ) return rsa . SignPKCS1v15 ( rand . Reader , sk . sk , crypto . SHA256 , hashed [ : ] ) }

// Sign returns a signature of the input data


func (sk *RsaPrivateKey) GetPublic() PubKey {
	if sk.pk == nil {
		sk.pk = &sk.sk.PublicKey
	}
	return &RsaPublicKey{sk.pk}
}

func ( sk * RsaPrivateKey ) GetPublic ( ) PubKey { if sk . pk == nil { sk . pk = & sk . sk . PublicKey } return & RsaPublicKey { sk . pk } }


func (sk *RsaPrivateKey) Decrypt(b []byte) ([]byte, error) {
	return rsa.DecryptPKCS1v15(rand.Reader, sk.sk, b)
}

func ( sk * RsaPrivateKey ) Decrypt ( b [ ] byte ) ( [ ] byte , error ) { return rsa . DecryptPKCS1v15 ( rand . Reader , sk . sk , b ) }

// Decrypt returns decrypted bytes of the input encrypted bytes


func UnmarshalRsaPrivateKey(b []byte) (PrivKey, error) {
	sk, err := x509.ParsePKCS1PrivateKey(b)
	if err != nil {
		return nil, err
	}
	if sk.N.BitLen() < 512 {
		return nil, ErrRsaKeyTooSmall
	}
	return &RsaPrivateKey{sk: sk}, nil
}

func UnmarshalRsaPrivateKey ( b [ ] byte ) ( PrivKey , error ) { sk , err := x509 . ParsePKCS1PrivateKey ( b ) if err != nil { return nil , err } if sk . N . BitLen ( ) < 512 { return nil , ErrRsaKeyTooSmall } return & RsaPrivateKey { sk : sk } , nil }

// UnmarshalRsaPrivateKey returns a private key from the input x509 bytes


func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
	return GenerateKeyPairWithReader(typ, bits, rand.Reader)
}

func GenerateKeyPair ( typ , bits int ) ( PrivKey , PubKey , error ) { return GenerateKeyPairWithReader ( typ , bits , rand . Reader ) }

// GenerateKeyPair generates a private and public key


func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) {
	switch typ {
	case RSA:
		return GenerateRSAKeyPair(bits, src)
	case Ed25519:
		return GenerateEd25519Key(src)
	case Secp256k1:
		return GenerateSecp256k1Key(src)
	case ECDSA:
		return GenerateECDSAKeyPair(src)
	default:
		return nil, nil, ErrBadKeyType
	}
}

func GenerateKeyPairWithReader ( typ , bits int , src io . Reader ) ( PrivKey , PubKey , error ) { switch typ { case RSA : return GenerateRSAKeyPair ( bits , src ) case Ed25519 : return GenerateEd25519Key ( src ) case Secp256k1 : return GenerateSecp256k1Key ( src ) case ECDSA : return GenerateECDSAKeyPair ( src ) default : return nil , nil , ErrBadKeyType } }

// GenerateKeyPairWithReader returns a keypair of the given type and bitsize


func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) {
	var curve elliptic.Curve

	switch curveName {
	case "P-256":
		curve = elliptic.P256()
	case "P-384":
		curve = elliptic.P384()
	case "P-521":
		curve = elliptic.P521()
	}

	priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
	if err != nil {
		return nil, nil, err
	}

	pubKey := elliptic.Marshal(curve, x, y)

	done := func(theirPub []byte) ([]byte, error) {
		// Verify and unpack node's public key.
		x, y := elliptic.Unmarshal(curve, theirPub)
		if x == nil {
			return nil, fmt.Errorf("malformed public key: %d %v", len(theirPub), theirPub)
		}

		if !curve.IsOnCurve(x, y) {
			return nil, errors.New("invalid public key")
		}

		// Generate shared secret.
		secret, _ := curve.ScalarMult(x, y, priv)

		return secret.Bytes(), nil
	}

	return pubKey, done, nil
}

func
GenerateEKeyPair
(
curveName
string
)
(
[
]
byte
,
GenSharedKey
,
error
)
{
var
curve
elliptic
.
Curve
switch
curveName
{
case
"
"
:
curve
=
elliptic
.
P256
(
)
case
"
"
:
curve
=
elliptic
.
P384
(
)
case
"
"
:
curve
=
elliptic
.
P521
(
)
}
priv
,
x
,
y
,
err
:=
elliptic
.
GenerateKey
(
curve
,
rand
.
Reader
)
if
err
!=
{
return
,
,
err
}
pubKey
:=
elliptic
.
Marshal
(
curve
,
x
,
y
)
done
:=
func
(
theirPub
[
]
byte
)
(
[
]
byte
,
error
)
{
// Verify and unpack node's public key.
x
,
y
:=
elliptic
.
Unmarshal
(
curve
,
theirPub
)
if
x
==
{
return
,
fmt
.
Errorf
(
"
"
,
len
(
theirPub
)
,
theirPub
)
}
if
!
curve
.
IsOnCurve
(
x
,
y
)
{
return
,
errors
.
New
(
"
"
)
}
// Generate shared secret.
secret
,
_
:=
curve
.
ScalarMult
(
x
,
y
,
priv
)
return
secret
.
Bytes
(
)
,
}
return
pubKey
,
done
,
}

// GenerateEKeyPair returns an ephemeral public key and returns a function that will compute
// the shared secret key.  Used in the identify module.
//
// Focuses only on ECDH now, but can be made more general in the future.

GenerateEKeyPair returns an ephemeral public key and returns a function that will compute the shared secret key . Used in the identify module . Focuses only on ECDH now but can be made more general in the future .


func UnmarshalPublicKey(data []byte) (PubKey, error) {
	pmes := new(pb.PublicKey)
	err := proto.Unmarshal(data, pmes)
	if err != nil {
		return nil, err
	}

	um, ok := PubKeyUnmarshallers[pmes.GetType()]
	if !ok {
		return nil, ErrBadKeyType
	}

	return um(pmes.GetData())
}

func UnmarshalPublicKey ( data [ ] byte ) ( PubKey , error ) { pmes := new ( pb . PublicKey ) err := proto . Unmarshal ( data , pmes ) if err != nil { return nil , err } um , ok := PubKeyUnmarshallers [ pmes . GetType ( ) ] if ! ok { return nil , ErrBadKeyType } return um ( pmes . GetData ( ) ) }

// UnmarshalPublicKey converts a protobuf serialized public key into its
// representative object

UnmarshalPublicKey converts a protobuf serialized public key into its representative object


func MarshalPublicKey(k PubKey) ([]byte, error) {
	pbmes := new(pb.PublicKey)
	pbmes.Type = k.Type()
	data, err := k.Raw()
	if err != nil {
		return nil, err
	}
	pbmes.Data = data

	return proto.Marshal(pbmes)
}

func MarshalPublicKey ( k PubKey ) ( [ ] byte , error ) { pbmes := new ( pb . PublicKey ) pbmes . Type = k . Type ( ) data , err := k . Raw ( ) if err != nil { return nil , err } pbmes . Data = data return proto . Marshal ( pbmes ) }

// MarshalPublicKey converts a public key object into a protobuf serialized
// public key

MarshalPublicKey converts a public key object into a protobuf serialized public key


func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
	pmes := new(pb.PrivateKey)
	err := proto.Unmarshal(data, pmes)
	if err != nil {
		return nil, err
	}

	um, ok := PrivKeyUnmarshallers[pmes.GetType()]
	if !ok {
		return nil, ErrBadKeyType
	}

	return um(pmes.GetData())
}

func UnmarshalPrivateKey ( data [ ] byte ) ( PrivKey , error ) { pmes := new ( pb . PrivateKey ) err := proto . Unmarshal ( data , pmes ) if err != nil { return nil , err } um , ok := PrivKeyUnmarshallers [ pmes . GetType ( ) ] if ! ok { return nil , ErrBadKeyType } return um ( pmes . GetData ( ) ) }

// UnmarshalPrivateKey converts a protobuf serialized private key into its
// representative object

UnmarshalPrivateKey converts a protobuf serialized private key into its representative object


func MarshalPrivateKey(k PrivKey) ([]byte, error) {
	pbmes := new(pb.PrivateKey)
	pbmes.Type = k.Type()
	data, err := k.Raw()
	if err != nil {
		return nil, err
	}

	pbmes.Data = data
	return proto.Marshal(pbmes)
}

func MarshalPrivateKey ( k PrivKey ) ( [ ] byte , error ) { pbmes := new ( pb . PrivateKey ) pbmes . Type = k . Type ( ) data , err := k . Raw ( ) if err != nil { return nil , err } pbmes . Data = data return proto . Marshal ( pbmes ) }

// MarshalPrivateKey converts a key object into its protobuf serialized form.

MarshalPrivateKey converts a key object into its protobuf serialized form .


func KeyEqual(k1, k2 Key) bool {
	if k1 == k2 {
		return true
	}

	b1, err1 := k1.Bytes()
	b2, err2 := k2.Bytes()
	return bytes.Equal(b1, b2) && err1 == err2
}

func KeyEqual ( k1 , k2 Key ) bool { if k1 == k2 { return true } b1 , err1 := k1 . Bytes ( ) b2 , err2 := k2 . Bytes ( ) return bytes . Equal ( b1 , b2 ) && err1 == err2 }


func GenerateECDSAKeyPair(src io.Reader) (PrivKey, PubKey, error) {
	return GenerateECDSAKeyPairWithCurve(ECDSACurve, src)
}

func GenerateECDSAKeyPair ( src io . Reader ) ( PrivKey , PubKey , error ) { return GenerateECDSAKeyPairWithCurve ( ECDSACurve , src ) }

// GenerateECDSAKeyPair generates a new ecdsa private and public key


func GenerateECDSAKeyPairWithCurve(curve elliptic.Curve, src io.Reader) (PrivKey, PubKey, error) {
	priv, err := ecdsa.GenerateKey(curve, src)
	if err != nil {
		return nil, nil, err
	}

	return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
}

func GenerateECDSAKeyPairWithCurve ( curve elliptic . Curve , src io . Reader ) ( PrivKey , PubKey , error ) { priv , err := ecdsa . GenerateKey ( curve , src ) if err != nil { return nil , nil , err } return & ECDSAPrivateKey { priv } , & ECDSAPublicKey { & priv . PublicKey } , nil }

// GenerateECDSAKeyPairWithCurve generates a new ecdsa private and public key with a speicified curve


func ECDSAKeyPairFromKey(priv *ecdsa.PrivateKey) (PrivKey, PubKey, error) {
	if priv == nil {
		return nil, nil, ErrNilPrivateKey
	}

	return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
}

func ECDSAKeyPairFromKey ( priv * ecdsa . PrivateKey ) ( PrivKey , PubKey , error ) { if priv == nil { return nil , nil , ErrNilPrivateKey } return & ECDSAPrivateKey { priv } , & ECDSAPublicKey { & priv . PublicKey } , nil }

// ECDSAKeyPairFromKey generates a new ecdsa private and public key from an input private key


func UnmarshalECDSAPrivateKey(data []byte) (PrivKey, error) {
	priv, err := x509.ParseECPrivateKey(data)
	if err != nil {
		return nil, err
	}

	return &ECDSAPrivateKey{priv}, nil
}

func UnmarshalECDSAPrivateKey ( data [ ] byte ) ( PrivKey , error ) { priv , err := x509 . ParseECPrivateKey ( data ) if err != nil { return nil , err } return & ECDSAPrivateKey { priv } , nil }

// UnmarshalECDSAPrivateKey returns a private key from x509 bytes


func UnmarshalECDSAPublicKey(data []byte) (PubKey, error) {
	pubIfc, err := x509.ParsePKIXPublicKey(data)
	if err != nil {
		return nil, err
	}

	pub, ok := pubIfc.(*ecdsa.PublicKey)
	if !ok {
		return nil, ErrNotECDSAPubKey
	}

	return &ECDSAPublicKey{pub}, nil
}

func UnmarshalECDSAPublicKey ( data [ ] byte ) ( PubKey , error ) { pubIfc , err := x509 . ParsePKIXPublicKey ( data ) if err != nil { return nil , err } pub , ok := pubIfc . ( * ecdsa . PublicKey ) if ! ok { return nil , ErrNotECDSAPubKey } return & ECDSAPublicKey { pub } , nil }

// UnmarshalECDSAPublicKey returns the public key from x509 bytes


func (ePriv *ECDSAPrivateKey) Equals(o Key) bool {
	oPriv, ok := o.(*ECDSAPrivateKey)
	if !ok {
		return false
	}

	return ePriv.priv.D.Cmp(oPriv.priv.D) == 0
}

func ( ePriv * ECDSAPrivateKey ) Equals ( o Key ) bool { oPriv , ok := o . ( * ECDSAPrivateKey ) if ! ok { return false } return ePriv . priv . D . Cmp ( oPriv . priv . D ) == 0 }


func (ePriv *ECDSAPrivateKey) Sign(data []byte) ([]byte, error) {
	hash := sha256.Sum256(data)
	r, s, err := ecdsa.Sign(rand.Reader, ePriv.priv, hash[:])
	if err != nil {
		return nil, err
	}

	return asn1.Marshal(ECDSASig{
		R: r,
		S: s,
	})
}

func ( ePriv * ECDSAPrivateKey ) Sign ( data [ ] byte ) ( [ ] byte , error ) { hash := sha256 . Sum256 ( data ) r , s , err := ecdsa . Sign ( rand . Reader , ePriv . priv , hash [ : ] ) if err != nil { return nil , err } return asn1 . Marshal ( ECDSASig { R : r , S : s , } ) }

// Sign returns the signature of the input data


func (ePub *ECDSAPublicKey) Equals(o Key) bool {
	oPub, ok := o.(*ECDSAPublicKey)
	if !ok {
		return false
	}

	return ePub.pub.X != nil && ePub.pub.Y != nil && oPub.pub.X != nil && oPub.pub.Y != nil &&
		0 == ePub.pub.X.Cmp(oPub.pub.X) && 0 == ePub.pub.Y.Cmp(oPub.pub.Y)
}

func ( ePub * ECDSAPublicKey ) Equals ( o Key ) bool { oPub , ok := o . ( * ECDSAPublicKey ) if ! ok { return false } return ePub . pub . X != nil && ePub . pub . Y != nil && oPub . pub . X != nil && oPub . pub . Y != nil && 0 == ePub . pub . X . Cmp ( oPub . pub . X ) && 0 == ePub . pub . Y . Cmp ( oPub . pub . Y ) }


func (ePub *ECDSAPublicKey) Verify(data, sigBytes []byte) (bool, error) {
	sig := new(ECDSASig)
	if _, err := asn1.Unmarshal(sigBytes, sig); err != nil {
		return false, err
	}
	if sig == nil {
		return false, ErrNilSig
	}

	hash := sha256.Sum256(data)

	return ecdsa.Verify(ePub.pub, hash[:], sig.R, sig.S), nil
}

func ( ePub * ECDSAPublicKey ) Verify ( data , sigBytes [ ] byte ) ( bool , error ) { sig := new ( ECDSASig ) if _ , err := asn1 . Unmarshal ( sigBytes , sig ) ; err != nil { return false , err } if sig == nil { return false , ErrNilSig } hash := sha256 . Sum256 ( data ) return ecdsa . Verify ( ePub . pub , hash [ : ] , sig . R , sig . S ) , nil }


func GenerateSecp256k1Key(src io.Reader) (PrivKey, PubKey, error) {
	privk, err := btcec.NewPrivateKey(btcec.S256())
	if err != nil {
		return nil, nil, err
	}

	k := (*Secp256k1PrivateKey)(privk)
	return k, k.GetPublic(), nil
}

func GenerateSecp256k1Key ( src io . Reader ) ( PrivKey , PubKey , error ) { privk , err := btcec . NewPrivateKey ( btcec . S256 ( ) ) if err != nil { return nil , nil , err } k := ( * Secp256k1PrivateKey ) ( privk ) return k , k . GetPublic ( ) , nil }

// GenerateSecp256k1Key generates a new Secp256k1 private and public key pair


func UnmarshalSecp256k1PrivateKey(data []byte) (PrivKey, error) {
	if len(data) != btcec.PrivKeyBytesLen {
		return nil, fmt.Errorf("expected secp256k1 data size to be %d", btcec.PrivKeyBytesLen)
	}

	privk, _ := btcec.PrivKeyFromBytes(btcec.S256(), data)
	return (*Secp256k1PrivateKey)(privk), nil
}

func UnmarshalSecp256k1PrivateKey ( data [ ] byte ) ( PrivKey , error ) { if len ( data ) != btcec . PrivKeyBytesLen { return nil , fmt . Errorf ( " " , btcec . PrivKeyBytesLen ) } privk , _ := btcec . PrivKeyFromBytes ( btcec . S256 ( ) , data ) return ( * Secp256k1PrivateKey ) ( privk ) , nil }

// UnmarshalSecp256k1PrivateKey returns a private key from bytes


func UnmarshalSecp256k1PublicKey(data []byte) (PubKey, error) {
	k, err := btcec.ParsePubKey(data, btcec.S256())
	if err != nil {
		return nil, err
	}

	return (*Secp256k1PublicKey)(k), nil
}

func UnmarshalSecp256k1PublicKey ( data [ ] byte ) ( PubKey , error ) { k , err := btcec . ParsePubKey ( data , btcec . S256 ( ) ) if err != nil { return nil , err } return ( * Secp256k1PublicKey ) ( k ) , nil }

// UnmarshalSecp256k1PublicKey returns a public key from bytes


func (k *Secp256k1PrivateKey) Equals(o Key) bool {
	sk, ok := o.(*Secp256k1PrivateKey)
	if !ok {
		return false
	}

	return k.D.Cmp(sk.D) == 0
}

func ( k * Secp256k1PrivateKey ) Equals ( o Key ) bool { sk , ok := o . ( * Secp256k1PrivateKey ) if ! ok { return false } return k . D . Cmp ( sk . D ) == 0 }


func (k *Secp256k1PrivateKey) Sign(data []byte) ([]byte, error) {
	hash := sha256.Sum256(data)
	sig, err := (*btcec.PrivateKey)(k).Sign(hash[:])
	if err != nil {
		return nil, err
	}

	return sig.Serialize(), nil
}

func ( k * Secp256k1PrivateKey ) Sign ( data [ ] byte ) ( [ ] byte , error ) { hash := sha256 . Sum256 ( data ) sig , err := ( * btcec . PrivateKey ) ( k ) . Sign ( hash [ : ] ) if err != nil { return nil , err } return sig . Serialize ( ) , nil }

// Sign returns a signature from input data


func (k *Secp256k1PublicKey) Equals(o Key) bool {
	sk, ok := o.(*Secp256k1PublicKey)
	if !ok {
		return false
	}

	return (*btcec.PublicKey)(k).IsEqual((*btcec.PublicKey)(sk))
}

func ( k * Secp256k1PublicKey ) Equals ( o Key ) bool { sk , ok := o . ( * Secp256k1PublicKey ) if ! ok { return false } return ( * btcec . PublicKey ) ( k ) . IsEqual ( ( * btcec . PublicKey ) ( sk ) ) }


func (k *Secp256k1PublicKey) Verify(data []byte, sigStr []byte) (bool, error) {
	sig, err := btcec.ParseDERSignature(sigStr, btcec.S256())
	if err != nil {
		return false, err
	}

	hash := sha256.Sum256(data)
	return sig.Verify(hash[:], (*btcec.PublicKey)(k)), nil
}

func ( k * Secp256k1PublicKey ) Verify ( data [ ] byte , sigStr [ ] byte ) ( bool , error ) { sig , err := btcec . ParseDERSignature ( sigStr , btcec . S256 ( ) ) if err != nil { return false , err } hash := sha256 . Sum256 ( data ) return sig . Verify ( hash [ : ] , ( * btcec . PublicKey ) ( k ) ) , nil }

// Verify compares a signature against the input data


func (k *Ed25519PrivateKey) Raw() ([]byte, error) {
	// The Ed25519 private key contains two 32-bytes curve points, the private
	// key and the public key.
	// It makes it more efficient to get the public key without re-computing an
	// elliptic curve multiplication.
	buf := make([]byte, len(k.k))
	copy(buf, k.k)

	return buf, nil
}


func (k *Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
	return ed25519.Sign(k.k, msg), nil
}

func ( k * Ed25519PrivateKey ) Sign ( msg [ ] byte ) ( [ ] byte , error ) { return ed25519 . Sign ( k . k , msg ) , nil }

// Sign returns a signature from an input message.

Sign returns a signature from an input message .


func (k *Ed25519PublicKey) Equals(o Key) bool {
	edk, ok := o.(*Ed25519PublicKey)
	if !ok {
		return false
	}

	return bytes.Equal(k.k, edk.k)
}

func ( k * Ed25519PublicKey ) Equals ( o Key ) bool { edk , ok := o . ( * Ed25519PublicKey ) if ! ok { return false } return bytes . Equal ( k . k , edk . k ) }

// Equals compares two ed25519 public keys.

Equals compares two ed25519 public keys .


func (k *Ed25519PublicKey) Verify(data []byte, sig []byte) (bool, error) {
	return ed25519.Verify(k.k, data, sig), nil
}

func ( k * Ed25519PublicKey ) Verify ( data [ ] byte , sig [ ] byte ) ( bool , error ) { return ed25519 . Verify ( k . k , data , sig ) , nil }

// Verify checks a signature agains the input data.

Verify checks a signature agains the input data .


func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) {
	if len(data) != 32 {
		return nil, errors.New("expect ed25519 public key data size to be 32")
	}

	return &Ed25519PublicKey{
		k: ed25519.PublicKey(data),
	}, nil
}

func UnmarshalEd25519PublicKey ( data [ ] byte ) ( PubKey , error ) { if len ( data ) != 32 { return nil , errors . New ( " " ) } return & Ed25519PublicKey { k : ed25519 . PublicKey ( data ) , } , nil }

// UnmarshalEd25519PublicKey returns a public key from input bytes.

UnmarshalEd25519PublicKey returns a public key from input bytes .


func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
	switch len(data) {
	case ed25519.PrivateKeySize + ed25519.PublicKeySize:
		// Remove the redundant public key. See issue #36.
		redundantPk := data[ed25519.PrivateKeySize:]
		pk := data[ed25519.PrivateKeySize-ed25519.PublicKeySize : ed25519.PrivateKeySize]
		if !bytes.Equal(pk, redundantPk) {
			return nil, errors.New("expected redundant ed25519 public key to be redundant")
		}

		// No point in storing the extra data.
		newKey := make([]byte, ed25519.PrivateKeySize)
		copy(newKey, data[:ed25519.PrivateKeySize])
		data = newKey
	case ed25519.PrivateKeySize:
	default:
		return nil, fmt.Errorf(
			"expected ed25519 data size to be %d or %d, got %d",
			ed25519.PrivateKeySize,
			ed25519.PrivateKeySize+ed25519.PublicKeySize,
			len(data),
		)
	}

	return &Ed25519PrivateKey{
		k: ed25519.PrivateKey(data),
	}, nil
}

// UnmarshalEd25519PrivateKey returns a private key from input bytes.

UnmarshalEd25519PrivateKey returns a private key from input bytes .


func EditScriptForStrings(source []rune, target []rune, op Options) EditScript {
	return backtrace(len(source), len(target),
		MatrixForStrings(source, target, op), op)
}

func EditScriptForStrings ( source [ ] rune , target [ ] rune , op Options ) EditScript { return backtrace ( len ( source ) , len ( target ) , MatrixForStrings ( source , target , op ) , op ) }

// EditScriptForStrings returns an optimal edit script to turn source into
// target.

EditScriptForStrings returns an optimal edit script to turn source into target .


func EditScriptForMatrix(matrix [][]int, op Options) EditScript {
	return backtrace(len(matrix)-1, len(matrix[0])-1, matrix, op)
}

func EditScriptForMatrix ( matrix [ ] [ ] int , op Options ) EditScript { return backtrace ( len ( matrix ) - 1 , len ( matrix [ 0 ] ) - 1 , matrix , op ) }

// EditScriptForMatrix returns an optimal edit script based on the given
// Levenshtein matrix.

EditScriptForMatrix returns an optimal edit script based on the given Levenshtein matrix .


func WriteMatrix(source []rune, target []rune, matrix [][]int, writer io.Writer) {
	fmt.Fprintf(writer, "    ")
	for _, targetRune := range target {
		fmt.Fprintf(writer, "  %c", targetRune)
	}
	fmt.Fprintf(writer, "\n")
	fmt.Fprintf(writer, "  %2d", matrix[0][0])
	for j, _ := range target {
		fmt.Fprintf(writer, " %2d", matrix[0][j+1])
	}
	fmt.Fprintf(writer, "\n")
	for i, sourceRune := range source {
		fmt.Fprintf(writer, "%c %2d", sourceRune, matrix[i+1][0])
		for j, _ := range target {
			fmt.Fprintf(writer, " %2d", matrix[i+1][j+1])
		}
		fmt.Fprintf(writer, "\n")
	}
}

func WriteMatrix ( source [ ] rune , target [ ] rune , matrix [ ] [ ] int , writer io . Writer ) { fmt . Fprintf ( writer , " " ) for _ , targetRune := range target { fmt . Fprintf ( writer , " " , targetRune ) } fmt . Fprintf ( writer , " \n " ) fmt . Fprintf ( writer , " " , matrix [ 0 ] [ 0 ] ) for j , _ := range target { fmt . Fprintf ( writer , " " , matrix [ 0 ] [ j + 1 ] ) } fmt . Fprintf ( writer , " \n " ) for i , sourceRune := range source { fmt . Fprintf ( writer , " " , sourceRune , matrix [ i + 1 ] [ 0 ] ) for j , _ := range target { fmt . Fprintf ( writer , " " , matrix [ i + 1 ] [ j + 1 ] ) } fmt . Fprintf ( writer , " \n " ) } }

// WriteMatrix writes a visual representation of the given matrix for the given
// strings to the given writer.

WriteMatrix writes a visual representation of the given matrix for the given strings to the given writer .


func New(path string) (Lockfile, error) {
	if !filepath.IsAbs(path) {
		return Lockfile(""), ErrNeedAbsPath
	}
	return Lockfile(path), nil
}

func New ( path string ) ( Lockfile , error ) { if ! filepath . IsAbs ( path ) { return Lockfile ( " " ) , ErrNeedAbsPath } return Lockfile ( path ) , nil }

// New describes a new filename located at the given absolute path.

New describes a new filename located at the given absolute path .


func (l Lockfile) GetOwner() (*os.Process, error) {
	name := string(l)

	// Ok, see, if we have a stale lockfile here
	content, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, err
	}

	// try hard for pids. If no pid, the lockfile is junk anyway and we delete it.
	pid, err := scanPidLine(content)
	if err != nil {
		return nil, err
	}
	running, err := isRunning(pid)
	if err != nil {
		return nil, err
	}

	if running {
		proc, err := os.FindProcess(pid)
		if err != nil {
			return nil, err
		}
		return proc, nil
	}
	return nil, ErrDeadOwner

}

// GetOwner returns who owns the lockfile.

GetOwner returns who owns the lockfile .


func (l Lockfile) TryLock() error {
	name := string(l)

	// This has been checked by New already. If we trigger here,
	// the caller didn't use New and re-implemented it's functionality badly.
	// So panic, that he might find this easily during testing.
	if !filepath.IsAbs(name) {
		panic(ErrNeedAbsPath)
	}

	tmplock, err := ioutil.TempFile(filepath.Dir(name), filepath.Base(name)+".")
	if err != nil {
		return err
	}

	cleanup := func() {
		_ = tmplock.Close()
		_ = os.Remove(tmplock.Name())
	}
	defer cleanup()

	if err := writePidLine(tmplock, os.Getpid()); err != nil {
		return err
	}

	// EEXIST and similiar error codes, caught by os.IsExist, are intentionally ignored,
	// as it means that someone was faster creating this link
	// and ignoring this kind of error is part of the algorithm.
	// The we will probably fail the pid owner check later, if this process is still alive.
	// We cannot ignore ALL errors, since failure to support hard links, disk full
	// as well as many other errors can happen to a filesystem operation
	// and we really want to abort on those.
	if err := os.Link(tmplock.Name(), name); err != nil {
		if !os.IsExist(err) {
			return err
		}
	}

	fiTmp, err := os.Lstat(tmplock.Name())
	if err != nil {
		return err
	}
	fiLock, err := os.Lstat(name)
	if err != nil {
		// tell user that a retry would be a good idea
		if os.IsNotExist(err) {
			return ErrNotExist
		}
		return err
	}

	// Success
	if os.SameFile(fiTmp, fiLock) {
		return nil
	}

	proc, err := l.GetOwner()
	switch err {
	default:
		// Other errors -> defensively fail and let caller handle this
		return err
	case nil:
		if proc.Pid != os.Getpid() {
			return ErrBusy
		}
	case ErrDeadOwner, ErrInvalidPid:
		// cases we can fix below
	}

	// clean stale/invalid lockfile
	err = os.Remove(name)
	if err != nil {
		// If it doesn't exist, then it doesn't matter who removed it.
		if !os.IsNotExist(err) {
			return err
		}
	}

	// now that the stale lockfile is gone, let's recurse
	return l.TryLock()
}

// TryLock tries to own the lock.
// It Returns nil, if successful and and error describing the reason, it didn't work out.
// Please note, that existing lockfiles containing pids of dead processes
// and lockfiles containing no pid at all are simply deleted.

TryLock tries to own the lock . It Returns nil if successful and and error describing the reason it didn t work out . Please note that existing lockfiles containing pids of dead processes and lockfiles containing no pid at all are simply deleted .


func (l Lockfile) Unlock() error {
	proc, err := l.GetOwner()
	switch err {
	case ErrInvalidPid, ErrDeadOwner:
		return ErrRogueDeletion
	case nil:
		if proc.Pid == os.Getpid() {
			// we really own it, so let's remove it.
			return os.Remove(string(l))
		}
		// Not owned by me, so don't delete it.
		return ErrRogueDeletion
	default:
		// This is an application error or system error.
		// So give a better error for logging here.
		if os.IsNotExist(err) {
			return ErrRogueDeletion
		}
		// Other errors -> defensively fail and let caller handle this
		return err
	}
}

// Unlock a lock again, if we owned it. Returns any error that happend during release of lock.

Unlock a lock again if we owned it . Returns any error that happend during release of lock .


func NewBase(configs ...baseConfigFunc) *Base {
	b := &Base{
		clock: glock.NewRealClock(),

		config:    NewConfig(),
		logLevel:  LevelDebug,
		sequence:  0,
		BaseAttrs: NewAttrs(),

		loggers:      make([]Logger, 0),
		hookPreQueue: make([]HookPreQueue, 0),
	}

	for _, f := range configs {
		f(b)
	}

	return b
}

func NewBase ( configs ... baseConfigFunc ) * Base { b := & Base { clock : glock . NewRealClock ( ) , config : NewConfig ( ) , logLevel : LevelDebug , sequence : 0 , BaseAttrs : NewAttrs ( ) , loggers : make ( [ ] Logger , 0 ) , hookPreQueue : make ( [ ] HookPreQueue , 0 ) , } for _ , f := range configs { f ( b ) } return b }

// NewBase creates a new instance of Base with default values set.

NewBase creates a new instance of Base with default values set .


func (b *Base) SetFallbackLogger(logger Logger) error {
	if logger == nil {
		if b.fallbackLogger != nil && b.fallbackLogger.IsInitialized() {
			b.fallbackLogger.ShutdownLogger()
		}
		b.fallbackLogger = nil
		return nil
	}

	if !logger.IsInitialized() {
		err := logger.InitLogger()
		if err != nil {
			return err
		}
	}

	// Shut down any old logger we might already have a reference to
	if b.fallbackLogger != nil && b.fallbackLogger.IsInitialized() {
		b.fallbackLogger.ShutdownLogger()
	}

	b.fallbackLogger = logger

	return nil
}

// SetFallbackLogger sets a Logger to be used if there aren't any loggers added or any of
// the added loggers are in a degraded or unhealthy state.  A Logger passed to SetFallbackLogger
// will be initialized if it hasn't been already.  In addition, if the Logger fails to initialize
// completely the fallback logger will fail to be set.

SetFallbackLogger sets a Logger to be used if there aren t any loggers added or any of the added loggers are in a degraded or unhealthy state . A Logger passed to SetFallbackLogger will be initialized if it hasn t been already . In addition if the Logger fails to initialize completely the fallback logger will fail to be set .


func (b *Base) AddLogger(logger Logger) error {
	if b.IsInitialized() && !logger.IsInitialized() {
		err := logger.InitLogger()
		if err != nil {
			return err
		}
	} else if !b.IsInitialized() && logger.IsInitialized() {
		err := logger.ShutdownLogger()
		if err != nil {
			return err
		}
	}
	b.loggers = append(b.loggers, logger)

	if hook, ok := logger.(HookPreQueue); ok {
		b.hookPreQueue = append(b.hookPreQueue, hook)
	}

	logger.SetBase(b)
	return nil
}

func ( b * Base ) AddLogger ( logger Logger ) error { if b . IsInitialized ( ) && ! logger . IsInitialized ( ) { err := logger . InitLogger ( ) if err != nil { return err } } else if ! b . IsInitialized ( ) && logger . IsInitialized ( ) { err := logger . ShutdownLogger ( ) if err != nil { return err } } b . loggers = append ( b . loggers , logger ) if hook , ok := logger . ( HookPreQueue ) ; ok { b . hookPreQueue = append ( b . hookPreQueue , hook ) } logger . SetBase ( b ) return nil }

// AddLogger adds a new logger instance to the Base


func (b *Base) LogWithTime(level LogLevel, ts time.Time, m *Attrs, msg string, a ...interface{}) error {
	if !b.shouldLog(level) {
		return nil
	}

	if !b.isInitialized {
		return ErrNotInitialized
	}

	if len(b.config.FilenameAttr) > 0 || len(b.config.LineNumberAttr) > 0 {
		file, line := getCallerInfo()
		if m == nil {
			m = NewAttrs()
		}
		if len(b.config.FilenameAttr) > 0 {
			m.SetAttr(b.config.FilenameAttr, file)
		}
		if len(b.config.LineNumberAttr) > 0 {
			m.SetAttr(b.config.LineNumberAttr, line)
		}
	}

	if len(b.config.SequenceAttr) > 0 {
		if m == nil {
			m = NewAttrs()
		}
		seq := atomic.AddUint64(&b.sequence, 1)
		m.SetAttr(b.config.SequenceAttr, seq)
	}

	nm := newMessage(ts, b, level, m, msg, a...)

	for _, hook := range b.hookPreQueue {
		err := hook.PreQueue(nm)
		if err != nil {
			return err
		}
	}

	return b.queue.queueMessage(nm)
}

func ( b * Base ) LogWithTime ( level LogLevel , ts time . Time , m * Attrs , msg string , a ... interface { } ) error { if ! b . shouldLog ( level ) { return nil } if ! b . isInitialized { return ErrNotInitialized } if len ( b . config . FilenameAttr ) > 0 || len ( b . config . LineNumberAttr ) > 0 { file , line := getCallerInfo ( ) if m == nil { m = NewAttrs ( ) } if len ( b . config . FilenameAttr ) > 0 { m . SetAttr ( b . config . FilenameAttr , file ) } if len ( b . config . LineNumberAttr ) > 0 { m . SetAttr ( b . config . LineNumberAttr , line ) } } if len ( b . config . SequenceAttr ) > 0 { if m == nil { m = NewAttrs ( ) } seq := atomic . AddUint64 ( & b . sequence , 1 ) m . SetAttr ( b . config . SequenceAttr , seq ) } nm := newMessage ( ts , b , level , m , msg , a ... ) for _ , hook := range b . hookPreQueue { err := hook . PreQueue ( nm ) if err != nil { return err } } return b . queue . queueMessage ( nm ) }

// LogWithTime will log a message at the provided level to all added loggers with the timestamp set to the
// value of ts.

LogWithTime will log a message at the provided level to all added loggers with the timestamp set to the value of ts .


func (b *Base) Log(level LogLevel, m *Attrs, msg string, a ...interface{}) error {
	return b.LogWithTime(level, b.clock.Now(), m, msg, a...)
}

func ( b * Base ) Log ( level LogLevel , m * Attrs , msg string , a ... interface { } ) error { return b . LogWithTime ( level , b . clock . Now ( ) , m , msg , a ... ) }

// Log will log a message at the provided level to all added loggers with the timestamp set to the time
// Log was called.

Log will log a message at the provided level to all added loggers with the timestamp set to the time Log was called .


func (b *Base) Warnm(m *Attrs, msg string, a ...interface{}) error {
	return b.Warningm(m, msg, a...)
}

func ( b * Base ) Warnm ( m * Attrs , msg string , a ... interface { } ) error { return b . Warningm ( m , msg , a ... ) }

// Warnm is a short-hand version of Warningm

Warnm is a short - hand version of Warningm


func NewTemplateWithFuncMap(tpl string, funcMap template.FuncMap) (*Template, error) {
	var levels = []LogLevel{LevelNone, LevelDebug, LevelInfo, LevelWarning, LevelError, LevelFatal}
	tpls := make(map[LogLevel]*template.Template, 0)
	for _, level := range levels {
		// If color is overridden, we need to ensure that {{reset}} resets for all levels.
		_, forceReset := funcMap["color"]
		fMap := getFuncMap(level, forceReset)
		for name, f := range funcMap {
			fMap[name] = f
		}

		parsedTpl, err := template.New(getLevelName(level)).
			Funcs(fMap).
			Parse(tpl)
		if err != nil {
			return nil, err
		}
		tpls[level] = parsedTpl
	}

	newTpl := &Template{
		tpls: tpls,
	}

	return newTpl, nil
}

// NewTemplateWithFuncMap creates a new Template from the given string and a template FuncMap. The FuncMap available
// to the template during evaluation will also include the default values, if not overridden. An error is returned
// if the template fails to compile.

NewTemplateWithFuncMap creates a new Template from the given string and a template FuncMap . The FuncMap available to the template during evaluation will also include the default values if not overridden . An error is returned if the template fails to compile .


func (t *Template) Execute(msg *TemplateMsg, colorize bool) (string, error) {
	tplLevel := msg.Level
	if !colorize {
		tplLevel = LevelNone
	}
	var buf bytes.Buffer
	execTpl := t.tpls[tplLevel]
	if execTpl == nil {
		return "", ErrUnknownLevel
	}
	err := execTpl.Execute(&buf, msg)
	if err != nil {
		return "", err
	}

	return buf.String(), nil
}

func ( t * Template ) Execute ( msg * TemplateMsg , colorize bool ) ( string , error ) { tplLevel := msg . Level if ! colorize { tplLevel = LevelNone } var buf bytes . Buffer execTpl := t . tpls [ tplLevel ] if execTpl == nil { return " " , ErrUnknownLevel } err := execTpl . Execute ( & buf , msg ) if err != nil { return " " , err } return buf . String ( ) , nil }

// Execute takes a TemplateMsg and applies it to the Go template.  If colorize is true the template
// will insert ANSI color codes within the resulting string.

Execute takes a TemplateMsg and applies it to the Go template . If colorize is true the template will insert ANSI color codes within the resulting string .


func NewTemplateMsg(timestamp time.Time, level LogLevel, m map[string]interface{}, msg string) *TemplateMsg {
	msgAttrs := m
	if msgAttrs == nil {
		msgAttrs = make(map[string]interface{})
	}
	tplMsg := &TemplateMsg{
		Timestamp: timestamp,
		Message:   msg,
		Level:     level,
		LevelName: level.String(),
		Attrs:     msgAttrs,
	}
	return tplMsg
}

func NewTemplateMsg ( timestamp time . Time , level LogLevel , m map [ string ] interface { } , msg string ) * TemplateMsg { msgAttrs := m if msgAttrs == nil { msgAttrs = make ( map [ string ] interface { } ) } tplMsg := & TemplateMsg { Timestamp : timestamp , Message : msg , Level : level , LevelName : level . String ( ) , Attrs : msgAttrs , } return tplMsg }

// NewTemplateMsg will create a new TemplateMsg with values from the given parameters


func NewLogAdapterFor(base WrappableLogger, attrs *Attrs) *LogAdapter {
	if attrs == nil {
		attrs = NewAttrs()
	}

	return &LogAdapter{
		base:  base,
		attrs: attrs,
	}
}

func NewLogAdapterFor ( base WrappableLogger , attrs * Attrs ) * LogAdapter { if attrs == nil { attrs = NewAttrs ( ) } return & LogAdapter { base : base , attrs : attrs , } }

// NewLogAdapterFor creates a LogAdapter that wraps the given loger with the
// given attributes.

NewLogAdapterFor creates a LogAdapter that wraps the given loger with the given attributes .


func (la *LogAdapter) SetAttr(key string, value interface{}) {
	la.attrs.SetAttr(key, value)
}

func ( la * LogAdapter ) SetAttr ( key string , value interface { } ) { la . attrs . SetAttr ( key , value ) }

// SetAttr sets the attribute key to value for this LogAdapter only


func (la *LogAdapter) LogWithTime(level LogLevel, ts time.Time, attrs *Attrs, msg string, a ...interface{}) error {
	if la.logLevel != nil && level > *la.logLevel {
		return nil
	}

	mergedAttrs := la.attrs.clone()
	mergedAttrs.MergeAttrs(attrs)
	return la.base.LogWithTime(level, ts, mergedAttrs, msg, a...)
}

func ( la * LogAdapter ) LogWithTime ( level LogLevel , ts time . Time , attrs * Attrs , msg string , a ... interface { } ) error { if la . logLevel != nil && level > * la . logLevel { return nil } mergedAttrs := la . attrs . clone ( ) mergedAttrs . MergeAttrs ( attrs ) return la . base . LogWithTime ( level , ts , mergedAttrs , msg , a ... ) }

// LogWithTime will log a message at the provided level to all loggers added
// to the Base associated with this LogAdapter. It is similar to Log except
// the timestamp will be set to the value of ts.

LogWithTime will log a message at the provided level to all loggers added to the Base associated with this LogAdapter . It is similar to Log except the timestamp will be set to the value of ts .


func (la *LogAdapter) Log(level LogLevel, attrs *Attrs, msg string, a ...interface{}) error {
	if la.logLevel != nil && level > *la.logLevel {
		return nil
	}

	mergedAttrs := la.attrs.clone()
	mergedAttrs.MergeAttrs(attrs)
	return la.base.Log(level, mergedAttrs, msg, a...)
}

func ( la * LogAdapter ) Log ( level LogLevel , attrs * Attrs , msg string , a ... interface { } ) error { if la . logLevel != nil && level > * la . logLevel { return nil } mergedAttrs := la . attrs . clone ( ) mergedAttrs . MergeAttrs ( attrs ) return la . base . Log ( level , mergedAttrs , msg , a ... ) }

// Log will log a message at the provided level to all loggers added
// to the Base associated with this LogAdapter

Log will log a message at the provided level to all loggers added to the Base associated with this LogAdapter


func (la *LogAdapter) Dbgm(m *Attrs, msg string, a ...interface{}) error {
	return la.Debugm(m, msg, a...)
}

func ( la * LogAdapter ) Dbgm ( m * Attrs , msg string , a ... interface { } ) error { return la . Debugm ( m , msg , a ... ) }

// Dbgm is a short-hand version of Debugm

Dbgm is a short - hand version of Debugm


func NewAttrsFromMap(attrs map[string]interface{}) *Attrs {
	newAttrs := NewAttrs()
	for attrKey, attrVal := range attrs {
		newAttrs.SetAttr(attrKey, attrVal)
	}
	return newAttrs
}

func NewAttrsFromMap ( attrs map [ string ] interface { } ) * Attrs { newAttrs := NewAttrs ( ) for attrKey , attrVal := range attrs { newAttrs . SetAttr ( attrKey , attrVal ) } return newAttrs }

// NewAttrsFromMap will create a new Attrs struct with the given attributes pre-populated

NewAttrsFromMap will create a new Attrs struct with the given attributes pre - populated


func NewAttrsFromAttrs(attrs ...*Attrs) *Attrs {
	newAttrs := NewAttrs()
	for _, attr := range attrs {
		newAttrs.MergeAttrs(attr)
	}
	return newAttrs
}

func NewAttrsFromAttrs ( attrs ... * Attrs ) * Attrs { newAttrs := NewAttrs ( ) for _ , attr := range attrs { newAttrs . MergeAttrs ( attr ) } return newAttrs }

// NewAttrsFromAttrs is a convenience function that will accept zero or more existing Attrs, create
// a new Attrs and then merge all the supplied Attrs values into the new Attrs instance.

NewAttrsFromAttrs is a convenience function that will accept zero or more existing Attrs create a new Attrs and then merge all the supplied Attrs values into the new Attrs instance .


func (a *Attrs) MergeAttrs(attrs *Attrs) {
	if attrs == nil {
		return
	}
	a.attrsLock.Lock()
	defer a.attrsLock.Unlock()
	for hash, val := range attrs.attrs {
		a.attrs[hash] = val
	}
}

func ( a * Attrs ) MergeAttrs ( attrs * Attrs ) { if attrs == nil { return } a . attrsLock . Lock ( ) defer a . attrsLock . Unlock ( ) for hash , val := range attrs . attrs { a . attrs [ hash ] = val } }

// MergeAttrs accepts another existing Attrs and merges the attributes into its own.

MergeAttrs accepts another existing Attrs and merges the attributes into its own .


func (a *Attrs) SetAttr(key string, value interface{}) *Attrs {
	a.attrsLock.Lock()
	defer a.attrsLock.Unlock()

	valVal := reflect.ValueOf(value)
	switch valVal.Kind() {
	case reflect.Func:
		value = valVal.Type().String()
	}

	hash := getAttrHash(key)
	a.attrs[hash] = value
	return a
}

func ( a * Attrs ) SetAttr ( key string , value interface { } ) * Attrs { a . attrsLock . Lock ( ) defer a . attrsLock . Unlock ( ) valVal := reflect . ValueOf ( value ) switch valVal . Kind ( ) { case reflect . Func : value = valVal . Type ( ) . String ( ) } hash := getAttrHash ( key ) a . attrs [ hash ] = value return a }

// SetAttr will set key to the provided value.  If the attribute already exists the value will
// be replaced with the new value.

SetAttr will set key to the provided value . If the attribute already exists the value will be replaced with the new value .


func (a *Attrs) GetAttr(key string) interface{} {
	a.attrsLock.RLock()
	defer a.attrsLock.RUnlock()

	return a.attrs[getAttrHash(key)]
}

func ( a * Attrs ) GetAttr ( key string ) interface { } { a . attrsLock . RLock ( ) defer a . attrsLock . RUnlock ( ) return a . attrs [ getAttrHash ( key ) ] }

// GetAttr gets the value of the attribute with the provided name.  If the attribute does not
// exist, nil will be returned

GetAttr gets the value of the attribute with the provided name . If the attribute does not exist nil will be returned


func (a *Attrs) RemoveAttr(key string) {
	a.attrsLock.Lock()
	defer a.attrsLock.Unlock()

	delete(a.attrs, getAttrHash(key))
}

func ( a * Attrs ) RemoveAttr ( key string ) { a . attrsLock . Lock ( ) defer a . attrsLock . Unlock ( ) delete ( a . attrs , getAttrHash ( key ) ) }

// RemoveAttr will remove the attribute with the provided name.

RemoveAttr will remove the attribute with the provided name .


func (a *Attrs) Attrs() map[string]interface{} {
	a.attrsLock.RLock()
	defer a.attrsLock.RUnlock()

	attrs := make(map[string]interface{})
	for hash, val := range a.attrs {
		key, _ := getHashAttr(hash)
		attrs[key] = val
	}
	return attrs
}

func ( a * Attrs ) Attrs ( ) map [ string ] interface { } { a . attrsLock . RLock ( ) defer a . attrsLock . RUnlock ( ) attrs := make ( map [ string ] interface { } ) for hash , val := range a . attrs { key , _ := getHashAttr ( hash ) attrs [ key ] = val } return attrs }

// Attrs will return a map of the attributes added to the struct.

Attrs will return a map of the attributes added to the struct .


func Debugm(m *Attrs, msg string, a ...interface{}) error {
	return curDefault.Debugm(m, msg, a...)
}

func Debugm ( m * Attrs , msg string , a ... interface { } ) error { return curDefault . Debugm ( m , msg , a ... ) }

// Debugm executes the same function on the default Base instance


func Infom(m *Attrs, msg string, a ...interface{}) error {
	return curDefault.Infom(m, msg, a...)
}

func Infom ( m * Attrs , msg string , a ... interface { } ) error { return curDefault . Infom ( m , msg , a ... ) }

// Infom executes the same function on the default Base instance


func Warningm(m *Attrs, msg string, a ...interface{}) error {
	return curDefault.Warningm(m, msg, a...)
}

func Warningm ( m * Attrs , msg string , a ... interface { } ) error { return curDefault . Warningm ( m , msg , a ... ) }

// Warningm executes the same function on the default Base instance


func Errm(m *Attrs, msg string, a ...interface{}) error {
	return Errorm(m, msg, a...)
}

func Errm ( m * Attrs , msg string , a ... interface { } ) error { return Errorm ( m , msg , a ... ) }

// Errm executes the same function on the default Base instance


func Errorm(m *Attrs, msg string, a ...interface{}) error {
	return curDefault.Errorm(m, msg, a...)
}

func Errorm ( m * Attrs , msg string , a ... interface { } ) error { return curDefault . Errorm ( m , msg , a ... ) }

// Errorm executes the same function on the default Base instance


func Fatalm(m *Attrs, msg string, a ...interface{}) error {
	return curDefault.Fatalm(m, msg, a...)
}

func Fatalm ( m * Attrs , msg string , a ... interface { } ) error { return curDefault . Fatalm ( m , msg , a ... ) }

// Fatalm executes the same function on the default Base instance


func Dief(exitCode int, msg string, a ...interface{}) {
	curDefault.Dief(exitCode, msg, a...)
}

func Dief ( exitCode int , msg string , a ... interface { } ) { curDefault . Dief ( exitCode , msg , a ... ) }

// Dief executes the same function on the default Base instance


func Diem(exitCode int, m *Attrs, msg string, a ...interface{}) {
	curDefault.Diem(exitCode, m, msg, a...)
}

func Diem ( exitCode int , m * Attrs , msg string , a ... interface { } ) { curDefault . Diem ( exitCode , m , msg , a ... ) }

// Diem executes the same function on the default Base instance


func ToLogLevel(level string) (LogLevel, error) {
	lowLevel := strings.ToLower(level)

	switch lowLevel {
	case "dbg":
		fallthrough
	case "debug":
		return LevelDebug, nil
	case "info":
		return LevelInfo, nil
	case "warn":
		fallthrough
	case "warning":
		return LevelWarning, nil
	case "err":
		fallthrough
	case "error":
		return LevelError, nil
	case "fatal":
		return LevelFatal, nil
	case "none":
		return LevelNone, nil
	}

	return 0, ErrUnknownLevel
}

func ToLogLevel ( level string ) ( LogLevel , error ) { lowLevel := strings . ToLower ( level ) switch lowLevel { case " " : fallthrough case " " : return LevelDebug , nil case " " : return LevelInfo , nil case " " : fallthrough case " " : return LevelWarning , nil case " " : fallthrough case " " : return LevelError , nil case " " : return LevelFatal , nil case " " : return LevelNone , nil } return 0 , ErrUnknownLevel }

// ToLogLevel will take a string and return the appropriate log level for
// the string if known.  If the string is not recognized it will return
// an ErrUnknownLevel error.

ToLogLevel will take a string and return the appropriate log level for the string if known . If the string is not recognized it will return an ErrUnknownLevel error .


func CallErr(f func() error) error {
	checkRun()
	errChan := make(chan error)
	callQueue <- func() {
		errChan <- f()
	}
	return <-errChan
}

func CallErr ( f func ( ) error ) error { checkRun ( ) errChan := make ( chan error ) callQueue <- func ( ) { errChan <- f ( ) } return <- errChan }

// CallErr queues function f on the main thread and returns an error returned by f.

CallErr queues function f on the main thread and returns an error returned by f .


func New(opts ...Option) (*StackdriverHook, error) {
	var err error

	sh := &StackdriverHook{
		levels: logrus.AllLevels,
	}

	// apply opts
	for _, o := range opts {
		err = o(sh)
		if err != nil {
			return nil, err
		}
	}

	// check service, resource, logName set
	if sh.service == nil && sh.agentClient == nil {
		return nil, errors.New("no stackdriver service was provided")
	}
	if sh.resource == nil && sh.agentClient == nil {
		return nil, errors.New("the monitored resource was not provided")
	}
	if sh.projectID == "" && sh.agentClient == nil {
		return nil, errors.New("the project id was not provided")
	}

	// set default project name
	if sh.logName == "" {
		err = LogName(DefaultName)(sh)
		if err != nil {
			return nil, err
		}
	}

	// If error reporting log name not set, set it to log name
	// plus string suffix
	if sh.errorReportingLogName == "" {
		sh.errorReportingLogName = sh.logName + "_errors"
	}

	return sh, nil
}

// New creates a StackdriverHook using the provided options that is suitible
// for using with logrus for logging to Google Stackdriver.

New creates a StackdriverHook using the provided options that is suitible for using with logrus for logging to Google Stackdriver .


func (sh *StackdriverHook) Fire(entry *logrus.Entry) error {
	sh.waitGroup.Add(1)
	go func(entry *logrus.Entry) {
		defer sh.waitGroup.Done()
		var httpReq *logging.HttpRequest

		// convert entry data to labels
		labels := make(map[string]string, len(entry.Data))
		for k, v := range entry.Data {
			switch x := v.(type) {
			case string:
				labels[k] = x

			case *http.Request:
				httpReq = &logging.HttpRequest{
					Referer:       x.Referer(),
					RemoteIp:      x.RemoteAddr,
					RequestMethod: x.Method,
					RequestUrl:    x.URL.String(),
					UserAgent:     x.UserAgent(),
				}

			case *logging.HttpRequest:
				httpReq = x

			default:
				labels[k] = fmt.Sprintf("%v", v)
			}
		}

		// write log entry
		if sh.agentClient != nil {
			sh.sendLogMessageViaAgent(entry, labels, httpReq)
		} else {
			sh.sendLogMessageViaAPI(entry, labels, httpReq)
		}
	}(sh.copyEntry(entry))

	return nil
}

func
(
sh
*
StackdriverHook
)
Fire
(
entry
*
logrus
.
Entry
)
error
{
sh
.
waitGroup
.
Add
(
1
)
go
func
(
entry
*
logrus
.
Entry
)
{
defer
sh
.
waitGroup
.
Done
(
)
var
httpReq
*
logging
.
HttpRequest
// convert entry data to labels
labels
:=
make
(
map
[
string
]
string
,
len
(
entry
.
Data
)
)
for
k
,
v
:=
range
entry
.
Data
{
switch
x
:=
v
.
(
type
)
{
case
string
:
labels
[
k
]
=
x
case
*
http
.
Request
:
httpReq
=
&
logging
.
HttpRequest
{
Referer
:
x
.
Referer
(
)
,
RemoteIp
:
x
.
RemoteAddr
,
RequestMethod
:
x
.
Method
,
RequestUrl
:
x
.
URL
.
String
(
)
,
UserAgent
:
x
.
UserAgent
(
)
,
}
case
*
logging
.
HttpRequest
:
httpReq
=
x
default
:
labels
[
k
]
=
fmt
.
Sprintf
(
"
"
,
v
)
}
}
// write log entry
if
sh
.
agentClient
!=
{
sh
.
sendLogMessageViaAgent
(
entry
,
labels
,
httpReq
)
}
else
{
sh
.
sendLogMessageViaAPI
(
entry
,
labels
,
httpReq
)
}
}
(
sh
.
copyEntry
(
entry
)
)
return
}

// Fire writes the message to the Stackdriver entry service.

Fire writes the message to the Stackdriver entry service .


func Levels(levels ...logrus.Level) Option {
	return func(sh *StackdriverHook) error {
		sh.levels = levels
		return nil
	}
}

func Levels ( levels ... logrus . Level ) Option { return func ( sh * StackdriverHook ) error { sh . levels = levels return nil } }

// Levels is an option that sets the logrus levels that the StackdriverHook
// will create log entries for.

Levels is an option that sets the logrus levels that the StackdriverHook will create log entries for .


func ProjectID(projectID string) Option {
	return func(sh *StackdriverHook) error {
		sh.projectID = projectID
		return nil
	}
}

func ProjectID ( projectID string ) Option { return func ( sh * StackdriverHook ) error { sh . projectID = projectID return nil } }

// ProjectID is an option that sets the project ID which is needed for the log
// name.

ProjectID is an option that sets the project ID which is needed for the log name .


func EntriesService(service *logging.EntriesService) Option {
	return func(sh *StackdriverHook) error {
		sh.service = service
		return nil
	}
}

func EntriesService ( service * logging . EntriesService ) Option { return func ( sh * StackdriverHook ) error { sh . service = service return nil } }

// EntriesService is an option that sets the Google API entry service to use
// with Stackdriver.

EntriesService is an option that sets the Google API entry service to use with Stackdriver .


func LoggingService(service *logging.Service) Option {
	return func(sh *StackdriverHook) error {
		sh.service = service.Entries
		return nil
	}
}

func LoggingService ( service * logging . Service ) Option { return func ( sh * StackdriverHook ) error { sh . service = service . Entries return nil } }

// LoggingService is an option that sets the Google API logging service to use.

LoggingService is an option that sets the Google API logging service to use .


func ErrorService(errorService *errorReporting.Service) Option {
	return func(sh *StackdriverHook) error {
		sh.errorService = errorService
		return nil
	}
}

func ErrorService ( errorService * errorReporting . Service ) Option { return func ( sh * StackdriverHook ) error { sh . errorService = errorService return nil } }

// ErrorService is an option that sets the Google API error reporting service to use.

ErrorService is an option that sets the Google API error reporting service to use .


func HTTPClient(client *http.Client) Option {
	return func(sh *StackdriverHook) error {
		// create logging service
		l, err := logging.New(client)
		if err != nil {
			return err
		}
		// create error reporting service
		e, err := errorReporting.New(client)
		if err != nil {
			return err
		} else {
			ErrorService(e)
		}

		return LoggingService(l)(sh)
	}
}

func
HTTPClient
(
client
*
http
.
Client
)
Option
{
return
func
(
sh
*
StackdriverHook
)
error
{
// create logging service
l
,
err
:=
logging
.
New
(
client
)
if
err
!=
{
return
err
}
// create error reporting service
e
,
err
:=
errorReporting
.
New
(
client
)
if
err
!=
{
return
err
}
else
{
ErrorService
(
e
)
}
return
LoggingService
(
l
)
(
sh
)
}
}

// HTTPClient is an option that sets the http.Client to be used when creating
// the Stackdriver service.

HTTPClient is an option that sets the http . Client to be used when creating the Stackdriver service .


func MonitoredResource(resource *logging.MonitoredResource) Option {
	return func(sh *StackdriverHook) error {
		sh.resource = resource
		return nil
	}
}

func MonitoredResource ( resource * logging . MonitoredResource ) Option { return func ( sh * StackdriverHook ) error { sh . resource = resource return nil } }

// MonitoredResource is an option that sets the monitored resource to send with
// each log entry.

MonitoredResource is an option that sets the monitored resource to send with each log entry .


func ErrorReportingLogName(name string) Option {
	return func(sh *StackdriverHook) error {
		sh.errorReportingLogName = name
		return nil
	}
}

func ErrorReportingLogName ( name string ) Option { return func ( sh * StackdriverHook ) error { sh . errorReportingLogName = name return nil } }

// ErrorReportingLogName is an option that sets the log name to send
// with each error message for error reporting.
// Only used when ErrorReportingService has been set.

ErrorReportingLogName is an option that sets the log name to send with each error message for error reporting . Only used when ErrorReportingService has been set .


func Labels(labels map[string]string) Option {
	return func(sh *StackdriverHook) error {
		sh.labels = labels
		return nil
	}
}

func Labels ( labels map [ string ] string ) Option { return func ( sh * StackdriverHook ) error { sh . labels = labels return nil } }

// Labels is an option that sets the labels to send with each log entry.

Labels is an option that sets the labels to send with each log entry .


func PartialSuccess(enabled bool) Option {
	return func(sh *StackdriverHook) error {
		sh.partialSuccess = enabled
		return nil
	}
}

func PartialSuccess ( enabled bool ) Option { return func ( sh * StackdriverHook ) error { sh . partialSuccess = enabled return nil } }

// PartialSuccess is an option that toggles whether or not to write partial log
// entries.

PartialSuccess is an option that toggles whether or not to write partial log entries .


func GoogleComputeCredentials(serviceAccount string) Option {
	return func(sh *StackdriverHook) error {
		var err error

		// get compute metadata scopes associated with the service account
		scopes, err := metadata.Scopes(serviceAccount)
		if err != nil {
			return err
		}

		// check if all the necessary scopes are provided
		for _, s := range requiredScopes {
			if !sliceContains(scopes, s) {
				// NOTE: if you are seeing this error, you probably need to
				// recreate your compute instance with the correct scope
				//
				// as of August 2016, there is not a way to add a scope to an
				// existing compute instance
				return fmt.Errorf("missing required scope %s in compute metadata", s)
			}
		}

		return HTTPClient(&http.Client{
			Transport: &oauth2.Transport{
				Source: google.ComputeTokenSource(serviceAccount),
			},
		})(sh)
	}
}

// GoogleComputeCredentials is an option that loads the Google Service Account
// credentials from the GCE metadata associated with the GCE compute instance.
// If serviceAccount is empty, then the default service account credentials
// associated with the GCE instance will be used.

GoogleComputeCredentials is an option that loads the Google Service Account credentials from the GCE metadata associated with the GCE compute instance . If serviceAccount is empty then the default service account credentials associated with the GCE instance will be used .


func (c Codec) NewEncoder(w io.Writer) *Encoder {
	return NewEncoder(c.NewEmitter(w))
}

func ( c Codec ) NewEncoder ( w io . Writer ) * Encoder { return NewEncoder ( c . NewEmitter ( w ) ) }

// NewEncoder returns a new encoder that outputs to w.

NewEncoder returns a new encoder that outputs to w .


func (c Codec) NewDecoder(r io.Reader) *Decoder {
	return NewDecoder(c.NewParser(r))
}

func ( c Codec ) NewDecoder ( r io . Reader ) * Decoder { return NewDecoder ( c . NewParser ( r ) ) }

// NewDecoder returns a new decoder that takes input from r.

NewDecoder returns a new decoder that takes input from r .


func (c Codec) NewStreamEncoder(w io.Writer) *StreamEncoder {
	return NewStreamEncoder(c.NewEmitter(w))
}

func ( c Codec ) NewStreamEncoder ( w io . Writer ) * StreamEncoder { return NewStreamEncoder ( c . NewEmitter ( w ) ) }

// NewStreamEncoder returns a new stream encoder that outputs to w.

NewStreamEncoder returns a new stream encoder that outputs to w .


func (c Codec) NewStreamDecoder(r io.Reader) *StreamDecoder {
	return NewStreamDecoder(c.NewParser(r))
}

func ( c Codec ) NewStreamDecoder ( r io . Reader ) * StreamDecoder { return NewStreamDecoder ( c . NewParser ( r ) ) }

// NewStreamDecoder returns a new stream decoder that takes input from r.

NewStreamDecoder returns a new stream decoder that takes input from r .


func (reg *Registry) Register(mimetype string, codec Codec) {
	defer reg.mutex.Unlock()
	reg.mutex.Lock()

	if reg.codecs == nil {
		reg.codecs = make(map[string]Codec)
	}

	reg.codecs[mimetype] = codec
}

func ( reg * Registry ) Register ( mimetype string , codec Codec ) { defer reg . mutex . Unlock ( ) reg . mutex . Lock ( ) if reg . codecs == nil { reg . codecs = make ( map [ string ] Codec ) } reg . codecs [ mimetype ] = codec }

// Register adds a codec for a mimetype to r.

Register adds a codec for a mimetype to r .


func (reg *Registry) Unregister(mimetype string) {
	defer reg.mutex.Unlock()
	reg.mutex.Lock()

	delete(reg.codecs, mimetype)
}

func ( reg * Registry ) Unregister ( mimetype string ) { defer reg . mutex . Unlock ( ) reg . mutex . Lock ( ) delete ( reg . codecs , mimetype ) }

// Unregister removes the codec for a mimetype from r.

Unregister removes the codec for a mimetype from r .


func (reg *Registry) Lookup(mimetype string) (codec Codec, ok bool) {
	reg.mutex.RLock()
	codec, ok = reg.codecs[mimetype]
	reg.mutex.RUnlock()
	return
}

func ( reg * Registry ) Lookup ( mimetype string ) ( codec Codec , ok bool ) { reg . mutex . RLock ( ) codec , ok = reg . codecs [ mimetype ] reg . mutex . RUnlock ( ) return }

// Lookup returns the codec associated with mimetype, ok is set to true or false
// based on whether a codec was found.

Lookup returns the codec associated with mimetype ok is set to true or false based on whether a codec was found .


func (reg *Registry) Codecs() (codecs map[string]Codec) {
	codecs = make(map[string]Codec)
	reg.mutex.RLock()
	for mimetype, codec := range reg.codecs {
		codecs[mimetype] = codec
	}
	reg.mutex.RUnlock()
	return
}

func ( reg * Registry ) Codecs ( ) ( codecs map [ string ] Codec ) { codecs = make ( map [ string ] Codec ) reg . mutex . RLock ( ) for mimetype , codec := range reg . codecs { codecs [ mimetype ] = codec } reg . mutex . RUnlock ( ) return }

// Codecs returns a map of all codecs registered in reg.

Codecs returns a map of all codecs registered in reg .


func (e *Error) Type() string {
	s := e.Error()

	if i := strings.IndexByte(s, ' '); i < 0 {
		s = ""
	} else {
		s = s[:i]

		for _, c := range s {
			if !unicode.IsUpper(c) {
				s = ""
				break
			}
		}
	}

	return s
}

func
(
e
*
Error
)
Type
(
)
string
{
s
:=
e
.
Error
(
)
if
i
:=
strings
.
IndexByte
(
s
,
' '
)
;
i
<
0
{
s
=
"
"
}
else
{
s
=
s
[
:
i
]
for
_
,
c
:=
range
s
{
if
!
unicode
.
IsUpper
(
c
)
{
s
=
"
"
break
}
}
}
return
s
}

// Type returns the RESP error type, which is represented by the leading
// uppercase word in the error string.

Type returns the RESP error type which is represented by the leading uppercase word in the error string .


func Install(typ reflect.Type, adapter Adapter) {
	if adapter.Encode == nil {
		panic("objconv: the encoder function of an adapter cannot be nil")
	}

	if adapter.Decode == nil {
		panic("objconv: the decoder function of an adapter cannot be nil")
	}

	adapterMutex.Lock()
	adapterStore[typ] = adapter
	adapterMutex.Unlock()

	// We have to clear the struct cache because it may now have become invalid.
	// Because installing adapters is done in the package initialization phase
	// it's unlikely that any encoding or decoding operations are taking place
	// at this time so there should be no performance impact of clearing the
	// cache.
	structCache.clear()
}

// Install adds an adapter for typ.
//
// The function panics if one of the encoder and decoder functions of the
// adapter are nil.
//
// A typical use case for this function is to be called during the package
// initialization phase to extend objconv support for new types.

Install adds an adapter for typ . The function panics if one of the encoder and decoder functions of the adapter are nil . A typical use case for this function is to be called during the package initialization phase to extend objconv support for new types .


func AdapterOf(typ reflect.Type) (a Adapter, ok bool) {
	adapterMutex.RLock()
	a, ok = adapterStore[typ]
	adapterMutex.RUnlock()
	return
}

func AdapterOf ( typ reflect . Type ) ( a Adapter , ok bool ) { adapterMutex . RLock ( ) a , ok = adapterStore [ typ ] adapterMutex . RUnlock ( ) return }

// AdapterOf returns the adapter for typ, setting ok to true if one was found,
// false otherwise.

AdapterOf returns the adapter for typ setting ok to true if one was found false otherwise .


func AppendDuration(b []byte, d time.Duration) []byte {
	// Largest time is 2540400h10m10.000000000s
	var buf [32]byte
	w := len(buf)

	u := uint64(d)
	neg := d < 0
	if neg {
		u = -u
	}

	if u < uint64(time.Second) {
		// Special case: if duration is smaller than a second,
		// use smaller units, like 1.2ms
		var prec int
		w--
		buf[w] = 's'
		w--
		switch {
		case u == 0:
			return append(b, '0', 's')
		case u < uint64(time.Microsecond):
			// print nanoseconds
			prec = 0
			buf[w] = 'n'
		case u < uint64(time.Millisecond):
			// print microseconds
			prec = 3
			// U+00B5 'µ' micro sign == 0xC2 0xB5
			w-- // Need room for two bytes.
			copy(buf[w:], "µ")
		default:
			// print milliseconds
			prec = 6
			buf[w] = 'm'
		}
		w, u = fmtFrac(buf[:w], u, prec)
		w = fmtInt(buf[:w], u)
	} else {
		w--
		buf[w] = 's'

		w, u = fmtFrac(buf[:w], u, 9)

		// u is now integer seconds
		w = fmtInt(buf[:w], u%60)
		u /= 60

		// u is now integer minutes
		if u > 0 {
			w--
			buf[w] = 'm'
			w = fmtInt(buf[:w], u%60)
			u /= 60

			// u is now integer hours
			// Stop at hours because days can be different lengths.
			if u > 0 {
				w--
				buf[w] = 'h'
				w = fmtInt(buf[:w], u)
			}
		}
	}

	if neg {
		w--
		buf[w] = '-'
	}

	return append(b, buf[w:]...)
}

// AppendDuration appends a human-readable representation of d to b.
//
// The function copies the implementation of time.Duration.String but prevents
// Go from making a dynamic memory allocation on the returned value.

AppendDuration appends a human - readable representation of d to b . The function copies the implementation of time . Duration . String but prevents Go from making a dynamic memory allocation on the returned value .


func fmtInt(buf []byte, v uint64) int {
	w := len(buf)
	if v == 0 {
		w--
		buf[w] = '0'
	} else {
		for v > 0 {
			w--
			buf[w] = byte(v%10) + '0'
			v /= 10
		}
	}
	return w
}

func fmtInt ( buf [ ] byte , v uint64 ) int { w := len ( buf ) if v == 0 { w -- buf [ w ] = '0' } else { for v > 0 { w -- buf [ w ] = byte ( v % 10 ) + '0' v /= 10 } } return w }

// fmtInt formats v into the tail of buf.
// It returns the index where the output begins.

fmtInt formats v into the tail of buf . It returns the index where the output begins .


func NewDecoder(r io.Reader) *objconv.Decoder {
	return objconv.NewDecoder(NewParser(r))
}

func NewDecoder ( r io . Reader ) * objconv . Decoder { return objconv . NewDecoder ( NewParser ( r ) ) }

// NewDecoder returns a new JSON decoder that parses values from r.

NewDecoder returns a new JSON decoder that parses values from r .


func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder {
	return objconv.NewStreamDecoder(NewParser(r))
}

func NewStreamDecoder ( r io . Reader ) * objconv . StreamDecoder { return objconv . NewStreamDecoder ( NewParser ( r ) ) }

// NewStreamDecoder returns a new JSON stream decoder that parses values from r.

NewStreamDecoder returns a new JSON stream decoder that parses values from r .


func Unmarshal(b []byte, v interface{}) error {
	u := unmarshalerPool.Get().(*unmarshaler)
	u.reset(b)

	err := (objconv.Decoder{Parser: u}).Decode(v)

	u.reset(nil)
	unmarshalerPool.Put(u)
	return err
}

func Unmarshal ( b [ ] byte , v interface { } ) error { u := unmarshalerPool . Get ( ) . ( * unmarshaler ) u . reset ( b ) err := ( objconv . Decoder { Parser : u } ) . Decode ( v ) u . reset ( nil ) unmarshalerPool . Put ( u ) return err }

// Unmarshal decodes a JSON representation of v from b.

Unmarshal decodes a JSON representation of v from b .


func (t Type) String() string {
	switch t {
	case Nil:
		return "nil"
	case Bool:
		return "bool"
	case Int:
		return "int"
	case Uint:
		return "uint"
	case Float:
		return "float"
	case String:
		return "string"
	case Bytes:
		return "bytes"
	case Time:
		return "time"
	case Duration:
		return "duration"
	case Error:
		return "error"
	case Array:
		return "array"
	case Map:
		return "map"
	default:
		return "<type>"
	}
}

func ( t Type ) String ( ) string { switch t { case Nil : return " " case Bool : return " " case Int : return " " case Uint : return " " case Float : return " " case String : return " " case Bytes : return " " case Time : return " " case Duration : return " " case Error : return " " case Array : return " " case Map : return " " default : return " " } }

// String returns a human readable representation of the type.

String returns a human readable representation of the type .


func zeroValueOf(t reflect.Type) reflect.Value {
	zeroMutex.RLock()
	v, ok := zeroCache[t]
	zeroMutex.RUnlock()

	if !ok {
		v = reflect.Zero(t)
		zeroMutex.Lock()
		zeroCache[t] = v
		zeroMutex.Unlock()
	}

	return v
}

func zeroValueOf ( t reflect . Type ) reflect . Value { zeroMutex . RLock ( ) v , ok := zeroCache [ t ] zeroMutex . RUnlock ( ) if ! ok { v = reflect . Zero ( t ) zeroMutex . Lock ( ) zeroCache [ t ] = v zeroMutex . Unlock ( ) } return v }

// zeroValueOf and the related cache is used to keep the zero values so they
// don't need to be reallocated every time they're used.

zeroValueOf and the related cache is used to keep the zero values so they don t need to be reallocated every time they re used .


func NewValueParser(v interface{}) *ValueParser {
	return &ValueParser{
		stack: []reflect.Value{reflect.ValueOf(v)},
	}
}

func NewValueParser ( v interface { } ) * ValueParser { return & ValueParser { stack : [ ] reflect . Value { reflect . ValueOf ( v ) } , } }

// NewValueParser creates a new parser that exposes the value v.

NewValueParser creates a new parser that exposes the value v .


func ParseTag(s string) Tag {
	var name string
	var omitzero bool
	var omitempty bool

	name, s = parseNextTagToken(s)

	for len(s) != 0 {
		var token string
		switch token, s = parseNextTagToken(s); token {
		case "omitempty":
			omitempty = true
		case "omitzero":
			omitzero = true
		}
	}

	return Tag{
		Name:      name,
		Omitempty: omitempty,
		Omitzero:  omitzero,
	}
}

func ParseTag ( s string ) Tag { var name string var omitzero bool var omitempty bool name , s = parseNextTagToken ( s ) for len ( s ) != 0 { var token string switch token , s = parseNextTagToken ( s ) ; token { case " " : omitempty = true case " " : omitzero = true } } return Tag { Name : name , Omitempty : omitempty , Omitzero : omitzero , } }

// ParseTag parses a raw tag obtained from a struct field, returning the results
// as a tag value.

ParseTag parses a raw tag obtained from a struct field returning the results as a tag value .


func NewEncoder(w io.Writer) *objconv.Encoder {
	return objconv.NewEncoder(NewEmitter(w))
}

func NewEncoder ( w io . Writer ) * objconv . Encoder { return objconv . NewEncoder ( NewEmitter ( w ) ) }

// NewEncoder returns a new JSON encoder that writes to w.

NewEncoder returns a new JSON encoder that writes to w .


func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder {
	return objconv.NewStreamEncoder(NewEmitter(w))
}

func NewStreamEncoder ( w io . Writer ) * objconv . StreamEncoder { return objconv . NewStreamEncoder ( NewEmitter ( w ) ) }

// NewStreamEncoder returns a new JSON stream encoder that writes to w.

NewStreamEncoder returns a new JSON stream encoder that writes to w .


func NewPrettyEncoder(w io.Writer) *objconv.Encoder {
	return objconv.NewEncoder(NewPrettyEmitter(w))
}

func NewPrettyEncoder ( w io . Writer ) * objconv . Encoder { return objconv . NewEncoder ( NewPrettyEmitter ( w ) ) }

// NewPrettyEncoder returns a new JSON encoder that writes to w.

NewPrettyEncoder returns a new JSON encoder that writes to w .


func NewPrettyStreamEncoder(w io.Writer) *objconv.StreamEncoder {
	return objconv.NewStreamEncoder(NewPrettyEmitter(w))
}

func NewPrettyStreamEncoder ( w io . Writer ) * objconv . StreamEncoder { return objconv . NewStreamEncoder ( NewPrettyEmitter ( w ) ) }

// NewPrettyStreamEncoder returns a new JSON stream encoder that writes to w.

NewPrettyStreamEncoder returns a new JSON stream encoder that writes to w .


func Marshal(v interface{}) (b []byte, err error) {
	m := marshalerPool.Get().(*marshaler)
	m.b.Truncate(0)

	if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil {
		b = make([]byte, m.b.Len())
		copy(b, m.b.Bytes())
	}

	marshalerPool.Put(m)
	return
}

func Marshal ( v interface { } ) ( b [ ] byte , err error ) { m := marshalerPool . Get ( ) . ( * marshaler ) m . b . Truncate ( 0 ) if err = ( objconv . Encoder { Emitter : m } ) . Encode ( v ) ; err == nil { b = make ( [ ] byte , m . b . Len ( ) ) copy ( b , m . b . Bytes ( ) ) } marshalerPool . Put ( m ) return }

// Marshal writes the JSON representation of v to a byte slice returned in b.

Marshal writes the JSON representation of v to a byte slice returned in b .


func NewEncoder(e Emitter) *Encoder {
	if e == nil {
		panic("objconv: the emitter is nil")
	}
	return &Encoder{Emitter: e}
}

func NewEncoder ( e Emitter ) * Encoder { if e == nil { panic ( " " ) } return & Encoder { Emitter : e } }

// NewEncoder returns a new encoder that outputs values to e.
//
// Encoders created by this function use the default encoder configuration,
// which is equivalent to using a zero-value EncoderConfig with only the Emitter
// field set.
//
// The function panics if e is nil.

NewEncoder returns a new encoder that outputs values to e . Encoders created by this function use the default encoder configuration which is equivalent to using a zero - value EncoderConfig with only the Emitter field set . The function panics if e is nil .