func (o *Object) GetMetadataAll(attr bool) map[string]string {
	metadataAll := make(map[string]string)
	for k, v := range o.Metadata {
		metadataAll[k] = v.value
	}
	return metadataAll
}

func ( o * Object ) GetMetadataAll ( attr bool ) map [ string ] string { metadataAll := make ( map [ string ] string ) for k , v := range o . Metadata { metadataAll [ k ] = v . value } return metadataAll }

// GetMetadataAll gets a map that contains all metadata of the object.

GetMetadataAll gets a map that contains all metadata of the object .


func (x *Exception) SetRule(rule string) error {
	ruleRegexp, err := regexp.Compile("(?i)" + rule)
	if err != nil {
		return err
	}
	x.Rule = ruleRegexp
	return nil
}

func ( x * Exception ) SetRule ( rule string ) error { ruleRegexp , err := regexp . Compile ( " " + rule ) if err != nil { return err } x . Rule = ruleRegexp return nil }

// SetRule sets the regular expresion that should match the name of the rule.

SetRule sets the regular expresion that should match the name of the rule .


func (x *Exception) SetObject(object string) error {
	objectRegexp, err := regexp.Compile("(?i)" + object)
	if err != nil {
		return err
	}
	x.Object = objectRegexp
	return nil
}

func ( x * Exception ) SetObject ( object string ) error { objectRegexp , err := regexp . Compile ( " " + object ) if err != nil { return err } x . Object = objectRegexp return nil }

// SetObject sets the regular expresion that should match the name of the
// object.

SetObject sets the regular expresion that should match the name of the object .


func (x *Exception) SetNline(nLine int) error {
	x.Nline = &nLine
	return nil
}

func ( x * Exception ) SetNline ( nLine int ) error { x . Nline = & nLine return nil }

// SetNline sets the number of line where secret should be found.

SetNline sets the number of line where secret should be found .


func (x *Exception) SetContent(content string) error {
	contentRegexp, err := regexp.Compile("(?i)" + content)
	if err != nil {
		return err
	}
	x.Content = contentRegexp
	return nil
}

func ( x * Exception ) SetContent ( content string ) error { contentRegexp , err := regexp . Compile ( " " + content ) if err != nil { return err } x . Content = contentRegexp return nil }

// SetContent sets the regular expresion that should match the content of the
// object.

SetContent sets the regular expresion that should match the content of the object .


func (x *Exception) Run(s *Secret) bool {
	match := true

	if match && x.Rule != nil && !x.Rule.MatchString(s.Rule.Name) {
		match = false
	}

	if match && x.Object != nil && !x.Object.MatchString(s.Object.Name) {
		match = false
	}

	if match && x.Nline != nil && *x.Nline != s.Nline {
		match = false
	}

	if match && x.Content != nil && !x.Content.MatchString(s.Line) {
		match = false
	}

	return match
}

func ( x * Exception ) Run ( s * Secret ) bool { match := true if match && x . Rule != nil && ! x . Rule . MatchString ( s . Rule . Name ) { match = false } if match && x . Object != nil && ! x . Object . MatchString ( s . Object . Name ) { match = false } if match && x . Nline != nil && * x . Nline != s . Nline { match = false } if match && x . Content != nil && ! x . Content . MatchString ( s . Line ) { match = false } return match }

// Run executes the exception into a secret to determine if it's an exception
// or not.

Run executes the exception into a secret to determine if it s an exception or not .


func (s *Seekret) AddRule(rule models.Rule, enabled bool) {
	if enabled {
		rule.Enable()
	}
	s.ruleList = append(s.ruleList, rule)
}

func ( s * Seekret ) AddRule ( rule models . Rule , enabled bool ) { if enabled { rule . Enable ( ) } s . ruleList = append ( s . ruleList , rule ) }

// AddRule adds a new rule into the context.

AddRule adds a new rule into the context .


func (s *Seekret) LoadRulesFromFile(file string, defaulEnabled bool) error {
	var ruleYamlMap map[string]ruleYaml

	if file == "" {
		return nil
	}

	filename, _ := filepath.Abs(file)

	ruleBase := filepath.Base(filename)
	if filepath.Ext(ruleBase) == ".rule" {
		ruleBase = ruleBase[0 : len(ruleBase)-5]
	}

	yamlData, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(yamlData, &ruleYamlMap)
	if err != nil {
		return err
	}

	for k, v := range ruleYamlMap {
		rule, err := models.NewRule(ruleBase+"."+k, v.Match)
		if err != nil {
			return err
		}

		for _, e := range v.Unmatch {
			rule.AddUnmatch(e)
		}
		s.AddRule(*rule, defaulEnabled)
	}

	return nil
}

func ( s * Seekret ) LoadRulesFromFile ( file string , defaulEnabled bool ) error { var ruleYamlMap map [ string ] ruleYaml if file == " " { return nil } filename , _ := filepath . Abs ( file ) ruleBase := filepath . Base ( filename ) if filepath . Ext ( ruleBase ) == " " { ruleBase = ruleBase [ 0 : len ( ruleBase ) - 5 ] } yamlData , err := ioutil . ReadFile ( filename ) if err != nil { return err } err = yaml . Unmarshal ( yamlData , & ruleYamlMap ) if err != nil { return err } for k , v := range ruleYamlMap { rule , err := models . NewRule ( ruleBase + " " + k , v . Match ) if err != nil { return err } for _ , e := range v . Unmatch { rule . AddUnmatch ( e ) } s . AddRule ( * rule , defaulEnabled ) } return nil }

// LoadRulesFromFile loads rules from a YAML file.

LoadRulesFromFile loads rules from a YAML file .


func (s *Seekret) LoadRulesFromDir(dir string, defaulEnabled bool) error {
	fi, err := os.Stat(dir)
	if err != nil {
		return err
	}

	if !fi.IsDir() {
		err := fmt.Errorf("%s is not a directory", dir)
		return err
	}

	fileList, err := filepath.Glob(dir + "/*")
	if err != nil {
		return err
	}
	for _, file := range fileList {
		if strings.HasSuffix(file, ".rule") {
			err := s.LoadRulesFromFile(file, defaulEnabled)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func ( s * Seekret ) LoadRulesFromDir ( dir string , defaulEnabled bool ) error { fi , err := os . Stat ( dir ) if err != nil { return err } if ! fi . IsDir ( ) { err := fmt . Errorf ( " " , dir ) return err } fileList , err := filepath . Glob ( dir + " " ) if err != nil { return err } for _ , file := range fileList { if strings . HasSuffix ( file , " " ) { err := s . LoadRulesFromFile ( file , defaulEnabled ) if err != nil { return err } } } return nil }

// LoadRulesFromFile loads rules from all YAML files inside a directory.

LoadRulesFromFile loads rules from all YAML files inside a directory .


func DefaultRulesPath() string {
	rulesPath := os.Getenv("SEEKRET_RULES_PATH")
	if rulesPath == "" {
		rulesPath = os.ExpandEnv(defaultRulesDir)
	}
	return rulesPath
}

func DefaultRulesPath ( ) string { rulesPath := os . Getenv ( " " ) if rulesPath == " " { rulesPath = os . ExpandEnv ( defaultRulesDir ) } return rulesPath }

// DefaultRulesPath return the default PATH that contains rules.

DefaultRulesPath return the default PATH that contains rules .


func (s *Seekret) EnableRule(name string) error {
	return setRuleEnabled(s.ruleList, name, true)
}

func ( s * Seekret ) EnableRule ( name string ) error { return setRuleEnabled ( s . ruleList , name , true ) }


func (s *Seekret) DisableRule(name string) error {
	return setRuleEnabled(s.ruleList, name, false)
}

func ( s * Seekret ) DisableRule ( name string ) error { return setRuleEnabled ( s . ruleList , name , false ) }


func (s *Seekret) EnableRuleByRegexp(name string) int {
	return setRuleEnabledByRegexp(s.ruleList, name, true)
}

func ( s * Seekret ) EnableRuleByRegexp ( name string ) int { return setRuleEnabledByRegexp ( s . ruleList , name , true ) }

// EnableRule enables rules that match with a regular expression.

EnableRule enables rules that match with a regular expression .


func (s *Seekret) DisableRuleByRegexp(name string) int {
	return setRuleEnabledByRegexp(s.ruleList, name, false)
}

func ( s * Seekret ) DisableRuleByRegexp ( name string ) int { return setRuleEnabledByRegexp ( s . ruleList , name , false ) }

// DisableRule disables rules that match with a regular expression.

DisableRule disables rules that match with a regular expression .


func (s *Seekret) LoadObjects(st SourceType, source string, opt LoadOptions) error {
	objectList, err := st.LoadObjects(source, opt)
	if err != nil {
		return err
	}
	s.objectList = append(s.objectList, objectList...)
	return nil
}

func ( s * Seekret ) LoadObjects ( st SourceType , source string , opt LoadOptions ) error { objectList , err := st . LoadObjects ( source , opt ) if err != nil { return err } s . objectList = append ( s . objectList , objectList ... ) return nil }

// LoadObjects loads objects form an specific source. It can load objects from
// different source types, that are implemented following the SourceType
// interface.

LoadObjects loads objects form an specific source . It can load objects from different source types that are implemented following the SourceType interface .


func (s *Seekret) GroupObjectsByMetadata(k string) map[string][]models.Object {
	return models.GroupObjectsByMetadata(s.objectList, k)
}

func ( s * Seekret ) GroupObjectsByMetadata ( k string ) map [ string ] [ ] models . Object { return models . GroupObjectsByMetadata ( s . objectList , k ) }

// GroupObjectsByMetadata returns a map with all objects grouped by specific
// metadata key.

GroupObjectsByMetadata returns a map with all objects grouped by specific metadata key .


func (s *Seekret) GroupObjectsByPrimaryKeyHash() map[string][]models.Object {
	return models.GroupObjectsByPrimaryKeyHash(s.objectList)
}

func ( s * Seekret ) GroupObjectsByPrimaryKeyHash ( ) map [ string ] [ ] models . Object { return models . GroupObjectsByPrimaryKeyHash ( s . objectList ) }

// GroupObjectsByPrimaryKeyHash returns a map with all objects grouped by
// the primary key hash, that is calculated from all metadata keys with the
// primary attribute.
// All returned objects could have the same content, even if are not the same.

GroupObjectsByPrimaryKeyHash returns a map with all objects grouped by the primary key hash that is calculated from all metadata keys with the primary attribute . All returned objects could have the same content even if are not the same .


func (s *Seekret) AddException(exception models.Exception) {
	s.exceptionList = append(s.exceptionList, exception)
}

func ( s * Seekret ) AddException ( exception models . Exception ) { s . exceptionList = append ( s . exceptionList , exception ) }

// AddException adds a new exception into the context.

AddException adds a new exception into the context .


func (s *Seekret) LoadExceptionsFromFile(file string) error {
	var exceptionYamlList []exceptionYaml

	if file == "" {
		return nil
	}

	filename, _ := filepath.Abs(file)
	yamlData, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(yamlData, &exceptionYamlList)
	if err != nil {
		return err
	}

	for _, v := range exceptionYamlList {
		x := models.NewException()

		if v.Rule != nil {
			err := x.SetRule(*v.Rule)
			if err != nil {
				return err
			}
		}

		if v.Object != nil {
			err := x.SetObject(*v.Object)
			if err != nil {
				return err
			}
		}

		if v.Line != nil {
			err := x.SetNline(*v.Line)
			if err != nil {
				return err
			}
		}

		if v.Content != nil {
			err := x.SetContent(*v.Content)
			if err != nil {
				return err
			}
		}

		s.AddException(*x)
	}

	return nil
}

func ( s * Seekret ) LoadExceptionsFromFile ( file string ) error { var exceptionYamlList [ ] exceptionYaml if file == " " { return nil } filename , _ := filepath . Abs ( file ) yamlData , err := ioutil . ReadFile ( filename ) if err != nil { return err } err = yaml . Unmarshal ( yamlData , & exceptionYamlList ) if err != nil { return err } for _ , v := range exceptionYamlList { x := models . NewException ( ) if v . Rule != nil { err := x . SetRule ( * v . Rule ) if err != nil { return err } } if v . Object != nil { err := x . SetObject ( * v . Object ) if err != nil { return err } } if v . Line != nil { err := x . SetNline ( * v . Line ) if err != nil { return err } } if v . Content != nil { err := x . SetContent ( * v . Content ) if err != nil { return err } } s . AddException ( * x ) } return nil }

// LoadExceptionsFromFile loads exceptions from a YAML file.

LoadExceptionsFromFile loads exceptions from a YAML file .


func printPlainResults(results Results) error {
	for _, res := range results {
		// Explicitely start with the string and error output
		fmt.Printf("Source = %s\n", res.origString)
		fmt.Printf("    String = %s\n", res.String)

		if res.Error != "" {
			fmt.Printf("    Error = %s\n", res.Error)
			continue
		}

		// Dynamically loop over the rest of the fields
		typ := reflect.TypeOf(*res)
		val := reflect.ValueOf(*res)

		for i := 0; i < typ.NumField(); i++ {
			field := typ.Field(i)
			if field.Name == "Error" || field.Name == "String" {
				continue
			}
			if field.PkgPath != "" {
				// ignore unexported fields
				continue
			}
			fmt.Printf("    %s = %v\n", field.Name, val.Field(i).Interface())
		}

		fmt.Print("\n")
	}
	return nil
}

// printPlainResults prints plain-text output for results

printPlainResults prints plain - text output for results


func printJsonResults(results Results) error {
	data, err := json.MarshalIndent(results, "", "    ")
	if err != nil {
		return fmt.Errorf("Failed to convert results to JSON: %s", err.Error())
	}

	if _, err = io.Copy(os.Stdout, bytes.NewReader(data)); err != nil {
		return fmt.Errorf("Failed to write json output: %s", err.Error())
	}

	fmt.Print("\n")
	return nil
}

func printJsonResults ( results Results ) error { data , err := json . MarshalIndent ( results , " " , " " ) if err != nil { return fmt . Errorf ( " " , err . Error ( ) ) } if _ , err = io . Copy ( os . Stdout , bytes . NewReader ( data ) ) ; err != nil { return fmt . Errorf ( " " , err . Error ( ) ) } fmt . Print ( " \n " ) return nil }

// printJsonResults prints json-formatted output for results

printJsonResults prints json - formatted output for results


func NewXor64Source(seed int64) *Xor64Source {
	var s Xor64Source
	s.Seed(seed)
	return &s
}

func NewXor64Source ( seed int64 ) * Xor64Source { var s Xor64Source s . Seed ( seed ) return & s }

// NewXor64Source returns a pointer to a new Xor64Source seeded with the given
// value.

NewXor64Source returns a pointer to a new Xor64Source seeded with the given value .


func xor64(x uint64) uint64 {
	x ^= x << 13
	x ^= x >> 7
	x ^= x << 17
	return x
}

func xor64 ( x uint64 ) uint64 { x ^= x << 13 x ^= x >> 7 x ^= x << 17 return x }

// xor64 generates the next value of a pseudo-random sequence given a current
// state x.

xor64 generates the next value of a pseudo - random sequence given a current state x .


func (s *Xor64Source) next() uint64 {
	x := xor64(uint64(*s))
	*s = Xor64Source(x)
	return x
}

func ( s * Xor64Source ) next ( ) uint64 { x := xor64 ( uint64 ( * s ) ) * s = Xor64Source ( x ) return x }

// next advances the generators internal state to the next value and returns
// this value as an uint64.

next advances the generators internal state to the next value and returns this value as an uint64 .


func (s *Xor64Source) Seed(seed int64) {
	if seed == 0 {
		seed = seed0
	}
	*s = Xor64Source(seed)
}

func ( s * Xor64Source ) Seed ( seed int64 ) { if seed == 0 { seed = seed0 } * s = Xor64Source ( seed ) }

// Seed uses the given value to initialize the generator. If this value is 0, a
// pre-defined seed is used instead, since the xorshift algorithm requires at
// least one bit of the internal state to be set.

Seed uses the given value to initialize the generator . If this value is 0 a pre - defined seed is used instead since the xorshift algorithm requires at least one bit of the internal state to be set .


func NewFrameSet(frange string) (*FrameSet, error) {
	// Process the frame range and get a slice of match slices
	matches, err := frameRangeMatches(frange)
	if err != nil {
		return nil, err
	}

	frameSet := &FrameSet{frange, &ranges.InclusiveRanges{}}

	// Process each slice match and add it to the frame set
	for _, match := range matches {
		if err = frameSet.handleMatch(match); err != nil {
			return nil, err
		}
	}

	return frameSet, nil
}

// Create a new FrameSet from a given frame range string
// Returns an error if the frame range could not be parsed.

Create a new FrameSet from a given frame range string Returns an error if the frame range could not be parsed .


func (s *FrameSet) handleMatch(match []string) error {
	switch len(match) {

	// Single frame match
	case 1:
		f, err := parseInt(match[0])
		if err != nil {
			return err
		}
		s.rangePtr.AppendUnique(f, f, 1)

	// Simple frame range
	case 2:
		start, err := parseInt(match[0])
		if err != nil {
			return err
		}
		end, err := parseInt(match[1])
		if err != nil {
			return err
		}

		// Handle descending frame ranges, like 10-1
		var inc int
		if start > end {
			inc = -1
		} else {
			inc = 1
		}

		s.rangePtr.AppendUnique(start, end, inc)

	// Complex frame range
	case 4:
		var (
			err               error
			mod               string
			start, end, chunk int
		)
		chunk, err = parseInt(match[3])
		if err != nil {
			return err
		}
		if chunk == 0 {
			return fmt.Errorf("Failed to parse part of range %v. "+
				"Encountered invalid 0 value", match[3])
		}
		if start, err = parseInt(match[0]); err != nil {
			return err
		}
		if end, err = parseInt(match[1]); err != nil {
			return err
		}
		if mod = match[2]; !isModifier(mod) {
			return fmt.Errorf("%q is not one of the valid modifier 'xy:'", mod)
		}

		switch mod {
		case `x`:
			s.rangePtr.AppendUnique(start, end, chunk)

		case `y`:
			// TODO: Add proper support for adding inverse of range.
			// This approach will add excessive amounts of singe
			// range elements. They could be compressed into chunks
			skip := start
			aRange := ranges.NewInclusiveRange(start, end, 1)
			var val int
			for it := aRange.IterValues(); !it.IsDone(); {
				val = it.Next()
				if val == skip {
					skip += chunk
					continue
				}
				s.rangePtr.AppendUnique(val, val, 1)
			}

		case `:`:
			for ; chunk > 0; chunk-- {
				s.rangePtr.AppendUnique(start, end, chunk)
			}
		}

	default:
		return fmt.Errorf("Unexpected match []string size: %v", match)
	}

	return nil
}


func (s *FrameSet) Index(frame int) int {
	return s.rangePtr.Index(frame)
}

func ( s * FrameSet ) Index ( frame int ) int { return s . rangePtr . Index ( frame ) }

// Index returns the index position of the frame value
// within the frame set.
// If the given frame does not exist, then return -1

Index returns the index position of the frame value within the frame set . If the given frame does not exist then return - 1


func (s *FrameSet) Frame(index int) (int, error) {
	return s.rangePtr.Value(index)
}

func ( s * FrameSet ) Frame ( index int ) ( int , error ) { return s . rangePtr . Value ( index ) }

// Frame returns the frame number value for a given index into
// the frame set.
// If the index is outside the bounds of the frame set range,
// then an error is returned.

Frame returns the frame number value for a given index into the frame set . If the index is outside the bounds of the frame set range then an error is returned .


func (s *FrameSet) HasFrame(frame int) bool {
	return s.rangePtr.Contains(frame)
}

func ( s * FrameSet ) HasFrame ( frame int ) bool { return s . rangePtr . Contains ( frame ) }

// HasFrame returns true if the frameset contains the given
// frame value.

HasFrame returns true if the frameset contains the given frame value .


func (s *FrameSet) FrameRangePadded(pad int) string {
	return PadFrameRange(s.frange, pad)
}

func ( s * FrameSet ) FrameRangePadded ( pad int ) string { return PadFrameRange ( s . frange , pad ) }

// FrameRangePadded returns the range string that was used
// to initialize the FrameSet, with each number padded out
// with zeros to a given width

FrameRangePadded returns the range string that was used to initialize the FrameSet with each number padded out with zeros to a given width


func (s *FrameSet) Normalize() *FrameSet {
	ptr := s.rangePtr.Normalized()
	return &FrameSet{ptr.String(), ptr}
}

func ( s * FrameSet ) Normalize ( ) * FrameSet { ptr := s . rangePtr . Normalized ( ) return & FrameSet { ptr . String ( ) , ptr } }

// Normalize returns a new sorted and compacted FrameSet


func FramesToFrameRange(frames []int, sorted bool, zfill int) string {
	count := len(frames)
	if count == 0 {
		return ""
	}

	if count == 1 {
		return zfillInt(frames[0], zfill)
	}

	if sorted {
		sort.Ints(frames)
	}

	var i, frame, step int
	var start, end string
	var buf strings.Builder

	// Keep looping until all frames are consumed
	for len(frames) > 0 {
		count = len(frames)
		// If we get to the last element, just write it
		// and end
		if count <= 2 {
			for _, frame = range frames {
				if buf.Len() > 0 {
					buf.WriteString(",")
				}
				buf.WriteString(zfillInt(frame, zfill))
			}
			break
		}
		// At this point, we have 3 or more frames to check.
		// Scan the current window of the slice to see how
		// many frames we can consume into a group
		step = frames[1] - frames[0]
		for i = 0; i < len(frames)-1; i++ {
			// We have scanned as many frames as we can
			// for this group. Now write them and stop
			// looping on this window
			if (frames[i+1] - frames[i]) != step {
				break
			}
		}

		// Subsequent groups are comma-separated
		if buf.Len() > 0 {
			buf.WriteString(",")
		}

		// We only have a single frame to write for this group
		if i == 0 {
			buf.WriteString(zfillInt(frames[0], zfill))
			frames = frames[1:]
			continue
		}

		// First do a check to see if we could have gotten a larger range
		// out of subsequent values with a different step size
		if i == 1 && count > 3 {
			// Check if the next two pairwise frames have the same step.
			// If so, then it is better than our current grouping.
			if (frames[2] - frames[1]) == (frames[3] - frames[2]) {
				// Just consume the first frame, and allow the next
				// loop to scan the new stepping
				buf.WriteString(zfillInt(frames[0], zfill))
				frames = frames[1:]
				continue
			}
		}

		// Otherwise write out this step range
		start = zfillInt(frames[0], zfill)
		end = zfillInt(frames[i], zfill)
		buf.WriteString(fmt.Sprintf("%s-%s", start, end))
		if step > 1 {
			buf.WriteString(fmt.Sprintf("x%d", step))
		}
		frames = frames[i+1:]
	}

	return buf.String()
}

// FramesToFrameRange takes a slice of frame numbers and
// compresses them into a frame range string.
//
// If sorted == true, pre-sort the frames instead of respecting
// their current order in the range.
//
// If zfill > 1, then pad out each number with "0" to the given
// total width.

FramesToFrameRange takes a slice of frame numbers and compresses them into a frame range string . If sorted == true pre - sort the frames instead of respecting their current order in the range . If zfill > 1 then pad out each number with 0 to the given total width .


func frameRangeMatches(frange string) ([][]string, error) {
	for _, k := range defaultPadding.AllChars() {
		frange = strings.Replace(frange, k, "", -1)
	}

	var (
		matched bool
		match   []string
		rx      *regexp.Regexp
	)

	frange = strings.Replace(frange, " ", "", -1)

	// For each comma-sep component, we will parse a frame range
	parts := strings.Split(frange, ",")
	size := len(parts)
	matches := make([][]string, size, size)

	for i, part := range parts {

		matched = false

		// Build up frames for all comma-sep components
		for _, rx = range rangePatterns {
			if match = rx.FindStringSubmatch(part); match == nil {
				continue
			}
			matched = true
			matches[i] = match[1:]
		}

		// If any component of the comma-sep frame range fails to
		// parse, we bail out
		if !matched {
			err := fmt.Errorf("Failed to parse frame range: %s on part %q", frange, part)
			return nil, err
		}
	}

	return matches, nil
}

// frameRangeMatches breaks down the string frame range
// into groups of range matches, for further processing.

frameRangeMatches breaks down the string frame range into groups of range matches for further processing .


func toRange(start, end, step int) []int {
	nums := []int{}
	if step < 1 {
		step = 1
	}
	if start <= end {
		for i := start; i <= end; {
			nums = append(nums, i)
			i += step
		}
	} else {
		for i := start; i >= end; {
			nums = append(nums, i)
			i -= step
		}
	}
	return nums
}

func toRange ( start , end , step int ) [ ] int { nums := [ ] int { } if step < 1 { step = 1 } if start <= end { for i := start ; i <= end ; { nums = append ( nums , i ) i += step } } else { for i := start ; i >= end ; { nums = append ( nums , i ) i -= step } } return nums }

// Expands a start, end, and stepping value
// into the full range of int values.

Expands a start end and stepping value into the full range of int values .


func NewWorkManager() *workManager {
	var fileopts []fileseq.FileOption
	if Options.AllFiles {
		fileopts = append(fileopts, fileseq.HiddenFiles)
	}
	if !Options.SeqsOnly {
		fileopts = append(fileopts, fileseq.SingleFiles)
	}

	s := &workManager{
		inDirs:   make(chan string),
		inSeqs:   make(chan *fileseq.FileSequence),
		outSeqs:  make(chan fileseq.FileSequences),
		fileOpts: fileopts,
	}
	return s
}

func NewWorkManager ( ) * workManager { var fileopts [ ] fileseq . FileOption if Options . AllFiles { fileopts = append ( fileopts , fileseq . HiddenFiles ) } if ! Options . SeqsOnly { fileopts = append ( fileopts , fileseq . SingleFiles ) } s := & workManager { inDirs : make ( chan string ) , inSeqs : make ( chan * fileseq . FileSequence ) , outSeqs : make ( chan fileseq . FileSequences ) , fileOpts : fileopts , } return s }

// Create a new workManager, with input and output channels,
// with a given list of options

Create a new workManager with input and output channels with a given list of options


func (w *workManager) processSources() {
	var (
		ok   bool
		path string
		seq  *fileseq.FileSequence
	)

	fileopts := w.fileOpts

	inDirs := w.inDirs
	inSeqs := w.inSeqs
	outSeqs := w.outSeqs

	isDone := func() bool {
		return (inDirs == nil && inSeqs == nil)
	}

	for !isDone() {
		select {

		// Directory paths will be scanned for contents
		case path, ok = <-inDirs:
			if !ok {
				inDirs = nil
				continue
			}
			seqs, err := fileseq.FindSequencesOnDisk(path, fileopts...)
			if err != nil {
				fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, path, err)
				continue
			}
			outSeqs <- seqs

		// Sequence paths will be scanned for a direct match
		// against the sequence pattern
		case seq, ok = <-inSeqs:
			if !ok {
				inSeqs = nil
				continue
			}

			path, err := seq.Format("{{dir}}{{base}}{{pad}}{{ext}}")
			if err != nil {
				fmt.Fprintf(errOut, "%s %q: Not a valid path\n", ErrorPattern, path)
				continue
			}

			seq, err := fileseq.FindSequenceOnDisk(path)
			if err != nil {
				if !os.IsNotExist(err) {
					fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPattern, path, err)
				}
				continue
			}

			if seq != nil {
				outSeqs <- fileseq.FileSequences{seq}
			}
		}
	}
}

// processSources pulls from input channels, and processes
// them into the output channel until there is no more work

processSources pulls from input channels and processes them into the output channel until there is no more work


func (w *workManager) isInputDone() bool {
	if w.inDirs != nil {
		return false
	}
	if w.inSeqs != nil {
		return false
	}
	return true
}

func ( w * workManager ) isInputDone ( ) bool { if w . inDirs != nil { return false } if w . inSeqs != nil { return false } return true }

// Returns true if the input channels are nil


func (w *workManager) closeInputs() {
	if w.inDirs != nil {
		close(w.inDirs)

	}
	if w.inSeqs != nil {
		close(w.inSeqs)
	}
}

func ( w * workManager ) closeInputs ( ) { if w . inDirs != nil { close ( w . inDirs ) } if w . inSeqs != nil { close ( w . inSeqs ) } }

// CloseInputs closes the input channels indicating
// that no more paths will be loaded.

CloseInputs closes the input channels indicating that no more paths will be loaded .


func (w *workManager) load(paths []string) {
	dirs, seqs := preparePaths(paths)

	for _, s := range seqs {
		w.inSeqs <- s
	}

	for _, r := range dirs {
		w.inDirs <- r
	}
}

func ( w * workManager ) load ( paths [ ] string ) { dirs , seqs := preparePaths ( paths ) for _ , s := range seqs { w . inSeqs <- s } for _ , r := range dirs { w . inDirs <- r } }

// loadStandard takes paths and loads them into the
// dir input channel for processing

loadStandard takes paths and loads them into the dir input channel for processing


func (w *workManager) loadRecursive(paths []string) {

	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}

		var isDir bool

		if info.IsDir() {
			isDir = true
		} else if info, err = os.Stat(path); err == nil && info.IsDir() {
			isDir = true
		}

		if isDir {

			if !Options.AllFiles {
				// Skip tranversing into hidden dirs
				if len(info.Name()) > 1 && strings.HasPrefix(info.Name(), ".") {
					return walk.SkipDir
				}
			}

			// Add the path to the input channel for sequence scanning
			w.inDirs <- path
		}

		return nil
	}

	dirs, seqs := preparePaths(paths)

	for _, s := range seqs {
		w.inSeqs <- s
	}

	for _, r := range dirs {
		r := r
		if err := walk.Walk(r, walkFn); err != nil {
			if err != walk.SkipDir {
				fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, r, err)
			}
		}
	}
}

// Parallel walk the root paths and populate the path
// channel for the worker routines to consume.

Parallel walk the root paths and populate the path channel for the worker routines to consume .


func preparePaths(paths []string) ([]string, fileseq.FileSequences) {
	var (
		fi  os.FileInfo
		err error
	)

	dirs := make([]string, 0)
	seqs := make(fileseq.FileSequences, 0)
	previous := make(map[string]struct{})

	for _, p := range paths {
		p := strings.TrimSpace(filepath.Clean(p))
		if p == "" {
			continue
		}

		if _, seen := previous[p]; seen {
			continue
		}
		previous[p] = struct{}{}

		if fi, err = os.Stat(p); err != nil {

			// If the path doesn't exist, test it for
			// a valid fileseq pattern
			if seq, err := fileseq.NewFileSequence(p); err == nil {
				seqs = append(seqs, seq)
				continue
			}

			fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, p, err)
			continue
		}

		if !fi.IsDir() {
			continue
		}

		dirs = append(dirs, p)
	}

	return dirs, seqs
}

// Take a list of paths and reduce them to cleaned
// and unique paths. Return two slices, separated by
// directory paths, and sequence patterns

Take a list of paths and reduce them to cleaned and unique paths . Return two slices separated by directory paths and sequence patterns


func PadFrameRange(frange string, pad int) string {
	// We don't need to do anything if they gave us
	// an invalid pad number
	if pad < 2 {
		return frange
	}

	size := strings.Count(frange, ",") + 1
	parts := make([]string, size, size)

	for i, part := range strings.Split(frange, ",") {

		didMatch := false

		for _, rx := range rangePatterns {
			matched := rx.FindStringSubmatch(part)
			if len(matched) == 0 {
				continue
			}
			matched = matched[1:]
			size = len(matched)
			switch size {
			case 1:
				parts[i] = zfillString(matched[0], pad)
			case 2:
				parts[i] = fmt.Sprintf("%s-%s",
					zfillString(matched[0], pad),
					zfillString(matched[1], pad))
			case 4:
				parts[i] = fmt.Sprintf("%s-%s%s%s",
					zfillString(matched[0], pad),
					zfillString(matched[1], pad),
					matched[2], matched[3])
			default:
				// No match. Try the next pattern
				continue
			}
			// If we got here, we matched a case and can stop
			// checking the rest of the patterns
			didMatch = true
			break
		}
		// If we didn't match one of our expected patterns
		// then just take the original part and add it unmodified
		if !didMatch {
			parts = append(parts, part)
		}
	}
	return strings.Join(parts, ",")
}

// PadFrameRange takes a frame range string and returns a
// new range with each number padded out with zeros to a given width

PadFrameRange takes a frame range string and returns a new range with each number padded out with zeros to a given width


func zfillString(src string, z int) string {
	size := len(src)
	if size >= z {
		return src
	}

	fill := strings.Repeat("0", z-size)
	if strings.HasPrefix(src, "-") {
		return fmt.Sprintf("-%s%s", fill, src[1:])
	}
	return fmt.Sprintf("%s%s", fill, src)
}

func zfillString ( src string , z int ) string { size := len ( src ) if size >= z { return src } fill := strings . Repeat ( " " , z - size ) if strings . HasPrefix ( src , " " ) { return fmt . Sprintf ( " " , fill , src [ 1 : ] ) } return fmt . Sprintf ( " " , fill , src ) }

// Left pads a string to a given with, using "0".
// If the string begins with a negative "-" character, then
// padding is inserted between the "-" and the remaining characters.

Left pads a string to a given with using 0 . If the string begins with a negative - character then padding is inserted between the - and the remaining characters .


func zfillInt(src int, z int) string {
	if z < 2 {
		return strconv.Itoa(src)
	}
	return fmt.Sprintf(fmt.Sprintf("%%0%dd", z), src)
}

func zfillInt ( src int , z int ) string { if z < 2 { return strconv . Itoa ( src ) } return fmt . Sprintf ( fmt . Sprintf ( " " , z ) , src ) }

// Left pads an int to a given with, using "0".
// If the string begins with a negative "-" character, then
// padding is inserted between the "-" and the remaining characters.

Left pads an int to a given with using 0 . If the string begins with a negative - character then padding is inserted between the - and the remaining characters .


func NewInclusiveRange(start, end, step int) *InclusiveRange {
	if step == 0 {
		if start <= end {
			step = 1

		} else {
			step = -1
		}
	}

	r := &InclusiveRange{
		start: start,
		end:   end,
		step:  step,
	}
	return r
}

func NewInclusiveRange ( start , end , step int ) * InclusiveRange { if step == 0 { if start <= end { step = 1 } else { step = - 1 } } r := & InclusiveRange { start : start , end : end , step : step , } return r }

// NewInclusiveRange creates a new InclusiveRange instance


func (r *InclusiveRange) String() string {
	var buf strings.Builder

	// Always for a single value
	buf.WriteString(strconv.Itoa(r.Start()))

	// If we have a range, express the end value
	if r.End() != r.Start() {
		buf.WriteString(`-`)
		buf.WriteString(strconv.Itoa(r.End()))

		// Express the stepping, if its not 1
		step := r.Step()
		if step > 1 || step < -1 {
			buf.WriteString(`x`)
			buf.WriteString(strconv.Itoa(r.Step()))
		}
	}
	return buf.String()
}

// String returns a formatted string representation
// of the integer range

String returns a formatted string representation of the integer range


func (r *InclusiveRange) End() int {
	if r.isEndCached {
		return r.cachedEnd
	}

	r.isEndCached = true

	// If we aren't stepping, or we don't have
	// a full range, then just use the end value
	if r.step == 1 || r.step == -1 || r.start == r.end {
		r.cachedEnd = r.end
		return r.cachedEnd
	}

	// If the step is in the wrong direction,
	// compared to the range direction, then
	// just use the start as the end.
	if (r.end < r.start) && r.step < (r.end-r.start) {
		r.cachedEnd = r.start
		return r.cachedEnd

	} else if (r.end > r.start) && r.step > (r.end-r.start) {
		r.cachedEnd = r.start
		return r.cachedEnd
	}

	// Calculate the end, taking into account the stepping
	r.cachedEnd = r.closestInRange(r.end, r.start, r.end, r.step)
	return r.cachedEnd
}

// End returns the end of the range. This value may
// be different from the end value given when the
// range was first initialized, since it takes into
// account the stepping value. The end value may be
// shifted to the closest valid value within the
// stepped range.

End returns the end of the range . This value may be different from the end value given when the range was first initialized since it takes into account the stepping value . The end value may be shifted to the closest valid value within the stepped range .


func (r *InclusiveRange) Len() int {
	if r.isLenCached {
		return r.cachedLen
	}

	// Offset by one to include the end value
	diff := math.Abs(float64(r.end-r.start)) + 1
	r.cachedLen = int(math.Ceil(diff / math.Abs(float64(r.step))))
	r.isLenCached = true
	return r.cachedLen
}

// Len returns the number of values in the range


func (r *InclusiveRange) Min() int {
	start := r.Start()
	end := r.End()
	if start < end {
		return start
	}
	return end
}

func ( r * InclusiveRange ) Min ( ) int { start := r . Start ( ) end := r . End ( ) if start < end { return start } return end }

// Min returns the smallest value in the range


func (r *InclusiveRange) Max() int {
	start := r.Start()
	end := r.End()
	if start > end {
		return start
	}
	return end
}

func ( r * InclusiveRange ) Max ( ) int { start := r . Start ( ) end := r . End ( ) if start > end { return start } return end }

// Max returns the highest value in the range


func (r *InclusiveRange) Contains(value int) bool {
	// If we attempt to find the closest value, given
	// the start of the range and the step, we can check
	// if it is still the same number. If it hasn't changed,
	// then it is in the range.
	closest := r.closestInRange(value, r.start, r.End(), r.step)
	return closest == value
}

// Contains returns true if the given value is a valid
// value within the value range.

Contains returns true if the given value is a valid value within the value range .


func (*InclusiveRange) closestInRange(value, start, end, step int) int {
	// Possibly clamp the value if it is outside the range
	if end >= start {
		if value < start {
			return start
		} else if value > end {
			return end
		}

	} else {
		if value > start {
			return start
		} else if value < end {
			return end
		}
	}

	// No calculation needed if there is no stepping
	if step == 1 || step == -1 {
		return value
	}

	// Modified the value so that it is a properly stepped
	// increment within the range
	return (((value - start) / step) * step) + start
}

// closestInRange finds the closest valid value within the range,
// to a given value. Values outside the range are clipped to either
// the range min or max.

closestInRange finds the closest valid value within the range to a given value . Values outside the range are clipped to either the range min or max .


func (f *InclusiveRange) Index(value int) int {
	closest := f.closestInRange(value, f.start, f.End(), f.step)
	if closest != value {
		return -1
	}
	idx := (value - f.start) / f.step
	if idx < 0 {
		idx *= -1
	}
	return idx
}

func ( f * InclusiveRange ) Index ( value int ) int { closest := f . closestInRange ( value , f . start , f . End ( ) , f . step ) if closest != value { return - 1 } idx := ( value - f . start ) / f . step if idx < 0 { idx *= - 1 } return idx }

// Index returns the 0-based index of the first occurrence
// given value, within the range.
// If the value does not exist in the range, a
// value of -1 will be returned

Index returns the 0 - based index of the first occurrence given value within the range . If the value does not exist in the range a value of - 1 will be returned


func (l *InclusiveRanges) String() string {
	var buf strings.Builder
	for i, b := range l.blocks {
		if i > 0 {
			buf.WriteString(`,`)
		}
		buf.WriteString(b.String())
	}
	return buf.String()
}

func ( l * InclusiveRanges ) String ( ) string { var buf strings . Builder for i , b := range l . blocks { if i > 0 { buf . WriteString ( `,` ) } buf . WriteString ( b . String ( ) ) } return buf . String ( ) }

// String returns the formatted representation of
// the combination of all internal InclusiveRange instances

String returns the formatted representation of the combination of all internal InclusiveRange instances


func (l *InclusiveRanges) Len() int {
	var totalLen int
	for _, b := range l.blocks {
		totalLen += b.Len()
	}
	return totalLen
}

func ( l * InclusiveRanges ) Len ( ) int { var totalLen int for _ , b := range l . blocks { totalLen += b . Len ( ) } return totalLen }

// Len returns the total number of values across all ranges


func (l *InclusiveRanges) Start() int {
	for _, b := range l.blocks {
		return b.Start()
	}
	return 0
}

func ( l * InclusiveRanges ) Start ( ) int { for _ , b := range l . blocks { return b . Start ( ) } return 0 }

// Start returns the first value of the first range


func (l *InclusiveRanges) End() int {
	if l.blocks == nil {
		return 0
	}
	return l.blocks[len(l.blocks)-1].End()
}

func ( l * InclusiveRanges ) End ( ) int { if l . blocks == nil { return 0 } return l . blocks [ len ( l . blocks ) - 1 ] . End ( ) }

// End returns the last value of the last range


func (l *InclusiveRanges) Min() int {
	val := l.Start()
	for _, aRange := range l.blocks {
		next := aRange.Min()
		if next < val {
			val = next
		}
	}
	return val
}

func ( l * InclusiveRanges ) Min ( ) int { val := l . Start ( ) for _ , aRange := range l . blocks { next := aRange . Min ( ) if next < val { val = next } } return val }

// Min returns the smallest value in the total range


func (l *InclusiveRanges) Max() int {
	val := l.End()
	for _, aRange := range l.blocks {
		next := aRange.Max()
		if next > val {
			val = next
		}
	}
	return val
}

func ( l * InclusiveRanges ) Max ( ) int { val := l . End ( ) for _ , aRange := range l . blocks { next := aRange . Max ( ) if next > val { val = next } } return val }

// Max returns the highest value in the total range


func (l *InclusiveRanges) numRanges() int {
	if l.blocks == nil {
		return 0
	}
	return len(l.blocks)
}

func ( l * InclusiveRanges ) numRanges ( ) int { if l . blocks == nil { return 0 } return len ( l . blocks ) }

// NumRanges returns the number of discreet sets
// of ranges that were appended.

NumRanges returns the number of discreet sets of ranges that were appended .


func (l *InclusiveRanges) rangeAt(idx int) *InclusiveRange {
	if idx < 0 || idx >= l.numRanges() {
		return nil
	}
	return l.blocks[idx]
}

func ( l * InclusiveRanges ) rangeAt ( idx int ) * InclusiveRange { if idx < 0 || idx >= l . numRanges ( ) { return nil } return l . blocks [ idx ] }

// rangeAt returns the underlying InclusiveRange instance
// that was appended, at a given index

rangeAt returns the underlying InclusiveRange instance that was appended at a given index


func (l *InclusiveRanges) Append(start, end, step int) {
	block := NewInclusiveRange(start, end, step)
	l.blocks = append(l.blocks, block)
}

func ( l * InclusiveRanges ) Append ( start , end , step int ) { block := NewInclusiveRange ( start , end , step ) l . blocks = append ( l . blocks , block ) }

// Append creates and adds another range of values
// to the total range list.

Append creates and adds another range of values to the total range list .


func (l *InclusiveRanges) AppendUnique(start, end, step int) {
	if step == 0 {
		return
	}

	subStart := start
	subEnd := start
	subStep := step
	last := start
	pending := 0 // Track unique value count

	// Handle loop test for both increasing
	// and decreasing ranges
	var pred func() bool
	if start <= end {
		if step < 0 {
			step *= -1
		}
		pred = func() bool { return subEnd <= end }
	} else {
		if step > 0 {
			step *= -1
		}
		pred = func() bool { return subEnd >= end }
	}

	// Short-circuit if this is the first range being added
	if len(l.blocks) == 0 {
		l.Append(start, end, step)
		return
	}

	// TODO: More intelligent fast-paths for easy-to-identify
	// overlapping ranges. Such as when the existing range is:
	// 1-100x1 and we are appending 50-150x1. Should be easy
	// enough to just know we can Append(101,150,1)

	for ; pred(); subEnd += step {
		if !l.Contains(subEnd) {
			// Is a unique value in the range
			last = subEnd
			if pending == 0 {
				subStart = last
			}
			pending++
			continue
		}

		if pending == 0 {
			// Nothing to add yet
			continue
		}

		// Current value is already in range.
		// Add previous values
		l.Append(subStart, last, subStep)
		subStart = subEnd + step
		pending = 0
	}

	// Flush the remaining values
	if pending > 0 {
		l.Append(subStart, last, subStep)
	}
}

// AppendUnique creates and adds another range of values
// to the total range list. Only unique values from the
// given range are appended to the total range.

AppendUnique creates and adds another range of values to the total range list . Only unique values from the given range are appended to the total range .


func (l *InclusiveRanges) Contains(value int) bool {
	for _, b := range l.blocks {
		if b.Contains(value) {
			return true
		}
	}
	return false
}

func ( l * InclusiveRanges ) Contains ( value int ) bool { for _ , b := range l . blocks { if b . Contains ( value ) { return true } } return false }

// Contains returns true if a given value is a valid
// value within the total range.

Contains returns true if a given value is a valid value within the total range .


func (l *InclusiveRanges) Index(value int) int {
	var idx, n int

	for _, b := range l.blocks {
		// If the value is within the current block
		// then return the local index, offset by the
		// number of previous values we have tracked
		if idx = b.Index(value); idx >= 0 {
			return idx + n
		}
		// Update the offset for the values we have seen
		n += b.Len()
	}

	// The previous loop ended in error
	return -1
}

// Index returns the 0-based index of the first occurrence
// of the given value, within the range.
// If the value does not exist in the range, a
// value of -1 will be returned.

Index returns the 0 - based index of the first occurrence of the given value within the range . If the value does not exist in the range a value of - 1 will be returned .


func (s *FileSequence) FrameRange() string {
	if s.frameSet == nil {
		return ""
	}
	return s.frameSet.FrameRange()
}

func ( s * FileSequence ) FrameRange ( ) string { if s . frameSet == nil { return " " } return s . frameSet . FrameRange ( ) }

// FrameRange returns the string frame range component,
// parsed from the sequence. If no frame range was parsed,
// then this method will return an empty string.

FrameRange returns the string frame range component parsed from the sequence . If no frame range was parsed then this method will return an empty string .


func (s *FileSequence) FrameRangePadded() string {
	if s.frameSet == nil {
		return ""
	}
	return s.frameSet.FrameRangePadded(s.zfill)
}

func ( s * FileSequence ) FrameRangePadded ( ) string { if s . frameSet == nil { return " " } return s . frameSet . FrameRangePadded ( s . zfill ) }

// FrameRangePadded returns the string frame range component,
// parsed from the sequence, and padded out by the pad characters.
// If no frame range was parsed, then this method will return an empty string.

FrameRangePadded returns the string frame range component parsed from the sequence and padded out by the pad characters . If no frame range was parsed then this method will return an empty string .


func (s *FileSequence) Index(idx int) string {
	if s.frameSet == nil {
		return s.String()
	}
	frame, err := s.frameSet.Frame(idx)
	if err != nil {
		return ""
	}
	path, err := s.Frame(frame)
	if err != nil {
		return ""
	}
	return path
}

func ( s * FileSequence ) Index ( idx int ) string { if s . frameSet == nil { return s . String ( ) } frame , err := s . frameSet . Frame ( idx ) if err != nil { return " " } path , err := s . Frame ( frame ) if err != nil { return " " } return path }

// Index returns the path to the file at the given index
// in the sequence. If a frame range was not parsed from
// the sequence, this will always returns the original path.
// If the index is not valid, this will return an empty string.

Index returns the path to the file at the given index in the sequence . If a frame range was not parsed from the sequence this will always returns the original path . If the index is not valid this will return an empty string .


func (s *FileSequence) SetDirname(dir string) {
	if !strings.HasSuffix(dir, string(filepath.Separator)) {
		dir = dir + string(filepath.Separator)
	}
	s.dir = dir
}

func ( s * FileSequence ) SetDirname ( dir string ) { if ! strings . HasSuffix ( dir , string ( filepath . Separator ) ) { dir = dir + string ( filepath . Separator ) } s . dir = dir }


func (s *FileSequence) SetPadding(padChars string) {
	s.padChar = padChars
	s.zfill = s.padMapper.PaddingCharsSize(padChars)
}

func ( s * FileSequence ) SetPadding ( padChars string ) { s . padChar = padChars s . zfill = s . padMapper . PaddingCharsSize ( padChars ) }

// Set a new padding characters for the sequence


func (s *FileSequence) SetPaddingStyle(style PadStyle) {
	s.padMapper = padders[style]
	s.SetPadding(s.padMapper.PaddingChars(s.ZFill()))
}

func ( s * FileSequence ) SetPaddingStyle ( style PadStyle ) { s . padMapper = padders [ style ] s . SetPadding ( s . padMapper . PaddingChars ( s . ZFill ( ) ) ) }

// Set a new padding style for mapping between characters and
// their numeric width

Set a new padding style for mapping between characters and their numeric width


func (s *FileSequence) SetExt(ext string) {
	if !strings.HasPrefix(ext, ".") {
		ext = "." + ext
	}
	s.ext = ext
}

func ( s * FileSequence ) SetExt ( ext string ) { if ! strings . HasPrefix ( ext , " " ) { ext = " " + ext } s . ext = ext }


func (s *FileSequence) SetFrameRange(frameRange string) error {
	frameSet, err := NewFrameSet(frameRange)
	if err != nil {
		return err
	}
	s.frameSet = frameSet
	return nil
}

func ( s * FileSequence ) SetFrameRange ( frameRange string ) error { frameSet , err := NewFrameSet ( frameRange ) if err != nil { return err } s . frameSet = frameSet return nil }

// Set a new FrameSet, by way of providing a string frame range.
// If the frame range cannot be parsed, an error will be returned.

Set a new FrameSet by way of providing a string frame range . If the frame range cannot be parsed an error will be returned .


func (s *FileSequence) Len() int {
	if s.frameSet == nil {
		return 1
	}
	return s.frameSet.Len()
}

func ( s * FileSequence ) Len ( ) int { if s . frameSet == nil { return 1 } return s . frameSet . Len ( ) }

// Len returns the number of frames in the FrameSet.
// If a frame range was not parsed, this will always return 1

Len returns the number of frames in the FrameSet . If a frame range was not parsed this will always return 1


func (s *FileSequence) String() string {
	var fs string
	if s.frameSet != nil {
		fs = s.frameSet.String()
	}
	buf := bytes.NewBufferString(s.dir)
	buf.WriteString(s.basename)
	buf.WriteString(fs)
	buf.WriteString(s.padChar)
	buf.WriteString(s.ext)
	return buf.String()
}

func ( s * FileSequence ) String ( ) string { var fs string if s . frameSet != nil { fs = s . frameSet . String ( ) } buf := bytes . NewBufferString ( s . dir ) buf . WriteString ( s . basename ) buf . WriteString ( fs ) buf . WriteString ( s . padChar ) buf . WriteString ( s . ext ) return buf . String ( ) }

// String returns the formatted sequence


func (s *FileSequence) Copy() *FileSequence {
	seq, _ := NewFileSequence(s.String())
	return seq
}

func ( s * FileSequence ) Copy ( ) * FileSequence { seq , _ := NewFileSequence ( s . String ( ) ) return seq }

// Copy returns a copy of the FileSequence


func NewClient(url string, tls bool, header interface{}) *Client {
	return &Client{
		url:    url,
		tls:    tls,
		header: header,
	}
}

func NewClient ( url string , tls bool , header interface { } ) * Client { return & Client { url : url , tls : tls , header : header , } }


func (h *Header) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var (
		token xml.Token
		err   error
	)
Loop:
	for {
		if token, err = d.Token(); err != nil {
			return err
		}
		if token == nil {
			break
		}
		switch se := token.(type) {
		case xml.StartElement:
			if err = d.DecodeElement(h.Content, &se); err != nil {
				return err
			}
		case xml.EndElement:
			break Loop
		}
	}
	return nil
}

func ( h * Header ) UnmarshalXML ( d * xml . Decoder , start xml . StartElement ) error { var ( token xml . Token err error ) Loop : for { if token , err = d . Token ( ) ; err != nil { return err } if token == nil { break } switch se := token . ( type ) { case xml . StartElement : if err = d . DecodeElement ( h . Content , & se ) ; err != nil { return err } case xml . EndElement : break Loop } } return nil }


func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	if b.Content == nil {
		return xml.UnmarshalError("Content must be a pointer to a struct")
	}
	var (
		token    xml.Token
		err      error
		consumed bool
	)
Loop:
	for {
		if token, err = d.Token(); err != nil {
			return err
		}
		if token == nil {
			break
		}
		envelopeNameSpace := "http://schemas.xmlsoap.org/soap/envelope/"
		switch se := token.(type) {
		case xml.StartElement:
			if consumed {
				return xml.UnmarshalError(
					"Found multiple elements inside SOAP body; not wrapped-document/literal WS-I compliant")
			} else if se.Name.Space == envelopeNameSpace && se.Name.Local == "Fault" {
				b.Fault = &Fault{}
				b.Content = nil
				err = d.DecodeElement(b.Fault, &se)
				if err != nil {
					return err
				}
				consumed = true
			} else {
				if err = d.DecodeElement(b.Content, &se); err != nil {
					return err
				}
				consumed = true
			}
		case xml.EndElement:
			break Loop
		}
	}
	return nil
}

func ( b * Body ) UnmarshalXML ( d * xml . Decoder , start xml . StartElement ) error { if b . Content == nil { return xml . UnmarshalError ( " " ) } var ( token xml . Token err error consumed bool ) Loop : for { if token , err = d . Token ( ) ; err != nil { return err } if token == nil { break } envelopeNameSpace := " " switch se := token . ( type ) { case xml . StartElement : if consumed { return xml . UnmarshalError ( " " ) } else if se . Name . Space == envelopeNameSpace && se . Name . Local == " " { b . Fault = & Fault { } b . Content = nil err = d . DecodeElement ( b . Fault , & se ) if err != nil { return err } consumed = true } else { if err = d . DecodeElement ( b . Content , & se ) ; err != nil { return err } consumed = true } case xml . EndElement : break Loop } } return nil }


func (s *Client) Call(soapAction string, request, response, header interface{}) error {
	var envelope Envelope
	if s.header != nil {
		envelope = Envelope{
			Header: &Header{
				Content: s.header,
			},
			Body: Body{
				Content: request,
			},
		}
	} else {
		envelope = Envelope{
			Body: Body{
				Content: request,
			},
		}
	}
	buffer := new(bytes.Buffer)
	encoder := xml.NewEncoder(buffer)
	encoder.Indent("  ", "    ")
	if err := encoder.Encode(envelope); err != nil {
		return errors.Wrap(err, "failed to encode envelope")
	}
	if err := encoder.Flush(); err != nil {
		return errors.Wrap(err, "failed to flush encoder")
	}

	req, err := http.NewRequest("POST", s.url, buffer)
	if err != nil {
		return errors.Wrap(err, "failed to create POST request")
	}
	req.Header.Add("Content-Type", "text/xml; charset=\"utf-8\"")
	req.Header.Set("SOAPAction", soapAction)
	req.Header.Set("User-Agent", s.userAgent)
	req.Close = true

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: s.tls,
		},
		Dial: dialTimeout,
	}

	client := &http.Client{Transport: tr}
	res, err := client.Do(req)
	if err != nil {
		return errors.Wrap(err, "failed to send SOAP request")
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		soapFault, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return errors.Wrap(err, "failed to read SOAP fault response body")
		}
		msg := fmt.Sprintf("HTTP Status Code: %d, SOAP Fault: \n%s", res.StatusCode, string(soapFault))
		return errors.New(msg)
	}

	rawbody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return errors.Wrap(err, "failed to read SOAP body")
	}
	if len(rawbody) == 0 {
		return nil
	}
	respEnvelope := Envelope{}
	respEnvelope.Body = Body{Content: response}
	if header != nil {
		respEnvelope.Header = &Header{Content: header}
	}

	if err = xml.Unmarshal(rawbody, &respEnvelope); err != nil {
		return errors.Wrap(err, "failed to unmarshal response SOAP Envelope")
	}
	return nil
}

func ( s * Client ) Call ( soapAction string , request , response , header interface { } ) error { var envelope Envelope if s . header != nil { envelope = Envelope { Header : & Header { Content : s . header , } , Body : Body { Content : request , } , } } else { envelope = Envelope { Body : Body { Content : request , } , } } buffer := new ( bytes . Buffer ) encoder := xml . NewEncoder ( buffer ) encoder . Indent ( " " , " " ) if err := encoder . Encode ( envelope ) ; err != nil { return errors . Wrap ( err , " " ) } if err := encoder . Flush ( ) ; err != nil { return errors . Wrap ( err , " " ) } req , err := http . NewRequest ( " " , s . url , buffer ) if err != nil { return errors . Wrap ( err , " " ) } req . Header . Add ( " " , " \" \" " ) req . Header . Set ( " " , soapAction ) req . Header . Set ( " " , s . userAgent ) req . Close = true tr := & http . Transport { TLSClientConfig : & tls . Config { InsecureSkipVerify : s . tls , } , Dial : dialTimeout , } client := & http . Client { Transport : tr } res , err := client . Do ( req ) if err != nil { return errors . Wrap ( err , " " ) } defer res . Body . Close ( ) if res . StatusCode != http . StatusOK { soapFault , err := ioutil . ReadAll ( res . Body ) if err != nil { return errors . Wrap ( err , " " ) } msg := fmt . Sprintf ( " \n " , res . StatusCode , string ( soapFault ) ) return errors . New ( msg ) } rawbody , err := ioutil . ReadAll ( res . Body ) if err != nil { return errors . Wrap ( err , " " ) } if len ( rawbody ) == 0 { return nil } respEnvelope := Envelope { } respEnvelope . Body = Body { Content : response } if header != nil { respEnvelope . Header = & Header { Content : header } } if err = xml . Unmarshal ( rawbody , & respEnvelope ) ; err != nil { return errors . Wrap ( err , " " ) } return nil }


func JSONDoc(path string) (json.RawMessage, error) {
	data, err := swag.LoadFromFileOrHTTP(path)
	if err != nil {
		return nil, err
	}
	return json.RawMessage(data), nil
}

func JSONDoc ( path string ) ( json . RawMessage , error ) { data , err := swag . LoadFromFileOrHTTP ( path ) if err != nil { return nil , err } return json . RawMessage ( data ) , nil }

// JSONDoc loads a json document from either a file or a remote url


func AddLoader(predicate DocMatcher, load DocLoader) {
	prev := loaders
	loaders = &loader{
		Match: predicate,
		Fn:    load,
		Next:  prev,
	}
	spec.PathLoader = loaders.Fn
}

func AddLoader ( predicate DocMatcher , load DocLoader ) { prev := loaders loaders = & loader { Match : predicate , Fn : load , Next : prev , } spec . PathLoader = loaders . Fn }


func JSONSpec(path string) (*Document, error) {
	data, err := JSONDoc(path)
	if err != nil {
		return nil, err
	}
	// convert to json
	return Analyzed(data, "")
}

func
JSONSpec
(
path
string
)
(
*
Document
,
error
)
{
data
,
err
:=
JSONDoc
(
path
)
if
err
!=
{
return
,
err
}
// convert to json
return
Analyzed
(
data
,
"
"
)
}

// JSONSpec loads a spec from a json document


func Embedded(orig, flat json.RawMessage) (*Document, error) {
	var origSpec, flatSpec spec.Swagger
	if err := json.Unmarshal(orig, &origSpec); err != nil {
		return nil, err
	}
	if err := json.Unmarshal(flat, &flatSpec); err != nil {
		return nil, err
	}
	return &Document{
		raw:      orig,
		origSpec: &origSpec,
		spec:     &flatSpec,
	}, nil
}

func Embedded ( orig , flat json . RawMessage ) ( * Document , error ) { var origSpec , flatSpec spec . Swagger if err := json . Unmarshal ( orig , & origSpec ) ; err != nil { return nil , err } if err := json . Unmarshal ( flat , & flatSpec ) ; err != nil { return nil , err } return & Document { raw : orig , origSpec : & origSpec , spec : & flatSpec , } , nil }

// Embedded returns a Document based on embedded specs. No analysis is required

Embedded returns a Document based on embedded specs . No analysis is required


func Spec(path string) (*Document, error) {
	specURL, err := url.Parse(path)
	if err != nil {
		return nil, err
	}
	var lastErr error
	for l := loaders.Next; l != nil; l = l.Next {
		if loaders.Match(specURL.Path) {
			b, err2 := loaders.Fn(path)
			if err2 != nil {
				lastErr = err2
				continue
			}
			doc, err3 := Analyzed(b, "")
			if err3 != nil {
				return nil, err3
			}
			if doc != nil {
				doc.specFilePath = path
			}
			return doc, nil
		}
	}
	if lastErr != nil {
		return nil, lastErr
	}
	b, err := defaultLoader.Fn(path)
	if err != nil {
		return nil, err
	}

	document, err := Analyzed(b, "")
	if document != nil {
		document.specFilePath = path
	}

	return document, err
}

func Spec ( path string ) ( * Document , error ) { specURL , err := url . Parse ( path ) if err != nil { return nil , err } var lastErr error for l := loaders . Next ; l != nil ; l = l . Next { if loaders . Match ( specURL . Path ) { b , err2 := loaders . Fn ( path ) if err2 != nil { lastErr = err2 continue } doc , err3 := Analyzed ( b , " " ) if err3 != nil { return nil , err3 } if doc != nil { doc . specFilePath = path } return doc , nil } } if lastErr != nil { return nil , lastErr } b , err := defaultLoader . Fn ( path ) if err != nil { return nil , err } document , err := Analyzed ( b , " " ) if document != nil { document . specFilePath = path } return document , err }


func Analyzed(data json.RawMessage, version string) (*Document, error) {
	if version == "" {
		version = "2.0"
	}
	if version != "2.0" {
		return nil, fmt.Errorf("spec version %q is not supported", version)
	}

	raw := data
	trimmed := bytes.TrimSpace(data)
	if len(trimmed) > 0 {
		if trimmed[0] != '{' && trimmed[0] != '[' {
			yml, err := swag.BytesToYAMLDoc(trimmed)
			if err != nil {
				return nil, fmt.Errorf("analyzed: %v", err)
			}
			d, err := swag.YAMLToJSON(yml)
			if err != nil {
				return nil, fmt.Errorf("analyzed: %v", err)
			}
			raw = d
		}
	}

	swspec := new(spec.Swagger)
	if err := json.Unmarshal(raw, swspec); err != nil {
		return nil, err
	}

	origsqspec, err := cloneSpec(swspec)
	if err != nil {
		return nil, err
	}

	d := &Document{
		Analyzer: analysis.New(swspec),
		schema:   spec.MustLoadSwagger20Schema(),
		spec:     swspec,
		raw:      raw,
		origSpec: origsqspec,
	}
	return d, nil
}

func Analyzed ( data json . RawMessage , version string ) ( * Document , error ) { if version == " " { version = " " } if version != " " { return nil , fmt . Errorf ( " " , version ) } raw := data trimmed := bytes . TrimSpace ( data ) if len ( trimmed ) > 0 { if trimmed [ 0 ] != '{' && trimmed [ 0 ] != '[' { yml , err := swag . BytesToYAMLDoc ( trimmed ) if err != nil { return nil , fmt . Errorf ( " " , err ) } d , err := swag . YAMLToJSON ( yml ) if err != nil { return nil , fmt . Errorf ( " " , err ) } raw = d } } swspec := new ( spec . Swagger ) if err := json . Unmarshal ( raw , swspec ) ; err != nil { return nil , err } origsqspec , err := cloneSpec ( swspec ) if err != nil { return nil , err } d := & Document { Analyzer : analysis . New ( swspec ) , schema : spec . MustLoadSwagger20Schema ( ) , spec : swspec , raw : raw , origSpec : origsqspec , } return d , nil }

// Analyzed creates a new analyzed spec document


func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
	swspec := new(spec.Swagger)
	if err := json.Unmarshal(d.raw, swspec); err != nil {
		return nil, err
	}

	var expandOptions *spec.ExpandOptions
	if len(options) > 0 {
		expandOptions = options[0]
	} else {
		expandOptions = &spec.ExpandOptions{
			RelativeBase: d.specFilePath,
		}
	}

	if err := spec.ExpandSpec(swspec, expandOptions); err != nil {
		return nil, err
	}

	dd := &Document{
		Analyzer:     analysis.New(swspec),
		spec:         swspec,
		specFilePath: d.specFilePath,
		schema:       spec.MustLoadSwagger20Schema(),
		raw:          d.raw,
		origSpec:     d.origSpec,
	}
	return dd, nil
}

func ( d * Document ) Expanded ( options ... * spec . ExpandOptions ) ( * Document , error ) { swspec := new ( spec . Swagger ) if err := json . Unmarshal ( d . raw , swspec ) ; err != nil { return nil , err } var expandOptions * spec . ExpandOptions if len ( options ) > 0 { expandOptions = options [ 0 ] } else { expandOptions = & spec . ExpandOptions { RelativeBase : d . specFilePath , } } if err := spec . ExpandSpec ( swspec , expandOptions ) ; err != nil { return nil , err } dd := & Document { Analyzer : analysis . New ( swspec ) , spec : swspec , specFilePath : d . specFilePath , schema : spec . MustLoadSwagger20Schema ( ) , raw : d . raw , origSpec : d . origSpec , } return dd , nil }

// Expanded expands the ref fields in the spec document and returns a new spec document


func (d *Document) ResetDefinitions() *Document {
	defs := make(map[string]spec.Schema, len(d.origSpec.Definitions))
	for k, v := range d.origSpec.Definitions {
		defs[k] = v
	}

	d.spec.Definitions = defs
	return d
}

func ( d * Document ) ResetDefinitions ( ) * Document { defs := make ( map [ string ] spec . Schema , len ( d . origSpec . Definitions ) ) for k , v := range d . origSpec . Definitions { defs [ k ] = v } d . spec . Definitions = defs return d }

// ResetDefinitions gives a shallow copy with the models reset


func (d *Document) Pristine() *Document {
	dd, _ := Analyzed(d.Raw(), d.Version())
	return dd
}

func ( d * Document ) Pristine ( ) * Document { dd , _ := Analyzed ( d . Raw ( ) , d . Version ( ) ) return dd }

// Pristine creates a new pristine document instance based on the input data


func OpenDb(files []string, flag int) (*GeoIP, error) {
	if len(files) == 0 {
		files = []string{
			"/usr/share/GeoIP/GeoIP.dat",       // Linux default
			"/usr/share/local/GeoIP/GeoIP.dat", // source install?
			"/usr/local/share/GeoIP/GeoIP.dat", // FreeBSD
			"/opt/local/share/GeoIP/GeoIP.dat", // MacPorts
			"/usr/share/GeoIP/GeoIP.dat",       // ArchLinux
		}
	}

	g := &GeoIP{}
	runtime.SetFinalizer(g, (*GeoIP).free)

	var err error

	for _, file := range files {

		// libgeoip prints errors if it can't open the file, so check first
		if _, err := os.Stat(file); err != nil {
			if os.IsExist(err) {
				log.Println(err)
			}
			continue
		}

		cbase := C.CString(file)
		defer C.free(unsafe.Pointer(cbase))

		g.db, err = C.GeoIP_open(cbase, C.int(flag))
		if g.db != nil && err != nil {
			break
		}
	}
	if err != nil {
		return nil, fmt.Errorf("Error opening GeoIP database (%s): %s", files, err)
	}

	if g.db == nil {
		return nil, fmt.Errorf("Didn't open GeoIP database (%s)", files)
	}

	C.GeoIP_set_charset(g.db, C.GEOIP_CHARSET_UTF8)
	return g, nil
}

// Opens a GeoIP database by filename with specified GeoIPOptions flag.
// All formats supported by libgeoip are supported though there are only
// functions to access some of the databases in this API.
// If you don't pass a filename, it will try opening the database from
// a list of common paths.

Opens a GeoIP database by filename with specified GeoIPOptions flag . All formats supported by libgeoip are supported though there are only functions to access some of the databases in this API . If you don t pass a filename it will try opening the database from a list of common paths .


func (gi *GeoIP) GetOrg(ip string) string {
	name, _ := gi.GetName(ip)
	return name
}

func ( gi * GeoIP ) GetOrg ( ip string ) string { name , _ := gi . GetName ( ip ) return name }

// Takes an IPv4 address string and returns the organization name for that IP.
// Requires the GeoIP organization database.

Takes an IPv4 address string and returns the organization name for that IP . Requires the GeoIP organization database .


func (gi *GeoIP) GetRegion(ip string) (string, string) {
	if gi.db == nil {
		return "", ""
	}

	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))

	gi.mu.Lock()
	region := C.GeoIP_region_by_addr(gi.db, cip)
	gi.mu.Unlock()

	if region == nil {
		return "", ""
	}

	countryCode := C.GoString(&region.country_code[0])
	regionCode := C.GoString(&region.region[0])
	defer C.free(unsafe.Pointer(region))

	return countryCode, regionCode
}

func ( gi * GeoIP ) GetRegion ( ip string ) ( string , string ) { if gi . db == nil { return " " , " " } cip := C . CString ( ip ) defer C . free ( unsafe . Pointer ( cip ) ) gi . mu . Lock ( ) region := C . GeoIP_region_by_addr ( gi . db , cip ) gi . mu . Unlock ( ) if region == nil { return " " , " " } countryCode := C . GoString ( & region . country_code [ 0 ] ) regionCode := C . GoString ( & region . region [ 0 ] ) defer C . free ( unsafe . Pointer ( region ) ) return countryCode , regionCode }

// Returns the country code and region code for an IP address. Requires
// the GeoIP Region database.

Returns the country code and region code for an IP address . Requires the GeoIP Region database .


func GetRegionName(countryCode, regionCode string) string {

	cc := C.CString(countryCode)
	defer C.free(unsafe.Pointer(cc))

	rc := C.CString(regionCode)
	defer C.free(unsafe.Pointer(rc))

	region := C.GeoIP_region_name_by_code(cc, rc)
	if region == nil {
		return ""
	}

	// it's a static string constant, don't free this
	regionName := C.GoString(region)

	return regionName
}

// Returns the region name given a country code and region code


func (gi *GeoIP) GetCountry(ip string) (cc string, netmask int) {
	if gi.db == nil {
		return
	}

	gi.mu.Lock()
	defer gi.mu.Unlock()

	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	ccountry := C.GeoIP_country_code_by_addr(gi.db, cip)

	if ccountry != nil {
		cc = C.GoString(ccountry)
		netmask = int(C.GeoIP_last_netmask(gi.db))
		return
	}
	return
}

func ( gi * GeoIP ) GetCountry ( ip string ) ( cc string , netmask int ) { if gi . db == nil { return } gi . mu . Lock ( ) defer gi . mu . Unlock ( ) cip := C . CString ( ip ) defer C . free ( unsafe . Pointer ( cip ) ) ccountry := C . GeoIP_country_code_by_addr ( gi . db , cip ) if ccountry != nil { cc = C . GoString ( ccountry ) netmask = int ( C . GeoIP_last_netmask ( gi . db ) ) return } return }

// Takes an IPv4 address string and returns the country code for that IP
// and the netmask for that IP range.

Takes an IPv4 address string and returns the country code for that IP and the netmask for that IP range .


func NewRotatingFileHandler(fileName string, maxBytes int, backupCount int) (*RotatingFileHandler, error) {
	dir := path.Dir(fileName)
	os.MkdirAll(dir, 0777)

	h := new(RotatingFileHandler)

	if maxBytes <= 0 {
		return nil, fmt.Errorf("invalid max bytes")
	}

	h.fileName = fileName
	h.maxBytes = maxBytes
	h.backupCount = backupCount

	var err error
	h.fd, err = os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return nil, err
	}

	f, err := h.fd.Stat()
	if err != nil {
		return nil, err
	}
	h.curBytes = int(f.Size())

	return h, nil
}

func NewRotatingFileHandler ( fileName string , maxBytes int , backupCount int ) ( * RotatingFileHandler , error ) { dir := path . Dir ( fileName ) os . MkdirAll ( dir , 0777 ) h := new ( RotatingFileHandler ) if maxBytes <= 0 { return nil , fmt . Errorf ( " " ) } h . fileName = fileName h . maxBytes = maxBytes h . backupCount = backupCount var err error h . fd , err = os . OpenFile ( fileName , os . O_CREATE | os . O_WRONLY | os . O_APPEND , 0666 ) if err != nil { return nil , err } f , err := h . fd . Stat ( ) if err != nil { return nil , err } h . curBytes = int ( f . Size ( ) ) return h , nil }

// NewRotatingFileHandler creates a RotatingFileHandler


func (h *RotatingFileHandler) Close() error {
	if h.fd != nil {
		return h.fd.Close()
	}
	return nil
}

func ( h * RotatingFileHandler ) Close ( ) error { if h . fd != nil { return h . fd . Close ( ) } return nil }


func (l Level) String() string {
	switch l {
	case LevelTrace:
		return "trace"
	case LevelDebug:
		return "debug"
	case LevelInfo:
		return "info"
	case LevelWarn:
		return "warn"
	case LevelError:
		return "error"
	case LevelFatal:
		return "fatal"
	}
	// return default info
	return "info"
}

func
(
l
Level
)
String
(
)
string
{
switch
l
{
case
LevelTrace
:
return
"
"
case
LevelDebug
:
return
"
"
case
LevelInfo
:
return
"
"
case
LevelWarn
:
return
"
"
case
LevelError
:
return
"
"
case
LevelFatal
:
return
"
"
}
// return default info
return
"
"
}


func New(handler Handler, flag int) *Logger {
	var l = new(Logger)

	l.level = LevelInfo
	l.handler = handler

	l.flag = flag

	l.bufs = sync.Pool{
		New: func() interface{} {
			return make([]byte, 0, 1024)
		},
	}

	return l
}

func New ( handler Handler , flag int ) * Logger { var l = new ( Logger ) l . level = LevelInfo l . handler = handler l . flag = flag l . bufs = sync . Pool { New : func ( ) interface { } { return make ( [ ] byte , 0 , 1024 ) } , } return l }

// New creates a logger with specified handler and flag


func (l *Logger) Close() {
	l.hLock.Lock()
	defer l.hLock.Unlock()
	l.handler.Close()
}

func ( l * Logger ) Close ( ) { l . hLock . Lock ( ) defer l . hLock . Unlock ( ) l . handler . Close ( ) }


func (l *Logger) SetLevelByName(name string) {
	level := LevelInfo
	switch strings.ToLower(name) {
	case "trace":
		level = LevelTrace
	case "debug":
		level = LevelDebug
	case "warn", "warning":
		level = LevelWarn
	case "error":
		level = LevelError
	case "fatal":
		level = LevelFatal
	default:
		level = LevelInfo
	}

	l.SetLevel(level)
}

func ( l * Logger ) SetLevelByName ( name string ) { level := LevelInfo switch strings . ToLower ( name ) { case " " : level = LevelTrace case " " : level = LevelDebug case " " , " " : level = LevelWarn case " " : level = LevelError case " " : level = LevelFatal default : level = LevelInfo } l . SetLevel ( level ) }

// SetLevelByName sets log level by name


func (l *Logger) Output(callDepth int, level Level, msg string) {
	if l.level > level {
		return
	}

	buf := l.bufs.Get().([]byte)
	buf = buf[0:0]
	defer l.bufs.Put(buf)

	if l.flag&Ltime > 0 {
		now := time.Now().Format(timeFormat)
		buf = append(buf, '[')
		buf = append(buf, now...)
		buf = append(buf, "] "...)
	}

	if l.flag&Llevel > 0 {
		buf = append(buf, '[')
		buf = append(buf, level.String()...)
		buf = append(buf, "] "...)
	}

	if l.flag&Lfile > 0 {
		_, file, line, ok := runtime.Caller(callDepth)
		if !ok {
			file = "???"
			line = 0
		} else {
			for i := len(file) - 1; i > 0; i-- {
				if file[i] == '/' {
					file = file[i+1:]
					break
				}
			}
		}

		buf = append(buf, file...)
		buf = append(buf, ':')

		buf = strconv.AppendInt(buf, int64(line), 10)
		buf = append(buf, ' ')
	}

	buf = append(buf, msg...)
	if len(msg) == 0 || msg[len(msg)-1] != '\n' {
		buf = append(buf, '\n')
	}

	l.hLock.Lock()
	l.handler.Write(buf)
	l.hLock.Unlock()
}

func
(
l
*
Logger
)
Output
(
callDepth
int
,
level
Level
,
msg
string
)
{
if
l
.
level
>
level
{
return
}
buf
:=
l
.
bufs
.
Get
(
)
.
(
[
]
byte
)
buf
=
buf
[
0
:
0
]
defer
l
.
bufs
.
Put
(
buf
)
if
l
.
flag
&
Ltime
>
0
{
now
:=
time
.
Now
(
)
.
Format
(
timeFormat
)
buf
=
append
(
buf
,
'['
)
buf
=
append
(
buf
,
now
...
)
buf
=
append
(
buf
,
"
"
...
)
}
if
l
.
flag
&
Llevel
>
0
{
buf
=
append
(
buf
,
'['
)
buf
=
append
(
buf
,
level
.
String
(
)
...
)
buf
=
append
(
buf
,
"
"
...
)
}
if
l
.
flag
&
Lfile
>
0
{
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
callDepth
)
if
!
ok
{
file
=
"
"
line
=
0
}
else
{
for
i
:=
len
(
file
)
1
;
i
>
0
;
i
{
if
file
[
i
]
==
'/'
{
file
=
file
[
i
+
1
:
]
break
}
}
}
buf
=
append
(
buf
,
file
...
)
buf
=
append
(
buf
,
':'
)
buf
=
strconv
.
AppendInt
(
buf
,
int64
(
line
)
,
10
)
buf
=
append
(
buf
,
' '
)
}
buf
=
append
(
buf
,
msg
...
)
if
len
(
msg
)
==
0
||
msg
[
len
(
msg
)
1
]
!=
'\n'
{
buf
=
append
(
buf
,
'\n'
)
}
l
.
hLock
.
Lock
(
)
l
.
handler
.
Write
(
buf
)
l
.
hLock
.
Unlock
(
)
}

// Output records the log with special callstack depth and log level.

Output records the log with special callstack depth and log level .


func (l *Logger) OutputJson(callDepth int, level Level, body interface{}) {
	if l.level > level {
		return
	}

	buf := l.bufs.Get().([]byte)
	buf = buf[0:0]
	defer l.bufs.Put(buf)

	type JsonLog struct {
		Time string `json:"log_time"`
		Level string `json:"log_level"`
		File string `json:"log_file"`
		Line string `json:"log_line"`
		Body interface{} `json:"log_body"`
	}

	var jsonlog JsonLog
	if l.flag&Ltime > 0 {
		now := time.Now().Format(timeFormat)
		jsonlog.Time = now
	}

	if l.flag&Llevel > 0 {
		jsonlog.Level = level.String()
	}

	if l.flag&Lfile > 0 {
		_, file, line, ok := runtime.Caller(callDepth)
		if !ok {
			file = "???"
			line = 0
		} else {
			for i := len(file) - 1; i > 0; i-- {
				if file[i] == '/' {
					file = file[i+1:]
					break
				}
			}
		}

		jsonlog.File = file
		jsonlog.Line = string(strconv.AppendInt(buf, int64(line), 10))
	}

	jsonlog.Body = body

	msg, _ := json.Marshal(jsonlog)
	msg = append(msg, '\n')

	l.hLock.Lock()
	l.handler.Write(msg)
	l.hLock.Unlock()
}

func ( l * Logger ) OutputJson ( callDepth int , level Level , body interface { } ) { if l . level > level { return } buf := l . bufs . Get ( ) . ( [ ] byte ) buf = buf [ 0 : 0 ] defer l . bufs . Put ( buf ) type JsonLog struct { Time string `json:"log_time"` Level string `json:"log_level"` File string `json:"log_file"` Line string `json:"log_line"` Body interface { } `json:"log_body"` } var jsonlog JsonLog if l . flag & Ltime > 0 { now := time . Now ( ) . Format ( timeFormat ) jsonlog . Time = now } if l . flag & Llevel > 0 { jsonlog . Level = level . String ( ) } if l . flag & Lfile > 0 { _ , file , line , ok := runtime . Caller ( callDepth ) if ! ok { file = " " line = 0 } else { for i := len ( file ) - 1 ; i > 0 ; i -- { if file [ i ] == '/' { file = file [ i + 1 : ] break } } } jsonlog . File = file jsonlog . Line = string ( strconv . AppendInt ( buf , int64 ( line ) , 10 ) ) } jsonlog . Body = body msg , _ := json . Marshal ( jsonlog ) msg = append ( msg , '\n' ) l . hLock . Lock ( ) l . handler . Write ( msg ) l . hLock . Unlock ( ) }

// Output json format records the log with special callstack depth and log level.

Output json format records the log with special callstack depth and log level .


func (l *Logger) Print(args ...interface{}) {
	l.Output(2, LevelTrace, fmt.Sprint(args...))
}

func ( l * Logger ) Print ( args ... interface { } ) { l . Output ( 2 , LevelTrace , fmt . Sprint ( args ... ) ) }

// Print records the log with trace level


func (l *Logger) Println(args ...interface{}) {
	l.Output(2, LevelTrace, fmt.Sprintln(args...))
}

func ( l * Logger ) Println ( args ... interface { } ) { l . Output ( 2 , LevelTrace , fmt . Sprintln ( args ... ) ) }

// Println records the log with trace level


func (l *Logger) Debug(args ...interface{}) {
	l.Output(2, LevelDebug, fmt.Sprint(args...))
}

func ( l * Logger ) Debug ( args ... interface { } ) { l . Output ( 2 , LevelDebug , fmt . Sprint ( args ... ) ) }

// Debug records the log with debug level


func (l *Logger) Debugln(args ...interface{}) {
	l.Output(2, LevelDebug, fmt.Sprintln(args...))
}

func ( l * Logger ) Debugln ( args ... interface { } ) { l . Output ( 2 , LevelDebug , fmt . Sprintln ( args ... ) ) }

// Debugln records the log with debug level


func (l *Logger) Error(args ...interface{}) {
	l.Output(2, LevelError, fmt.Sprint(args...))
}

func ( l * Logger ) Error ( args ... interface { } ) { l . Output ( 2 , LevelError , fmt . Sprint ( args ... ) ) }

// Error records the log with error level


func (l *Logger) Errorln(args ...interface{}) {
	l.Output(2, LevelError, fmt.Sprintln(args...))
}

func ( l * Logger ) Errorln ( args ... interface { } ) { l . Output ( 2 , LevelError , fmt . Sprintln ( args ... ) ) }

// Errorln records the log with error level


func (l *Logger) Info(args ...interface{}) {
	l.Output(2, LevelInfo, fmt.Sprint(args...))
}

func ( l * Logger ) Info ( args ... interface { } ) { l . Output ( 2 , LevelInfo , fmt . Sprint ( args ... ) ) }


func (l *Logger) Infoln(args ...interface{}) {
	l.Output(2, LevelInfo, fmt.Sprintln(args...))
}

func ( l * Logger ) Infoln ( args ... interface { } ) { l . Output ( 2 , LevelInfo , fmt . Sprintln ( args ... ) ) }

// Infoln records the log with info level


func (l *Logger) Warn(args ...interface{}) {
	l.Output(2, LevelWarn, fmt.Sprint(args...))
}

func ( l * Logger ) Warn ( args ... interface { } ) { l . Output ( 2 , LevelWarn , fmt . Sprint ( args ... ) ) }


func (l *Logger) Warnln(args ...interface{}) {
	l.Output(2, LevelWarn, fmt.Sprintln(args...))
}

func ( l * Logger ) Warnln ( args ... interface { } ) { l . Output ( 2 , LevelWarn , fmt . Sprintln ( args ... ) ) }

// Warnln records the log with warn level


func NewStreamHandler(w io.Writer) (*StreamHandler, error) {
	h := new(StreamHandler)

	h.w = w

	return h, nil
}

func NewStreamHandler ( w io . Writer ) ( * StreamHandler , error ) { h := new ( StreamHandler ) h . w = w return h , nil }

// NewStreamHandler creates a StreamHandler


func Right(str string, length int, pad string) string {
	return str + times(pad, length-len(str))
}

func Right ( str string , length int , pad string ) string { return str + times ( pad , length - len ( str ) ) }

// Right right-pads the string with pad up to len runes

Right right - pads the string with pad up to len runes


func New(h string, a rsapi.Authenticator) *API {
	api := rsapi.New(h, a)
	api.Metadata = GenMetadata
	return &API{API: api}
}

func New ( h string , a rsapi . Authenticator ) * API { api := rsapi . New ( h , a ) api . Metadata = GenMetadata return & API { API : api } }

// New returns a Self-Service API client.

New returns a Self - Service API client .


func setupMetadata() (result map[string]*metadata.Resource) {
	result = make(map[string]*metadata.Resource)
	for n, r := range ssd.GenMetadata {
		result[n] = r
		for _, a := range r.Actions {
			for _, p := range a.PathPatterns {
				// remove "/api/designer" prefix
				p.Regexp = removePrefixes(p.Regexp, 2)
			}
		}
	}
	for n, r := range ssc.GenMetadata {
		result[n] = r
		for _, a := range r.Actions {
			for _, p := range a.PathPatterns {
				// remove "/api/catalog" prefix
				p.Regexp = removePrefixes(p.Regexp, 2)
			}
		}
	}
	for n, r := range ssm.GenMetadata {
		result[n] = r
		for _, a := range r.Actions {
			for _, p := range a.PathPatterns {
				// remove "/api/manager" prefix
				p.Regexp = removePrefixes(p.Regexp, 2)
			}
		}
	}
	return
}

func
setupMetadata
(
)
(
result
map
[
string
]
*
metadata
.
Resource
)
{
result
=
make
(
map
[
string
]
*
metadata
.
Resource
)
for
n
,
r
:=
range
ssd
.
GenMetadata
{
result
[
n
]
=
r
for
_
,
a
:=
range
r
.
Actions
{
for
_
,
p
:=
range
a
.
PathPatterns
{
// remove "/api/designer" prefix
p
.
Regexp
=
removePrefixes
(
p
.
Regexp
,
2
)
}
}
}
for
n
,
r
:=
range
ssc
.
GenMetadata
{
result
[
n
]
=
r
for
_
,
a
:=
range
r
.
Actions
{
for
_
,
p
:=
range
a
.
PathPatterns
{
// remove "/api/catalog" prefix
p
.
Regexp
=
removePrefixes
(
p
.
Regexp
,
2
)
}
}
}
for
n
,
r
:=
range
ssm
.
GenMetadata
{
result
[
n
]
=
r
for
_
,
a
:=
range
r
.
Actions
{
for
_
,
p
:=
range
a
.
PathPatterns
{
// remove "/api/manager" prefix
p
.
Regexp
=
removePrefixes
(
p
.
Regexp
,
2
)
}
}
}
return
}

// Initialize GenMetadata from each SS API generated metadata


func (p *ParamAnalyzer) recordTypes(root gen.DataType) {
	if o, ok := root.(*gen.ObjectDataType); ok {
		if _, found := p.ParamTypes[o.TypeName]; !found {
			p.ParamTypes[o.TypeName] = o
			for _, f := range o.Fields {
				p.recordTypes(f.Type)
			}
		}
	} else if a, ok := root.(*gen.ArrayDataType); ok {
		p.recordTypes(a.ElemType.Type)
	}
}

func ( p * ParamAnalyzer ) recordTypes ( root gen . DataType ) { if o , ok := root . ( * gen . ObjectDataType ) ; ok { if _ , found := p . ParamTypes [ o . TypeName ] ; ! found { p . ParamTypes [ o . TypeName ] = o for _ , f := range o . Fields { p . recordTypes ( f . Type ) } } } else if a , ok := root . ( * gen . ArrayDataType ) ; ok { p . recordTypes ( a . ElemType . Type ) } }

// Recursively record all type declarations


func appendSorted(params []*gen.ActionParam, param *gen.ActionParam) []*gen.ActionParam {
	params = append(params, param)
	sort.Sort(gen.ByName(params))
	return params
}

func appendSorted ( params [ ] * gen . ActionParam , param * gen . ActionParam ) [ ] * gen . ActionParam { params = append ( params , param ) sort . Sort ( gen . ByName ( params ) ) return params }


func (p *ParamAnalyzer) parseDataType(path string, child *gen.ActionParam) gen.DataType {
	param := p.rawParams[path].(map[string]interface{})
	class := "String"
	if c, ok := param["class"].(string); ok {
		class = c
	}
	var res gen.DataType
	switch class {
	case "Integer":
		i := gen.BasicDataType("int")
		res = &i
	case "String":
		s := gen.BasicDataType("string")
		res = &s
	case "Array":
		if child != nil {
			res = &gen.ArrayDataType{child}
		} else {
			s := gen.BasicDataType("string")
			p := p.newParam(fmt.Sprintf("%s[item]", path),
				map[string]interface{}{}, &s)
			res = &gen.ArrayDataType{p}
		}
	case "SourceUpload":
		res = new(gen.SourceUploadDataType)
	case "FileUpload", "Tempfile":
		res = &gen.UploadDataType{TypeName: "FileUpload"}
	case "Enumerable":
		res = new(gen.EnumerableDataType)
	case "Hash":
		if current, ok := p.parsed[path]; ok {
			res = current.Type
			o := res.(*gen.ObjectDataType)
			o.Fields = appendSorted(o.Fields, child)
		} else {
			oname := p.typeName(path)
			res = &gen.ObjectDataType{oname, []*gen.ActionParam{child}}
		}
	}
	return res
}

func ( p * ParamAnalyzer ) parseDataType ( path string , child * gen . ActionParam ) gen . DataType { param := p . rawParams [ path ] . ( map [ string ] interface { } ) class := " " if c , ok := param [ " " ] . ( string ) ; ok { class = c } var res gen . DataType switch class { case " " : i := gen . BasicDataType ( " " ) res = & i case " " : s := gen . BasicDataType ( " " ) res = & s case " " : if child != nil { res = & gen . ArrayDataType { child } } else { s := gen . BasicDataType ( " " ) p := p . newParam ( fmt . Sprintf ( " " , path ) , map [ string ] interface { } { } , & s ) res = & gen . ArrayDataType { p } } case " " : res = new ( gen . SourceUploadDataType ) case " " , " " : res = & gen . UploadDataType { TypeName : " " } case " " : res = new ( gen . EnumerableDataType ) case " " : if current , ok := p . parsed [ path ] ; ok { res = current . Type o := res . ( * gen . ObjectDataType ) o . Fields = appendSorted ( o . Fields , child ) } else { oname := p . typeName ( path ) res = & gen . ObjectDataType { oname , [ ] * gen . ActionParam { child } } } } return res }


func (p *ParamAnalyzer) parseParam(path string, param map[string]interface{}, child *gen.ActionParam) *gen.ActionParam {
	dType := p.parseDataType(path, child)
	return p.newParam(path, param, dType)
}

func ( p * ParamAnalyzer ) parseParam ( path string , param map [ string ] interface { } , child * gen . ActionParam ) * gen . ActionParam { dType := p . parseDataType ( path , child ) return p . newParam ( path , param , dType ) }

// Build action param struct from json data


func (p *ParamAnalyzer) newParam(path string, param map[string]interface{}, dType gen.DataType) *gen.ActionParam {
	var description, regexp string
	var mandatory, nonBlank bool
	var validValues []interface{}
	if d, ok := param["description"]; ok {
		description = d.(string)
	}
	if m, ok := param["mandatory"]; ok {
		mandatory = m.(bool)
	}
	if n, ok := param["non_blank"]; ok {
		nonBlank = n.(bool)
	}
	if r, ok := param["regexp"]; ok {
		regexp = r.(string)
	}
	if v, ok := param["valid_values"]; ok {
		validValues = v.([]interface{})
	}
	native := nativeNameFromPath(path)
	isLeaf := false
	if _, ok := dType.(*gen.EnumerableDataType); ok {
		isLeaf = true
	} else {
		for _, l := range p.leafParamNames {
			if path == l {
				isLeaf = true
				break
			}
		}
	}
	queryName := path
	if _, ok := dType.(*gen.ArrayDataType); ok {
		queryName += "[]"
	}
	actionParam := &gen.ActionParam{
		Name:        native,
		QueryName:   queryName,
		Description: removeBlankLines(description),
		VarName:     parseParamName(native),
		Type:        dType,
		Mandatory:   mandatory,
		NonBlank:    nonBlank,
		Regexp:      regexp,
		ValidValues: validValues,
	}
	if isLeaf {
		p.LeafParams = append(p.LeafParams, actionParam)
	}
	return actionParam
}

func ( p * ParamAnalyzer ) newParam ( path string , param map [ string ] interface { } , dType gen . DataType ) * gen . ActionParam { var description , regexp string var mandatory , nonBlank bool var validValues [ ] interface { } if d , ok := param [ " " ] ; ok { description = d . ( string ) } if m , ok := param [ " " ] ; ok { mandatory = m . ( bool ) } if n , ok := param [ " " ] ; ok { nonBlank = n . ( bool ) } if r , ok := param [ " " ] ; ok { regexp = r . ( string ) } if v , ok := param [ " " ] ; ok { validValues = v . ( [ ] interface { } ) } native := nativeNameFromPath ( path ) isLeaf := false if _ , ok := dType . ( * gen . EnumerableDataType ) ; ok { isLeaf = true } else { for _ , l := range p . leafParamNames { if path == l { isLeaf = true break } } } queryName := path if _ , ok := dType . ( * gen . ArrayDataType ) ; ok { queryName += " " } actionParam := & gen . ActionParam { Name : native , QueryName : queryName , Description : removeBlankLines ( description ) , VarName : parseParamName ( native ) , Type : dType , Mandatory : mandatory , NonBlank : nonBlank , Regexp : regexp , ValidValues : validValues , } if isLeaf { p . LeafParams = append ( p . LeafParams , actionParam ) } return actionParam }


func toGoReturnTypeName(name string, slice bool) string {
	slicePrefix := ""
	if slice {
		slicePrefix = "[]"
	}
	return fmt.Sprintf("%s*%s", slicePrefix, toGoTypeName(name))
}

func toGoReturnTypeName ( name string , slice bool ) string { slicePrefix := " " if slice { slicePrefix = " " } return fmt . Sprintf ( " " , slicePrefix , toGoTypeName ( name ) ) }


func toGoTypeName(name string) string {
	switch name {
	case "String", "Symbol":
		return "string"
	case "Integer":
		return "int"
	case "Boolean":
		return "bool"
	case "Struct", "Collection":
		panic("Uh oh, trying to infer a go type name for a unnamed struct or collection (" + name + ")")
	default:
		if strings.Contains(name, "::") {
			elems := strings.Split(name, "::")
			return strings.Join(elems[2:len(elems)], "")
		}
		return name
	}

}

func toGoTypeName ( name string ) string { switch name { case " " , " " : return " " case " " : return " " case " " : return " " case " " , " " : panic ( " " + name + " " ) default : if strings . Contains ( name , " " ) { elems := strings . Split ( name , " " ) return strings . Join ( elems [ 2 : len ( elems ) ] , " " ) } return name } }

// Produce go type name from given ruby type name


func prettify(o interface{}) string {
	s, err := json.MarshalIndent(o, "", "    ")
	if err != nil {
		return fmt.Sprintf("%+v", o)
	}
	return string(s)
}

func prettify ( o interface { } ) string { s , err := json . MarshalIndent ( o , " " , " " ) if err != nil { return fmt . Sprintf ( " " , o ) } return string ( s ) }

// Return dumpable representation of given object


func isBuiltInType(name string) bool {
	for _, n := range BuiltInTypes {
		if name == n {
			return true
		}
	}
	return false
}

func isBuiltInType ( name string ) bool { for _ , n := range BuiltInTypes { if name == n { return true } } return false }

// Returns true if given name is the name of a built-in type

Returns true if given name is the name of a built - in type


func (a *Action) MatchHref(href string) bool {
	hrefs := []string{href, href + "/"}
	for _, pattern := range a.PathPatterns {
		for _, href := range hrefs {
			indices := pattern.Regexp.FindStringIndex(href)
			// it is only an exact match if the pattern matches from the beginning to the length of the string
			if indices != nil && indices[0] == 0 && indices[1] == len(href) {
				return true
			}
		}
	}
	return false
}

// MatchHref returns true if the given href matches one of the action's href patterns exactly

MatchHref returns true if the given href matches one of the action s href patterns exactly


func (p *PathPattern) Substitute(vars []*PathVariable) (string, []string) {
	values := make([]interface{}, len(p.Variables))
	var missing []string
	var used []string
	for i, n := range p.Variables {
		for _, v := range vars {
			if v.Name == n {
				values[i] = v.Value
				used = append(used, n)
				break
			}
		}
		if values[i] == nil {
			missing = append(missing, n)
		}
	}
	if len(missing) > 0 {
		return "", missing
	}
	return fmt.Sprintf(p.Pattern, values...), used
}

func ( p * PathPattern ) Substitute ( vars [ ] * PathVariable ) ( string , [ ] string ) { values := make ( [ ] interface { } , len ( p . Variables ) ) var missing [ ] string var used [ ] string for i , n := range p . Variables { for _ , v := range vars { if v . Name == n { values [ i ] = v . Value used = append ( used , n ) break } } if values [ i ] == nil { missing = append ( missing , n ) } } if len ( missing ) > 0 { return " " , missing } return fmt . Sprintf ( p . Pattern , values ... ) , used }

// Substitute attemps to substitute the path pattern variables with the given values.
// - If the substitution succeeds, it returns the resulting path and the list of variable names
//   that were used to build it.
// - If the substitution fails, it returns an empty string and the list of variable names that are
//   missing from the list of given values.

Substitute attemps to substitute the path pattern variables with the given values . - If the substitution succeeds it returns the resulting path and the list of variable names that were used to build it . - If the substitution fails it returns an empty string and the list of variable names that are missing from the list of given values .


func (f *FileUpload) MarshalJSON() ([]byte, error) {
	b, err := ioutil.ReadAll(f.Reader)
	if err != nil {
		return nil, err
	}
	return json.Marshal(string(b))
}

func ( f * FileUpload ) MarshalJSON ( ) ( [ ] byte , error ) { b , err := ioutil . ReadAll ( f . Reader ) if err != nil { return nil , err } return json . Marshal ( string ( b ) ) }

// MarshalJSON just inserts the contents of the file from disk inline into the json


func writeMultipartParams(w *multipart.Writer, payload APIParams, prefix string) error {
	for k, v := range payload {
		fieldName := k
		if prefix != "" {
			fieldName = fmt.Sprintf("%s[%s]", prefix, k)
		}
		// Add more types as needed. These two cover both CM15 and SS.
		switch v.(type) {
		case string:
			err := w.WriteField(fieldName, v.(string))
			if err != nil {
				return err
			}
		case APIParams:
			err := writeMultipartParams(w, v.(APIParams), fieldName)
			if err != nil {
				return err
			}
		default:
			return fmt.Errorf("Unknown type for multipart form section %s: %#v", fieldName, v)
		}
	}
	return nil
}

// Handle payload params. Each payload param gets its own multipart
// form section with the section name being the variable name and
// section contents being the variable contents. Handle recursion as well.

Handle payload params . Each payload param gets its own multipart form section with the section name being the variable name and section contents being the variable contents . Handle recursion as well .


func (a *API) PerformRequest(req *http.Request) (*http.Response, error) {
	// Sign last so auth headers don't get printed or logged
	if a.Auth != nil {
		if err := a.Auth.Sign(req); err != nil {
			return nil, err
		}
	}
	resp, err := a.Client.Do(req)
	if err != nil {
		return nil, err
	}

	return resp, err
}

// PerformRequest logs the request, dumping its content if required then makes the request and logs
// and dumps the corresponding response.

PerformRequest logs the request dumping its content if required then makes the request and logs and dumps the corresponding response .


func (a *API) PerformRequestWithContext(ctx context.Context, req *http.Request) (*http.Response, error) {
	// Sign last so auth headers don't get printed or logged
	if a.Auth != nil {
		if err := a.Auth.Sign(req); err != nil {
			return nil, err
		}
	}
	resp, err := a.Client.DoWithContext(ctx, req)
	if err != nil {
		return nil, err
	}

	return resp, err
}

// PerformRequestWithContext performs everything the PerformRequest does but is also context-aware.

PerformRequestWithContext performs everything the PerformRequest does but is also context - aware .


func (a *API) LoadResponse(resp *http.Response) (interface{}, error) {
	defer resp.Body.Close()
	var respBody interface{}
	jsonResp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("Failed to read response (%s)", err)
	}
	if len(jsonResp) > 0 {
		err = json.Unmarshal(jsonResp, &respBody)
		if err != nil {
			return nil, fmt.Errorf("Failed to load response (%s)", err)
		}
	}
	// Special case for "Location" header, assume that if there is a location there is no body
	loc := resp.Header.Get("Location")
	if len(loc) > 0 {
		var bodyMap = make(map[string]interface{})
		bodyMap["Location"] = loc
		respBody = interface{}(bodyMap)
	}
	return respBody, err
}

// LoadResponse deserializes the JSON response into a generic object.
// If the response has a "Location" header then the returned object is a map with one key "Location"
// containing the value of the header.

LoadResponse deserializes the JSON response into a generic object . If the response has a Location header then the returned object is a map with one key Location containing the value of the header .


func (api *API) ScheduleLocator(href string) *ScheduleLocator {
	return &ScheduleLocator{Href(href), api}
}

func ( api * API ) ScheduleLocator ( href string ) * ScheduleLocator { return & ScheduleLocator { Href ( href ) , api } }

// ScheduleLocator builds a locator from the given href.

ScheduleLocator builds a locator from the given href .


func (api *API) TemplateLocator(href string) *TemplateLocator {
	return &TemplateLocator{Href(href), api}
}

func ( api * API ) TemplateLocator ( href string ) * TemplateLocator { return & TemplateLocator { Href ( href ) , api } }

// TemplateLocator builds a locator from the given href.

TemplateLocator builds a locator from the given href .


func fetchDetails(client *cm15.API, envName string, envDetail EnvironmentDetail, sshConfig *[]SSHConfig) {
	for nickname, name := range envDetail.ServerArrays {
		// Obtain the resource
		instances := serverArray(client, name)
		// Obtain the IP address of the first instance (only one instance is considered here -- for now)
		for _, instance := range instances {
			ipAddress := instance.PublicIpAddresses[0]
			number := getInstanceNumber(instance.Name)
			*sshConfig = append(*sshConfig, SSHConfig{Name: envName + "_" + nickname + number, IPAddress: ipAddress})
		}
	}
	for nickname, name := range envDetail.Servers {
		instance := server(client, name)
		ipAddress := instance.PublicIpAddresses[0]
		*sshConfig = append(*sshConfig, SSHConfig{Name: envName + "_" + nickname, IPAddress: ipAddress})
	}
}

// Fetch details about all servers and server arrays in an environment


func buildAliases(sshConfig []SSHConfig, sshOptions, sshUser string) string {
	var aliases string
	for _, conf := range sshConfig {
		aliases = aliases + fmt.Sprintf("alias %v='ssh %v %v@%v'\n", conf.Name, sshOptions, sshUser, conf.IPAddress)
	}
	return aliases
}

func buildAliases ( sshConfig [ ] SSHConfig , sshOptions , sshUser string ) string { var aliases string for _ , conf := range sshConfig { aliases = aliases + fmt . Sprintf ( " \n " , conf . Name , sshOptions , sshUser , conf . IPAddress ) } return aliases }

// Builds the aliases string based on the SSH configuration of all servers and server arrays in all environments.

Builds the aliases string based on the SSH configuration of all servers and server arrays in all environments .